PluginProbe
Media Cloud Sync / 1.4.1
Media Cloud Sync v1.4.1
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / Aws / Api / Parser / AbstractRestParser.php

AbstractRestParser.php in Media Cloud Sync 1.4.1, at includes/sdk/s3/Aws/Api/Parser/AbstractRestParser.php

164 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\Api\Parser;
4
5 use Dudlewebs\WPMCS\s3\Aws\Api\DateTimeResult;
6 use Dudlewebs\WPMCS\s3\Aws\Api\Shape;
7 use Dudlewebs\WPMCS\s3\Aws\Api\StructureShape;
8 use Dudlewebs\WPMCS\s3\Aws\Result;
9 use Dudlewebs\WPMCS\s3\Aws\CommandInterface;
10 use Dudlewebs\WPMCS\s3\Psr\Http\Message\ResponseInterface;
11 /**
12 * @internal
13 */
14 abstract class AbstractRestParser extends AbstractParser
15 {
16 use PayloadParserTrait;
17 /**
18 * Parses a payload from a response.
19 *
20 * @param ResponseInterface $response Response to parse.
21 * @param StructureShape $member Member to parse
22 * @param array $result Result value
23 *
24 * @return mixed
25 */
26 protected abstract function payload(ResponseInterface $response, StructureShape $member, array &$result);
27 public function __invoke(CommandInterface $command, ResponseInterface $response)
28 {
29 $output = $this->api->getOperation($command->getName())->getOutput();
30 $result = [];
31 if ($payload = $output['payload']) {
32 $this->extractPayload($payload, $output, $response, $result);
33 }
34 foreach ($output->getMembers() as $name => $member) {
35 switch ($member['location']) {
36 case 'header':
37 $this->extractHeader($name, $member, $response, $result);
38 break;
39 case 'headers':
40 $this->extractHeaders($name, $member, $response, $result);
41 break;
42 case 'statusCode':
43 $this->extractStatus($name, $response, $result);
44 break;
45 }
46 }
47 $body = $response->getBody();
48 if (!$payload && (!$body->isSeekable() || $body->getSize()) && \count($output->getMembers()) > 0) {
49 // if no payload was found, then parse the contents of the body
50 $this->payload($response, $output, $result);
51 }
52 return new Result($result);
53 }
54 private function extractPayload($payload, StructureShape $output, ResponseInterface $response, array &$result)
55 {
56 $member = $output->getMember($payload);
57 $body = $response->getBody();
58 if (!empty($member['eventstream'])) {
59 $result[$payload] = new EventParsingIterator($body, $member, $this);
60 } elseif ($member instanceof StructureShape) {
61 //Unions must have at least one member set to a non-null value
62 // If the body is empty, we can assume it is unset
63 if (!empty($member['union']) && ($body->isSeekable() && !$body->getSize())) {
64 return;
65 }
66 $result[$payload] = [];
67 $this->payload($response, $member, $result[$payload]);
68 } else {
69 // Always set the payload to the body stream, regardless of content
70 $result[$payload] = $body;
71 }
72 }
73 /**
74 * Extract a single header from the response into the result.
75 */
76 private function extractHeader($name, Shape $shape, ResponseInterface $response, &$result)
77 {
78 $value = $response->getHeaderLine($shape['locationName'] ?: $name);
79 // Empty headers should not be deserialized
80 if ($value === null || $value === '') {
81 return;
82 }
83 switch ($shape->getType()) {
84 case 'float':
85 case 'double':
86 $value = match ($value) {
87 'NaN', 'Infinity', '-Infinity' => $value,
88 default => (float) $value,
89 };
90 break;
91 case 'long':
92 case 'integer':
93 $value = (int) $value;
94 break;
95 case 'boolean':
96 $value = \filter_var($value, \FILTER_VALIDATE_BOOLEAN);
97 break;
98 case 'blob':
99 $value = \base64_decode($value);
100 break;
101 case 'timestamp':
102 try {
103 $value = DateTimeResult::fromTimestamp($value, !empty($shape['timestampFormat']) ? $shape['timestampFormat'] : null);
104 break;
105 } catch (\Exception $e) {
106 // If the value cannot be parsed, then do not add it to the
107 // output structure.
108 return;
109 }
110 case 'string':
111 try {
112 if ($shape['jsonvalue']) {
113 $value = $this->parseJson(\base64_decode($value), $response);
114 }
115 // If value is not set, do not add to output structure.
116 if (!isset($value)) {
117 return;
118 }
119 break;
120 } catch (\Exception $e) {
121 //If the value cannot be parsed, then do not add it to the
122 //output structure.
123 return;
124 }
125 case 'list':
126 $listMember = $shape->getMember();
127 $type = $listMember->getType();
128 // Only boolean lists require special handling
129 // other types can be returned as-is
130 if ($type !== 'boolean') {
131 break;
132 }
133 $items = \array_map('trim', \explode(',', $value));
134 $value = \array_map(static fn($item) => \filter_var($item, \FILTER_VALIDATE_BOOLEAN), $items);
135 break;
136 }
137 $result[$name] = $value;
138 }
139 /**
140 * Extract a map of headers with an optional prefix from the response.
141 */
142 private function extractHeaders($name, Shape $shape, ResponseInterface $response, &$result)
143 {
144 // Check if the headers are prefixed by a location name
145 $result[$name] = [];
146 $prefix = $shape['locationName'];
147 $prefixLen = $prefix !== null ? \strlen($prefix) : 0;
148 foreach ($response->getHeaders() as $k => $values) {
149 if (!$prefixLen) {
150 $result[$name][$k] = \implode(', ', $values);
151 } elseif (\stripos($k, $prefix) === 0) {
152 $result[$name][\substr($k, $prefixLen)] = \implode(', ', $values);
153 }
154 }
155 }
156 /**
157 * Places the status code of the response into the result array.
158 */
159 private function extractStatus($name, ResponseInterface $response, array &$result)
160 {
161 $result[$name] = (int) $response->getStatusCode();
162 }
163 }
164