Completed
Push — master ( 193986...cdf399 )
by Andrey
11:47
created

ClientResolver::throwRequired()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 3
nop 1
dl 0
loc 16
rs 9.4222
c 0
b 0
f 0
1
<?php
2
namespace Aws;
3
4
use Aws\Api\Validator;
5
use Aws\Api\ApiProvider;
6
use Aws\Api\Service;
7
use Aws\Credentials\Credentials;
8
use Aws\Credentials\CredentialsInterface;
9
use Aws\Endpoint\Partition;
10
use Aws\Endpoint\PartitionEndpointProvider;
11
use Aws\Endpoint\PartitionProviderInterface;
12
use Aws\Signature\SignatureProvider;
13
use Aws\Endpoint\EndpointProvider;
14
use Aws\Credentials\CredentialProvider;
15
use GuzzleHttp\Promise;
16
use InvalidArgumentException as IAE;
17
use Psr\Http\Message\RequestInterface;
18
19
/**
20
 * @internal Resolves a hash of client arguments to construct a client.
21
 */
22
class ClientResolver
23
{
24
    /** @var array */
25
    private $argDefinitions;
26
27
    /** @var array Map of types to a corresponding function */
28
    private static $typeMap = [
29
        'resource' => 'is_resource',
30
        'callable' => 'is_callable',
31
        'int'      => 'is_int',
32
        'bool'     => 'is_bool',
33
        'string'   => 'is_string',
34
        'object'   => 'is_object',
35
        'array'    => 'is_array',
36
    ];
37
38
    private static $defaultArgs = [
39
        'service' => [
40
            'type'     => 'value',
41
            'valid'    => ['string'],
42
            'doc'      => 'Name of the service to utilize. This value will be supplied by default when using one of the SDK clients (e.g., Aws\\S3\\S3Client).',
43
            'required' => true,
44
            'internal' => true
45
        ],
46
        'exception_class' => [
47
            'type'     => 'value',
48
            'valid'    => ['string'],
49
            'doc'      => 'Exception class to create when an error occurs.',
50
            'default'  => 'Aws\Exception\AwsException',
51
            'internal' => true
52
        ],
53
        'scheme' => [
54
            'type'     => 'value',
55
            'valid'    => ['string'],
56
            'default'  => 'https',
57
            'doc'      => 'URI scheme to use when connecting connect. The SDK will utilize "https" endpoints (i.e., utilize SSL/TLS connections) by default. You can attempt to connect to a service over an unencrypted "http" endpoint by setting ``scheme`` to "http".',
58
        ],
59
        'endpoint' => [
60
            'type'  => 'value',
61
            'valid' => ['string'],
62
            'doc'   => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).',
63
            'fn'    => [__CLASS__, '_apply_endpoint'],
64
        ],
65
        'region' => [
66
            'type'     => 'value',
67
            'valid'    => ['string'],
68
            'required' => [__CLASS__, '_missing_region'],
69
            'doc'      => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.',
70
        ],
71
        'version' => [
72
            'type'     => 'value',
73
            'valid'    => ['string'],
74
            'required' => [__CLASS__, '_missing_version'],
75
            'doc'      => 'The version of the webservice to utilize (e.g., 2006-03-01).',
76
        ],
77
        'signature_provider' => [
78
            'type'    => 'value',
79
            'valid'   => ['callable'],
80
            'doc'     => 'A callable that accepts a signature version name (e.g., "v4"), a service name, and region, and  returns a SignatureInterface object or null. This provider is used to create signers utilized by the client. See Aws\\Signature\\SignatureProvider for a list of built-in providers',
81
            'default' => [__CLASS__, '_default_signature_provider'],
82
        ],
83
        'api_provider' => [
84
            'type'     => 'value',
85
            'valid'    => ['callable'],
86
            'doc'      => 'An optional PHP callable that accepts a type, service, and version argument, and returns an array of corresponding configuration data. The type value can be one of api, waiter, or paginator.',
87
            'fn'       => [__CLASS__, '_apply_api_provider'],
88
            'default'  => [ApiProvider::class, 'defaultProvider'],
89
        ],
90
        'endpoint_provider' => [
91
            'type'     => 'value',
92
            'valid'    => ['callable'],
93
            'fn'       => [__CLASS__, '_apply_endpoint_provider'],
94
            'doc'      => 'An optional PHP callable that accepts a hash of options including a "service" and "region" key and returns NULL or a hash of endpoint data, of which the "endpoint" key is required. See Aws\\Endpoint\\EndpointProvider for a list of built-in providers.',
95
            'default' => [__CLASS__, '_default_endpoint_provider'],
96
        ],
97
        'serializer' => [
98
            'default'   => [__CLASS__, '_default_serializer'],
99
            'fn'        => [__CLASS__, '_apply_serializer'],
100
            'internal'  => true,
101
            'type'      => 'value',
102
            'valid'     => ['callable'],
103
        ],
104
        'signature_version' => [
105
            'type'    => 'config',
106
            'valid'   => ['string'],
107
            'doc'     => 'A string representing a custom signature version to use with a service (e.g., v4). Note that per/operation signature version MAY override this requested signature version.',
108
            'default' => [__CLASS__, '_default_signature_version'],
109
        ],
110
        'signing_name' => [
111
            'type'    => 'config',
112
            'valid'   => ['string'],
113
            'doc'     => 'A string representing a custom service name to be used when calculating a request signature.',
114
            'default' => [__CLASS__, '_default_signing_name'],
115
        ],
116
        'signing_region' => [
117
            'type'    => 'config',
118
            'valid'   => ['string'],
119
            'doc'     => 'A string representing a custom region name to be used when calculating a request signature.',
120
            'default' => [__CLASS__, '_default_signing_region'],
121
        ],
122
        'profile' => [
123
            'type'  => 'config',
124
            'valid' => ['string'],
125
            'doc'   => 'Allows you to specify which profile to use when credentials are created from the AWS credentials file in your HOME directory. This setting overrides the AWS_PROFILE environment variable. Note: Specifying "profile" will cause the "credentials" key to be ignored.',
126
            'fn'    => [__CLASS__, '_apply_profile'],
127
        ],
128
        'credentials' => [
129
            'type'    => 'value',
130
            'valid'   => [CredentialsInterface::class, CacheInterface::class, 'array', 'bool', 'callable'],
131
            'doc'     => 'Specifies the credentials used to sign requests. Provide an Aws\Credentials\CredentialsInterface object, an associative array of "key", "secret", and an optional "token" key, `false` to use null credentials, or a callable credentials provider used to create credentials or return null. See Aws\\Credentials\\CredentialProvider for a list of built-in credentials providers. If no credentials are provided, the SDK will attempt to load them from the environment.',
132
            'fn'      => [__CLASS__, '_apply_credentials'],
133
            'default' => [CredentialProvider::class, 'defaultProvider'],
134
        ],
135
        'stats' => [
136
            'type'  => 'value',
137
            'valid' => ['bool', 'array'],
138
            'default' => false,
139
            'doc'   => 'Set to true to gather transfer statistics on requests sent. Alternatively, you can provide an associative array with the following keys: retries: (bool) Set to false to disable reporting on retries attempted; http: (bool) Set to true to enable collecting statistics from lower level HTTP adapters (e.g., values returned in GuzzleHttp\TransferStats). HTTP handlers must support an http_stats_receiver option for this to have an effect; timer: (bool) Set to true to enable a command timer that reports the total wall clock time spent on an operation in seconds.',
140
            'fn'    => [__CLASS__, '_apply_stats'],
141
        ],
142
        'retries' => [
143
            'type'    => 'value',
144
            'valid'   => ['int'],
145
            'doc'     => 'Configures the maximum number of allowed retries for a client (pass 0 to disable retries). ',
146
            'fn'      => [__CLASS__, '_apply_retries'],
147
            'default' => 3,
148
        ],
149
        'validate' => [
150
            'type'    => 'value',
151
            'valid'   => ['bool', 'array'],
152
            'default' => true,
153
            'doc'     => 'Set to false to disable client-side parameter validation. Set to true to utilize default validation constraints. Set to an associative array of validation options to enable specific validation constraints.',
154
            'fn'      => [__CLASS__, '_apply_validate'],
155
        ],
156
        'debug' => [
157
            'type'  => 'value',
158
            'valid' => ['bool', 'array'],
159
            'doc'   => 'Set to true to display debug information when sending requests. Alternatively, you can provide an associative array with the following keys: logfn: (callable) Function that is invoked with log messages; stream_size: (int) When the size of a stream is greater than this number, the stream data will not be logged (set to "0" to not log any stream data); scrub_auth: (bool) Set to false to disable the scrubbing of auth data from the logged messages; http: (bool) Set to false to disable the "debug" feature of lower level HTTP adapters (e.g., verbose curl output).',
160
            'fn'    => [__CLASS__, '_apply_debug'],
161
        ],
162
        'http' => [
163
            'type'    => 'value',
164
            'valid'   => ['array'],
165
            'default' => [],
166
            'doc'     => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).',
167
        ],
