Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws;
3
 
4
use Aws\Api\ApiProvider;
5
use Aws\Api\Service;
6
use Aws\Api\Validator;
7
use Aws\ClientSideMonitoring\ApiCallAttemptMonitoringMiddleware;
8
use Aws\ClientSideMonitoring\ApiCallMonitoringMiddleware;
9
use Aws\ClientSideMonitoring\Configuration;
10
use Aws\Configuration\ConfigurationResolver;
11
use Aws\Credentials\CredentialProvider;
12
use Aws\Credentials\Credentials;
13
use Aws\Credentials\CredentialsInterface;
14
use Aws\DefaultsMode\ConfigurationInterface as ConfigModeInterface;
15
use Aws\DefaultsMode\ConfigurationProvider as ConfigModeProvider;
16
use Aws\Endpoint\EndpointProvider;
17
use Aws\Endpoint\PartitionEndpointProvider;
18
use Aws\Endpoint\UseDualstackEndpoint\Configuration as UseDualStackEndpointConfiguration;
19
use Aws\Endpoint\UseDualstackEndpoint\ConfigurationInterface as UseDualStackEndpointConfigurationInterface;
20
use Aws\Endpoint\UseDualstackEndpoint\ConfigurationProvider as UseDualStackConfigProvider;
21
use Aws\Endpoint\UseFipsEndpoint\Configuration as UseFipsEndpointConfiguration;
22
use Aws\Endpoint\UseFipsEndpoint\ConfigurationInterface as UseFipsEndpointConfigurationInterface;
23
use Aws\Endpoint\UseFipsEndpoint\ConfigurationProvider as UseFipsConfigProvider;
24
use Aws\EndpointDiscovery\ConfigurationInterface;
25
use Aws\EndpointDiscovery\ConfigurationProvider;
26
use Aws\EndpointV2\EndpointDefinitionProvider;
27
use Aws\Exception\AwsException;
28
use Aws\Exception\InvalidRegionException;
29
use Aws\Retry\ConfigurationInterface as RetryConfigInterface;
30
use Aws\Retry\ConfigurationProvider as RetryConfigProvider;
31
use Aws\Signature\SignatureProvider;
32
use Aws\Token\Token;
33
use Aws\Token\TokenInterface;
34
use Aws\Token\TokenProvider;
35
use GuzzleHttp\Promise\PromiseInterface;
36
use InvalidArgumentException as IAE;
37
use Psr\Http\Message\RequestInterface;
38
 
39
/**
40
 * @internal Resolves a hash of client arguments to construct a client.
41
 */
