Passed
Push — master ( 2bc6a1...487703 )
by Tom
02:53
created

Lib::fsIsStreamUri()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
ccs 4
cts 4
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines;
6
7
use UnexpectedValueException;
8
9
class Lib
10
{
11 2
    public static function r(&$v, $d)
12
    {
13 2
        if (isset($v)) {
14 1
            return $v;
15
        }
16
17 1
        return $d;
18
    }
19
20
    /**
21
     * @param mixed $v variable reference
22
     * @param mixed $d [optional]  default value (null)
23
     * @return void
24
     */
25 2
    public static function v(&$v, $d = null)
26
    {
27 2
        if (!isset($v)) {
28 1
            $v = $d;
29
        }
30 2
    }
31
32
    /**
33
     * @return string UUID version 4
34
     */
35 1
    public static function generateUuid()
36
    {
37 1
        return sprintf(
38 1
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
39
40
            // 32 bits for "time_low"
41 1
            mt_rand(0, 0xffff),
42 1
            mt_rand(0, 0xffff),
43
44
            // 16 bits for "time_mid"
45 1
            mt_rand(0, 0xffff),
46
47
            // 16 bits for "time_hi_and_version",
48
            // four most significant bits holds version number 4
49 1
            mt_rand(0, 0x0fff) | 0x4000,
50
51
            // 16 bits, 8 bits for "clk_seq_hi_res",
52
            // 8 bits for "clk_seq_low",
53
            // two most significant bits holds zero and one for variant DCE1.1
54 1
            mt_rand(0, 0x3fff) | 0x8000,
55
56
            // 48 bits for "node"
57 1
            mt_rand(0, 0xffff),
58 1
            mt_rand(0, 0xffff),
59 1
            mt_rand(0, 0xffff)
60
        );
61
    }
62
63 2
    public static function cmd($command, array $arguments)
64
    {
65 2
        $buffer = $command;
66
67 2
        $arguments = call_user_func_array('self::merge', $arguments);
68
69 2
        foreach ($arguments as $argument) {
70 2
            $buffer .= ' ' . self::quoteArg($argument);
71
        }
72
73 2
        return $buffer;
74
    }
75
76
    /**
77
     * quote an argument to preserve its value verbatim when used as
78
     * a utility argument in shell
79
     *
80
     * @param string $argument
81
     * @return string
82
     */
83 8
    public static function quoteArg($argument)
84
    {
85 8
        $parts = explode("'", $argument);
86
87 8
        $buffer = '';
88 8
        foreach ($parts as $index => $part) {
89 8
            $index && $buffer .= "\\'";
90 8
            $safe = preg_match('~^[a-zA-Z0-9,._+@%/-]*$~', $part);
91 8
            $buffer .= $safe ? $part : "'${part}'";
92
        }
93
94
        if ("" === $buffer) {
95
            $buffer = "''";
96
        }
97
98
        return $buffer;
99
    }
100
101
    /**
102
     * Turn multi-line string into an array of lines.
103
     *
104
     * Handles no newline at the end of buffer
105
     *
106
     * @param string $buffer
107
     * @return array
108
     */
109
    public static function lines($buffer)
110
    {
111 1
        $lines = explode("\n", $buffer);
112 1
        if ($c = count($lines) and '' === $lines[$c - 1]) {
113 1
            array_pop($lines);
114
        }
115
116 1
        return $lines;
117
    }
118
119
    /**
120
     * merge n parameters, if a scalar, turned into array, otherwise must be an array
121
     */
122
    public static function merge()
123
    {
124 4
        if (!$arrays = func_get_args()) {
125 1
            return $arrays;
126
        }
127
128 3
        foreach ($arrays as $key => $value) {
129 3
            if (!is_array($value)) {
130 3
                $arrays[$key] = (array)$value;
131
            }
132
        }
133
134 3
        return call_user_func_array('array_merge', $arrays);
135
    }
136
137
    /**
138
     * expand brace "{}" in pattern
139
     *
140
     * @param string $pattern
141
     * @throws \UnexpectedValueException
142
     * @return array of all patterns w/o braces, no duplicates
143
     */
144
    public static function expandBrace($pattern)
145
    {
146 16
        $stack = array($pattern);
147
148 16
        for ($i = 0; isset($stack[$i]); $i++) {
149 16
            $subject = $stack[$i];
150 16
            $result = self::expandBraceInnerMatch($subject, $matches);
151 16
            if (0 === $result) {
152 16
                continue;
153
            }
154
            // match
155 9
            $segments = preg_split('~\\\\.(*SKIP)(*FAIL)|,~', $matches[2]);
156 9
            $segments = array_unique(/** @scrutinizer ignore-type */ $segments);
157 9
            foreach ($segments as $segment) {
158 9
                $permutation = $matches[1] . $segment . $matches[3];
159 9
                in_array($permutation, $stack, true) || $stack[] = $permutation;
160
            }
161 9
            unset($stack[$i]);
162
        }
163
164
        // inline escaped brace characters
165
        $stack = array_map(function ($str) {
166 16
            return strtr($str, array(
167 16
                '\\\\' => '\\\\',
168
                '\\{' => '{', '\\}' => '}', '\\,' => ','
169
            ));
170 16
        }, $stack);
171
172 16
        return array_values($stack);
173
    }
174
175
    /**
176
     * check if path is absolute
177
     *
178
     * @param string $path
179
     * @return bool
180
     */
181
    public static function fsIsAbsolutePath($path)
182
    {
183
        // TODO: a variant with PHP stream wrapper prefix support
184
185 8
        $count = strspn($path, '/', 0, 3) % 2;
186
187 8
        return (bool)$count;
188
    }
189
190
    /**
191
     * check if path is basename
192
     *
193
     * @param string $path
194
     * @return bool
195
     */
196
    public static function fsIsBasename($path)
197
    {
198 5
        if (in_array($path, array('', '.', '..'), true)) {
199 1
            return false;
200
        }
201
202 4
        if (false !== strpos($path, '/')) {
203 3
            return false;
204
        }
205
206 1
        return true;
207
    }
208
209
    /**
210
     * create directory if not yet exists
211
     *
212
     * @param string $path
213
     * @throws \RuntimeException
214
     */
215
    public static function fsMkdir($path)
216
    {
217 2
        if (!is_dir($path)) {
218
            /** @noinspection NestedPositiveIfStatementsInspection */
219 2
            if (!mkdir($path, 0777, true) && !is_dir($path)) {
220
                // @codeCoverageIgnoreStart
221
                throw new \RuntimeException(
222
                    sprintf('Directory "%s" was not created', $path)
223
                );
224
                // @codeCoverageIgnoreEnd
225
            }
226
        }
227 2
    }
228
229
    /**
230
     * @param string $link
231
     */
232
    public static function fsUnlink($link)
233
    {
234 1
        if (is_link($link)) {
235 1
            unlink($link);
236
        }
237 1
    }
238
239
    /**
240
     * create symbolic link, recreate if it exists
241
     *
242
     * @param string $target
243
     * @param string $link
244
     */
245
    public static function fsSymlink($target, $link)
246
    {
247 1
        self::fsUnlink($link);
248 1
        symlink($target, $link);
249 1
    }
250
251
    /**
252
     * locate (readable) file by basename upward all parent directories
253
     *
254
     * @param string $basename
255
     * @param string $directory [optional] directory to operate from, defaults
256
     *               to "." (relative path of present working directory)
257
     * @return string
258
     */
259
    public static function fsFileLookUp($basename, $directory = null)
260
    {
261 4
        if ("" === $directory || null === $directory) {
262 1
            $directory = ".";
263
        }
264
265
        for (
266 4
            $dirName = $directory, $old = null;
267 4
            $old !== $dirName;
268 2
            $old = $dirName, $dirName = dirname($dirName)
269
        ) {
270 4
            $test = $dirName . '/' . $basename;
271 4
            if (is_file($test) && is_readable($test)) {
272 3
                return $test;
273
            }
274
        }
275
276 1
        return null;
277
    }
278
279
    /**
280
     * @param string $path
281
     * @return bool
282
     */
283
    public static function fsIsStreamUri($path)
284
    {
285 2
        $scheme = parse_url($path, PHP_URL_SCHEME);
286 2
        if (null === $scheme) {
287 1
            return false;
288
        }
289
290 1
        return in_array($scheme, stream_get_wrappers(), true);
291
    }
292
293
    /**
294
     * @param string $subject
295
     * @param array $matches
296
     * @throws UnexpectedValueException
297
     * @return false|int
298
     */
299
    private static function expandBraceInnerMatch($subject, &$matches)
300
    {
301 16
        $result = preg_match_all(
302 16
            '~(\\\\.(*SKIP)(*FAIL)|(?P<token>[,{}]))~',
303 16
            $subject,
304 16
            $lookup,
305 16
            PREG_OFFSET_CAPTURE
306
        );
307
308 16
        if (false === $result) {
309
            throw new UnexpectedValueException('regex pattern failure'); // @codeCoverageIgnore
310
        }
311
312 16
        if (0 === $result) {
313 12
            return $result;
314
        }
315
316 11
        $open = null;
317 11
        $comma = null;
318
319 11
        foreach ($lookup['token'] as $token) {
320 11
            list($type, $pos) = $token;
321 11
            if ('{' === $type) {
322 10
                $open = $token;
323 10
                $comma = null;
324 11
            } elseif (',' === $type) {
325 10
                $comma = $token;
326 11
            } elseif ($open && $comma) {
327
                $matches = array(
328 9
                    $subject,
329 9
                    substr($subject, 0, $open[1]),
330 9
                    substr($subject, $open[1] + 1, $pos - $open[1] - 1),
331 9
                    substr($subject, $pos + 1),
332
                );
333
334 11
                return 1;
335
            }
336
        }
337
338 4
        return 0;
339
    }
340
}
341