Issues (23)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Parser/IdentifierAndResource.php (6 issues)

Upgrade to new PHP Analysis Engine

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 $hasData 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 $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
The variable $hasLinks 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 $links 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...
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
Bug Compatibility introduced by
The expression $this->links; of type null|array adds the type array to the return on line 251 which is incompatible with the return type declared by the interface Neomerx\JsonApi\Contract...urceInterface::getLinks of type Neomerx\JsonApi\Contracts\Parser\iterable.
Loading history...
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