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\DocModel;
6
use Aws\Api\Service;
7
use Aws\EndpointDiscovery\EndpointDiscoveryMiddleware;
8
use Aws\EndpointV2\EndpointProviderV2;
9
use Aws\Exception\AwsException;
10
use Aws\Signature\SignatureProvider;
11
use GuzzleHttp\Psr7\Uri;
12
 
13
/**
14
 * Default AWS client implementation
15
 */
16
class AwsClient implements AwsClientInterface
17
{
18
    use AwsClientTrait;
19
 
20
    /** @var array */
21
    private $aliases;
22
 
23
    /** @var array */
24
    private $config;
25
 
26
    /** @var string */
27
    private $region;
28
 
29
    /** @var string */
30
    private $endpoint;
31
 
32
    /** @var Service */
33
    private $api;
34
 
35
    /** @var callable */
36
    private $signatureProvider;
37
 
38
    /** @var callable */
39
    private $credentialProvider;
40
 
41
    /** @var callable */
42
    private $tokenProvider;
43
 
44
    /** @var HandlerList */
45
    private $handlerList;
46
 
47
    /** @var array*/
48
    private $defaultRequestOptions;
49
 
50
    /** @var array*/
51
    private $clientContextParams = [];
52
 
53
    /** @var array*/
54
    protected $clientBuiltIns = [];
55
 
56
    /** @var  EndpointProviderV2 | callable */
57
    protected $endpointProvider;
58
 
59
    /** @var callable */
60
    protected $serializer;
61
 
62
    /**
63
     * Get an array of client constructor arguments used by the client.
64
     *
65
     * @return array
66
     */
67
    public static function getArguments()
68
    {
69
        return ClientResolver::getDefaultArguments();
70
    }
71
 
72
    /**
73
     * The client constructor accepts the following options:
74
     *
75
     * - api_provider: (callable) An optional PHP callable that accepts a
76
     *   type, service, and version argument, and returns an array of
77
     *   corresponding configuration data. The type value can be one of api,
78
     *   waiter, or paginator.
79
     * - credentials:
80
     *   (Aws\Credentials\CredentialsInterface|array|bool|callable) Specifies
81
     *   the credentials used to sign requests. Provide an
82
     *   Aws\Credentials\CredentialsInterface object, an associative array of
83
     *   "key", "secret", and an optional "token" key, `false` to use null
84
     *   credentials, or a callable credentials provider used to create
85
     *   credentials or return null. See Aws\Credentials\CredentialProvider for
86
     *   a list of built-in credentials providers. If no credentials are
87
     *   provided, the SDK will attempt to load them from the environment.
88
     * - token:
89
     *   (Aws\Token\TokenInterface|array|bool|callable) Specifies
90
     *   the token used to authorize requests. Provide an
91
     *   Aws\Token\TokenInterface object, an associative array of
92
     *   "token" and an optional "expires" key, `false` to use no
93
     *   token, or a callable token provider used to create a
94
     *   token or return null. See Aws\Token\TokenProvider for
95
     *   a list of built-in token providers. If no token is
96
     *   provided, the SDK will attempt to load one from the environment.
97
     * - csm:
98
     *   (Aws\ClientSideMonitoring\ConfigurationInterface|array|callable) Specifies
99
     *   the credentials used to sign requests. Provide an
100
     *   Aws\ClientSideMonitoring\ConfigurationInterface object, a callable
101
     *   configuration provider used to create client-side monitoring configuration,
102
     *   `false` to disable csm, or an associative array with the following keys:
103
     *   enabled: (bool) Set to true to enable client-side monitoring, defaults
104
     *   to false; host: (string) the host location to send monitoring events to,
105
     *   defaults to 127.0.0.1; port: (int) The port used for the host connection,
106
     *   defaults to 31000; client_id: (string) An identifier for this project
107
     * - debug: (bool|array) Set to true to display debug information when
108
     *   sending requests. Alternatively, you can provide an associative array
109
     *   with the following keys: logfn: (callable) Function that is invoked
110
     *   with log messages; stream_size: (int) When the size of a stream is
111
     *   greater than this number, the stream data will not be logged (set to
112
     *   "0" to not log any stream data); scrub_auth: (bool) Set to false to
113
     *   disable the scrubbing of auth data from the logged messages; http:
114
     *   (bool) Set to false to disable the "debug" feature of lower level HTTP
115
     *   adapters (e.g., verbose curl output).
116
     * - stats: (bool|array) Set to true to gather transfer statistics on
117
     *   requests sent. Alternatively, you can provide an associative array with
118
     *   the following keys: retries: (bool) Set to false to disable reporting
119
     *   on retries attempted; http: (bool) Set to true to enable collecting
120
     *   statistics from lower level HTTP adapters (e.g., values returned in
121
     *   GuzzleHttp\TransferStats). HTTP handlers must support an
122
     *   `http_stats_receiver` option for this to have an effect; timer: (bool)
123
     *   Set to true to enable a command timer that reports the total wall clock
124
     *   time spent on an operation in seconds.
125
     * - disable_host_prefix_injection: (bool) Set to true to disable host prefix
126
     *   injection logic for services that use it. This disables the entire
127
     *   prefix injection, including the portions supplied by user-defined
128
     *   parameters. Setting this flag will have no effect on services that do
129
     *   not use host prefix injection.
130
     * - endpoint: (string) The full URI of the webservice. This is only
131
     *   required when connecting to a custom endpoint (e.g., a local version
132
     *   of S3).
133
     * - endpoint_discovery: (Aws\EndpointDiscovery\ConfigurationInterface,
134
     *   Aws\CacheInterface, array, callable) Settings for endpoint discovery.
135
     *   Provide an instance of Aws\EndpointDiscovery\ConfigurationInterface,
136
     *   an instance Aws\CacheInterface, a callable that provides a promise for
137
     *   a Configuration object, or an associative array with the following
138
     *   keys: enabled: (bool) Set to true to enable endpoint discovery, false
139
     *   to explicitly disable it, defaults to false; cache_limit: (int) The
140
     *   maximum number of keys in the endpoints cache, defaults to 1000.
141
     * - endpoint_provider: (callable) An optional PHP callable that
142
     *   accepts a hash of options including a "service" and "region" key and
143
     *   returns NULL or a hash of endpoint data, of which the "endpoint" key
144
     *   is required. See Aws\Endpoint\EndpointProvider for a list of built-in
145
     *   providers.
146
     * - handler: (callable) A handler that accepts a command object,
147
     *   request object and returns a promise that is fulfilled with an
148
     *   Aws\ResultInterface object or rejected with an
149
     *   Aws\Exception\AwsException. A handler does not accept a next handler
150
     *   as it is terminal and expected to fulfill a command. If no handler is
151
     *   provided, a default Guzzle handler will be utilized.
152
     * - http: (array, default=array(0)) Set to an array of SDK request
153
     *   options to apply to each request (e.g., proxy, verify, etc.).
154
     * - http_handler: (callable) An HTTP handler is a function that
155
     *   accepts a PSR-7 request object and returns a promise that is fulfilled
156
     *   with a PSR-7 response object or rejected with an array of exception
157
     *   data. NOTE: This option supersedes any provided "handler" option.
158
     * - idempotency_auto_fill: (bool|callable) Set to false to disable SDK to
159
     *   populate parameters that enabled 'idempotencyToken' trait with a random
160
     *   UUID v4 value on your behalf. Using default value 'true' still allows
161
     *   parameter value to be overwritten when provided. Note: auto-fill only
162
     *   works when cryptographically secure random bytes generator functions
163
     *   (random_bytes, openssl_random_pseudo_bytes or mcrypt_create_iv) can be
164
     *   found. You may also provide a callable source of random bytes.
165
     * - profile: (string) Allows you to specify which profile to use when
166
     *   credentials are created from the AWS credentials file in your HOME
167
     *   directory. This setting overrides the AWS_PROFILE environment
168
     *   variable. Note: Specifying "profile" will cause the "credentials" key
169
     *   to be ignored.
170
     * - region: (string, required) Region to connect to. See
171
     *   http://docs.aws.amazon.com/general/latest/gr/rande.html for a list of
172
     *   available regions.
173
     * - retries: (int, Aws\Retry\ConfigurationInterface, Aws\CacheInterface,
174
     *   array, callable) Configures the retry mode and maximum number of
175
     *   allowed retries for a client (pass 0 to disable retries). Provide an
176
     *   integer for 'legacy' mode with the specified number of retries.
177
     *   Otherwise provide an instance of Aws\Retry\ConfigurationInterface, an
178
     *   instance of  Aws\CacheInterface, a callable function, or an array with
179
     *   the following keys: mode: (string) Set to 'legacy', 'standard' (uses
180
     *   retry quota management), or 'adapative' (an experimental mode that adds
181
     *   client-side rate limiting to standard mode); max_attempts (int) The
182
     *   maximum number of attempts for a given request.
183
     * - scheme: (string, default=string(5) "https") URI scheme to use when
184
     *   connecting connect. The SDK will utilize "https" endpoints (i.e.,
185
     *   utilize SSL/TLS connections) by default. You can attempt to connect to
186
     *   a service over an unencrypted "http" endpoint by setting ``scheme`` to
187
     *   "http".
188
     * - signature_provider: (callable) A callable that accepts a signature
189
     *   version name (e.g., "v4"), a service name, and region, and
190
     *   returns a SignatureInterface object or null. This provider is used to
191
     *   create signers utilized by the client. See
192
     *   Aws\Signature\SignatureProvider for a list of built-in providers
193
     * - signature_version: (string) A string representing a custom
194
     *   signature version to use with a service (e.g., v4). Note that
195
     *   per/operation signature version MAY override this requested signature
196
     *   version.
197
     * - use_aws_shared_config_files: (bool, default=bool(true)) Set to false to
198
     *   disable checking for shared config file in '~/.aws/config' and
199
     *   '~/.aws/credentials'.  This will override the AWS_CONFIG_FILE
200
     *   environment variable.
201
     * - validate: (bool, default=bool(true)) Set to false to disable
202
     *   client-side parameter validation.
203
     * - version: (string, required) The version of the webservice to
204
     *   utilize (e.g., 2006-03-01).
205
     *
206
     * @param array $args Client configuration arguments.
207
     *
208
     * @throws \InvalidArgumentException if any required options are missing or
209
     *                                   the service is not supported.
210
     */
211
    public function __construct(array $args)
212
    {
213
        list($service, $exceptionClass) = $this->parseClass();
214
        if (!isset($args['service'])) {
215
            $args['service'] = manifest($service)['endpoint'];
216
        }
217
        if (!isset($args['exception_class'])) {
218
            $args['exception_class'] = $exceptionClass;
219
        }
220
        $this->handlerList = new HandlerList();
221
        $resolver = new ClientResolver(static::getArguments());
222
        $config = $resolver->resolve($args, $this->handlerList);
223
        $this->api = $config['api'];
224
        $this->signatureProvider = $config['signature_provider'];
225
        $this->endpoint = new Uri($config['endpoint']);
226
        $this->credentialProvider = $config['credentials'];
227
        $this->tokenProvider = $config['token'];
228
        $this->region = isset($config['region']) ? $config['region'] : null;
229
        $this->config = $config['config'];
230
        $this->setClientBuiltIns($args);
231
        $this->clientContextParams = $this->setClientContextParams($args);
232
        $this->defaultRequestOptions = $config['http'];
233
        $this->endpointProvider = $config['endpoint_provider'];
234
        $this->serializer = $config['serializer'];
235
        $this->addSignatureMiddleware();
236
        $this->addInvocationId();
237
        $this->addEndpointParameterMiddleware($args);
238
        $this->addEndpointDiscoveryMiddleware($config, $args);
239
        $this->addRequestCompressionMiddleware($config);
240
        $this->loadAliases();
241
        $this->addStreamRequestPayload();
242
        $this->addRecursionDetection();
243
        $this->addRequestBuilder();
244
 
245
        if (!$config['suppress_php_deprecation_warning']) {
246
            $this->emitDeprecationWarning();
247
        }
248
 
249
        if (isset($args['with_resolved'])) {
250
            $args['with_resolved']($config);
251
        }
252
    }
253
 
254
    public function getHandlerList()
255
    {
256
        return $this->handlerList;
257
    }
258
 
259
    public function getConfig($option = null)
260
    {
261
        return $option === null
262
            ? $this->config
263
            : (isset($this->config[$option])
264
                ? $this->config[$option]
265
                : null);
266
    }
267
 
268
    public function getCredentials()
269
    {
270
        $fn = $this->credentialProvider;
271
        return $fn();
272
    }
273
 
274
 
275
    public function getEndpoint()
276
    {
277
        return $this->endpoint;
278
    }
279
 
280
    public function getRegion()
281
    {
282
        return $this->region;
283
    }
284
 
285
    public function getApi()
286
    {
287
        return $this->api;
288
    }
289
 
290
    public function getCommand($name, array $args = [])
291
    {
292
        // Fail fast if the command cannot be found in the description.
293
        if (!isset($this->getApi()['operations'][$name])) {
294
            $name = ucfirst($name);
295
            if (!isset($this->getApi()['operations'][$name])) {
296
                throw new \InvalidArgumentException("Operation not found: $name");
297
            }
298
        }
299
 
300
        if (!isset($args['@http'])) {
301
            $args['@http'] = $this->defaultRequestOptions;
302
        } else {
303
            $args['@http'] += $this->defaultRequestOptions;
304
        }
305
 
306
        return new Command($name, $args, clone $this->getHandlerList());
307
    }
308
 
309
    public function getEndpointProvider()
310
    {
311
        return $this->endpointProvider;
312
    }
313
 
314
    /**
315
     * Provides the set of service context parameter
316
     * key-value pairs used for endpoint resolution.
317
     *
318
     * @return array
319
     */
320
    public function getClientContextParams()
321
    {
322
        return $this->clientContextParams;
323
    }
324
 
325
    /**
326
     * Provides the set of built-in keys and values
327
     * used for endpoint resolution
328
     *
329
     * @return array
330
     */
331
    public function getClientBuiltIns()
332
    {
333
        return $this->clientBuiltIns;
334
    }
335
 
336
    public function __sleep()
337
    {
338
        throw new \RuntimeException('Instances of ' . static::class
339
            . ' cannot be serialized');
340
    }
341
 
342
    /**
343
     * Get the signature_provider function of the client.
344
     *
345
     * @return callable
346
     */
347
    final public function getSignatureProvider()
348
    {
349
        return $this->signatureProvider;
350
    }
351
 
352
    /**
353
     * Parse the class name and setup the custom exception class of the client
354
     * and return the "service" name of the client and "exception_class".
355
     *
356
     * @return array
357
     */
358
    private function parseClass()
359
    {
360
        $klass = get_class($this);
361
 
362
        if ($klass === __CLASS__) {
363
            return ['', AwsException::class];
364
        }
365
 
366
        $service = substr($klass, strrpos($klass, '\\') + 1, -6);
367
 
368
        return [
369
            strtolower($service),
370
            "Aws\\{$service}\\Exception\\{$service}Exception"
371
        ];
372
    }
373
 
374
    private function addEndpointParameterMiddleware($args)
375
    {
376
        if (empty($args['disable_host_prefix_injection'])) {
377
            $list = $this->getHandlerList();
378
            $list->appendBuild(
379
                EndpointParameterMiddleware::wrap(
380
                    $this->api
381
                ),
382
                'endpoint_parameter'
383
            );
384
        }
385
    }
386
 
387
    private function addEndpointDiscoveryMiddleware($config, $args)
388
    {
389
        $list = $this->getHandlerList();
390
 
391
        if (!isset($args['endpoint'])) {
392
            $list->appendBuild(
393
                EndpointDiscoveryMiddleware::wrap(
394
                    $this,
395
                    $args,
396
                    $config['endpoint_discovery']
397
                ),
398
                'EndpointDiscoveryMiddleware'
399
            );
400
        }
401
    }
402
 
403
    private function addSignatureMiddleware()
404
    {
405
        $api = $this->getApi();
406
        $provider = $this->signatureProvider;
407
        $version = $this->config['signature_version'];
408
        $name = $this->config['signing_name'];
409
        $region = $this->config['signing_region'];
410
 
411
        $resolver = static function (
412
            CommandInterface $c
413
        ) use ($api, $provider, $name, $region, $version) {
414
            if (!empty($c['@context']['signing_region'])) {
415
                $region = $c['@context']['signing_region'];
416
            }
417
            if (!empty($c['@context']['signing_service'])) {
418
                $name = $c['@context']['signing_service'];
419
            }
420
 
421
            $authType = $api->getOperation($c->getName())['authtype'];
422
            switch ($authType){
423
                case 'none':
424
                    $version = 'anonymous';
425
                    break;
426
                case 'v4-unsigned-body':
427
                    $version = 'v4-unsigned-body';
428
                    break;
429
                case 'bearer':
430
                    $version = 'bearer';
431
                    break;
432
            }
433
            if (isset($c['@context']['signature_version'])) {
434
                if ($c['@context']['signature_version'] == 'v4a') {
435
                    $version = 'v4a';
436
                }
437
            }
438
            if (!empty($endpointAuthSchemes = $c->getAuthSchemes())) {
439
                $version = $endpointAuthSchemes['version'];
440
                $name = isset($endpointAuthSchemes['name']) ?
441
                    $endpointAuthSchemes['name'] : $name;
442
                $region = isset($endpointAuthSchemes['region']) ?
443
                    $endpointAuthSchemes['region'] : $region;
444
            }
445
            return SignatureProvider::resolve($provider, $version, $name, $region);
446
        };
447
        $this->handlerList->appendSign(
448
            Middleware::signer($this->credentialProvider, $resolver, $this->tokenProvider),
449
            'signer'
450
        );
451
    }
452
 
453
    private function addRequestCompressionMiddleware($config)
454
    {
455
        if (empty($config['disable_request_compression'])) {
456
            $list = $this->getHandlerList();
457
            $list->appendBuild(
458
                RequestCompressionMiddleware::wrap($config),
459
                'request-compression'
460
            );
461
        }
462
    }
463
 
464
    private function addInvocationId()
465
    {
466
        // Add invocation id to each request
467
        $this->handlerList->prependSign(Middleware::invocationId(), 'invocation-id');
468
    }
469
 
470
    private function loadAliases($file = null)
471
    {
472
        if (!isset($this->aliases)) {
473
            if (is_null($file)) {
474
                $file = __DIR__ . '/data/aliases.json';
475
            }
476
            $aliases = \Aws\load_compiled_json($file);
477
            $serviceId = $this->api->getServiceId();
478
            $version = $this->getApi()->getApiVersion();
479
            if (!empty($aliases['operations'][$serviceId][$version])) {
480
                $this->aliases = array_flip($aliases['operations'][$serviceId][$version]);
481
            }
482
        }
483
    }
484
 
485
    private function addStreamRequestPayload()
486
    {
487
        $streamRequestPayloadMiddleware = StreamRequestPayloadMiddleware::wrap(
488
            $this->api
489
        );
490
 
491
        $this->handlerList->prependSign(
492
            $streamRequestPayloadMiddleware,
493
            'StreamRequestPayloadMiddleware'
494
        );
495
    }
496
 
497
    private function addRecursionDetection()
498
    {
499
        // Add recursion detection header to requests
500
        // originating in supported Lambda runtimes
501
        $this->handlerList->appendBuild(
502
            Middleware::recursionDetection(), 'recursion-detection'
503
        );
504
    }
505
 
506
    /**
507
     * Adds the `builder` middleware such that a client's endpoint
508
     * provider and endpoint resolution arguments can be passed.
509
     */
510
    private function addRequestBuilder()
511
    {
512
        $handlerList = $this->getHandlerList();
513
        $serializer = $this->serializer;
514
        $endpointProvider = $this->endpointProvider;
515
        $endpointArgs = $this->getEndpointProviderArgs();
516
 
517
        $handlerList->prependBuild(
518
            Middleware::requestBuilder(
519
                $serializer,
520
                $endpointProvider,
521
                $endpointArgs
522
            ),
523
            'builderV2'
524
        );
525
    }
526
 
527
    /**
528
     * Retrieves client context param definition from service model,
529
     * creates mapping of client context param names with client-provided
530
     * values.
531
     *
532
     * @return array
533
     */
534
    private function setClientContextParams($args)
535
    {
536
        $api = $this->getApi();
537
        $resolvedParams = [];
538
        if (!empty($paramDefinitions = $api->getClientContextParams())) {
539
            foreach($paramDefinitions as $paramName => $paramValue) {
540
                if (isset($args[$paramName])) {
541
                   $result[$paramName] = $args[$paramName];
542
               }
543
            }
544
        }
545
        return $resolvedParams;
546
    }
547
 
548
    /**
549
     * Retrieves and sets default values used for endpoint resolution.
550
     */
551
    private function setClientBuiltIns($args)
552
    {
553
        $builtIns = [];
554
        $config = $this->getConfig();
555
        $service = $args['service'];
556
 
557
        $builtIns['SDK::Endpoint'] = isset($args['endpoint']) ? $args['endpoint'] : null;
558
        $builtIns['AWS::Region'] = $this->getRegion();
559
        $builtIns['AWS::UseFIPS'] = $config['use_fips_endpoint']->isUseFipsEndpoint();
560
        $builtIns['AWS::UseDualStack'] = $config['use_dual_stack_endpoint']->isUseDualstackEndpoint();
561
        if ($service === 's3' || $service === 's3control'){
562
            $builtIns['AWS::S3::UseArnRegion'] = $config['use_arn_region']->isUseArnRegion();
563
        }
564
        if ($service === 's3') {
565
            $builtIns['AWS::S3::UseArnRegion'] = $config['use_arn_region']->isUseArnRegion();
566
            $builtIns['AWS::S3::Accelerate'] = $config['use_accelerate_endpoint'];
567
            $builtIns['AWS::S3::ForcePathStyle'] = $config['use_path_style_endpoint'];
568
            $builtIns['AWS::S3::DisableMultiRegionAccessPoints'] = $config['disable_multiregion_access_points'];
569
        }
570
        $this->clientBuiltIns += $builtIns;
571
    }
572
 
573
    /**
574
     * Retrieves arguments to be used in endpoint resolution.
575
     *
576
     * @return array
577
     */
578
    public function getEndpointProviderArgs()
579
    {
580
        return $this->normalizeEndpointProviderArgs();
581
    }
582
 
583
    /**
584
     * Combines built-in and client context parameter values in
585
     * order of specificity.  Client context parameter values supersede
586
     * built-in values.
587
     *
588
     * @return array
589
     */
590
    private function normalizeEndpointProviderArgs()
591
    {
592
        $normalizedBuiltIns = [];
593
 
594
        foreach($this->clientBuiltIns as $name => $value) {
595
            $normalizedName = explode('::', $name);
596
            $normalizedName = $normalizedName[count($normalizedName) - 1];
597
            $normalizedBuiltIns[$normalizedName] = $value;
598
        }
599
 
600
        return array_merge($normalizedBuiltIns, $this->getClientContextParams());
601
    }
602
 
603
    protected function isUseEndpointV2()
604
    {
605
        return $this->endpointProvider instanceof EndpointProviderV2;
606
    }
607
 
608
    public static function emitDeprecationWarning() {
609
        $phpVersion = PHP_VERSION_ID;
610
        if ($phpVersion <  70205) {
611
            $phpVersionString = phpversion();
612
            @trigger_error(
613
                "This installation of the SDK is using PHP version"
614
                .  " {$phpVersionString}, which will be deprecated on August"
615
                .  " 15th, 2023.  Please upgrade your PHP version to a minimum of"
616
                .  " 7.2.5 before then to continue receiving updates to the AWS"
617
                .  " SDK for PHP.  To disable this warning, set"
618
                .  " suppress_php_deprecation_warning to true on the client constructor"
619
                .  " or set the environment variable AWS_SUPPRESS_PHP_DEPRECATION_WARNING"
620
                .  " to true.",
621
                E_USER_DEPRECATED
622
            );
623
        }
624
    }
625
 
626
 
627
    /**
628
     * Returns a service model and doc model with any necessary changes
629
     * applied.
630
     *
631
     * @param array $api  Array of service data being documented.
632
     * @param array $docs Array of doc model data.
633
     *
634
     * @return array Tuple containing a [Service, DocModel]
635
     *
636
     * @internal This should only used to document the service API.
637
     * @codeCoverageIgnore
638
     */
639
    public static function applyDocFilters(array $api, array $docs)
640
    {
641
        $aliases = \Aws\load_compiled_json(__DIR__ . '/data/aliases.json');
642
        $serviceId = $api['metadata']['serviceId'];
643
        $version = $api['metadata']['apiVersion'];
644
 
645
        // Replace names for any operations with SDK aliases
646
        if (!empty($aliases['operations'][$serviceId][$version])) {
647
            foreach ($aliases['operations'][$serviceId][$version] as $op => $alias) {
648
                $api['operations'][$alias] = $api['operations'][$op];
649
                $docs['operations'][$alias] = $docs['operations'][$op];
650
                unset($api['operations'][$op], $docs['operations'][$op]);
651
            }
652
        }
653
        ksort($api['operations']);
654
 
655
        return [
656
            new Service($api, ApiProvider::defaultProvider()),
657
            new DocModel($docs)
658
        ];
659
    }
660
 
661
    /**
662
     * @deprecated
663
     * @return static
664
     */
665
    public static function factory(array $config = [])
666
    {
667
        return new static($config);
668
    }
669
}