42
class ClientResolver
43
{
44
    /** @var array */
45
    private $argDefinitions;
46
 
47
    /** @var array Map of types to a corresponding function */
48
    private static $typeMap = [
49
        'resource' => 'is_resource',
50
        'callable' => 'is_callable',
51
        'int'      => 'is_int',
52
        'bool'     => 'is_bool',
53
        'boolean'  => 'is_bool',
54
        'string'   => 'is_string',
55
        'object'   => 'is_object',
56
        'array'    => 'is_array',
57
    ];
58
 
59
    private static $defaultArgs = [
60
        'service' => [
61
            'type'     => 'value',
62
            'valid'    => ['string'],
63
            '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).',
64
            'required' => true,
65
            'internal' => true
66
        ],
67
        'exception_class' => [
68
            'type'     => 'value',
69
            'valid'    => ['string'],
70
            'doc'      => 'Exception class to create when an error occurs.',
71
            'default'  => AwsException::class,
72
            'internal' => true
73
        ],
74
        'scheme' => [
75
            'type'     => 'value',
76
            'valid'    => ['string'],
77
            'default'  => 'https',
78
            '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".',
79
        ],
80
        'disable_host_prefix_injection' => [
81
            'type'      => 'value',
82
            'valid'     => ['bool'],
83
            'doc'       => 'Set to true to disable host prefix injection logic for services that use it. This disables the entire prefix injection, including the portions supplied by user-defined parameters. Setting this flag will have no effect on services that do not use host prefix injection.',
84
            'default'   => false,
85
        ],
86
        'endpoint' => [
87
            'type'  => 'value',
88
            'valid' => ['string'],
89
            'doc'   => 'The full URI of the webservice. This is only required when connecting to a custom endpoint (e.g., a local version of S3).',
90
            'fn'    => [__CLASS__, '_apply_endpoint'],
91
        ],
92
        'region' => [
93
            'type'     => 'value',
94
            'valid'    => ['string'],
95
            'required' => [__CLASS__, '_missing_region'],
96
            'doc'      => 'Region to connect to. See http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of available regions.',
97
        ],
98
        'version' => [
99
            'type'     => 'value',
100
            'valid'    => ['string'],
101
            'doc'      => 'The version of the webservice to utilize (e.g., 2006-03-01).',
102
            'default' => 'latest',
103
        ],
104
        'signature_provider' => [
105
            'type'    => 'value',
106
            'valid'   => ['callable'],
107
            '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',
108
            'default' => [__CLASS__, '_default_signature_provider'],
109
        ],
110
        'api_provider' => [
111
            'type'     => 'value',
112
            'valid'    => ['callable'],
113
            '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.',
114
            'fn'       => [__CLASS__, '_apply_api_provider'],
115
            'default'  => [ApiProvider::class, 'defaultProvider'],
116
        ],
117
        'configuration_mode' => [
118
            'type'    => 'value',
119
            'valid'   => [ConfigModeInterface::class, CacheInterface::class, 'string', 'closure'],
120
            'doc'     => "Sets the default configuration mode. Otherwise provide an instance of Aws\DefaultsMode\ConfigurationInterface, an instance of  Aws\CacheInterface, or a string containing a valid mode",
121
            'fn'      => [__CLASS__, '_apply_defaults'],
122
            'default' => [ConfigModeProvider::class, 'defaultProvider']
123
        ],
124
        'use_fips_endpoint' => [
125
            'type'      => 'value',
126
            'valid'     => ['bool', UseFipsEndpointConfiguration::class, CacheInterface::class, 'callable'],
127
            'doc'       => 'Set to true to enable the use of FIPS pseudo regions',
128
            'fn'        => [__CLASS__, '_apply_use_fips_endpoint'],
129
            'default'   => [__CLASS__, '_default_use_fips_endpoint'],
130
        ],
131
        'use_dual_stack_endpoint' => [
132
            'type'      => 'value',
133
            'valid'     => ['bool', UseDualStackEndpointConfiguration::class, CacheInterface::class, 'callable'],
134
            'doc'       => 'Set to true to enable the use of dual-stack endpoints',
135
            'fn'        => [__CLASS__, '_apply_use_dual_stack_endpoint'],
136
            'default'   => [__CLASS__, '_default_use_dual_stack_endpoint'],
137
        ],
138
        'endpoint_provider' => [
139
            'type'     => 'value',
140
            'valid'    => ['callable', EndpointV2\EndpointProviderV2::class],
141
            'fn'       => [__CLASS__, '_apply_endpoint_provider'],
142
            '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.',
143
            'default'  => [__CLASS__, '_default_endpoint_provider'],
144
        ],
145
        'serializer' => [
146
            'default'   => [__CLASS__, '_default_serializer'],
147
            'internal'  => true,
148
            'type'      => 'value',
149
            'valid'     => ['callable'],
150
        ],
151
        'signature_version' => [
152
            'type'    => 'config',
153
            'valid'   => ['string'],
154
            '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.',
155
            'default' => [__CLASS__, '_default_signature_version'],
156
        ],
157
        'signing_name' => [
158
            'type'    => 'config',
159
            'valid'   => ['string'],
160
            'doc'     => 'A string representing a custom service name to be used when calculating a request signature.',
161
            'default' => [__CLASS__, '_default_signing_name'],
162
        ],
163
        'signing_region' => [
164
            'type'    => 'config',
165
            'valid'   => ['string'],
166
            'doc'     => 'A string representing a custom region name to be used when calculating a request signature.',
167
            'default' => [__CLASS__, '_default_signing_region'],
168
        ],
169
        'profile' => [
170
            'type'  => 'config',
171
            'valid' => ['string'],
172
            '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" and "use_aws_shared_config_files" keys to be ignored.',
173
            'fn'    => [__CLASS__, '_apply_profile'],
174
        ],
175
        'credentials' => [
176
            'type'    => 'value',
177
            'valid'   => [CredentialsInterface::class, CacheInterface::class, 'array', 'bool', 'callable'],
178
            '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.',
179
            'fn'      => [__CLASS__, '_apply_credentials'],
180
            'default' => [__CLASS__, '_default_credential_provider'],
181
        ],
182
        'token' => [
183
            'type'    => 'value',
184
            'valid'   => [TokenInterface::class, CacheInterface::class, 'array', 'bool', 'callable'],
185
            'doc'     => 'Specifies the token used to authorize requests. Provide an Aws\Token\TokenInterface object, an associative array of "token", and an optional "expiration" key, `false` to use a null token, or a callable token provider used to fetch a token or return null. See Aws\\Token\\TokenProvider for a list of built-in credentials providers. If no token is provided, the SDK will attempt to load one from the environment.',
186
            'fn'      => [__CLASS__, '_apply_token'],
187
            'default' => [__CLASS__, '_default_token_provider'],
188
        ],
189
        'endpoint_discovery' => [
190
            'type'     => 'value',
191
            'valid'    => [ConfigurationInterface::class, CacheInterface::class, 'array', 'callable'],
192
            'doc'      => 'Specifies settings for endpoint discovery. Provide an instance of Aws\EndpointDiscovery\ConfigurationInterface, an instance Aws\CacheInterface, a callable that provides a promise for a Configuration object, or an associative array with the following keys: enabled: (bool) Set to true to enable endpoint discovery, false to explicitly disable it. Defaults to false; cache_limit: (int) The maximum number of keys in the endpoints cache. Defaults to 1000.',
193
            'fn'       => [__CLASS__, '_apply_endpoint_discovery'],
194
            'default'  => [__CLASS__, '_default_endpoint_discovery_provider']
195
        ],
196
        'stats' => [
197
            'type'  => 'value',
198
            'valid' => ['bool', 'array'],
199
            'default' => false,
200
            '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.',
201
            'fn'    => [__CLASS__, '_apply_stats'],
202
        ],
203
        'retries' => [
204
            'type'    => 'value',
205
            'valid'   => ['int', RetryConfigInterface::class, CacheInterface::class, 'callable', 'array'],
206
            'doc'     => "Configures the retry mode and maximum number of allowed retries for a client (pass 0 to disable retries). Provide an integer for 'legacy' mode with the specified number of retries. Otherwise provide an instance of Aws\Retry\ConfigurationInterface, an instance of  Aws\CacheInterface, a callable function, or an array with the following keys: mode: (string) Set to 'legacy', 'standard' (uses retry quota management), or 'adapative' (an experimental mode that adds client-side rate limiting to standard mode); max_attempts: (int) The maximum number of attempts for a given request. ",
207
            'fn'      => [__CLASS__, '_apply_retries'],
208
            'default' => [RetryConfigProvider::class, 'defaultProvider']
209
        ],
210
        'validate' => [
211
            'type'    => 'value',
212
            'valid'   => ['bool', 'array'],
213
            'default' => true,
214
            '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.',
215
            'fn'      => [__CLASS__, '_apply_validate'],
216
        ],
217
        'debug' => [
218
            'type'  => 'value',
219
            'valid' => ['bool', 'array'],
220
            '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).',
221
            'fn'    => [__CLASS__, '_apply_debug'],
222
        ],
223
        'disable_request_compression' => [
224
            'type'      => 'value',
225
            'valid'     => ['bool', 'callable'],
226
            'doc'       => 'Set to true to disable request compression for supported operations',
227
            'fn'        => [__CLASS__, '_apply_disable_request_compression'],
228
            'default'   => [__CLASS__, '_default_disable_request_compression'],
229
        ],
230
        'request_min_compression_size_bytes' => [
231
            'type'      => 'value',
232
            'valid'     => ['int', 'callable'],
233
            'doc'       => 'Set to a value between between 0 and 10485760 bytes, inclusive. This value will be ignored if `disable_request_compression` is set to `true`',
234
            'fn'        => [__CLASS__, '_apply_min_compression_size'],
235
            'default'   => [__CLASS__, '_default_min_compression_size'],
236
        ],
237
        'csm' => [
238
            'type'     => 'value',
239
            'valid'    => [\Aws\ClientSideMonitoring\ConfigurationInterface::class, 'callable', 'array', 'bool'],
240
            'doc'      => 'CSM options for the client. Provides a callable wrapping a promise, a boolean "false", an instance of ConfigurationInterface, or an associative array of "enabled", "host", "port", and "client_id".',
241
            'fn'       => [__CLASS__, '_apply_csm'],
242
            'default'  => [\Aws\ClientSideMonitoring\ConfigurationProvider::class, 'defaultProvider']
243
        ],
244
        'http' => [
245
            'type'    => 'value',
246
            'valid'   => ['array'],
247
            'default' => [],
248
            'doc'     => 'Set to an array of SDK request options to apply to each request (e.g., proxy, verify, etc.).',
249
        ],
250
        'http_handler' => [
251
            'type'    => 'value',
252
            'valid'   => ['callable'],
253
            '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.',
254
            'fn'      => [__CLASS__, '_apply_http_handler']
255
        ],
256
        'handler' => [
257
            'type'     => 'value',
258
            'valid'    => ['callable'],
259
            '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.',
260
            'fn'       => [__CLASS__, '_apply_handler'],
261
            'default'  => [__CLASS__, '_default_handler']
262
        ],
263
        'ua_append' => [
264
            'type'     => 'value',
265
            'valid'    => ['string', 'array'],
266
            'doc'      => 'Provide a string or array of strings to send in the User-Agent header.',
267
            'fn'       => [__CLASS__, '_apply_user_agent'],
268
            'default'  => [],
269
        ],
270
        'idempotency_auto_fill' => [
271
            'type'      => 'value',
272
            'valid'     => ['bool', 'callable'],
273
            '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.',
274
            'default'   => true,
275
            'fn'        => [__CLASS__, '_apply_idempotency_auto_fill']
276
        ],
277
        'use_aws_shared_config_files' => [
278
            'type'      => 'value',
279
            'valid'     => ['bool'],
280
            'doc'       => 'Set to false to disable checking for shared aws config files usually located in \'~/.aws/config\' and \'~/.aws/credentials\'.  This will be ignored if you set the \'profile\' setting.',
281
            'default'   => true,
282
        ],
283
        'suppress_php_deprecation_warning' => [
284
            'type'      => 'value',
285
            'valid'     => ['bool'],
286
            'doc'       => 'Set to false to disable the deprecation warning of PHP versions 7.2.4 and below',
287
            'default'   => false,
288
            'fn'        => [__CLASS__, '_apply_suppress_php_deprecation_warning']
289
        ],
290
    ];
291
 
292
    /**
293
     * Gets an array of default client arguments, each argument containing a
294
     * hash of the following:
295
     *
296
     * - type: (string, required) option type described as follows:
297
     *   - value: The default option type.
298
     *   - config: The provided value is made available in the client's
299
     *     getConfig() method.
300
     * - valid: (array, required) Valid PHP types or class names. Note: null
301
     *   is not an allowed type.
302
     * - required: (bool, callable) Whether or not the argument is required.
303
     *   Provide a function that accepts an array of arguments and returns a
304
     *   string to provide a custom error message.
305
     * - default: (mixed) The default value of the argument if not provided. If
306
     *   a function is provided, then it will be invoked to provide a default
307
     *   value. The function is provided the array of options and is expected
308
     *   to return the default value of the option. The default value can be a
309
     *   closure and can not be a callable string that is not  part of the
310
     *   defaultArgs array.
311
     * - doc: (string) The argument documentation string.
312
     * - fn: (callable) Function used to apply the argument. The function
313
     *   accepts the provided value, array of arguments by reference, and an
314
     *   event emitter.
315
     *
316
     * Note: Order is honored and important when applying arguments.
317
     *
318
     * @return array
319
     */
320
    public static function getDefaultArguments()
321
    {
322
        return self::$defaultArgs;
323
    }
324
 
325
    /**
326
     * @param array $argDefinitions Client arguments.
327
     */
328
    public function __construct(array $argDefinitions)
329
    {
330
        $this->argDefinitions = $argDefinitions;
331
    }
332
 
333
    /**
334
     * Resolves client configuration options and attached event listeners.
335
     * Check for missing keys in passed arguments
336
     *
337
     * @param array       $args Provided constructor arguments.
338
     * @param HandlerList $list Handler list to augment.
339
     *
340
     * @return array Returns the array of provided options.
341
     * @throws \InvalidArgumentException
342
     * @see Aws\AwsClient::__construct for a list of available options.
343
     */
344
    public function resolve(array $args, HandlerList $list)
345
    {
346
        $args['config'] = [];
347
        foreach ($this->argDefinitions as $key => $a) {
348
            // Add defaults, validate required values, and skip if not set.
349
            if (!isset($args[$key])) {
350
                if (isset($a['default'])) {
351
                    // Merge defaults in when not present.
352
                    if (is_callable($a['default'])
353
                        && (
354
                            is_array($a['default'])
355
                            || $a['default'] instanceof \Closure
356
                        )
357
                    ) {
358
                        $args[$key] = $a['default']($args);
359
                    } else {
360
                        $args[$key] = $a['default'];
361
                    }
362
                } elseif (empty($a['required'])) {
363
                    continue;
364
                } else {
365
                    $this->throwRequired($args);
366
                }
367
            }
368
 
369
            // Validate the types against the provided value.
370
            foreach ($a['valid'] as $check) {
371
                if (isset(self::$typeMap[$check])) {
372
                    $fn = self::$typeMap[$check];
373
                    if ($fn($args[$key])) {
374
                        goto is_valid;
375
                    }
376
                } elseif ($args[$key] instanceof $check) {
377
                    goto is_valid;
378
                }
379
            }
380
 
381
            $this->invalidType($key, $args[$key]);
382
 
383
            // Apply the value
384
            is_valid:
385
            if (isset($a['fn'])) {
386
                $a['fn']($args[$key], $args, $list);
387
            }
388
 
389
            if ($a['type'] === 'config') {
390
                $args['config'][$key] = $args[$key];
391
            }
392
        }
393
        $this->_apply_client_context_params($args);
394
 
395
        return $args;
396
    }
397
 
398
    /**
399
     * Creates a verbose error message for an invalid argument.
400
     *
401
     * @param string $name        Name of the argument that is missing.
402
     * @param array  $args        Provided arguments
403
     * @param bool   $useRequired Set to true to show the required fn text if
404
     *                            available instead of the documentation.
405
     * @return string
406
     */
407
    private function getArgMessage($name, $args = [], $useRequired = false)
408
    {
409
        $arg = $this->argDefinitions[$name];
410
        $msg = '';
411
        $modifiers = [];
412
        if (isset($arg['valid'])) {
413
            $modifiers[] = implode('|', $arg['valid']);
414
        }
415
        if (isset($arg['choice'])) {
416
            $modifiers[] = 'One of ' . implode(', ', $arg['choice']);
417
        }
418
        if ($modifiers) {
419
            $msg .= '(' . implode('; ', $modifiers) . ')';
420
        }
421
        $msg = wordwrap("{$name}: {$msg}", 75, "\n  ");
422
 
423
        if ($useRequired && is_callable($arg['required'])) {
424
            $msg .= "\n\n  ";
425
            $msg .= str_replace("\n", "\n  ", call_user_func($arg['required'], $args));
426
        } elseif (isset($arg['doc'])) {
427
            $msg .= wordwrap("\n\n  {$arg['doc']}", 75, "\n  ");
428
        }
429
 
430
        return $msg;
431
    }
432
 
433
    /**
434
     * Throw when an invalid type is encountered.
435
     *
436
     * @param string $name     Name of the value being validated.
437
     * @param mixed  $provided The provided value.
438
     * @throws \InvalidArgumentException
439
     */
440
    private function invalidType($name, $provided)
441
    {
442
        $expected = implode('|', $this->argDefinitions[$name]['valid']);
443
        $msg = "Invalid configuration value "
444
            . "provided for \"{$name}\". Expected {$expected}, but got "
445
            . describe_type($provided) . "\n\n"
446
            . $this->getArgMessage($name);
447
        throw new IAE($msg);
448
    }
449
 
450
    /**
451
     * Throws an exception for missing required arguments.
452
     *
453
     * @param array $args Passed in arguments.
454
     * @throws \InvalidArgumentException
455
     */
456
    private function throwRequired(array $args)
457
    {
458
        $missing = [];
459
        foreach ($this->argDefinitions as $k => $a) {
460
            if (empty($a['required'])
461
                || isset($a['default'])
462
                || isset($args[$k])
463
            ) {
464
                continue;
465
            }
466
            $missing[] = $this->getArgMessage($k, $args, true);
467
        }
468
        $msg = "Missing required client configuration options: \n\n";
469
        $msg .= implode("\n\n", $missing);
470
        throw new IAE($msg);
471
    }
472
 
473
    public static function _apply_retries($value, array &$args, HandlerList $list)
474
    {
475
        // A value of 0 for the config option disables retries
476
        if ($value) {
477
            $config = RetryConfigProvider::unwrap($value);
478
 
479
            if ($config->getMode() === 'legacy') {
480
                // # of retries is 1 less than # of attempts
481
                $decider = RetryMiddleware::createDefaultDecider(
482
                    $config->getMaxAttempts() - 1
483
                );
484
                $list->appendSign(
485
                    Middleware::retry($decider, null, $args['stats']['retries']),
486
                    'retry'
487
                );
488
            } else {
489
                $list->appendSign(
490
                    RetryMiddlewareV2::wrap(
491
                        $config,
492
                        ['collect_stats' => $args['stats']['retries']]
493
                    ),
494
                    'retry'
495
                );
496
            }
497
        }
498
    }
499
 
500
    public static function _apply_defaults($value, array &$args, HandlerList $list)
501
    {
502
        $config = ConfigModeProvider::unwrap($value);
503
        if ($config->getMode() !== 'legacy') {
504
            if (!isset($args['retries']) && !is_null($config->getRetryMode())) {
505
                $args['retries'] = ['mode' => $config->getRetryMode()];
506
            }
507
            if (
508
                !isset($args['sts_regional_endpoints'])
509
                && !is_null($config->getStsRegionalEndpoints())
510
            ) {
511
                $args['sts_regional_endpoints'] = ['mode' => $config->getStsRegionalEndpoints()];
512
            }
513
            if (
514
                !isset($args['s3_us_east_1_regional_endpoint'])
515
                && !is_null($config->getS3UsEast1RegionalEndpoints())
516
            ) {
517
                $args['s3_us_east_1_regional_endpoint'] = ['mode' => $config->getS3UsEast1RegionalEndpoints()];
518
            }
519
 
520
            if (!isset($args['http'])) {
521
                $args['http'] = [];
522
            }
523
            if (
524
                !isset($args['http']['connect_timeout'])
525
                && !is_null($config->getConnectTimeoutInMillis())
526
            ) {
527
                $args['http']['connect_timeout'] = $config->getConnectTimeoutInMillis() / 1000;
528
            }
529
            if (
530
                !isset($args['http']['timeout'])
531
                && !is_null($config->getHttpRequestTimeoutInMillis())
532
            ) {
533
                $args['http']['timeout'] = $config->getHttpRequestTimeoutInMillis() / 1000;
534
            }
535
        }
536
    }
537
 
538
    public static function _apply_disable_request_compression($value, array &$args) {
539
        if (is_callable($value)) {
540
            $value = $value();
541
        }
542
        if (!is_bool($value)) {
543
           throw new IAE(
544
              "Invalid configuration value provided for 'disable_request_compression'."
545
              . " value must be a bool."
546
           );
547
        }
548
        $args['config']['disable_request_compression'] = $value;
549
    }
550
 
551
    public static function _default_disable_request_compression(array &$args) {
552
        return ConfigurationResolver::resolve(
553
            'disable_request_compression',
554
            false,
555
            'bool',
556
            $args
557
        );
558
    }
559
 
560
    public static function _apply_min_compression_size($value, array &$args) {
561
        if (is_callable($value)) {
562
            $value = $value();
563
        }
564
        if (!is_int($value)
565
            || (is_int($value)
566
            && ($value < 0 || $value > 10485760))
567
        ) {
568
            throw new IAE(" Invalid configuration value provided for 'min_compression_size_bytes'."
569
            . " value must be an integer between 0 and 10485760, inclusive.");
570
        }
571
        $args['config']['request_min_compression_size_bytes'] = $value;
572
    }
573
 
574
    public static function _default_min_compression_size(array &$args) {
575
        return ConfigurationResolver::resolve(
576
            'request_min_compression_size_bytes',
577
            10240,
578
            'int',
579
            $args
580
        );
581
    }
582
 
583
    public static function _apply_credentials($value, array &$args)
584
    {
585
        if (is_callable($value)) {
586
            return;
587
        }
588
 
589
        if ($value instanceof CredentialsInterface) {
590
            $args['credentials'] = CredentialProvider::fromCredentials($value);
591
        } elseif (is_array($value)
592
            && isset($value['key'])
593
            && isset($value['secret'])
594
        ) {
595
            $args['credentials'] = CredentialProvider::fromCredentials(
596
                new Credentials(
597
                    $value['key'],
598
                    $value['secret'],
599
                    isset($value['token']) ? $value['token'] : null,
600
                    isset($value['expires']) ? $value['expires'] : null
601
                )
602
            );
603
        } elseif ($value === false) {
604
            $args['credentials'] = CredentialProvider::fromCredentials(
605
                new Credentials('', '')
606
            );
607
            $args['config']['signature_version'] = 'anonymous';
608
        } elseif ($value instanceof CacheInterface) {
609
            $args['credentials'] = CredentialProvider::defaultProvider($args);
610
        } else {
611
            throw new IAE('Credentials must be an instance of '
612
                . "'" . CredentialsInterface::class . ', an associative '
613
                . 'array that contains "key", "secret", and an optional "token" '
614
                . 'key-value pairs, a credentials provider function, or false.');
615
        }
616
    }
617
 
618
    public static function _default_credential_provider(array $args)
619
    {
620
        return CredentialProvider::defaultProvider($args);
621
    }
622
 
623
    public static function _apply_token($value, array &$args)
624
    {
625
        if (is_callable($value)) {
626
            return;
627
        }
628
 
629
        if ($value instanceof Token) {
630
            $args['token'] = TokenProvider::fromToken($value);
631
        } elseif (is_array($value)
632
            && isset($value['token'])
633
        ) {
634
            $args['token'] = TokenProvider::fromToken(
635
                new Token(
636
                    $value['token'],
637
                    isset($value['expires']) ? $value['expires'] : null
638
                )
639
            );
640
        } elseif ($value instanceof CacheInterface) {
641
            $args['token'] = TokenProvider::defaultProvider($args);
642
        } else {
643
            throw new IAE('Token must be an instance of '
644
                . TokenInterface::class . ', an associative '
645
                . 'array that contains "token" and an optional "expires" '
646
                . 'key-value pairs, a token provider function, or false.');
647
        }
648
    }
649
 
650
    public static function _default_token_provider(array $args)
651
    {
652
        return TokenProvider::defaultProvider($args);
653
    }
654
 
655
    public static function _apply_csm($value, array &$args, HandlerList $list)
656
    {
657
        if ($value === false) {
658
            $value = new Configuration(
659
                false,
660
                \Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_HOST,
661
                \Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_PORT,
662
                \Aws\ClientSideMonitoring\ConfigurationProvider::DEFAULT_CLIENT_ID
663
            );
664
            $args['csm'] = $value;
665
        }
666
 
667
        $list->appendBuild(
668
            ApiCallMonitoringMiddleware::wrap(
669
                $args['credentials'],
670
                $value,
671
                $args['region'],
672
                $args['api']->getServiceId()
673
            ),
674
            'ApiCallMonitoringMiddleware'
675
        );
676
 
677
        $list->appendAttempt(
678
            ApiCallAttemptMonitoringMiddleware::wrap(
679
                $args['credentials'],
680
                $value,
681
                $args['region'],
682
                $args['api']->getServiceId()
683
            ),
684
            'ApiCallAttemptMonitoringMiddleware'
685
        );
686
    }
687
 
688
    public static function _apply_api_provider(callable $value, array &$args)
689
    {
690
        $api = new Service(
691
            ApiProvider::resolve(
692
                $value,
693
                'api',
694
                $args['service'],
695
                $args['version']
696
            ),
697
            $value
698
        );
699
 
700
        if (
701
            empty($args['config']['signing_name'])
702
            && isset($api['metadata']['signingName'])
703
        ) {
704
            $args['config']['signing_name'] = $api['metadata']['signingName'];
705
        }
706
 
707
        $args['api'] = $api;
708
        $args['parser'] = Service::createParser($api);
709
        $args['error_parser'] = Service::createErrorParser($api->getProtocol(), $api);
710
    }
711
 
712
    public static function _apply_endpoint_provider($value, array &$args)
713
    {
714
        if (!isset($args['endpoint'])) {
715
            if ($value instanceof \Aws\EndpointV2\EndpointProviderV2) {
716
                $options = self::getEndpointProviderOptions($args);
717
                $value = PartitionEndpointProvider::defaultProvider($options)
718
                    ->getPartition($args['region'], $args['service']);
719
            }
720
 
721
            $endpointPrefix = isset($args['api']['metadata']['endpointPrefix'])
722
                ? $args['api']['metadata']['endpointPrefix']
723
                : $args['service'];
724
 
725
            // Check region is a valid host label when it is being used to
726
            // generate an endpoint
727
            if (!self::isValidRegion($args['region'])) {
728
                throw new InvalidRegionException('Region must be a valid RFC'
729
                    . ' host label.');
730
            }
731
            $serviceEndpoints =
732
                is_array($value) && isset($value['services'][$args['service']]['endpoints'])
733
                    ? $value['services'][$args['service']]['endpoints']
734
                    : null;
735
            if (isset($serviceEndpoints[$args['region']]['deprecated'])) {
736
                trigger_error("The service " . $args['service'] . "has "
737
                    . " deprecated the region " . $args['region'] . ".",
738
                    E_USER_WARNING
739
                );
740
            }
741
 
742
            $args['region'] = \Aws\strip_fips_pseudo_regions($args['region']);
743
 
744
            // Invoke the endpoint provider and throw if it does not resolve.
745
            $result = EndpointProvider::resolve($value, [
746
                'service' => $endpointPrefix,
747
                'region'  => $args['region'],
748
                'scheme'  => $args['scheme'],
749
                'options' => self::getEndpointProviderOptions($args),
750
            ]);
751
 
752
            $args['endpoint'] = $result['endpoint'];
753
 
754
            if (empty($args['config']['signature_version'])) {
755
                if (
756
                    isset($args['api'])
757
                    && $args['api']->getSignatureVersion() == 'bearer'
758
                ) {
759
                    $args['config']['signature_version'] = 'bearer';
760
                } elseif (isset($result['signatureVersion'])) {
761
                    $args['config']['signature_version'] = $result['signatureVersion'];
762
                }
763
            }
764
 
765
            if (
766
                empty($args['config']['signing_region'])
767
                && isset($result['signingRegion'])
768
            ) {
769
                $args['config']['signing_region'] = $result['signingRegion'];
770
            }
771
 
772
            if (
773
                empty($args['config']['signing_name'])
774
                && isset($result['signingName'])
775
            ) {
776
                $args['config']['signing_name'] = $result['signingName'];
777
            }
778
        }
779
    }
780
 
781
    public static function _apply_endpoint_discovery($value, array &$args) {
782
        $args['endpoint_discovery'] = $value;
783
    }
784
 
785
    public static function _default_endpoint_discovery_provider(array $args)
786
    {
787
        return ConfigurationProvider::defaultProvider($args);
788
    }
789
 
790
    public static function _apply_use_fips_endpoint($value, array &$args) {
791
        if ($value instanceof CacheInterface) {
792
            $value = UseFipsConfigProvider::defaultProvider($args);
793
        }
794
        if (is_callable($value)) {
795
            $value = $value();
796
        }
797
        if ($value instanceof PromiseInterface) {
798
            $value = $value->wait();
799
        }
800
        if ($value instanceof UseFipsEndpointConfigurationInterface) {
801
            $args['config']['use_fips_endpoint'] = $value;
802
        } else {
803
            // The Configuration class itself will validate other inputs
804
            $args['config']['use_fips_endpoint'] = new UseFipsEndpointConfiguration($value);
805
        }
806
    }
807
 
808
    public static function _default_use_fips_endpoint(array &$args) {
809
        return UseFipsConfigProvider::defaultProvider($args);
810
    }
811
 
812
    public static function _apply_use_dual_stack_endpoint($value, array &$args) {
813
        if ($value instanceof CacheInterface) {
814
            $value = UseDualStackConfigProvider::defaultProvider($args);
815
        }
816
        if (is_callable($value)) {
817
            $value = $value();
818
        }
819
        if ($value instanceof PromiseInterface) {
820
            $value = $value->wait();
821
        }
822
        if ($value instanceof UseDualStackEndpointConfigurationInterface) {
823
            $args['config']['use_dual_stack_endpoint'] = $value;
824
        } else {
825
            // The Configuration class itself will validate other inputs
826
            $args['config']['use_dual_stack_endpoint'] =
827
                new UseDualStackEndpointConfiguration($value, $args['region']);
828
        }
829
    }
830
 
831
    public static function _default_use_dual_stack_endpoint(array &$args) {
832
        return UseDualStackConfigProvider::defaultProvider($args);
833
    }
834
 
835
    public static function _apply_debug($value, array &$args, HandlerList $list)
836
    {
837
        if ($value !== false) {
838
            $list->interpose(
839
                new TraceMiddleware(
840
                    $value === true ? [] : $value,
841
                    $args['api'])
842
            );
843
        }
844
    }
845
 
846
    public static function _apply_stats($value, array &$args, HandlerList $list)
847
    {
848
        // Create an array of stat collectors that are disabled (set to false)
849
        // by default. If the user has passed in true, enable all stat
850
        // collectors.
851
        $defaults = array_fill_keys(
852
            ['http', 'retries', 'timer'],
853
            $value === true
854
        );
855
        $args['stats'] = is_array($value)
856
            ? array_replace($defaults, $value)
857
            : $defaults;
858
 
859
        if ($args['stats']['timer']) {
860
            $list->prependInit(Middleware::timer(), 'timer');
861
        }
862
    }
863
 
864
    public static function _apply_profile($_, array &$args)
865
    {
866
        $args['credentials'] = CredentialProvider::ini($args['profile']);
867
    }
868
 
869
    public static function _apply_validate($value, array &$args, HandlerList $list)
870
    {
871
        if ($value === false) {
872
            return;
873
        }
874
 
875
        $validator = $value === true
876
            ? new Validator()
877
            : new Validator($value);
878
        $list->appendValidate(
879
            Middleware::validation($args['api'], $validator),
880
            'validation'
881
        );
882
    }
883
 
884
    public static function _apply_handler($value, array &$args, HandlerList $list)
885
    {
886
        $list->setHandler($value);
887
    }
888
 
889
    public static function _default_handler(array &$args)
890
    {
891
        return new WrappedHttpHandler(
892
            default_http_handler(),
893
            $args['parser'],
894
            $args['error_parser'],
895
            $args['exception_class'],
896
            $args['stats']['http']
897
        );
898
    }
899
 
900
    public static function _apply_http_handler($value, array &$args, HandlerList $list)
901
    {
902
        $args['handler'] = new WrappedHttpHandler(
903
            $value,
904
            $args['parser'],
905
            $args['error_parser'],
906
            $args['exception_class'],
907
            $args['stats']['http']
908
        );
909
    }
910
 
911
    public static function _apply_user_agent($inputUserAgent, array &$args, HandlerList $list)
912
    {
913
        //Add SDK version
914
        $userAgent = ['aws-sdk-php/' . Sdk::VERSION];
915
 
916
        //If on HHVM add the HHVM version
917
        if (defined('HHVM_VERSION')) {
918
            $userAgent []= 'HHVM/' . HHVM_VERSION;
919
        }
920
 
921
        //Add OS version
922
        $disabledFunctions = explode(',', ini_get('disable_functions'));
923
        if (function_exists('php_uname')
924
            && !in_array('php_uname', $disabledFunctions, true)
925
        ) {
926
            $osName = "OS/" . php_uname('s') . '#' . php_uname('r');
927
            if (!empty($osName)) {
928
                $userAgent []= $osName;
929
            }
930
        }
931
 
932
        //Add the language version
933
        $userAgent []= 'lang/php#' . phpversion();
934
 
935
        //Add exec environment if present
936
        if ($executionEnvironment = getenv('AWS_EXECUTION_ENV')) {
937
            $userAgent []= $executionEnvironment;
938
        }
939
 
940
        //Add endpoint discovery if set
941
        if (isset($args['endpoint_discovery'])) {
942
            if (($args['endpoint_discovery'] instanceof \Aws\EndpointDiscovery\Configuration
943
                && $args['endpoint_discovery']->isEnabled())
944
            ) {
945
                $userAgent []= 'cfg/endpoint-discovery';
946
            } elseif (is_array($args['endpoint_discovery'])
947
                && isset($args['endpoint_discovery']['enabled'])
948
                && $args['endpoint_discovery']['enabled']
949
            ) {
950
                $userAgent []= 'cfg/endpoint-discovery';
951
            }
952
        }
953
 
954
        //Add retry mode if set
955
        if (isset($args['retries'])) {
956
            if ($args['retries'] instanceof \Aws\Retry\Configuration) {
957
                $userAgent []= 'cfg/retry-mode#' . $args["retries"]->getMode();
958
            } elseif (is_array($args['retries'])
959
                && isset($args["retries"]["mode"])
960
            ) {
961
                $userAgent []= 'cfg/retry-mode#' . $args["retries"]["mode"];
962
            }
963
        }
964
        //Add the input to the end
965
        if ($inputUserAgent){
966
            if (!is_array($inputUserAgent)) {
967
                $inputUserAgent = [$inputUserAgent];
968
            }
969
            $inputUserAgent = array_map('strval', $inputUserAgent);
970
            $userAgent = array_merge($userAgent, $inputUserAgent);
971
        }
972
 
973
        $args['ua_append'] = $userAgent;
974
 
975
        $list->appendBuild(static function (callable $handler) use ($userAgent) {
976
            return function (
977
                CommandInterface $command,
978
                RequestInterface $request
979
            ) use ($handler, $userAgent) {
980
                return $handler(
981
                    $command,
982
                    $request->withHeader(
983
                        'X-Amz-User-Agent',
984
                        implode(' ', array_merge(
985
                            $userAgent,
986
                            $request->getHeader('X-Amz-User-Agent')
987
                        ))
988
                    )->withHeader(
989
                        'User-Agent',
990
                        implode(' ', array_merge(
991
                            $userAgent,
992
                            $request->getHeader('User-Agent')
993
                        ))
994
                    )
995
                );
996
            };
997
        });
998
    }
999
 
1000
    public static function _apply_endpoint($value, array &$args, HandlerList $list)
1001
    {
1002
        $args['endpoint'] = $value;
1003
    }
1004
 
1005
    public static function _apply_idempotency_auto_fill(
1006
        $value,
1007
        array &$args,
1008
        HandlerList $list
1009
    ) {
1010
        $enabled = false;
1011
        $generator = null;
1012
 
1013
 
1014
        if (is_bool($value)) {
1015
            $enabled = $value;
1016
        } elseif (is_callable($value)) {
1017
            $enabled = true;
1018
            $generator = $value;
1019
        }
1020
 
1021
        if ($enabled) {
1022
            $list->prependInit(
1023
                IdempotencyTokenMiddleware::wrap($args['api'], $generator),
1024
                'idempotency_auto_fill'
1025
            );
1026
        }
1027
    }
1028
 
1029
    public static function _apply_suppress_php_deprecation_warning($suppressWarning, array &$args) {
1030
        if ($suppressWarning) {
1031
            $args['suppress_php_deprecation_warning'] = true;
1032
        } elseif (!empty($_ENV["AWS_SUPPRESS_PHP_DEPRECATION_WARNING"])) {
1033
            $args['suppress_php_deprecation_warning'] =
1034
                $_ENV["AWS_SUPPRESS_PHP_DEPRECATION_WARNING"];
1035
        } elseif (!empty($_SERVER["AWS_SUPPRESS_PHP_DEPRECATION_WARNING"])) {
1036
            $args['suppress_php_deprecation_warning'] =
1037
                $_SERVER["AWS_SUPPRESS_PHP_DEPRECATION_WARNING"];
1038
        } elseif (!empty(getenv("AWS_SUPPRESS_PHP_DEPRECATION_WARNING"))) {
1039
            $args['suppress_php_deprecation_warning']
1040
                = getenv("AWS_SUPPRESS_PHP_DEPRECATION_WARNING");
1041
        }
1042
    }
1043
 
1044
    public static function _default_endpoint_provider(array $args)
1045
    {
1046
        $service =  isset($args['api']) ? $args['api'] : null;
1047
        $serviceName = isset($service) ? $service->getServiceName() : null;
1048
        $apiVersion = isset($service) ? $service->getApiVersion() : null;
1049
 
1050
        if (self::isValidService($serviceName)
1051
            && self::isValidApiVersion($serviceName, $apiVersion)
1052
        ) {
1053
            $ruleset = EndpointDefinitionProvider::getEndpointRuleset(
1054
                $service->getServiceName(),
1055
                $service->getApiVersion()
1056
            );
1057
            return new \Aws\EndpointV2\EndpointProviderV2(
1058
                $ruleset,
1059
                EndpointDefinitionProvider::getPartitions()
1060
            );
1061
        }
1062
        $options = self::getEndpointProviderOptions($args);
1063
        return PartitionEndpointProvider::defaultProvider($options)
1064
            ->getPartition($args['region'], $args['service']);
1065
    }
1066
 
1067
    public static function _default_serializer(array $args)
1068
    {
1069
        return Service::createSerializer(
1070
            $args['api'],
1071
            $args['endpoint']
1072
        );
1073
    }
1074
 
1075
    public static function _default_signature_provider()
1076
    {
1077
        return SignatureProvider::defaultProvider();
1078
    }
1079
 
1080
    public static function _default_signature_version(array &$args)
1081
    {
1082
        if (isset($args['config']['signature_version'])) {
1083
            return $args['config']['signature_version'];
1084
        }
1085
 
1086
        $args['__partition_result'] = isset($args['__partition_result'])
1087
            ? isset($args['__partition_result'])
1088
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
1089
                'service' => $args['service'],
1090
                'region' => $args['region'],
1091
            ]);
