Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\Api;
3
 
4
/**
5
 * Represents a web service API model.
6
 */
7
class Service extends AbstractModel
8
{
9
    /** @var callable */
10
    private $apiProvider;
11
 
12
    /** @var string */
13
    private $serviceName;
14
 
15
    /** @var string */
16
    private $apiVersion;
17
 
18
    /** @var array */
19
    private $clientContextParams = [];
20
 
21
    /** @var Operation[] */
22
    private $operations = [];
23
 
24
    /** @var array */
25
    private $paginators = null;
26
 
27
    /** @var array */
28
    private $waiters = null;
29
 
30
    /** @var boolean */
31
    private $modifiedModel = false;
32
 
1441 ariadna 33
    /** @var string */
34
    private $protocol;
35
 
1 efrain 36
    /**
37
     * @param array    $definition
38
     * @param callable $provider
39
     *
40
     * @internal param array $definition Service description
41
     */
42
    public function __construct(array $definition, callable $provider)
43
    {
44
        static $defaults = [
45
            'operations' => [],
46
            'shapes'     => [],
47
            'metadata'   => [],
48
            'clientContextParams' => []
49
        ], $defaultMeta = [
50
            'apiVersion'       => null,
51
            'serviceFullName'  => null,
52
            'serviceId'        => null,
53
            'endpointPrefix'   => null,
54
            'signingName'      => null,
55
            'signatureVersion' => null,
56
            'protocol'         => null,
57
            'uid'              => null
58
        ];
59
 
60
        $definition += $defaults;
61
        $definition['metadata'] += $defaultMeta;
62
        $this->definition = $definition;
63
        $this->apiProvider = $provider;
64
        parent::__construct($definition, new ShapeMap($definition['shapes']));
65
 
66
        if (isset($definition['metadata']['serviceIdentifier'])) {
67
            $this->serviceName = $this->getServiceName();
68
        } else {
69
            $this->serviceName = $this->getEndpointPrefix();
70
        }
71
        $this->apiVersion = $this->getApiVersion();
72
        if (isset($definition['clientContextParams'])) {
73
           $this->clientContextParams = $definition['clientContextParams'];
74
        }
1441 ariadna 75
 
76
        $this->protocol = $this->selectProtocol($definition);
1 efrain 77
    }
78
 
79
    /**
80
     * Creates a request serializer for the provided API object.
81
     *
82
     * @param Service $api      API that contains a protocol.
83
     * @param string  $endpoint Endpoint to send requests to.
84
     *
85
     * @return callable
86
     * @throws \UnexpectedValueException
87
     */
88
    public static function createSerializer(Service $api, $endpoint)
89
    {
90
        static $mapping = [
91
            'json'      => Serializer\JsonRpcSerializer::class,
92
            'query'     => Serializer\QuerySerializer::class,
93
            'rest-json' => Serializer\RestJsonSerializer::class,
94
            'rest-xml'  => Serializer\RestXmlSerializer::class
95
        ];
96
 
97
        $proto = $api->getProtocol();
98
 
99
        if (isset($mapping[$proto])) {
100
            return new $mapping[$proto]($api, $endpoint);
101
        }
102
 
103
        if ($proto == 'ec2') {
104
            return new Serializer\QuerySerializer($api, $endpoint, new Serializer\Ec2ParamBuilder());
105
        }
106
 
107
        throw new \UnexpectedValueException(
108
            'Unknown protocol: ' . $api->getProtocol()
109
        );
110
    }
111
 
112
    /**
113
     * Creates an error parser for the given protocol.
114
     *
115
     * Redundant method signature to preserve backwards compatibility.
116
     *
117
     * @param string $protocol Protocol to parse (e.g., query, json, etc.)
118
     *
119
     * @return callable
120
     * @throws \UnexpectedValueException
121
     */
1441 ariadna 122
    public static function createErrorParser($protocol, ?Service $api = null)
1 efrain 123
    {
124
        static $mapping = [
125
            'json'      => ErrorParser\JsonRpcErrorParser::class,
126
            'query'     => ErrorParser\XmlErrorParser::class,
127
            'rest-json' => ErrorParser\RestJsonErrorParser::class,
128
            'rest-xml'  => ErrorParser\XmlErrorParser::class,
129
            'ec2'       => ErrorParser\XmlErrorParser::class
130
        ];
131
 
132
        if (isset($mapping[$protocol])) {
133
            return new $mapping[$protocol]($api);
134
        }
135
 
136
        throw new \UnexpectedValueException("Unknown protocol: $protocol");
137
    }
138
 
139
    /**
140
     * Applies the listeners needed to parse client models.
141
     *
142
     * @param Service $api API to create a parser for
143
     * @return callable
144
     * @throws \UnexpectedValueException
145
     */
146
    public static function createParser(Service $api)
147
    {
148
        static $mapping = [
149
            'json'      => Parser\JsonRpcParser::class,
150
            'query'     => Parser\QueryParser::class,
151
            'rest-json' => Parser\RestJsonParser::class,
152
            'rest-xml'  => Parser\RestXmlParser::class
153
        ];
154
 
155
        $proto = $api->getProtocol();
156
        if (isset($mapping[$proto])) {
157
            return new $mapping[$proto]($api);
158
        }
159
 
160
        if ($proto == 'ec2') {
161
            return new Parser\QueryParser($api, null, false);
162
        }
163
 
164
        throw new \UnexpectedValueException(
165
            'Unknown protocol: ' . $api->getProtocol()
166
        );
167
    }
168
 
169
    /**
170
     * Get the full name of the service
171
     *
172
     * @return string
173
     */
174
    public function getServiceFullName()
175
    {
176
        return $this->definition['metadata']['serviceFullName'];
177
    }
178
 
179
    /**
180
     * Get the service id
181
     *
182
     * @return string
183
     */
184
    public function getServiceId()
185
    {
186
        return $this->definition['metadata']['serviceId'];
187
    }
188
 
189
    /**
190
     * Get the API version of the service
191
     *
192
     * @return string
193
     */
194
    public function getApiVersion()
195
    {
196
        return $this->definition['metadata']['apiVersion'];
197
    }
198
 
199
    /**
200
     * Get the API version of the service
201
     *
202
     * @return string
203
     */
204
    public function getEndpointPrefix()
205
    {
206
        return $this->definition['metadata']['endpointPrefix'];
207
    }
208
 
209
    /**
210
     * Get the signing name used by the service.
211
     *
212
     * @return string
213
     */
214
    public function getSigningName()
215
    {
216
        return $this->definition['metadata']['signingName']
217
            ?: $this->definition['metadata']['endpointPrefix'];
218
    }
219
 
220
    /**
221
     * Get the service name.
222
     *
223
     * @return string
224
     */
225
    public function getServiceName()
226
    {
1441 ariadna 227
        return $this->definition['metadata']['serviceIdentifier'] ?? null;
1 efrain 228
    }
229
 
230
    /**
231
     * Get the default signature version of the service.
232
     *
233
     * Note: this method assumes "v4" when not specified in the model.
234
     *
235
     * @return string
236
     */
237
    public function getSignatureVersion()
238
    {
239
        return $this->definition['metadata']['signatureVersion'] ?: 'v4';
240
    }
241
 
242
    /**
243
     * Get the protocol used by the service.
244
     *
245
     * @return string
246
     */
247
    public function getProtocol()
248
    {
1441 ariadna 249
        return $this->protocol;
1 efrain 250
    }
251
 
252
    /**
253
     * Get the uid string used by the service
254
     *
255
     * @return string
256
     */
257
    public function getUid()
258
    {
259
        return $this->definition['metadata']['uid'];
260
    }
261
 
262
    /**
263
     * Check if the description has a specific operation by name.
264
     *
265
     * @param string $name Operation to check by name
266
     *
267
     * @return bool
268
     */
269
    public function hasOperation($name)
270
    {
271
        return isset($this['operations'][$name]);
272
    }
273
 
274
    /**
275
     * Get an operation by name.
276
     *
277
     * @param string $name Operation to retrieve by name
278
     *
279
     * @return Operation
280
     * @throws \InvalidArgumentException If the operation is not found
281
     */
282
    public function getOperation($name)
283
    {
284
        if (!isset($this->operations[$name])) {
285
            if (!isset($this->definition['operations'][$name])) {
286
                throw new \InvalidArgumentException("Unknown operation: $name");
287
            }
288
            $this->operations[$name] = new Operation(
289
                $this->definition['operations'][$name],
290
                $this->shapeMap
291
            );
1441 ariadna 292
        } elseif ($this->modifiedModel) {
1 efrain 293
            $this->operations[$name] = new Operation(
294
                $this->definition['operations'][$name],
295
                $this->shapeMap
296
            );
297
        }
298
 
299
        return $this->operations[$name];
300
    }
301
 
302
    /**
303
     * Get all of the operations of the description.
304
     *
305
     * @return Operation[]
306
     */
307
    public function getOperations()
308
    {
309
        $result = [];
310
        foreach ($this->definition['operations'] as $name => $definition) {
311
            $result[$name] = $this->getOperation($name);
312
        }
313
 
314
        return $result;
315
    }
316
 
317
    /**
318
     * Get all of the error shapes of the service
319
     *
320
     * @return array
321
     */
322
    public function getErrorShapes()
323
    {
324
        $result = [];
325
        foreach ($this->definition['shapes'] as $name => $definition) {
326
            if (!empty($definition['exception'])) {
327
                $definition['name'] = $name;
328
                $result[] = new StructureShape($definition, $this->getShapeMap());
329
            }
330
        }
331
 
332
        return $result;
333
    }
334
 
335
    /**
336
     * Get all of the service metadata or a specific metadata key value.
337
     *
338
     * @param string|null $key Key to retrieve or null to retrieve all metadata
339
     *
340
     * @return mixed Returns the result or null if the key is not found
341
     */
342
    public function getMetadata($key = null)
343
    {
344
        if (!$key) {
345
            return $this['metadata'];
346
        }
347
 
348
        if (isset($this->definition['metadata'][$key])) {
349
            return $this->definition['metadata'][$key];
350
        }
351
 
352
        return null;
353
    }
354
 
355
    /**
356
     * Gets an associative array of available paginator configurations where
357
     * the key is the name of the paginator, and the value is the paginator
358
     * configuration.
359
     *
360
     * @return array
361
     * @unstable The configuration format of paginators may change in the future
362
     */
363
    public function getPaginators()
364
    {
365
        if (!isset($this->paginators)) {
366
            $res = call_user_func(
367
                $this->apiProvider,
368
                'paginator',
369
                $this->serviceName,
370
                $this->apiVersion
371
            );
372
            $this->paginators = isset($res['pagination'])
373
                ? $res['pagination']
374
                : [];
375
        }
376
 
377
        return $this->paginators;
378
    }
379
 
380
    /**
381
     * Determines if the service has a paginator by name.
382
     *
383
     * @param string $name Name of the paginator.
384
     *
385
     * @return bool
386
     */
387
    public function hasPaginator($name)
388
    {
389
        return isset($this->getPaginators()[$name]);
390
    }
391
 
392
    /**
393
     * Retrieve a paginator by name.
394
     *
395
     * @param string $name Paginator to retrieve by name. This argument is
396
     *                     typically the operation name.
397
     * @return array
398
     * @throws \UnexpectedValueException if the paginator does not exist.
399
     * @unstable The configuration format of paginators may change in the future
400
     */
401
    public function getPaginatorConfig($name)
402
    {
403
        static $defaults = [
404
            'input_token'  => null,
405
            'output_token' => null,
406
            'limit_key'    => null,
407
            'result_key'   => null,
408
            'more_results' => null,
409
        ];
410
 
411
        if ($this->hasPaginator($name)) {
412
            return $this->paginators[$name] + $defaults;
413
        }
414
 
415
        throw new \UnexpectedValueException("There is no {$name} "
416
            . "paginator defined for the {$this->serviceName} service.");
417
    }
418
 
419
    /**
420
     * Gets an associative array of available waiter configurations where the
421
     * key is the name of the waiter, and the value is the waiter
422
     * configuration.
423
     *
424
     * @return array
425
     */
426
    public function getWaiters()
427
    {
428
        if (!isset($this->waiters)) {
429
            $res = call_user_func(
430
                $this->apiProvider,
431
                'waiter',
432
                $this->serviceName,
433
                $this->apiVersion
434
            );
435
            $this->waiters = isset($res['waiters'])
436
                ? $res['waiters']
437
                : [];
438
        }
439
 
440
        return $this->waiters;
441
    }
442
 
443
    /**
444
     * Determines if the service has a waiter by name.
445
     *
446
     * @param string $name Name of the waiter.
447
     *
448
     * @return bool
449
     */
450
    public function hasWaiter($name)
451
    {
452
        return isset($this->getWaiters()[$name]);
453
    }
454
 
455
    /**
456
     * Get a waiter configuration by name.
457
     *
458
     * @param string $name Name of the waiter by name.
459
     *
460
     * @return array
461
     * @throws \UnexpectedValueException if the waiter does not exist.
462
     */
463
    public function getWaiterConfig($name)
464
    {
465
        // Error if the waiter is not defined
466
        if ($this->hasWaiter($name)) {
467
            return $this->waiters[$name];
468
        }
469
 
470
        throw new \UnexpectedValueException("There is no {$name} waiter "
471
            . "defined for the {$this->serviceName} service.");
472
    }
473
 
474
    /**
475
     * Get the shape map used by the API.
476
     *
477
     * @return ShapeMap
478
     */
479
    public function getShapeMap()
480
    {
481
        return $this->shapeMap;
482
    }
483
 
484
    /**
485
     * Get all the context params of the description.
486
     *
487
     * @return array
488
     */
489
    public function getClientContextParams()
490
    {
491
        return $this->clientContextParams;
492
    }
493
 
494
    /**
495
     * Get the service's api provider.
496
     *
497
     * @return callable
498
     */
499
    public function getProvider()
500
    {
501
        return $this->apiProvider;
502
    }
503
 
504
    /**
505
     * Get the service's definition.
506
     *
507
     * @return callable
508
     */
509
    public function getDefinition()
510
    {
511
        return $this->definition;
512
    }
513
 
514
    /**
515
     * Sets the service's api definition.
516
     * Intended for internal use only.
517
     *
518
     * @return void
519
     *
520
     * @internal
521
     */
522
    public function setDefinition($definition)
523
    {
524
        $this->definition = $definition;
1441 ariadna 525
        $this->shapeMap = new ShapeMap($definition['shapes']);
1 efrain 526
        $this->modifiedModel = true;
527
    }
528
 
529
    /**
530
     * Denotes whether or not a service's definition has
531
     * been modified.  Intended for internal use only.
532
     *
533
     * @return bool
534
     *
535
     * @internal
536
     */
537
    public function isModifiedModel()
538
    {
539
        return $this->modifiedModel;
540
    }
1441 ariadna 541
 
542
    /**
543
     * Accepts a list of protocols derived from the service model.
544
     * Returns the highest priority compatible auth scheme if the `protocols` trait is present.
545
     * Otherwise, returns the value of the `protocol` field, if set, or null.
546
     *
547
     * @param array $definition
548
     *
549
     * @return string|null
550
     */
551
    private function selectProtocol(array $definition): string | null
552
    {
553
        $modeledProtocols = $definition['metadata']['protocols'] ?? null;
554
        if (!empty($modeledProtocols)) {
555
            foreach(SupportedProtocols::cases() as $protocol) {
556
                if (in_array($protocol->value, $modeledProtocols)) {
557
                    return $protocol->value;
558
                }
559
            }
560
        }
561
 
562
        return $definition['metadata']['protocol'] ?? null;
563
    }
1 efrain 564
}