Completed
Push — master ( d1be6d...8440b6 )
by Andrey
07:58
created

Utilities::convertToEdmDateTime()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
233
    {
234
        foreach ((array) $sxml as $key => $value) {
235
            if (is_object($value) || (is_array($value))) {
236
                $arr[$key] = self::_sxml2arr($value);
0 ignored issues
show
Documentation introduced by
$value is of type object|array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression \DateTime::createFromFor...mat, $date, $timeZone); of type DateTime|false adds false to the return on line 359 which is incompatible with the return type documented by MicrosoftAzure\Storage\C...ties::rfc1123ToDateTime of type DateTime. It seems like you forgot to handle an error condition.
Loading history...
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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