168
        'http_handler' => [
169
            'type'    => 'value',
170
            'valid'   => ['callable'],
171
            'doc'     => 'An HTTP handler is a function that accepts a PSR-7 request object and returns a promise that is fulfilled with a PSR-7 response object or rejected with an array of exception data. NOTE: This option supersedes any provided "handler" option.',
172
            'fn'      => [__CLASS__, '_apply_http_handler']
173
        ],
174
        'handler' => [
175
            'type'     => 'value',
176
            'valid'    => ['callable'],
177
            'doc'      => 'A handler that accepts a command object, request object and returns a promise that is fulfilled with an Aws\ResultInterface object or rejected with an Aws\Exception\AwsException. A handler does not accept a next handler as it is terminal and expected to fulfill a command. If no handler is provided, a default Guzzle handler will be utilized.',
178
            'fn'       => [__CLASS__, '_apply_handler'],
179
            'default'  => [__CLASS__, '_default_handler']
180
        ],
181
        'ua_append' => [
182
            'type'     => 'value',
183
            'valid'    => ['string', 'array'],
184
            'doc'      => 'Provide a string or array of strings to send in the User-Agent header.',
185
            'fn'       => [__CLASS__, '_apply_user_agent'],
186
            'default'  => [],
187
        ],
188
        'idempotency_auto_fill' => [
189
            'type'      => 'value',
190
            'valid'     => ['bool', 'callable'],
191
            'doc'       => 'Set to false to disable SDK to populate parameters that enabled \'idempotencyToken\' trait with a random UUID v4 value on your behalf. Using default value \'true\' still allows parameter value to be overwritten when provided. Note: auto-fill only works when cryptographically secure random bytes generator functions(random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be found. You may also provide a callable source of random bytes.',
192
            'default'   => true,
193
            'fn'        => [__CLASS__, '_apply_idempotency_auto_fill']
194
        ],
