1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* this file is part of pipelines */ |
4
|
|
|
|
5
|
|
|
namespace Ktomk\Pipelines; |
6
|
|
|
|
7
|
|
|
class Lib |
8
|
|
|
{ |
9
|
|
|
/** |
10
|
|
|
* @param mixed $v |
11
|
|
|
* @param mixed $d |
12
|
|
|
* |
13
|
|
|
* @return mixed |
14
|
|
|
*/ |
15
|
2 |
|
public static function r(&$v, $d) |
16
|
|
|
{ |
17
|
2 |
|
if (isset($v)) { |
18
|
1 |
|
return $v; |
19
|
|
|
} |
20
|
|
|
|
21
|
1 |
|
return $d; |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @param mixed $v variable reference |
26
|
|
|
* @param mixed $d [optional] default value (null) |
27
|
|
|
* |
28
|
|
|
* @return void |
29
|
|
|
*/ |
30
|
2 |
|
public static function v(&$v, $d = null) |
31
|
|
|
{ |
32
|
2 |
|
if (!isset($v)) { |
33
|
1 |
|
$v = $d; |
34
|
|
|
} |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @return string UUID version 4 |
39
|
|
|
*/ |
40
|
1 |
|
public static function generateUuid() |
41
|
|
|
{ |
42
|
1 |
|
return sprintf( |
43
|
|
|
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x', |
44
|
|
|
|
45
|
|
|
// 32 bits for "time_low" |
46
|
1 |
|
mt_rand(0, 0xffff), |
47
|
1 |
|
mt_rand(0, 0xffff), |
48
|
|
|
|
49
|
|
|
// 16 bits for "time_mid" |
50
|
1 |
|
mt_rand(0, 0xffff), |
51
|
|
|
|
52
|
|
|
// 16 bits for "time_hi_and_version", |
53
|
|
|
// four most significant bits holds version number 4 |
54
|
1 |
|
mt_rand(0, 0x0fff) | 0x4000, |
55
|
|
|
|
56
|
|
|
// 16 bits, 8 bits for "clk_seq_hi_res", |
57
|
|
|
// 8 bits for "clk_seq_low", |
58
|
|
|
// two most significant bits holds zero and one for variant DCE1.1 |
59
|
1 |
|
mt_rand(0, 0x3fff) | 0x8000, |
60
|
|
|
|
61
|
|
|
// 48 bits for "node" |
62
|
1 |
|
mt_rand(0, 0xffff), |
63
|
1 |
|
mt_rand(0, 0xffff), |
64
|
1 |
|
mt_rand(0, 0xffff) |
65
|
|
|
); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @param string $command |
70
|
|
|
* @param array|string[] $arguments |
71
|
|
|
* |
72
|
|
|
* @return string |
73
|
|
|
*/ |
74
|
2 |
|
public static function cmd($command, array $arguments) |
75
|
|
|
{ |
76
|
2 |
|
$buffer = $command; |
77
|
|
|
|
78
|
2 |
|
$arguments = self::mergeArray($arguments); |
79
|
|
|
|
80
|
2 |
|
foreach ($arguments as $argument) { |
81
|
2 |
|
$buffer .= ' ' . self::quoteArg($argument); |
82
|
|
|
} |
83
|
|
|
|
84
|
2 |
|
return $buffer; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* quote an argument to preserve its value verbatim when used as |
89
|
|
|
* a utility argument in shell |
90
|
|
|
* |
91
|
|
|
* @param string $argument |
92
|
|
|
* |
93
|
|
|
* @return string |
94
|
|
|
*/ |
95
|
9 |
|
public static function quoteArg($argument) |
96
|
|
|
{ |
97
|
9 |
|
$parts = explode("'", $argument); |
98
|
|
|
|
99
|
9 |
|
$buffer = ''; |
100
|
9 |
|
foreach ($parts as $index => $part) { |
101
|
9 |
|
$index && $buffer .= "\\'"; |
102
|
9 |
|
$safe = preg_match('~^[a-zA-Z0-9,._+@%/-]*$~D', $part); |
103
|
9 |
|
$buffer .= $safe ? $part : "'${part}'"; |
104
|
|
|
} |
105
|
|
|
|
106
|
9 |
|
if ('' === $buffer) { |
107
|
1 |
|
$buffer = "''"; |
108
|
|
|
} |
109
|
|
|
|
110
|
9 |
|
return $buffer; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Turn multi-line string into an array of lines. |
115
|
|
|
* |
116
|
|
|
* Handles (no) newline at the end of buffer |
117
|
|
|
* |
118
|
|
|
* @param string $buffer |
119
|
|
|
* |
120
|
|
|
* @return array|string[] |
121
|
|
|
*/ |
122
|
1 |
|
public static function lines($buffer) |
123
|
|
|
{ |
124
|
1 |
|
$lines = explode("\n", $buffer); |
125
|
1 |
|
$c = count($lines); |
126
|
1 |
|
if ($c && '' === $lines[$c - 1]) { |
127
|
1 |
|
array_pop($lines); |
128
|
|
|
} |
129
|
|
|
|
130
|
1 |
|
return $lines; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* merge n array parameters |
135
|
|
|
* |
136
|
|
|
* all parameters should be of type array. if a parameter ist not |
137
|
|
|
* an array it is promoted to one as the following: |
138
|
|
|
* |
139
|
|
|
* - null => [] # null is an empty array |
140
|
|
|
* - skalar => [skalar] # skalar is an array with itself as single value |
141
|
|
|
* - resource => [resource] # same as skalar |
142
|
|
|
* - object => [object] # same as skalar |
143
|
|
|
* |
144
|
|
|
* to produce a merged array of all these arrays. |
145
|
|
|
* |
146
|
|
|
* examples: |
147
|
|
|
* |
148
|
|
|
* (null, null) => [] |
149
|
|
|
* ([null], [null]) => [null, null] |
150
|
|
|
* (1, 2, 3) => [1, 2, 3] |
151
|
|
|
* ([1, 2], 3) => [1, 2, 3] |
152
|
|
|
* ([1, 2], ['a', 'b']) => [1, 2, 'a', 'b'] |
153
|
|
|
* |
154
|
|
|
* @return array |
155
|
|
|
*/ |
156
|
2 |
|
public static function merge() |
157
|
|
|
{ |
158
|
2 |
|
if (!$arrays = func_get_args()) { |
159
|
1 |
|
return $arrays; |
160
|
|
|
} |
161
|
|
|
|
162
|
1 |
|
return self::mergeArray($arrays); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* merge n array parameters |
167
|
|
|
* |
168
|
|
|
* {@see Lib::merge} with a single parameter |
169
|
|
|
* |
170
|
|
|
* @return array of merged parameters |
171
|
|
|
*/ |
172
|
3 |
|
public static function mergeArray(array $parameters) |
173
|
|
|
{ |
174
|
3 |
|
if (!$parameters) { |
|
|
|
|
175
|
|
|
return $parameters; |
176
|
|
|
} |
177
|
|
|
|
178
|
3 |
|
foreach ($parameters as $key => $value) { |
179
|
3 |
|
if (!is_array($value)) { |
180
|
3 |
|
$parameters[$key] = null === $value ? array() : array($value); |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
3 |
|
return call_user_func_array('array_merge', $parameters); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Chunk an array of strings based on maximum string length per chunk |
189
|
|
|
* |
190
|
|
|
* @param array|string[] $array |
191
|
|
|
* @param int $maxLength |
192
|
|
|
* @param int $overHeadPerEntry |
193
|
|
|
* |
194
|
|
|
* @return array|array[] |
195
|
|
|
*/ |
196
|
2 |
|
public static function arrayChunkByStringLength(array $array, $maxLength, $overHeadPerEntry = 0) |
197
|
|
|
{ |
198
|
2 |
|
$chunks = array(); |
199
|
2 |
|
$chunkStringLength = 0; |
200
|
2 |
|
$chunk = array(); |
201
|
|
|
|
202
|
2 |
|
foreach ($array as $key => $value) { |
203
|
2 |
|
$entryLen = strlen($value) + $overHeadPerEntry; |
204
|
2 |
|
if ($chunkStringLength + $entryLen > $maxLength) { |
205
|
2 |
|
if (empty($chunk)) { |
206
|
1 |
|
throw new \InvalidArgumentException(sprintf( |
207
|
|
|
'maximum length of %d is too little to chunk the array at %s %s (%d chunk(s) so far)', |
208
|
|
|
$maxLength, |
209
|
1 |
|
is_string($key) ? 'key' : 'index', |
210
|
1 |
|
is_string($key) ? var_export($key, true) : (int)$key, |
211
|
1 |
|
count($chunks) |
212
|
|
|
)); |
213
|
|
|
} |
214
|
1 |
|
$chunks[] = $chunk; |
215
|
1 |
|
$chunk = array(); |
216
|
1 |
|
$chunkStringLength = 0; |
217
|
|
|
} |
218
|
1 |
|
$chunk[] = $value; |
219
|
1 |
|
$chunkStringLength += $entryLen; |
220
|
|
|
} |
221
|
|
|
|
222
|
1 |
|
if (!empty($chunk)) { |
223
|
1 |
|
$chunks[] = $chunk; |
224
|
|
|
} |
225
|
|
|
|
226
|
1 |
|
return $chunks; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Get shell environment variables only from $_SERVER in PHP CLI |
231
|
|
|
* |
232
|
|
|
* Filter an array like $_SERVER in PHP CLI shell for environment |
233
|
|
|
* variables only. |
234
|
|
|
* |
235
|
|
|
* @param array $server |
236
|
|
|
* |
237
|
|
|
* @return array|string[] |
238
|
|
|
*/ |
239
|
1 |
|
public static function env(array $server) |
240
|
|
|
{ |
241
|
1 |
|
return array_filter( |
242
|
|
|
// Pipelines must not support environment variable names with '=' in them |
243
|
1 |
|
array_flip(preg_grep('~=~', array_keys($server))) |
244
|
|
|
// What PHP might have added |
245
|
|
|
+ array( |
246
|
1 |
|
'PHP_SELF' => null, |
247
|
|
|
'SCRIPT_NAME' => null, |
248
|
|
|
'SCRIPT_FILENAME' => null, |
249
|
|
|
'PATH_TRANSLATED' => null, |
250
|
|
|
'DOCUMENT_ROOT' => null, |
251
|
|
|
'REQUEST_TIME_FLOAT' => null, |
252
|
|
|
'REQUEST_TIME' => null, |
253
|
|
|
'argv' => null, |
254
|
|
|
'argc' => null, |
255
|
|
|
) |
256
|
|
|
+ $server, |
257
|
|
|
'is_string' |
258
|
|
|
); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* fallback for the php 5.3 version which does not have PHP_BINARY. |
263
|
|
|
* |
264
|
|
|
* fallback for the php 5.4-8.0 versions which do have an empty |
265
|
|
|
* PHP_BINARY when executed w/o absolute path in argv[0] |
266
|
|
|
* |
267
|
|
|
* @return string |
268
|
|
|
*/ |
269
|
1 |
|
public static function phpBinary() |
270
|
|
|
{ |
271
|
1 |
|
return defined('PHP_BINARY') && '' !== constant('PHP_BINARY') ? constant('PHP_BINARY') : PHP_BINDIR . '/php'; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Empty "coalesce" function |
276
|
|
|
* |
277
|
|
|
* @return mixed |
278
|
|
|
*/ |
279
|
1 |
|
public static function emptyCoalesce() |
280
|
|
|
{ |
281
|
1 |
|
foreach (func_get_args() as $arg) { |
282
|
1 |
|
if (empty($arg)) { |
283
|
1 |
|
continue; |
284
|
|
|
} |
285
|
|
|
|
286
|
1 |
|
return $arg; |
287
|
|
|
} |
288
|
|
|
|
289
|
1 |
|
return null; |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.