Completed
Pull Request — master (#472)
by
unknown
02:28
created

AzureBlobStorage::parseErrorCode()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 6
nop 1
1
<?php
2
3
namespace Gaufrette\Adapter;
4
5
use Gaufrette\Adapter;
6
use Gaufrette\Util;
7
use Gaufrette\Adapter\AzureBlobStorage\BlobProxyFactoryInterface;
8
use MicrosoftAzure\Storage\Blob\Models\CreateBlobOptions;
9
use MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions;
10
use MicrosoftAzure\Storage\Blob\Models\DeleteContainerOptions;
11
use MicrosoftAzure\Storage\Blob\Models\ListBlobsOptions;
12
use MicrosoftAzure\Storage\Common\ServiceException;
13
use Psr\Http\Message\ResponseInterface;
14
15
/**
16
 * Microsoft Azure Blob Storage adapter.
17
 *
18
 * @author Luciano Mammino <[email protected]>
19
 * @author Paweł Czyżewski <[email protected]>
20
 */
21
class AzureBlobStorage implements Adapter,
0 ignored issues
show
Coding Style introduced by
The first item in a multi-line implements list must be on the line following the implements keyword
Loading history...
22
                                  MetadataSupporter
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces before interface name; 34 found
Loading history...
23
{
24
    /**
25
     * Error constants.
26
     */
27
    const ERROR_CONTAINER_ALREADY_EXISTS = 'ContainerAlreadyExists';
28
    const ERROR_CONTAINER_NOT_FOUND = 'ContainerNotFound';
29
30
    /**
31
     * @var AzureBlobStorage\BlobProxyFactoryInterface
32
     */
33
    protected $blobProxyFactory;
34
35
    /**
36
     * @var string
37
     */
38
    protected $containerName;
39
40
    /**
41
     * @var bool
42
     */
43
    protected $detectContentType;
44
45
    /**
46
     * @var \MicrosoftAzure\Storage\Blob\Internal\IBlob
47
     */
48
    protected $blobProxy;
49
50
    /**
51
     * @param AzureBlobStorage\BlobProxyFactoryInterface $blobProxyFactory
52
     * @param string                                     $containerName
53
     * @param bool                                       $create
54
     * @param bool                                       $detectContentType
55
     */
56
    public function __construct(BlobProxyFactoryInterface $blobProxyFactory, $containerName, $create = false, $detectContentType = true)
57
    {
58
        $this->blobProxyFactory = $blobProxyFactory;
59
        $this->containerName = $containerName;
60
        $this->detectContentType = $detectContentType;
61
        if ($create) {
62
            $this->createContainer($containerName);
63
        }
64
    }
65
66
    /**
67
     * Creates a new container.
68
     *
69
     * @param string                                                     $containerName
70
     * @param \MicrosoftAzure\Storage\Blob\Models\CreateContainerOptions $options
71
     *
72
     * @throws \RuntimeException if cannot create the container
73
     */
74 View Code Duplication
    public function createContainer($containerName, CreateContainerOptions $options = 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...
75
    {
76
        $this->init();
77
78
        try {
79
            $this->blobProxy->createContainer($containerName, $options);
80
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
81
            $errorCode = $this->getErrorCodeFromServiceException($e);
82
83
            if ($errorCode != self::ERROR_CONTAINER_ALREADY_EXISTS) {
84
                throw new \RuntimeException(sprintf(
85
                    'Failed to create the configured container "%s": %s (%s).',
86
                    $containerName,
87
                    $e->getErrorText(),
88
                    $errorCode
89
                ));
90
            }
91
        }
92
    }
93
94
    /**
95
     * Deletes a container.
96
     *
97
     * @param string                 $containerName
98
     * @param DeleteContainerOptions $options
99
     *
100
     * @throws \RuntimeException if cannot delete the container
101
     */
102 View Code Duplication
    public function deleteContainer($containerName, DeleteContainerOptions $options = 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...
103
    {
104
        $this->init();
105
106
        try {
107
            $this->blobProxy->deleteContainer($containerName, $options);
108
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
109
            $errorCode = $this->getErrorCodeFromServiceException($e);
110
111
            if ($errorCode != self::ERROR_CONTAINER_NOT_FOUND) {
112
                throw new \RuntimeException(sprintf(
113
                    'Failed to delete the configured container "%s": %s (%s).',
114
                    $containerName,
115
                    $e->getErrorText(),
116
                    $errorCode
117
                ), $e->getCode());
118
            }
119
        }
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 View Code Duplication
    public function read($key)
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...
126
    {
127
        $this->init();
128
129
        try {
130
            $blob = $this->blobProxy->getBlob($this->containerName, $key);
131
132
            return stream_get_contents($blob->getContentStream());
133
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
134
            $this->failIfContainerNotFound($e, sprintf('read key "%s"', $key));
135
136
            return false;
137
        }
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function write($key, $content)
144
    {
145
        $this->init();
146
147
        try {
148
            $options = new CreateBlobOptions();
149
150
            if ($this->detectContentType) {
151
                $contentType = $this->guessContentType($content);
152
153
                $options->setBlobContentType($contentType);
154
            }
155
156
            $this->blobProxy->createBlockBlob($this->containerName, $key, $content, $options);
157
158
            if (is_resource($content)) {
159
                return Util\Size::fromResource($content);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Gaufrette\Util\S...fromResource($content); (string) is incompatible with the return type declared by the interface Gaufrette\Adapter::write of type integer|boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
160
            }
161
162
            return Util\Size::fromContent($content);
163
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
164
            $this->failIfContainerNotFound($e, sprintf('write content for key "%s"', $key));
165
166
            return false;
167
        }
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function exists($key)
174
    {
175
        $this->init();
176
177
        $listBlobsOptions = new ListBlobsOptions();
178
        $listBlobsOptions->setPrefix($key);
179
180
        try {
181
            $blobsList = $this->blobProxy->listBlobs($this->containerName, $listBlobsOptions);
182
183
            foreach ($blobsList->getBlobs() as $blob) {
184
                if ($key === $blob->getName()) {
185
                    return true;
186
                }
187
            }
188
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
189
            $this->failIfContainerNotFound($e, 'check if key exists');
190
            $errorCode = $this->getErrorCodeFromServiceException($e);
191
192
            throw new \RuntimeException(sprintf(
193
                'Failed to check if key "%s" exists in container "%s": %s (%s).',
194
                $key,
195
                $this->containerName,
196
                $e->getErrorText(),
197
                $errorCode
198
            ), $e->getCode());
199
        }
200
201
        return false;
202
    }
203
204
    /**
205
     * {@inheritdoc}
206
     */
207
    public function keys()
208
    {
209
        $this->init();
210
211
        try {
212
            $blobList = $this->blobProxy->listBlobs($this->containerName);
213
214
            return array_map(
215
                function ($blob) {
216
                    return $blob->getName();
217
                },
218
                $blobList->getBlobs()
219
            );
220
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
221
            $this->failIfContainerNotFound($e, 'retrieve keys');
222
            $errorCode = $this->getErrorCodeFromServiceException($e);
223
224
            throw new \RuntimeException(sprintf(
225
                'Failed to list keys for the container "%s": %s (%s).',
226
                $this->containerName,
227
                $e->getErrorText(),
228
                $errorCode
229
            ), $e->getCode());
230
        }
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     */
236
    public function mtime($key)
237
    {
238
        $this->init();
239
240
        try {
241
            $properties = $this->blobProxy->getBlobProperties($this->containerName, $key);
242
243
            return $properties->getProperties()->getLastModified()->getTimestamp();
244
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
245
            $this->failIfContainerNotFound($e, sprintf('read mtime for key "%s"', $key));
246
247
            return false;
248
        }
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254 View Code Duplication
    public function delete($key)
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...
255
    {
256
        $this->init();
257
258
        try {
259
            $this->blobProxy->deleteBlob($this->containerName, $key);
260
261
            return true;
262
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
263
            $this->failIfContainerNotFound($e, sprintf('delete key "%s"', $key));
264
265
            return false;
266
        }
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272
    public function rename($sourceKey, $targetKey)
273
    {
274
        $this->init();
275
276
        try {
277
            $this->blobProxy->copyBlob($this->containerName, $targetKey, $this->containerName, $sourceKey);
278
            $this->blobProxy->deleteBlob($this->containerName, $sourceKey);
279
280
            return true;
281
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
282
            $this->failIfContainerNotFound($e, sprintf('rename key "%s"', $sourceKey));
283
284
            return false;
285
        }
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291
    public function isDirectory($key)
292
    {
293
        // Windows Azure Blob Storage does not support directories
294
        return false;
295
    }
296
297
    /**
298
     * {@inheritdoc}
299
     */
300 View Code Duplication
    public function setMetadata($key, $content)
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...
301
    {
302
        $this->init();
303
304
        try {
305
            $this->blobProxy->setBlobMetadata($this->containerName, $key, $content);
306
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
307
            $errorCode = $this->getErrorCodeFromServiceException($e);
308
309
            throw new \RuntimeException(sprintf(
310
                'Failed to set metadata for blob "%s" in container "%s": %s (%s).',
311
                $key,
312
                $this->containerName,
313
                $e->getErrorText(),
314
                $errorCode
315
            ), $e->getCode());
316
        }
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322 View Code Duplication
    public function getMetadata($key)
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...
323
    {
324
        $this->init();
325
326
        try {
327
            $properties = $this->blobProxy->getBlobProperties($this->containerName, $key);
328
329
            return $properties->getMetadata();
330
        } catch (ServiceException $e) {
0 ignored issues
show
Bug introduced by
The class MicrosoftAzure\Storage\Common\ServiceException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
331
            $errorCode = $this->getErrorCodeFromServiceException($e);
332
333
            throw new \RuntimeException(sprintf(
334
                'Failed to get metadata for blob "%s" in container "%s": %s (%s).',
335
                $key,
336
                $this->containerName,
337
                $e->getErrorText(),
338
                $errorCode
339
            ), $e->getCode());
340
        }
341
    }
342
343
    /**
344
     * Lazy initialization, automatically called when some method is called after construction.
345
     */
346
    protected function init()
347
    {
348
        if ($this->blobProxy == null) {
349
            $this->blobProxy = $this->blobProxyFactory->create();
350
        }
351
    }
352
353
    /**
354
     * Throws a runtime exception if a give ServiceException derived from a "container not found" error.
355
     *
356
     * @param ServiceException $exception
357
     * @param string           $action
358
     *
359
     * @throws \RuntimeException
360
     */
361
    protected function failIfContainerNotFound(ServiceException $exception, $action)
362
    {
363
        $errorCode = $this->getErrorCodeFromServiceException($exception);
364
365
        if ($errorCode == self::ERROR_CONTAINER_NOT_FOUND) {
366
            throw new \RuntimeException(sprintf(
367
                'Failed to %s: container "%s" not found.',
368
                $action,
369
                $this->containerName
370
            ), $exception->getCode());
371
        }
372
    }
373
374
    /**
375
     * Extracts the error code from a service exception.
376
     *
377
     * @param ServiceException $exception
378
     *
379
     * @return string
380
     */
381
    protected function getErrorCodeFromServiceException(ServiceException $exception)
382
    {
383
        if (method_exists($exception, 'getErrorReason')) {
384
            $xml = @simplexml_load_string($exception->getErrorReason());
385
386
            if ($xml && isset($xml->Code)) {
387
                return (string) $xml->Code;
388
            }
389
390
            return $exception->getErrorReason();
391
        } else {
392
            return static::parseErrorCode($exception->getResponse());
393
        }
394
    }
395
396
    /**
397
     * @param string $content
398
     *
399
     * @return string
400
     */
401 View Code Duplication
    private function guessContentType($content)
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...
402
    {
403
        $fileInfo = new \finfo(FILEINFO_MIME_TYPE);
404
405
        if (is_resource($content)) {
406
            return $fileInfo->file(stream_get_meta_data($content)['uri']);
407
        }
408
409
        return $fileInfo->buffer($content);
410
    }
411
412
    /**
413
     * Error message to be parsed.
414
     *
415
     * @param  ResponseInterface $response The response with a response body.
416
     *
417
     * @return string
418
     */
419
    protected static function parseErrorCode(ResponseInterface $response)
420
    {
421
        $errorCode = $response->getReasonPhrase();
422
423
        //try to parse using xml serializer, if failed, return the whole body
424
        //as the error message.
425
        try {
426
            $body = new \SimpleXMLElement($response->getBody());
427
            $data = static::xmlToArray($body);
0 ignored issues
show
Bug introduced by
Since xmlToArray() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of xmlToArray() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
428
429
            if (array_key_exists('Code', $data)) {
430
                $errorCode = $data['Code'];
431
            }
432
        } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
433
        }
434
435
        return $errorCode;
436
    }
437
438
    /**
439
     * Converts a SimpleXML object to an Array recursively
440
     * ensuring all sub-elements are arrays as well.
441
     *
442
     * @param string $sxml The SimpleXML object.
443
     * @param array  $arr  The array into which to store results.
444
     *
445
     * @return array
446
     */
447
    private static function xmlToArray($sxml, array $arr = null)
448
    {
449
        foreach ((array) $sxml as $key => $value) {
450
            if (is_object($value) || (is_array($value))) {
451
                $arr[$key] = static::xmlToArray($value);
0 ignored issues
show
Bug introduced by
Since xmlToArray() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of xmlToArray() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
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...
452
            } else {
453
                $arr[$key] = $value;
454
            }
455
        }
456
457
        return $arr;
458
    }
459
}
460