195
    ];
196
197
    /**
198
     * Gets an array of default client arguments, each argument containing a
199
     * hash of the following:
200
     *
201
     * - type: (string, required) option type described as follows:
202
     *   - value: The default option type.
203
     *   - config: The provided value is made available in the client's
204
     *     getConfig() method.
205
     * - valid: (array, required) Valid PHP types or class names. Note: null
206
     *   is not an allowed type.
207
     * - required: (bool, callable) Whether or not the argument is required.
208
     *   Provide a function that accepts an array of arguments and returns a
209
     *   string to provide a custom error message.
210
     * - default: (mixed) The default value of the argument if not provided. If
211
     *   a function is provided, then it will be invoked to provide a default
212
     *   value. The function is provided the array of options and is expected
213
     *   to return the default value of the option. The default value can be a
214
     *   closure and can not be a callable string that is not  part of the
215
     *   defaultArgs array.
216
     * - doc: (string) The argument documentation string.
217
     * - fn: (callable) Function used to apply the argument. The function
218
     *   accepts the provided value, array of arguments by reference, and an
219
     *   event emitter.
220
     *
221
     * Note: Order is honored and important when applying arguments.
222
     *
223
     * @return array
224
     */
225
    public static function getDefaultArguments()
226
    {
227
        return self::$defaultArgs;
228
    }
229
230
    /**
231
     * @param array $argDefinitions Client arguments.
232
     */
233
    public function __construct(array $argDefinitions)