1092
 
1093
        return isset($args['__partition_result']['signatureVersion'])
1094
            ? $args['__partition_result']['signatureVersion']
1095
            : $args['api']->getSignatureVersion();
1096
    }
1097
 
1098
    public static function _default_signing_name(array &$args)
1099
    {
1100
        if (isset($args['config']['signing_name'])) {
1101
            return $args['config']['signing_name'];
1102
        }
1103
 
1104
        $args['__partition_result'] = isset($args['__partition_result'])
1105
            ? isset($args['__partition_result'])
1106
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
1107
                'service' => $args['service'],
1108
                'region' => $args['region'],
1109
            ]);
1110
 
1111
        if (isset($args['__partition_result']['signingName'])) {
1112
            return $args['__partition_result']['signingName'];
1113
        }
1114
 
1115
        if ($signingName = $args['api']->getSigningName()) {
1116
            return $signingName;
1117
        }
1118
 
1119
        return $args['service'];
1120
    }
1121
 
1122
    public static function _default_signing_region(array &$args)
1123
    {
1124
        if (isset($args['config']['signing_region'])) {
1125
            return $args['config']['signing_region'];
1126
        }
1127
 
1128
        $args['__partition_result'] = isset($args['__partition_result'])
1129
            ? isset($args['__partition_result'])
1130
            : call_user_func(PartitionEndpointProvider::defaultProvider(), [
1131
                'service' => $args['service'],
1132
                'region' => $args['region'],
1133
            ]);
1134
 
1135
        return isset($args['__partition_result']['signingRegion'])
1136
            ? $args['__partition_result']['signingRegion']
1137
            : $args['region'];
1138
    }
