Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
namespace Aws;
3
 
4
use Aws\Api\ListShape;
5
use Aws\Api\MapShape;
6
use Aws\Api\Service;
7
use Aws\Api\Shape;
8
use Aws\Api\StructureShape;
9
use Closure;
10
 
11
/**
12
 * Inspects command input values and casts them to their modeled type.
13
 * This covers query compatible services which have migrated from query
14
 * to JSON wire protocols.
15
 *
16
 * @internal
17
 */
18
class QueryCompatibleInputMiddleware
19
{
20
 
21
    /** @var callable */
22
    private $nextHandler;
23
 
24
    /** @var Service */
25
    private $service;
26
 
27
    /** @var CommandInterface */
28
    private $command;
29
 
30
    /**
31
     * Create a middleware wrapper function.
32
     *
33
     * @param Service $service
34
     * @return Closure
35
     */
36
    public static function wrap(Service $service) : Closure
37
    {
38
        return static function (callable $handler) use ($service) {
39
            return new self($handler, $service);
40
        };
41
    }
42
 
43
    public function __construct(callable $nextHandler, Service $service)
44
    {
45
        $this->service = $service;
46
        $this->nextHandler = $nextHandler;
47
    }
48
 
49
    public function __invoke(CommandInterface $cmd)
50
    {
51
        $this->command = $cmd;
52
        $nextHandler = $this->nextHandler;
53
        $op = $this->service->getOperation($cmd->getName());
54
        $inputMembers = $op->getInput()->getMembers();
55
        $input = $cmd->toArray();
56
 
57
        foreach ($input as $param => $value) {
58
            if (isset($inputMembers[$param])) {
59
                $shape = $inputMembers[$param];
60
                $this->processInput($value, $shape, [$param]);
61
            }
62
        }
63
 
64
        return $nextHandler($this->command);
65
    }
66
 
67
    /**
68
     * Recurses a given input shape. if a given scalar input does not match its
69
     * modeled type, it is cast to its modeled type.
70
     *
71
     * @param $input
72
     * @param $shape
73
     * @param array $path
74
     *
75
     * @return void
76
     */
77
    private function processInput($input, $shape, array $path) : void
78
    {
79
        switch ($shape->getType()) {
80
            case 'structure':
81
                $this->processStructure($input, $shape, $path);
82
                break;
83
            case 'list':
84
                $this->processList($input, $shape, $path);
85
                break;
86
            case 'map':
87
                $this->processMap($input, $shape, $path);
88
                break;
89
            default:
90
                $this->processScalar($input, $shape, $path);
91
        }
92
    }
93
 
94
    /**
95
     * @param array $input
96
     * @param StructureShape $shape
97
     * @param array $path
98
     *
99
     * @return void
100
     */
101
    private function processStructure(
102
        array $input,
103
        StructureShape $shape,
104
        array $path
105
    ) : void
106
    {
107
        foreach ($input as $param => $value) {
108
            if ($shape->hasMember($param)) {
109
                $memberPath = array_merge($path, [$param]);
110
                $this->processInput($value, $shape->getMember($param), $memberPath);
111
            }
112
        }
113
    }
114
 
115
    /**
116
     * @param array $input
117
     * @param ListShape $shape
118
     * @param array $path
119
     *
120
     * @return void
121
     */
122
    private function processList(
123
        array $input,
124
        ListShape $shape,
125
        array $path
126
    ) : void
127
    {
128
        foreach ($input as $param => $value) {
129
            $memberPath = array_merge($path, [$param]);
130
            $this->processInput($value, $shape->getMember(), $memberPath);
131
        }
132
    }
133
 
134
    /**
135
     * @param array $input
136
     * @param MapShape $shape
137
     * @param array $path
138
     *
139
     * @return void
140
     */
141
    private function processMap(array $input, MapShape $shape, array $path) : void
142
    {
143
        foreach ($input as $param => $value) {
144
            $memberPath = array_merge($path, [$param]);
145
            $this->processInput($value, $shape->getValue(), $memberPath);
146
        }
147
    }
148
 
149
    /**
150
     * @param $input
151
     * @param Shape $shape
152
     * @param array $path
153
     *
154
     * @return void
155
     */
156
    private function processScalar($input, Shape $shape, array $path) : void
157
    {
158
        $expectedType = $shape->getType();
159
 
160
        if (!$this->isModeledType($input, $expectedType)) {
161
            trigger_error(
162
                "The provided type for `". implode(' -> ', $path) ."` value was `"
163
                . (gettype($input) ===  'double' ? 'float' : gettype($input)) . "`."
164
                . " The modeled type is `{$expectedType}`.",
165
                E_USER_WARNING
166
            );
167
            $value = $this->castValue($input, $expectedType);
168
            $this->changeValueAtPath($path, $value);
169
        }
170
    }
171
 
172
    /**
173
     * Modifies command in place
174
     *
175
     * @param array $path
176
     * @param $newValue
177
     *
178
     * @return void
179
     */
180
    private function changeValueAtPath(array $path, $newValue) : void
181
    {
182
        $commandRef = &$this->command;
183
 
184
        foreach ($path as $segment) {
185
            if (!isset($commandRef[$segment])) {
186
                return;
187
            }
188
            $commandRef = &$commandRef[$segment];
189
        }
190
        $commandRef = $newValue;
191
    }
192
 
193
    /**
194
     * @param $value
195
     * @param $type
196
     *
197
     * @return bool
198
     */
199
    private function isModeledType($value, $type) : bool
200
    {
201
        switch ($type) {
202
            case 'string':
203
                return is_string($value);
204
            case 'integer':
205
            case 'long':
206
                return is_int($value);
207
            case 'float':
208
                return is_float($value);
209
            default:
210
                return true;
211
        }
212
    }
213
 
214
    /**
215
     * @param $value
216
     * @param $type
217
     *
218
     * @return float|int|mixed|string
219
     */
220
    private function castValue($value, $type)
221
    {
222
        switch ($type) {
223
            case 'integer':
224
                return (int) $value;
225
            case 'long' :
226
                return $value + 0;
227
            case 'float':
228
                return (float) $value;
229
            case 'string':
230
                return (string) $value;
231
            default:
232
                return $value;
233
        }
234
    }
235
}