234
    {
235
        $this->argDefinitions = $argDefinitions;
236
    }
237
238
    /**
239
     * Resolves client configuration options and attached event listeners.
240
     * Check for missing keys in passed arguments
241
     *
242
     * @param array       $args Provided constructor arguments.
243
     * @param HandlerList $list Handler list to augment.
244
     *
245
     * @return array Returns the array of provided options.
246
     * @throws \InvalidArgumentException
247
     * @see Aws\AwsClient::__construct for a list of available options.
248
     */
249
    public function resolve(array $args, HandlerList $list)
250
    {
251
        $args['config'] = [];
252
        foreach ($this->argDefinitions as $key => $a) {
253
            // Add defaults, validate required values, and skip if not set.
254
            if (!isset($args[$key])) {
255
                if (isset($a['default'])) {
256
                    // Merge defaults in when not present.
257
                    if (is_callable($a['default'])
258
                        && (
259
                            is_array($a['default'])
260
                            || $a['default'] instanceof \Closure
261
                        )
262
                    ) {
263
                        $args[$key] = $a['default']($args);
264
                    } else {
265
                        $args[$key] = $a['default'];
266
                    }
267
                } elseif (empty($a['required'])) {
268
                    continue;
269
                } else {
270
                    $this->throwRequired($args);
271
                }
272
            }
273
274
            // Validate the types against the provided value.
275
            foreach ($a['valid'] as $check) {
276
                if (isset(self::$typeMap[$check])) {
277
                    $fn = self::$typeMap[$check];
278
                    if ($fn($args[$key])) {
279
                        goto is_valid;
280
                    }
281
                } elseif ($args[$key] instanceof $check) {
282
                    goto is_valid;
283
                }
284
            }
285
286
            $this->invalidType($key, $args[$key]);
287
288
            // Apply the value
289
            is_valid:
290
            if (isset($a['fn'])) {
291
                $a['fn']($args[$key], $args, $list);
292
            }
293
294
            if ($a['type'] === 'config') {
295
                $args['config'][$key] = $args[$key];
296
            }
297
        }
298
299
        return $args;
300
    }
301
302
    /**
303
     * Creates a verbose error message for an invalid argument.
304
     *
305
     * @param string $name        Name of the argument that is missing.
306
     * @param array  $args        Provided arguments
307
     * @param bool   $useRequired Set to true to show the required fn text if
308
     *                            available instead of the documentation.
309
     * @return string
310
     */
311
    private function getArgMessage($name, $args = [], $useRequired = false)
312
    {
313
        $arg = $this->argDefinitions[$name];
314
        $msg = '';
315
        $modifiers = [];
316
        if (isset($arg['valid'])) {
317
            $modifiers[] = implode('|', $arg['valid']);
318
        }
319
        if (isset($arg['choice'])) {
320
            $modifiers[] = 'One of ' . implode(', ', $arg['choice']);
321
        }
322
        if ($modifiers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $modifiers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
323
            $msg .= '(' . implode('; ', $modifiers) . ')';
324
        }
325
        $msg = wordwrap("{$name}: {$msg}", 75, "\n  ");
326
327
        if ($useRequired && is_callable($arg['required'])) {
328
            $msg .= "\n\n  ";
329
            $msg .= str_replace("\n", "\n  ", call_user_func($arg['required'], $args));
330
        } elseif (isset($arg['doc'])) {
331
            $msg .= wordwrap("\n\n  {$arg['doc']}", 75, "\n  ");
332
        }
333
334
        return $msg;
335
    }
336
337
    /**
338
     * Throw when an invalid type is encountered.
339
     *
340
     * @param string $name     Name of the value being validated.
341
     * @param mixed  $provided The provided value.
342
     * @throws \InvalidArgumentException
343
     */
344
    private function invalidType($name, $provided)
345
    {
346
        $expected = implode('|', $this->argDefinitions[$name]['valid']);
347
        $msg = "Invalid configuration value "
348
            . "provided for \"{$name}\". Expected {$expected}, but got "
349
            . describe_type($provided) . "\n\n"
350
            . $this->getArgMessage($name);
351
        throw new IAE($msg);
352
    }