1139
 
1140
    public static function _missing_region(array $args)
1141
    {
1142
        $service = isset($args['service']) ? $args['service'] : '';
1143
 
1144
        return <<<EOT
1145
A "region" configuration value is required for the "{$service}" service
1146
(e.g., "us-west-2"). A list of available public regions and endpoints can be
1147
found at http://docs.aws.amazon.com/general/latest/gr/rande.html.
1148
EOT;
1149
    }
1150
 
1151
    /**
1152
     * Extracts client options for the endpoint provider to its own array
1153
     *
1154
     * @param array $args
1155
     * @return array
1156
     */
1157
    private static function getEndpointProviderOptions(array $args)
1158
    {
1159
        $options = [];
1160
        $optionKeys = [
1161
            'sts_regional_endpoints',
1162
            's3_us_east_1_regional_endpoint',
1163
            ];
1164
        $configKeys = [
1165
            'use_dual_stack_endpoint',
1166
            'use_fips_endpoint',
1167
        ];
1168
        foreach ($optionKeys as $key) {
1169
            if (isset($args[$key])) {
1170
                $options[$key] = $args[$key];
1171
            }
1172
        }
1173
        foreach ($configKeys as $key) {
1174
            if (isset($args['config'][$key])) {
1175
                $options[$key] = $args['config'][$key];
1176
            }
1177
        }
1178
        return $options;
1179
    }
