vendor/aws/aws-sdk-php/src/ClientResolver.php line 1240

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