353
354
    /**
355
     * Throws an exception for missing required arguments.
356
     *
357
     * @param array $args Passed in arguments.
358
     * @throws \InvalidArgumentException
359
     */
360
    private function throwRequired(array $args)
361
    {
362
        $missing = [];
363
        foreach ($this->argDefinitions as $k => $a) {
364
            if (empty($a['required'])
365
                || isset($a['default'])
366
                || array_key_exists($k, $args)
367
            ) {
368
                continue;
369
            }
370
            $missing[] = $this->getArgMessage($k, $args, true);
371
        }
372
        $msg = "Missing required client configuration options: \n\n";
373
        $msg .= implode("\n\n", $missing);
374
        throw new IAE($msg);
375
    }
376
377
    public static function _apply_retries($value, array &$args, HandlerList $list)
378
    {
379
        if ($value) {
380
            $decider = RetryMiddleware::createDefaultDecider($value);
381
            $list->appendSign(
382
                Middleware::retry($decider, null, $args['stats']['retries']),
383
                'retry'
384
            );
385
        }
386
    }
387
388
    public static function _apply_credentials($value, array &$args)
389
    {
390
        if (is_callable($value)) {
391
            return;
392
        } elseif ($value instanceof CredentialsInterface) {
393
            $args['credentials'] = CredentialProvider::fromCredentials($value);
394
        } elseif (is_array($value)
395
            && isset($value['key'])
396
            && isset($value['secret'])
397
        ) {
398
            $args['credentials'] = CredentialProvider::fromCredentials(
399
                new Credentials(
400
                    $value['key'],
401
                    $value['secret'],
402
                    isset($value['token']) ? $value['token'] : null,
403
                    isset($value['expires']) ? $value['expires'] : null
404
                )
405
            );
406
        } elseif ($value === false) {
407
            $args['credentials'] = CredentialProvider::fromCredentials(
408
                new Credentials('', '')
409
            );
410
            $args['config']['signature_version'] = 'anonymous';
411
        } elseif ($value instanceof CacheInterface) {
412
            $args['credentials'] = CredentialProvider::defaultProvider($args);
413
        } else {
414
            throw new IAE('Credentials must be an instance of '
415
                . 'Aws\Credentials\CredentialsInterface, an associative '
416
                . 'array that contains "key", "secret", and an optional "token" '
417
                . 'key-value pairs, a credentials provider function, or false.');
418
        }
419
    }
420
421
    public static function _apply_api_provider(callable $value, array &$args)
422
    {
423
        $api = new Service(
424
            ApiProvider::resolve(
425
                $value,
426
                'api',
427
                $args['service'],
428
                $args['version']
429
            ),
430
            $value
431
        );
432
433
        if (
434
            empty($args['config']['signing_name'])
435
            && isset($api['metadata']['signingName'])
436
        ) {
437
            $args['config']['signing_name'] = $api['metadata']['signingName'];
438
        }
439
440
        $args['api'] = $api;
441
        $args['parser'] = Service::createParser($api);
442
        $args['error_parser'] = Service::createErrorParser($api->getProtocol());
443
    }
444
445
    public static function _apply_endpoint_provider(callable $value, array &$args)
446
    {
447
        if (!isset($args['endpoint'])) {
448
            $endpointPrefix = isset($args['api']['metadata']['endpointPrefix'])
449
                ? $args['api']['metadata']['endpointPrefix']
450
                : $args['service'];
451
452
            // Invoke the endpoint provider and throw if it does not resolve.
453
            $result = EndpointProvider::resolve($value, [
454
                'service' => $endpointPrefix,
455
                'region'  => $args['region'],
456
                'scheme'  => $args['scheme']
457
            ]);
458
459
            $args['endpoint'] = $result['endpoint'];
460
461 View Code Duplication
            if (
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...
462
                empty($args['config']['signature_version'])
463
                && isset($result['signatureVersion'])
464
            ) {
465
                $args['config']['signature_version']
466
                    = $result['signatureVersion'];
467
            }
468
469 View Code Duplication
            if (
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...
470
                empty($args['config']['signing_region'])
471
                && isset($result['signingRegion'])
472
            ) {
473
                $args['config']['signing_region'] = $result['signingRegion'];
474
            }
475
476 View Code Duplication
            if (
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...
477
                empty($args['config']['signing_name'])
478
                && isset($result['signingName'])
479
            ) {
480
                $args['config']['signing_name'] = $result['signingName'];
481
            }
482
        }
483
    }