1180
 
1181
    /**
1182
     * Validates a region to be used for endpoint construction
1183
     *
1184
     * @param $region
1185
     * @return bool
1186
     */
1187
    private static function isValidRegion($region)
1188
    {
1189
        return is_valid_hostlabel($region);
1190
    }
1191
 
1192
    private function _apply_client_context_params(array $args)
1193
    {
1194
        if (isset($args['api'])
1195
           && !empty($args['api']->getClientContextParams()))
1196
        {
1197
            $clientContextParams = $args['api']->getClientContextParams();
1198
            foreach($clientContextParams as $paramName => $paramDefinition) {
1199
                $definition = [
1200
                    'type' => 'value',
1201
                    'valid' => [$paramDefinition['type']],
1202
                    'doc' => isset($paramDefinition['documentation']) ?
1203
                        $paramDefinition['documentation'] : null
1204
                ];
1205
                $this->argDefinitions[$paramName] = $definition;
1206
 
1207
                if (isset($args[$paramName])) {
1208
                    $fn = self::$typeMap[$paramDefinition['type']];
1209
                    if (!$fn($args[$paramName])) {
1210
                        $this->invalidType($paramName, $args[$paramName]);
1211
                    }
1212
                }
1213
            }
1214
        }
1215
    }
1216
 
1217
    private static function isValidService($service) {
1218
        if (is_null($service)) {
1219
            return false;
1220
        }
1221
        $services = \Aws\manifest();
1222
        return isset($services[$service]);
1223
    }
1224
 
1225
    private static function isValidApiVersion($service, $apiVersion) {
1226
        if (is_null($apiVersion)) {
1227
            return false;
1228
        }
1229
        return is_dir(
1230
          __DIR__ . "/data/{$service}/$apiVersion"
1231
        );
1232
    }
1233
}