Passed
Push — master ( 3b22a1...94154d )
by Tom
03:44
created

Lib::r()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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