This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php declare(strict_types=1); |
||
2 | |||
3 | namespace Neomerx\JsonApi\Parser; |
||
4 | |||
5 | /** |
||
6 | * Copyright 2015-2020 [email protected] |
||
7 | * |
||
8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
9 | * you may not use this file except in compliance with the License. |
||
10 | * You may obtain a copy of the License at |
||
11 | * |
||
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
13 | * |
||
14 | * Unless required by applicable law or agreed to in writing, software |
||
15 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
17 | * See the License for the specific language governing permissions and |
||
18 | * limitations under the License. |
||
19 | */ |
||
20 | |||
21 | use Neomerx\JsonApi\Contracts\Factories\FactoryInterface; |
||
22 | use Neomerx\JsonApi\Contracts\Parser\EditableContextInterface; |
||
23 | use Neomerx\JsonApi\Contracts\Parser\ParserInterface; |
||
24 | use Neomerx\JsonApi\Contracts\Parser\ResourceInterface; |
||
25 | use Neomerx\JsonApi\Contracts\Schema\LinkInterface; |
||
26 | use Neomerx\JsonApi\Contracts\Schema\PositionInterface; |
||
27 | use Neomerx\JsonApi\Contracts\Schema\SchemaContainerInterface; |
||
28 | use Neomerx\JsonApi\Contracts\Schema\SchemaInterface; |
||
29 | use Neomerx\JsonApi\Parser\RelationshipData\ParseRelationshipDataTrait; |
||
30 | use Neomerx\JsonApi\Parser\RelationshipData\ParseRelationshipLinksTrait; |
||
31 | |||
32 | /** |
||
33 | * @package Neomerx\JsonApi |
||
34 | */ |
||
35 | class IdentifierAndResource implements ResourceInterface |
||
36 | { |
||
37 | use ParseRelationshipDataTrait, ParseRelationshipLinksTrait; |
||
38 | |||
39 | /** @var string */ |
||
40 | public const MSG_NO_SCHEMA_FOUND = 'No Schema found for resource `%s` at path `%s`.'; |
||
41 | |||
42 | /** @var string */ |
||
43 | public const MSG_INVALID_OPERATION = 'Invalid operation.'; |
||
44 | |||
45 | /** |
||
46 | * @var EditableContextInterface |
||
47 | */ |
||
48 | private $context; |
||
49 | |||
50 | /** |
||
51 | * @var PositionInterface |
||
52 | */ |
||
53 | private $position; |
||
54 | |||
55 | /** |
||
56 | * @var FactoryInterface |
||
57 | */ |
||
58 | private $factory; |
||
59 | |||
60 | /** |
||
61 | * @var SchemaContainerInterface |
||
62 | */ |
||
63 | private $schemaContainer; |
||
64 | |||
65 | /** |
||
66 | * @var SchemaInterface |
||
67 | */ |
||
68 | private $schema; |
||
69 | |||
70 | /** |
||
71 | * @var mixed |
||
72 | */ |
||
73 | private $data; |
||
74 | |||
75 | /** |
||
76 | * @var string |
||
77 | */ |
||
78 | private $index; |
||
79 | |||
80 | /** |
||
81 | * @var string |
||
82 | */ |
||
83 | private $type; |
||
84 | |||
85 | /** |
||
86 | * @var null|array |
||
87 | */ |
||
88 | private $links = null; |
||
89 | |||
90 | /** |
||
91 | * @var null|array |
||
92 | */ |
||
93 | private $relationshipsCache = null; |
||
94 | |||
95 | /** |
||
96 | * @param EditableContextInterface $context |
||
97 | * @param PositionInterface $position |
||
98 | * @param FactoryInterface $factory |
||
99 | * @param SchemaContainerInterface $container |
||
100 | * @param mixed $data |
||
101 | */ |
||
102 | 65 | public function __construct( |
|
103 | EditableContextInterface $context, |
||
104 | PositionInterface $position, |
||
105 | FactoryInterface $factory, |
||
106 | SchemaContainerInterface $container, |
||
107 | $data |
||
108 | ) { |
||
109 | 65 | \assert($position->getLevel() >= ParserInterface::ROOT_LEVEL); |
|
110 | |||
111 | 65 | $schema = $container->getSchema($data); |
|
112 | |||
113 | 65 | $this->context = $context; |
|
114 | 65 | $this->position = $position; |
|
115 | 65 | $this->factory = $factory; |
|
116 | 65 | $this->schemaContainer = $container; |
|
117 | 65 | $this->schema = $schema; |
|
118 | 65 | $this->data = $data; |
|
119 | 65 | $this->index = $schema->getId($data); |
|
120 | 65 | $this->type = $schema->getType(); |
|
121 | 65 | } |
|
122 | |||
123 | /** |
||
124 | * @inheritdoc |
||
125 | */ |
||
126 | 65 | public function getPosition(): PositionInterface |
|
127 | { |
||
128 | 65 | return $this->position; |
|
129 | } |
||
130 | |||
131 | /** |
||
132 | * @inheritdoc |
||
133 | */ |
||
134 | 65 | public function getId(): ?string |
|
135 | { |
||
136 | 65 | return $this->index; |
|
137 | } |
||
138 | |||
139 | /** |
||
140 | * @inheritdoc |
||
141 | */ |
||
142 | 65 | public function getType(): string |
|
143 | { |
||
144 | 65 | return $this->type; |
|
145 | } |
||
146 | |||
147 | /** |
||
148 | * @inheritdoc |
||
149 | */ |
||
150 | 35 | public function hasIdentifierMeta(): bool |
|
151 | { |
||
152 | 35 | return $this->schema->hasIdentifierMeta($this->data); |
|
153 | } |
||
154 | |||
155 | /** |
||
156 | * @inheritdoc |
||
157 | */ |
||
158 | 2 | public function getIdentifierMeta() |
|
159 | { |
||
160 | 2 | return $this->schema->getIdentifierMeta($this->data); |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * @inheritdoc |
||
165 | */ |
||
166 | 62 | public function getAttributes(): iterable |
|
167 | { |
||
168 | 62 | $this->getContext()->setPosition($this->getPosition()); |
|
169 | |||
170 | 62 | return $this->schema->getAttributes($this->data, $this->getContext()); |
|
171 | } |
||
172 | |||
173 | /** |
||
174 | * @inheritdoc |
||
175 | * |
||
176 | * @SuppressWarnings(PHPMD.UndefinedVariable) PHPMD currently do not support `list` in `[]` syntax |
||
177 | */ |
||
178 | 64 | public function getRelationships(): iterable |
|
179 | { |
||
180 | 64 | if ($this->relationshipsCache !== null) { |
|
181 | 61 | yield from $this->relationshipsCache; |
|
182 | |||
183 | 60 | return; |
|
184 | } |
||
185 | |||
186 | 64 | $this->relationshipsCache = []; |
|
187 | |||
188 | 64 | $currentPath = $this->position->getPath(); |
|
189 | 64 | $nextLevel = $this->position->getLevel() + 1; |
|
190 | 64 | $nextPathPrefix = empty($currentPath) === true ? '' : $currentPath . PositionInterface::PATH_SEPARATOR; |
|
191 | 64 | $this->getContext()->setPosition($this->getPosition()); |
|
192 | 64 | foreach ($this->schema->getRelationships($this->data, $this->getContext()) as $name => $description) { |
|
193 | 49 | \assert($this->assertRelationshipNameAndDescription($name, $description) === true); |
|
194 | |||
195 | 49 | [$hasData, $relationshipData, $nextPosition] = $this->parseRelationshipData( |
|
0 ignored issues
–
show
The variable
$relationshipData does not exist. Did you forget to declare it?
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.
Loading history...
The variable
$nextPosition does not exist. Did you forget to declare it?
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.
Loading history...
|
|||
196 | 49 | $this->factory, |
|
197 | 49 | $this->schemaContainer, |
|
198 | 49 | $this->getContext(), |
|
199 | 49 | $this->type, |
|
200 | 49 | $name, |
|
201 | 49 | $description, |
|
202 | 49 | $nextLevel, |
|
203 | 49 | $nextPathPrefix |
|
204 | ); |
||
205 | |||
206 | [$hasLinks, $links] = |
||
0 ignored issues
–
show
|
|||
207 | 49 | $this->parseRelationshipLinks($this->schema, $this->data, $name, $description); |
|
208 | |||
209 | 49 | $hasMeta = \array_key_exists(SchemaInterface::RELATIONSHIP_META, $description); |
|
210 | 49 | $meta = $hasMeta === true ? $description[SchemaInterface::RELATIONSHIP_META] : null; |
|
211 | |||
212 | 49 | \assert( |
|
213 | 49 | $hasData || $hasMeta || $hasLinks, |
|
214 | 49 | "Relationship `$name` for type `" . $this->getType() . |
|
215 | 49 | '` MUST contain at least one of the following: links, data or meta.' |
|
216 | ); |
||
217 | |||
218 | 49 | $relationship = $this->factory->createRelationship( |
|
219 | 49 | $nextPosition, |
|
220 | 49 | $hasData, |
|
221 | 49 | $relationshipData, |
|
222 | 49 | $hasLinks, |
|
223 | 49 | $links, |
|
224 | 49 | $hasMeta, |
|
225 | 49 | $meta |
|
226 | ); |
||
227 | |||
228 | 49 | $this->relationshipsCache[$name] = $relationship; |
|
229 | |||
230 | 49 | yield $name => $relationship; |
|
231 | } |
||
232 | 64 | } |
|
233 | |||
234 | /** |
||
235 | * @inheritdoc |
||
236 | */ |
||
237 | 62 | public function hasLinks(): bool |
|
238 | { |
||
239 | 62 | $this->cacheLinks(); |
|
240 | |||
241 | 62 | return empty($this->links) === false; |
|
242 | } |
||
243 | |||
244 | /** |
||
245 | * @inheritdoc |
||
246 | */ |
||
247 | 61 | public function getLinks(): iterable |
|
248 | { |
||
249 | 61 | $this->cacheLinks(); |
|
250 | |||
251 | 61 | return $this->links; |
|
0 ignored issues
–
show
|
|||
252 | } |
||
253 | |||
254 | /** |
||
255 | * @inheritdoc |
||
256 | */ |
||
257 | 62 | public function hasResourceMeta(): bool |
|
258 | { |
||
259 | 62 | return $this->schema->hasResourceMeta($this->data); |
|
260 | } |
||
261 | |||
262 | /** |
||
263 | * @inheritdoc |
||
264 | */ |
||
265 | 1 | public function getResourceMeta() |
|
266 | { |
||
267 | 1 | return $this->schema->getResourceMeta($this->data); |
|
268 | } |
||
269 | |||
270 | /** |
||
271 | * @return EditableContextInterface |
||
272 | */ |
||
273 | 65 | protected function getContext(): EditableContextInterface |
|
274 | { |
||
275 | 65 | return $this->context; |
|
276 | } |
||
277 | |||
278 | /** |
||
279 | * Read and parse links from schema. |
||
280 | */ |
||
281 | 62 | private function cacheLinks(): void |
|
282 | { |
||
283 | 62 | if ($this->links === null) { |
|
284 | 62 | $this->links = []; |
|
285 | 62 | foreach ($this->schema->getLinks($this->data) as $name => $link) { |
|
286 | 61 | \assert(\is_string($name) === true && empty($name) === false); |
|
287 | 61 | \assert($link instanceof LinkInterface); |
|
288 | 61 | $this->links[$name] = $link; |
|
289 | } |
||
290 | } |
||
291 | 62 | } |
|
292 | |||
293 | /** |
||
294 | * @param string $name |
||
295 | * @param array $description |
||
296 | * |
||
297 | * @return bool |
||
298 | */ |
||
299 | 49 | private function assertRelationshipNameAndDescription(string $name, array $description): bool |
|
300 | { |
||
301 | 49 | \assert( |
|
302 | 49 | \is_string($name) === true && empty($name) === false, |
|
303 | 49 | "Relationship names for type `" . $this->getType() . '` should be non-empty strings.' |
|
304 | ); |
||
305 | 49 | \assert( |
|
306 | 49 | \is_array($description) === true && empty($description) === false, |
|
307 | 49 | "Relationship `$name` for type `" . $this->getType() . '` should be a non-empty array.' |
|
308 | ); |
||
309 | |||
310 | 49 | return true; |
|
311 | } |
||
312 | } |
||
313 |
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.