1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* LICENSE: The MIT License (the "License") |
5
|
|
|
* you may not use this file except in compliance with the License. |
6
|
|
|
* You may obtain a copy of the License at |
7
|
|
|
* https://github.com/azure/azure-storage-php/LICENSE |
8
|
|
|
* |
9
|
|
|
* Unless required by applicable law or agreed to in writing, software |
10
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
11
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12
|
|
|
* See the License for the specific language governing permissions and |
13
|
|
|
* limitations under the License. |
14
|
|
|
* |
15
|
|
|
* PHP version 5 |
16
|
|
|
* |
17
|
|
|
* @ignore |
18
|
|
|
* @category Microsoft |
19
|
|
|
* @package MicrosoftAzure\Storage\Common\Internal |
20
|
|
|
* @author Azure Storage PHP SDK <[email protected]> |
21
|
|
|
* @copyright 2016 Microsoft Corporation |
22
|
|
|
* @license https://github.com/azure/azure-storage-php/LICENSE |
23
|
|
|
* @link https://github.com/azure/azure-storage-php |
24
|
|
|
*/ |
25
|
|
|
|
26
|
|
|
namespace MicrosoftAzure\Storage\Common\Internal; |
27
|
|
|
|
28
|
|
|
use GuzzleHttp\Psr7\Stream; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Utilities for the project |
32
|
|
|
* |
33
|
|
|
* @category Microsoft |
34
|
|
|
* @package MicrosoftAzure\Storage\Common\Internal |
35
|
|
|
* @author Azure Storage PHP SDK <[email protected]> |
36
|
|
|
* @copyright 2016 Microsoft Corporation |
37
|
|
|
* @license https://github.com/azure/azure-storage-php/LICENSE |
38
|
|
|
* @link https://github.com/azure/azure-storage-php |
39
|
|
|
*/ |
40
|
|
|
class Utilities |
41
|
|
|
{ |
42
|
|
|
/** |
43
|
|
|
* Returns the specified value of the $key passed from $array and in case that |
44
|
|
|
* this $key doesn't exist, the default value is returned. |
45
|
|
|
* |
46
|
|
|
* @param array $array The array to be used. |
47
|
|
|
* @param mixed $key The array key. |
48
|
|
|
* @param mixed $default The value to return if $key is not found in $array. |
49
|
|
|
* |
50
|
|
|
* @return mixed |
51
|
|
|
*/ |
52
|
|
|
public static function tryGetValue($array, $key, $default = null) |
53
|
|
|
{ |
54
|
|
|
return (!is_null($array)) && is_array($array) && array_key_exists($key, $array) |
55
|
|
|
? $array[$key] |
56
|
|
|
: $default; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Adds a url scheme if there is no scheme. Return null if input URL is null. |
61
|
|
|
* |
62
|
|
|
* @param string $url The URL. |
63
|
|
|
* @param string $scheme The scheme. By default HTTP |
64
|
|
|
* |
65
|
|
|
* @return string |
66
|
|
|
*/ |
67
|
|
|
public static function tryAddUrlScheme($url, $scheme = 'http') |
68
|
|
|
{ |
69
|
|
|
if ($url == null) { |
70
|
|
|
return $url; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
$urlScheme = parse_url($url, PHP_URL_SCHEME); |
74
|
|
|
|
75
|
|
|
if (empty($urlScheme)) { |
76
|
|
|
$url = "$scheme://" . $url; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return $url; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Parse storage account name from an endpoint url. |
84
|
|
|
* |
85
|
|
|
* @param string $url The endpoint $url |
86
|
|
|
* |
87
|
|
|
* @return string |
88
|
|
|
*/ |
89
|
|
|
public static function tryParseAccountNameFromUrl($url) |
90
|
|
|
{ |
91
|
|
|
$host = parse_url($url, PHP_URL_HOST); |
92
|
|
|
|
93
|
|
|
// first token of the url host is account name |
94
|
|
|
return explode('.', $host)[0]; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* tries to get nested array with index name $key from $array. |
99
|
|
|
* |
100
|
|
|
* Returns empty array object if the value is NULL. |
101
|
|
|
* |
102
|
|
|
* @param string $key The index name. |
103
|
|
|
* @param array $array The array object. |
104
|
|
|
* |
105
|
|
|
* @return array |
106
|
|
|
*/ |
107
|
|
|
public static function tryGetArray($key, array $array) |
108
|
|
|
{ |
109
|
|
|
return Utilities::getArray(Utilities::tryGetValue($array, $key)); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Adds the given key/value pair into array if the value doesn't satisfy empty(). |
114
|
|
|
* |
115
|
|
|
* This function just validates that the given $array is actually array. If it's |
116
|
|
|
* NULL the function treats it as array. |
117
|
|
|
* |
118
|
|
|
* @param string $key The key. |
119
|
|
|
* @param string $value The value. |
120
|
|
|
* @param array &$array The array. If NULL will be used as array. |
121
|
|
|
* |
122
|
|
|
* @return void |
123
|
|
|
*/ |
124
|
|
|
public static function addIfNotEmpty($key, $value, array &$array) |
125
|
|
|
{ |
126
|
|
|
if (!is_null($array)) { |
127
|
|
|
Validate::isArray($array, 'array'); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
if (!empty($value)) { |
131
|
|
|
$array[$key] = $value; |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Returns the specified value of the key chain passed from $array and in case |
137
|
|
|
* that key chain doesn't exist, null is returned. |
138
|
|
|
* |
139
|
|
|
* @param array $array Array to be used. |
140
|
|
|
* |
141
|
|
|
* @return mixed |
142
|
|
|
*/ |
143
|
|
|
public static function tryGetKeysChainValue(array $array) |
144
|
|
|
{ |
145
|
|
|
$arguments = func_get_args(); |
146
|
|
|
$numArguments = func_num_args(); |
147
|
|
|
|
148
|
|
|
$currentArray = $array; |
149
|
|
|
for ($i = 1; $i < $numArguments; $i++) { |
150
|
|
|
if (is_array($currentArray)) { |
151
|
|
|
if (array_key_exists($arguments[$i], $currentArray)) { |
152
|
|
|
$currentArray = $currentArray[$arguments[$i]]; |
153
|
|
|
} else { |
154
|
|
|
return null; |
155
|
|
|
} |
156
|
|
|
} else { |
157
|
|
|
return null; |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
return $currentArray; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Checks if the passed $string starts with $prefix |
166
|
|
|
* |
167
|
|
|
* @param string $string word to seaech in |
168
|
|
|
* @param string $prefix prefix to be matched |
169
|
|
|
* @param boolean $ignoreCase true to ignore case during the comparison; |
170
|
|
|
* otherwise, false |
171
|
|
|
* |
172
|
|
|
* @return boolean |
173
|
|
|
*/ |
174
|
|
|
public static function startsWith($string, $prefix, $ignoreCase = false) |
175
|
|
|
{ |
176
|
|
|
if ($ignoreCase) { |
177
|
|
|
$string = strtolower($string); |
178
|
|
|
$prefix = strtolower($prefix); |
179
|
|
|
} |
180
|
|
|
return ($prefix == substr($string, 0, strlen($prefix))); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Returns grouped items from passed $var |
185
|
|
|
* |
186
|
|
|
* @param array $var item to group |
187
|
|
|
* |
188
|
|
|
* @return array |
189
|
|
|
*/ |
190
|
|
|
public static function getArray(array $var) |
191
|
|
|
{ |
192
|
|
|
if (is_null($var) || empty($var)) { |
193
|
|
|
return array(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
foreach ($var as $value) { |
197
|
|
|
if ((gettype($value) == 'object') |
198
|
|
|
&& (get_class($value) == 'SimpleXMLElement') |
199
|
|
|
) { |
200
|
|
|
return (array) $var; |
201
|
|
|
} elseif (!is_array($value)) { |
202
|
|
|
return array($var); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
return $var; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Unserializes the passed $xml into array. |
211
|
|
|
* |
212
|
|
|
* @param string $xml XML to be parsed. |
213
|
|
|
* |
214
|
|
|
* @return array |
215
|
|
|
*/ |
216
|
|
|
public static function unserialize($xml) |
217
|
|
|
{ |
218
|
|
|
$sxml = new \SimpleXMLElement($xml); |
219
|
|
|
|
220
|
|
|
return self::_sxml2arr($sxml); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Converts a SimpleXML object to an Array recursively |
225
|
|
|
* ensuring all sub-elements are arrays as well. |
226
|
|
|
* |
227
|
|
|
* @param string $sxml SimpleXML object |
228
|
|
|
* @param array $arr Array into which to store results |
229
|
|
|
* |
230
|
|
|
* @return array |
231
|
|
|
*/ |
232
|
|
View Code Duplication |
private static function _sxml2arr($sxml, array $arr = null) |
|
|
|
|
233
|
|
|
{ |
234
|
|
|
foreach ((array) $sxml as $key => $value) { |
235
|
|
|
if (is_object($value) || (is_array($value))) { |
236
|
|
|
$arr[$key] = self::_sxml2arr($value); |
|
|
|
|
237
|
|
|
} else { |
238
|
|
|
$arr[$key] = $value; |
239
|
|
|
} |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
return $arr; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Serializes given array into xml. The array indices must be string to use |
247
|
|
|
* them as XML tags. |
248
|
|
|
* |
249
|
|
|
* @param array $array object to serialize represented in array. |
250
|
|
|
* @param string $rootName name of the XML root element. |
251
|
|
|
* @param string $defaultTag default tag for non-tagged elements. |
252
|
|
|
* @param string $standalone adds 'standalone' header tag, values 'yes'/'no' |
253
|
|
|
* |
254
|
|
|
* @return string |
255
|
|
|
*/ |
256
|
|
|
public static function serialize( |
257
|
|
|
array $array, |
258
|
|
|
$rootName, |
259
|
|
|
$defaultTag = null, |
260
|
|
|
$standalone = null |
261
|
|
|
) { |
262
|
|
|
$xmlVersion = '1.0'; |
263
|
|
|
$xmlEncoding = 'UTF-8'; |
264
|
|
|
|
265
|
|
|
if (!is_array($array)) { |
266
|
|
|
return false; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
$xmlw = new \XmlWriter(); |
270
|
|
|
$xmlw->openMemory(); |
271
|
|
|
$xmlw->startDocument($xmlVersion, $xmlEncoding, $standalone); |
272
|
|
|
|
273
|
|
|
$xmlw->startElement($rootName); |
274
|
|
|
|
275
|
|
|
self::_arr2xml($xmlw, $array, $defaultTag); |
276
|
|
|
|
277
|
|
|
$xmlw->endElement(); |
278
|
|
|
|
279
|
|
|
return $xmlw->outputMemory(true); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Takes an array and produces XML based on it. |
284
|
|
|
* |
285
|
|
|
* @param XMLWriter $xmlw XMLWriter object that was previously instanted |
286
|
|
|
* and is used for creating the XML. |
287
|
|
|
* @param array $data Array to be converted to XML |
288
|
|
|
* @param string $defaultTag Default XML tag to be used if none specified. |
289
|
|
|
* |
290
|
|
|
* @return void |
291
|
|
|
*/ |
292
|
|
|
private static function _arr2xml( |
293
|
|
|
\XMLWriter $xmlw, |
294
|
|
|
array $data, |
295
|
|
|
$defaultTag = null |
296
|
|
|
) { |
297
|
|
|
foreach ($data as $key => $value) { |
298
|
|
|
if (strcmp($key, '@attributes') == 0) { |
299
|
|
|
foreach ($value as $attributeName => $attributeValue) { |
300
|
|
|
$xmlw->writeAttribute($attributeName, $attributeValue); |
301
|
|
|
} |
302
|
|
View Code Duplication |
} elseif (is_array($value)) { |
|
|
|
|
303
|
|
|
if (!is_int($key)) { |
304
|
|
|
if ($key != Resources::EMPTY_STRING) { |
305
|
|
|
$xmlw->startElement($key); |
306
|
|
|
} else { |
307
|
|
|
$xmlw->startElement($defaultTag); |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
self::_arr2xml($xmlw, $value); |
312
|
|
|
|
313
|
|
|
if (!is_int($key)) { |
314
|
|
|
$xmlw->endElement(); |
315
|
|
|
} |
316
|
|
|
continue; |
317
|
|
|
} else { |
318
|
|
|
$xmlw->writeElement($key, $value); |
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Converts string into boolean value. |
325
|
|
|
* |
326
|
|
|
* @param string $obj boolean value in string format. |
327
|
|
|
* |
328
|
|
|
* @return bool |
329
|
|
|
*/ |
330
|
|
|
public static function toBoolean($obj) |
331
|
|
|
{ |
332
|
|
|
return filter_var($obj, FILTER_VALIDATE_BOOLEAN); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Converts string into boolean value. |
337
|
|
|
* |
338
|
|
|
* @param bool $obj boolean value to convert. |
339
|
|
|
* |
340
|
|
|
* @return string |
341
|
|
|
*/ |
342
|
|
|
public static function booleanToString($obj) |
343
|
|
|
{ |
344
|
|
|
return $obj ? 'true' : 'false'; |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* Converts a given date string into \DateTime object |
349
|
|
|
* |
350
|
|
|
* @param string $date windows azure date ins string represntation. |
351
|
|
|
* |
352
|
|
|
* @return \DateTime |
353
|
|
|
*/ |
354
|
|
|
public static function rfc1123ToDateTime($date) |
355
|
|
|
{ |
356
|
|
|
$timeZone = new \DateTimeZone('GMT'); |
357
|
|
|
$format = Resources::AZURE_DATE_FORMAT; |
358
|
|
|
|
359
|
|
|
return \DateTime::createFromFormat($format, $date, $timeZone); |
|
|
|
|
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* Generate ISO 8601 compliant date string in UTC time zone |
364
|
|
|
* |
365
|
|
|
* @param int $timestamp The unix timestamp to convert |
366
|
|
|
* (for DateTime check date_timestamp_get). |
367
|
|
|
* |
368
|
|
|
* @return string |
369
|
|
|
*/ |
370
|
|
|
public static function isoDate($timestamp = null) |
371
|
|
|
{ |
372
|
|
|
$tz = date_default_timezone_get(); |
373
|
|
|
date_default_timezone_set('UTC'); |
374
|
|
|
|
375
|
|
|
if (is_null($timestamp)) { |
376
|
|
|
$timestamp = time(); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
$returnValue = str_replace( |
380
|
|
|
'+00:00', |
381
|
|
|
'.0000000Z', |
382
|
|
|
date('c', $timestamp) |
383
|
|
|
); |
384
|
|
|
date_default_timezone_set($tz); |
385
|
|
|
return $returnValue; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Converts a DateTime object into an Edm.DaeTime value in UTC timezone, |
390
|
|
|
* represented as a string. |
391
|
|
|
* |
392
|
|
|
* @param mixed $value The datetime value. |
393
|
|
|
* |
394
|
|
|
* @return string |
395
|
|
|
*/ |
396
|
|
|
public static function convertToEdmDateTime($value) |
397
|
|
|
{ |
398
|
|
|
if (empty($value)) { |
399
|
|
|
return $value; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
if (is_string($value)) { |
403
|
|
|
$value = self::convertToDateTime($value); |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
Validate::isDate($value); |
407
|
|
|
|
408
|
|
|
$cloned = clone $value; |
409
|
|
|
$cloned->setTimezone(new \DateTimeZone('UTC')); |
410
|
|
|
return str_replace('+0000', 'Z', $cloned->format("Y-m-d\TH:i:s.u0O")); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
/** |
414
|
|
|
* Converts a string to a \DateTime object. Returns false on failure. |
415
|
|
|
* |
416
|
|
|
* @param string $value The string value to parse. |
417
|
|
|
* |
418
|
|
|
* @return \DateTime |
419
|
|
|
*/ |
420
|
|
|
public static function convertToDateTime($value) |
421
|
|
|
{ |
422
|
|
|
if ($value instanceof \DateTime) { |
423
|
|
|
return $value; |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
if (substr($value, -1) == 'Z') { |
427
|
|
|
$value = substr($value, 0, strlen($value) - 1); |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
return new \DateTime($value, new \DateTimeZone('UTC')); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Converts string to stream handle. |
435
|
|
|
* |
436
|
|
|
* @param string $string The string contents. |
437
|
|
|
* |
438
|
|
|
* @return resource |
439
|
|
|
*/ |
440
|
|
|
public static function stringToStream($string) |
441
|
|
|
{ |
442
|
|
|
return fopen('data://text/plain,' . urlencode($string), 'rb'); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* Sorts an array based on given keys order. |
447
|
|
|
* |
448
|
|
|
* @param array $array The array to sort. |
449
|
|
|
* @param array $order The keys order array. |
450
|
|
|
* |
451
|
|
|
* @return array |
452
|
|
|
*/ |
453
|
|
|
public static function orderArray(array $array, array $order) |
454
|
|
|
{ |
455
|
|
|
$ordered = array(); |
456
|
|
|
|
457
|
|
|
foreach ($order as $key) { |
458
|
|
|
if (array_key_exists($key, $array)) { |
459
|
|
|
$ordered[$key] = $array[$key]; |
460
|
|
|
} |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
return $ordered; |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Checks if a value exists in an array. The comparison is done in a case |
468
|
|
|
* insensitive manner. |
469
|
|
|
* |
470
|
|
|
* @param string $needle The searched value. |
471
|
|
|
* @param array $haystack The array. |
472
|
|
|
* |
473
|
|
|
* @return boolean |
474
|
|
|
*/ |
475
|
|
|
public static function inArrayInsensitive($needle, array $haystack) |
476
|
|
|
{ |
477
|
|
|
return in_array(strtolower($needle), array_map('strtolower', $haystack)); |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
/** |
481
|
|
|
* Checks if the given key exists in the array. The comparison is done in a case |
482
|
|
|
* insensitive manner. |
483
|
|
|
* |
484
|
|
|
* @param string $key The value to check. |
485
|
|
|
* @param array $search The array with keys to check. |
486
|
|
|
* |
487
|
|
|
* @return boolean |
488
|
|
|
*/ |
489
|
|
|
public static function arrayKeyExistsInsensitive($key, array $search) |
490
|
|
|
{ |
491
|
|
|
return array_key_exists(strtolower($key), array_change_key_case($search)); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* Returns the specified value of the $key passed from $array and in case that |
496
|
|
|
* this $key doesn't exist, the default value is returned. The key matching is |
497
|
|
|
* done in a case insensitive manner. |
498
|
|
|
* |
499
|
|
|
* @param string $key The array key. |
500
|
|
|
* @param array $haystack The array to be used. |
501
|
|
|
* @param mixed $default The value to return if $key is not found in $array. |
502
|
|
|
* |
503
|
|
|
* @return mixed |
504
|
|
|
*/ |
505
|
|
|
public static function tryGetValueInsensitive($key, $haystack, $default = null) |
506
|
|
|
{ |
507
|
|
|
$array = array_change_key_case($haystack); |
508
|
|
|
return Utilities::tryGetValue($array, strtolower($key), $default); |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
/** |
512
|
|
|
* Returns a string representation of a version 4 GUID, which uses random |
513
|
|
|
* numbers.There are 6 reserved bits, and the GUIDs have this format: |
514
|
|
|
* xxxxxxxx-xxxx-4xxx-[8|9|a|b]xxx-xxxxxxxxxxxx |
515
|
|
|
* where 'x' is a hexadecimal digit, 0-9a-f. |
516
|
|
|
* |
517
|
|
|
* See http://tools.ietf.org/html/rfc4122 for more information. |
518
|
|
|
* |
519
|
|
|
* Note: This function is available on all platforms, while the |
520
|
|
|
* com_create_guid() is only available for Windows. |
521
|
|
|
* |
522
|
|
|
* @return string A new GUID. |
523
|
|
|
*/ |
524
|
|
|
public static function getGuid() |
525
|
|
|
{ |
526
|
|
|
// @codingStandardsIgnoreStart |
527
|
|
|
|
528
|
|
|
return sprintf( |
529
|
|
|
'%04x%04x-%04x-%04x-%02x%02x-%04x%04x%04x', |
530
|
|
|
mt_rand(0, 65535), |
531
|
|
|
mt_rand(0, 65535), // 32 bits for "time_low" |
532
|
|
|
mt_rand(0, 65535), // 16 bits for "time_mid" |
533
|
|
|
mt_rand(0, 4096) + 16384, // 16 bits for "time_hi_and_version", with |
534
|
|
|
// the most significant 4 bits being 0100 |
535
|
|
|
// to indicate randomly generated version |
536
|
|
|
mt_rand(0, 64) + 128, // 8 bits for "clock_seq_hi", with |
537
|
|
|
// the most significant 2 bits being 10, |
538
|
|
|
// required by version 4 GUIDs. |
539
|
|
|
mt_rand(0, 256), // 8 bits for "clock_seq_low" |
540
|
|
|
mt_rand(0, 65535), // 16 bits for "node 0" and "node 1" |
541
|
|
|
mt_rand(0, 65535), // 16 bits for "node 2" and "node 3" |
542
|
|
|
mt_rand(0, 65535) // 16 bits for "node 4" and "node 5" |
543
|
|
|
); |
544
|
|
|
|
545
|
|
|
// @codingStandardsIgnoreEnd |
546
|
|
|
} |
547
|
|
|
|
548
|
|
|
/** |
549
|
|
|
* Creates a list of objects of type $class from the provided array using static |
550
|
|
|
* create method. |
551
|
|
|
* |
552
|
|
|
* @param array $parsed The object in array representation |
553
|
|
|
* @param string $class The class name. Must have static method create. |
554
|
|
|
* |
555
|
|
|
* @return array |
556
|
|
|
*/ |
557
|
|
|
public static function createInstanceList(array $parsed, $class) |
558
|
|
|
{ |
559
|
|
|
$list = array(); |
560
|
|
|
|
561
|
|
|
foreach ($parsed as $value) { |
562
|
|
|
$list[] = $class::create($value); |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
return $list; |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
/** |
569
|
|
|
* Takes a string and return if it ends with the specified character/string. |
570
|
|
|
* |
571
|
|
|
* @param string $haystack The string to search in. |
572
|
|
|
* @param string $needle postfix to match. |
573
|
|
|
* @param boolean $ignoreCase Set true to ignore case during the comparison; |
574
|
|
|
* otherwise, false |
575
|
|
|
* |
576
|
|
|
* @return boolean |
577
|
|
|
*/ |
578
|
|
|
public static function endsWith($haystack, $needle, $ignoreCase = false) |
579
|
|
|
{ |
580
|
|
|
if ($ignoreCase) { |
581
|
|
|
$haystack = strtolower($haystack); |
582
|
|
|
$needle = strtolower($needle); |
583
|
|
|
} |
584
|
|
|
$length = strlen($needle); |
585
|
|
|
if ($length == 0) { |
586
|
|
|
return true; |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
return (substr($haystack, -$length) === $needle); |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Get id from entity object or string. |
594
|
|
|
* If entity is object than validate type and return $entity->$method() |
595
|
|
|
* If entity is string than return this string |
596
|
|
|
* |
597
|
|
|
* @param object|string $entity Entity with id property |
598
|
|
|
* @param string $type Entity type to validate |
599
|
|
|
* @param string $method Methods that gets id (getId by default) |
600
|
|
|
* |
601
|
|
|
* @return string |
602
|
|
|
*/ |
603
|
|
|
public static function getEntityId($entity, $type, $method = 'getId') |
604
|
|
|
{ |
605
|
|
|
if (is_string($entity)) { |
606
|
|
|
return $entity; |
607
|
|
|
} else { |
608
|
|
|
Validate::isA($entity, $type, 'entity'); |
609
|
|
|
Validate::methodExists($entity, $method, $type); |
610
|
|
|
|
611
|
|
|
return $entity->$method(); |
612
|
|
|
} |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
/** |
616
|
|
|
* Generate a pseudo-random string of bytes using a cryptographically strong |
617
|
|
|
* algorithm. |
618
|
|
|
* |
619
|
|
|
* @param int $length Length of the string in bytes |
620
|
|
|
* |
621
|
|
|
* @return string|boolean Generated string of bytes on success, or FALSE on |
622
|
|
|
* failure. |
623
|
|
|
*/ |
624
|
|
|
public static function generateCryptoKey($length) |
625
|
|
|
{ |
626
|
|
|
return openssl_random_pseudo_bytes($length); |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
/** |
630
|
|
|
* Convert base 256 number to decimal number. |
631
|
|
|
* |
632
|
|
|
* @param string $number Base 256 number |
633
|
|
|
* |
634
|
|
|
* @return string Decimal number |
635
|
|
|
*/ |
636
|
|
|
public static function base256ToDec($number) |
637
|
|
|
{ |
638
|
|
|
Validate::isString($number, 'number'); |
639
|
|
|
|
640
|
|
|
$result = 0; |
641
|
|
|
$base = 1; |
642
|
|
|
for ($i = strlen($number) - 1; $i >= 0; $i--) { |
643
|
|
|
$result = bcadd($result, bcmul(ord($number[$i]), $base)); |
644
|
|
|
$base = bcmul($base, 256); |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
return $result; |
648
|
|
|
} |
649
|
|
|
|
650
|
|
|
/** |
651
|
|
|
* To evaluate if the stream is larger than a certain size. To restore |
652
|
|
|
* the stream, it has to be seekable, so will return true if the stream |
653
|
|
|
* is not seekable. |
654
|
|
|
* @param Stream $stream The stream to be evaluated. |
655
|
|
|
* @param int $size The size if the string is larger than. |
656
|
|
|
* |
657
|
|
|
* @return boolean true if the stream is larger than the given size. |
658
|
|
|
*/ |
659
|
|
|
public static function isStreamLargerThanSizeOrNotSeekable(Stream $stream, $size) |
660
|
|
|
{ |
661
|
|
|
Validate::isInteger($size, 'size'); |
662
|
|
|
Validate::isTrue( |
663
|
|
|
$stream instanceof Stream, |
664
|
|
|
sprintf(Resources::INVALID_PARAM_MSG, 'stream', 'Guzzle\Stream') |
665
|
|
|
); |
666
|
|
|
$result = true; |
667
|
|
|
if ($stream->isSeekable()) { |
668
|
|
|
$position = $stream->tell(); |
669
|
|
|
try { |
670
|
|
|
$stream->seek($size); |
671
|
|
|
} catch (\RuntimeException $e) { |
672
|
|
|
$pos = strpos( |
673
|
|
|
$e->getMessage(), |
674
|
|
|
'to seek to stream position ' |
675
|
|
|
); |
676
|
|
|
if ($pos == null) { |
677
|
|
|
throw $e; |
678
|
|
|
} |
679
|
|
|
$result = false; |
680
|
|
|
} |
681
|
|
|
if ($stream->eof()) { |
682
|
|
|
$result = false; |
683
|
|
|
} elseif ($stream->read(1) == '') { |
684
|
|
|
$result = false; |
685
|
|
|
} |
686
|
|
|
$stream->seek($position); |
687
|
|
|
} |
688
|
|
|
return $result; |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
/** |
692
|
|
|
* Gets metadata array by parsing them from given headers. |
693
|
|
|
* |
694
|
|
|
* @param array $headers HTTP headers containing metadata elements. |
695
|
|
|
* |
696
|
|
|
* @return array |
697
|
|
|
*/ |
698
|
|
|
public static function getMetadataArray(array $headers) |
699
|
|
|
{ |
700
|
|
|
$metadata = array(); |
701
|
|
|
foreach ($headers as $key => $value) { |
702
|
|
|
$isMetadataHeader = Utilities::startsWith( |
703
|
|
|
strtolower($key), |
704
|
|
|
Resources::X_MS_META_HEADER_PREFIX |
705
|
|
|
); |
706
|
|
|
|
707
|
|
|
if ($isMetadataHeader) { |
708
|
|
|
// Metadata name is case-presrved and case insensitive |
709
|
|
|
$MetadataName = str_ireplace( |
710
|
|
|
Resources::X_MS_META_HEADER_PREFIX, |
711
|
|
|
Resources::EMPTY_STRING, |
712
|
|
|
$key |
713
|
|
|
); |
714
|
|
|
$metadata[$MetadataName] = $value; |
715
|
|
|
} |
716
|
|
|
} |
717
|
|
|
|
718
|
|
|
return $metadata; |
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
/** |
722
|
|
|
* Validates the provided metadata array. |
723
|
|
|
* |
724
|
|
|
* @param array $metadata The metadata array. |
725
|
|
|
* |
726
|
|
|
* @return void |
727
|
|
|
*/ |
728
|
|
View Code Duplication |
public static function validateMetadata(array $metadata = null) |
|
|
|
|
729
|
|
|
{ |
730
|
|
|
if (!is_null($metadata)) { |
731
|
|
|
Validate::isArray($metadata, 'metadata'); |
732
|
|
|
} else { |
733
|
|
|
$metadata = array(); |
734
|
|
|
} |
735
|
|
|
|
736
|
|
|
foreach ($metadata as $key => $value) { |
737
|
|
|
Validate::isString($key, 'metadata key'); |
738
|
|
|
Validate::isString($value, 'metadata value'); |
739
|
|
|
} |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Append the content to file. |
744
|
|
|
* @param string $path The file to append to. |
745
|
|
|
* @param string $content The content to append. |
746
|
|
|
* |
747
|
|
|
* @return void |
748
|
|
|
*/ |
749
|
|
|
public static function appendToFile($path, $content) |
750
|
|
|
{ |
751
|
|
|
$resource = @fopen($path, 'a+'); |
752
|
|
|
if ($resource != null) { |
753
|
|
|
fwrite($resource, $content); |
754
|
|
|
fclose($resource); |
755
|
|
|
} |
756
|
|
|
} |
757
|
|
|
|
758
|
|
|
/** |
759
|
|
|
* Check if all the bytes are zero. |
760
|
|
|
* @param string $content The content. |
761
|
|
|
*/ |
762
|
|
|
public static function allZero($content) |
763
|
|
|
{ |
764
|
|
|
$size = strlen($content); |
765
|
|
|
|
766
|
|
|
// If all Zero, skip this range |
767
|
|
|
for ($i = 0; $i < $size; $i++) { |
768
|
|
|
if (ord($content[$i] != 0)) { |
769
|
|
|
return false; |
770
|
|
|
} |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
return true; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
/** |
777
|
|
|
* Append the delimiter to the string. The delimiter will not be added if |
778
|
|
|
* the string already ends with this delimiter. |
779
|
|
|
* |
780
|
|
|
* @param string $string The string to add delimiter to. |
781
|
|
|
* @param string $delimiter The delimiter to be added. |
782
|
|
|
* |
783
|
|
|
* @return string |
784
|
|
|
*/ |
785
|
|
|
public static function appendDelimiter($string, $delimiter) |
786
|
|
|
{ |
787
|
|
|
if (!self::endsWith($string, $delimiter)) { |
788
|
|
|
$string .= $delimiter; |
789
|
|
|
} |
790
|
|
|
|
791
|
|
|
return $string; |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
/** |
795
|
|
|
* Static function used to determine if the request is performed against |
796
|
|
|
* secondary endpoint. |
797
|
|
|
* |
798
|
|
|
* @param Psr\Http\Message\RequestInterface $request The request performed. |
799
|
|
|
* @param array $options The options of the |
800
|
|
|
* request. Must contain |
801
|
|
|
* Resources::ROS_SECONDARY_URI |
802
|
|
|
* |
803
|
|
|
* @return boolean |
804
|
|
|
*/ |
805
|
|
|
public static function requestSentToSecondary( |
806
|
|
|
\Psr\Http\Message\RequestInterface $request, |
807
|
|
|
array $options |
808
|
|
|
) { |
809
|
|
|
$uri = $request->getUri(); |
810
|
|
|
$secondaryUri = $options[Resources::ROS_SECONDARY_URI]; |
811
|
|
|
$isSecondary = false; |
812
|
|
|
if (strpos((string)$uri, (string)$secondaryUri) !== false) { |
813
|
|
|
$isSecondary = true; |
814
|
|
|
} |
815
|
|
|
return $isSecondary; |
816
|
|
|
} |
817
|
|
|
|
818
|
|
|
/** |
819
|
|
|
* Gets the location value from the headers. |
820
|
|
|
* |
821
|
|
|
* @param array $headers request/response headers. |
822
|
|
|
* |
823
|
|
|
* @return string |
824
|
|
|
*/ |
825
|
|
|
public static function getLocationFromHeaders(array $headers) |
826
|
|
|
{ |
827
|
|
|
$value = Utilities::tryGetValue( |
828
|
|
|
$headers, |
829
|
|
|
Resources::X_MS_CONTINUATION_LOCATION_MODE |
830
|
|
|
); |
831
|
|
|
|
832
|
|
|
$result = ''; |
833
|
|
|
if (\is_string($value)) { |
834
|
|
|
$result = $value; |
835
|
|
|
} elseif (!empty($value)) { |
836
|
|
|
$result = $value[0]; |
837
|
|
|
} |
838
|
|
|
return $result; |
839
|
|
|
} |
840
|
|
|
|
841
|
|
|
/** |
842
|
|
|
* Gets if the value is a double value or string representation of a double |
843
|
|
|
* value |
844
|
|
|
* |
845
|
|
|
* @param mixed $value The value to be verified. |
846
|
|
|
* |
847
|
|
|
* @return boolean |
848
|
|
|
*/ |
849
|
|
|
public static function isDouble($value) |
850
|
|
|
{ |
851
|
|
|
return is_double($value + 0); |
852
|
|
|
} |
853
|
|
|
|
854
|
|
|
/** |
855
|
|
|
* Calculates the content MD5 which is base64 encoded. This should be align |
856
|
|
|
* with the server calculated MD5. |
857
|
|
|
* |
858
|
|
|
* @param string $content the content to be calculated. |
859
|
|
|
* |
860
|
|
|
* @return string |
861
|
|
|
*/ |
862
|
|
|
public static function calculateContentMD5($content) |
863
|
|
|
{ |
864
|
|
|
Validate::notNull($content, 'content'); |
865
|
|
|
Validate::isString($content, 'content'); |
866
|
|
|
|
867
|
|
|
return base64_encode(md5($content, true)); |
868
|
|
|
} |
869
|
|
|
} |
870
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.