484
485
    public static function _apply_serializer($value, array &$args, HandlerList $list)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
486
    {
487
        $list->prependBuild(Middleware::requestBuilder($value), 'builder');
488
    }
489
490
    public static function _apply_debug($value, array &$args, HandlerList $list)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
491
    {
492
        if ($value !== false) {
493
            $list->interpose(new TraceMiddleware($value === true ? [] : $value));
494
        }
495
    }
496
497
    public static function _apply_stats($value, array &$args, HandlerList $list)
498
    {
499
        // Create an array of stat collectors that are disabled (set to false)
500
        // by default. If the user has passed in true, enable all stat
501
        // collectors.
502
        $defaults = array_fill_keys(
503
            ['http', 'retries', 'timer'],
504
            $value === true
505
        );
506
        $args['stats'] = is_array($value)
507
            ? array_replace($defaults, $value)
508
            : $defaults;
509
510
        if ($args['stats']['timer']) {
511
            $list->prependInit(Middleware::timer(), 'timer');
512
        }
513
    }
514
515
    public static function _apply_profile($_, array &$args)
0 ignored issues
show
Unused Code introduced by
The parameter $_ is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
516
    {
517
        $args['credentials'] = CredentialProvider::ini($args['profile']);
518
    }
519
520
    public static function _apply_validate($value, array &$args, HandlerList $list)
521
    {
522
        if ($value === false) {
523
            return;
524
        }
525
526
        $validator = $value === true
527
            ? new Validator()
528
            : new Validator($value);
529
        $list->appendValidate(
530
            Middleware::validation($args['api'], $validator),
531
            'validation'
532
        );
533
    }
534
535
    public static function _apply_handler($value, array &$args, HandlerList $list)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
536
    {
537
        $list->setHandler($value);
538
    }
539
540
    public static function _default_handler(array &$args)
541
    {
542
        return new WrappedHttpHandler(
543
            default_http_handler(),
544
            $args['parser'],
545
            $args['error_parser'],
546
            $args['exception_class'],
547
            $args['stats']['http']
548
        );
549
    }
550
551
    public static function _apply_http_handler($value, array &$args, HandlerList $list)
0 ignored issues
show
Unused Code introduced by
The parameter $list is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
552
    {
553
        $args['handler'] = new WrappedHttpHandler(
554
            $value,
555
            $args['parser'],
556
            $args['error_parser'],
557
            $args['exception_class'],
558
            $args['stats']['http']
559
        );
560
    }
561
562
    public static function _apply_user_agent($value, array &$args, HandlerList $list)
563
    {
564
        if (!is_array($value)) {
565
            $value = [$value];
566
        }
567
568
        $value = array_map('strval', $value);
569
570
        array_unshift($value, 'aws-sdk-php/' . Sdk::VERSION);
571
        $args['ua_append'] = $value;
572
573
        $list->appendBuild(static function (callable $handler) use ($value) {
574
            return function (
575
                CommandInterface $command,
576
                RequestInterface $request
577
            ) use ($handler, $value) {
578
                return $handler($command, $request->withHeader(
579
                    'User-Agent',
580
                    implode(' ', array_merge(
581
                        $value,
582
                        $request->getHeader('User-Agent')
583
                    ))
584
                ));
585
            };
586
        });
587
    }
588
589
    public static function _apply_endpoint($value, array &$args, HandlerList $list)
0 ignored issues
show
Unused Code introduced by
The parameter $list is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
590
    {
591
        $parts = parse_url($value);
592
        if (empty($parts['scheme']) || empty($parts['host'])) {
593
            throw new IAE(
594
                'Endpoints must be full URIs and include a scheme and host'
595
            );
596
        }
597
598
        $args['endpoint'] = $value;
599
    }
600
601
    public static function _apply_idempotency_auto_fill(
602
        $value,
603
        array &$args,
604
        HandlerList $list
605
    ) {
606
        $enabled = false;
607
        $generator = null;
608
609
610
        if (is_bool($value)) {
611
            $enabled = $value;
612
        } elseif (is_callable($value)) {
613
            $enabled = true;
614
            $generator = $value;
615
        }
616
617
        if ($enabled) {
618
            $list->prependInit(
619
                IdempotencyTokenMiddleware::wrap($args['api'], $generator),
620
                'idempotency_auto_fill'
621
            );
622
        }
623
    }
624
625
    public static function _default_endpoint_provider(array $args)
626
    {
627
        return PartitionEndpointProvider::defaultProvider()
628
            ->getPartition($args['region'], $args['service']);
629
    }
630
631
    public static function _default_serializer(array $args)
632
    {
633
        return Service::createSerializer(
634
            $args['api'],
635
            $args['endpoint']
636
        );
637
    }
638
639
    public static function _default_signature_provider()
640
    {
641
        return SignatureProvider::defaultProvider();
642
    }
643
644 View Code Duplication
    public static function _default_signature_version(array &$args)
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...
645
    {
646
        if (isset($args['config']['signature_version'])) {
647
            return $args['config']['signature_version'];
648
        }
649
650
        $args['__partition_result'] = isset($args['__partition_result'])
651
            ? isset($args['__partition_result'])
652
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
653
                'service' => $args['service'],
654
                'region' => $args['region'],
655
            ]);
656
657
        return isset($args['__partition_result']['signatureVersion'])
658
            ? $args['__partition_result']['signatureVersion']
659
            : $args['api']->getSignatureVersion();
660
    }
661
662
    public static function _default_signing_name(array &$args)
663
    {
664
        if (isset($args['config']['signing_name'])) {
665
            return $args['config']['signing_name'];
666
        }
667
668
        $args['__partition_result'] = isset($args['__partition_result'])
669
            ? isset($args['__partition_result'])
670
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
671
                'service' => $args['service'],
672
                'region' => $args['region'],
673
            ]);
674
675
        if (isset($args['__partition_result']['signingName'])) {
676
            return $args['__partition_result']['signingName'];
677
        }
678
679
        if ($signingName = $args['api']->getSigningName()) {
680
            return $signingName;
681
        }
682
683
        return $args['service'];
684
    }
685
686 View Code Duplication
    public static function _default_signing_region(array &$args)
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...
687
    {
688
        if (isset($args['config']['signing_region'])) {
689
            return $args['config']['signing_region'];
690
        }
691
692
        $args['__partition_result'] = isset($args['__partition_result'])
693
            ? isset($args['__partition_result'])
694
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
695
                'service' => $args['service'],
696
                'region' => $args['region'],
697
            ]);
698
699
        return isset($args['__partition_result']['signingRegion'])
700
            ? $args['__partition_result']['signingRegion']
701
            : $args['region'];
702
    }
703
704
    public static function _missing_version(array $args)
705
    {
706
        $service = isset($args['service']) ? $args['service'] : '';
707
        $versions = ApiProvider::defaultProvider()->getVersions($service);
708
        $versions = implode("\n", array_map(function ($v) {
709
            return "* \"$v\"";
710
        }, $versions)) ?: '* (none found)';
711
712
        return <<<EOT
713
A "version" configuration value is required. Specifying a version constraint
714
ensures that your code will not be affected by a breaking change made to the
715
service. For example, when using Amazon S3, you can lock your API version to
716
"2006-03-01".
717
718
Your build of the SDK has the following version(s) of "{$service}": {$versions}
719
720
You may provide "latest" to the "version" configuration value to utilize the
721
most recent available API version that your client's API provider can find.
722
Note: Using 'latest' in a production application is not recommended.
723
724
A list of available API versions can be found on each client's API documentation
725
page: http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html. If you are
726
unable to load a specific API version, then you may need to update your copy of
727
the SDK.
728
EOT;
729
    }
730
731
    public static function _missing_region(array $args)
732
    {
733
        $service = isset($args['service']) ? $args['service'] : '';
734
735
        return <<<EOT
736
A "region" configuration value is required for the "{$service}" service
737
(e.g., "us-west-2"). A list of available public regions and endpoints can be
738
found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
739
EOT;
740
    }
741
}
742