Issues (104)

Security Analysis    not enabled

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/Metadata/EntityMetadata.php (4 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
2
3
namespace As3\Modlr\Metadata;
4
5
use As3\Modlr\Exception\MetadataException;
6
7
/**
8
 * Defines the metadata for an entity (e.g. a database object).
9
 * Should be loaded using the MetadataFactory, not instantiated directly.
10
 *
11
 * @author  Jacob Bare <[email protected]>
12
 * @todo    This should be renamed to ModelMetadata.
13
 */
14
class EntityMetadata implements Interfaces\AttributeInterface, Interfaces\EmbedInterface, Interfaces\MergeableInterface, Interfaces\MixinInterface, Interfaces\RelationshipInterface
15
{
16
    /**
17
     * Uses attributes.
18
     */
19
    use Traits\AttributesTrait;
20
21
    /**
22
     * Uses embeds.
23
     */
24
    use Traits\EmbedsTrait;
25
26
    /**
27
     * Uses mixins.
28
     */
29
    use Traits\MixinsTrait;
30
31
    /**
32
     * Uses merged properties.
33
     */
34
    use Traits\PropertiesTrait;
35
36
    /**
37
     * Uses relationships.
38
     */
39
    use Traits\RelationshipsTrait;
40
41
    /**
42
     * The id key name and type.
43
     */
44
    const ID_KEY  = 'id';
45
    const ID_TYPE = 'string';
46
47
    /**
48
     * The model type key.
49
     */
50
    const TYPE_KEY = 'type';
51
52
    /**
53
     * Whether this class is abstract.
54
     *
55
     * @var bool
56
     */
57
    public $abstract = false;
58
59
    /**
60
     * An array of attribute default values for this model.
61
     * Keyed by field name.
62
     *
63
     * @var array
64
     */
65
    public $defaultValues = [];
66
67
    /**
68
     * The entity type this entity extends.
69
     *
70
     * @var string|null
71
     */
72
    public $extends;
73
74
    /**
75
     * Child entity types this entity owns.
76
     * Only used for polymorphic entities.
77
     *
78
     * @var array
79
     */
80
    public $ownedTypes = [];
81
82
    /**
83
     * The persistence metadata for this entity.
84
     *
85
     * @var Interfaces\StorageLayerInterface
86
     */
87
    public $persistence;
88
89
    /**
90
     * Whether this class is considered polymorphic.
91
     *
92
     * @var bool
93
     */
94
    public $polymorphic = false;
95
96
    /**
97
     * The search metadata for this entity.
98
     *
99
     * @var Interfaces\StorageLayerInterface
100
     */
101
    public $search;
102
103
    /**
104
     * Uniquely defines the type of entity.
105
     *
106
     * @var string
107
     */
108
    public $type;
109
110
    /**
111
     * Constructor.
112
     *
113
     * @param   string  $type   The resource identifier type.
114
     */
115
    public function __construct($type)
116
    {
117
        $this->setType($type);
118
    }
119
120
    /**
121
     * Gets the parent entity type.
122
     * For entities that are extended.
123
     *
124
     * @return  string|null
125
     */
126
    public function getParentEntityType()
127
    {
128
        return $this->extends;
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function getProperties()
135
    {
136
        return array_merge($this->getAttributes(), $this->getRelationships(), $this->getEmbeds());
137
    }
138
139
    /**
140
     * Whether this metadata represents an abstract class.
141
     *
142
     * @return  bool
143
     */
144
    public function isAbstract()
145
    {
146
        return (Boolean) $this->abstract;
147
    }
148
149
    /**
150
     * Whether this metadata represents a polymorphic class.
151
     *
152
     * @return  bool
153
     */
154
    public function isPolymorphic()
155
    {
156
        return (Boolean) $this->polymorphic;
157
    }
158
159
    /**
160
     * Deteremines whether search is enabled for this model.
161
     *
162
     * @return  bool
163
     */
164
    public function isSearchEnabled()
165
    {
166
        return null !== $this->search;
167
    }
168
169
    /**
170
     * Determines if this is a child entity of another entity.
171
     *
172
     * @return  bool
173
     */
174
    public function isChildEntity()
175
    {
176
        return null !== $this->getParentEntityType();
177
    }
178
179
    /**
180
     * {@inheritDoc}
181
     */
182
    public function merge(Interfaces\MergeableInterface $metadata)
183
    {
184
        if (!$metadata instanceof EntityMetadata) {
185
            throw new MetadataException('Unable to merge metadata. The provided metadata instance is not compatible.');
186
        }
187
188
        $this->setType($metadata->type);
189
        $this->setPolymorphic($metadata->isPolymorphic());
190
        $this->setAbstract($metadata->isAbstract());
191
        $this->extends = $metadata->extends;
192
        $this->ownedTypes = $metadata->ownedTypes;
193
        $this->defaultValues = array_merge($this->defaultValues, $metadata->defaultValues);
194
195
        $this->persistence->merge($metadata->persistence);
196
197
        if ($this->search instanceof Interfaces\StorageLayerInterface && $metadata->search instanceof Interfaces\StorageLayerInterface) {
198
            $this->search->merge($metadata->search);
199
        }
200
201
        $this->mergeAttributes($metadata->getAttributes());
202
        $this->mergeRelationships($metadata->getRelationships());
203
        $this->mergeEmbeds($metadata->getEmbeds());
204
        $this->mergeMixins($metadata->getMixins());
205
206
        return $this;
207
    }
208
209
    /**
210
     * Sets this metadata as representing an abstract class.
211
     *
212
     * @param   bool    $bit
213
     * @return  self
214
     */
215
    public function setAbstract($bit = true)
216
    {
217
        $this->abstract = (Boolean) $bit;
218
        return $this;
219
    }
220
221
    /**
222
     * Sets the persistence metadata for this entity.
223
     *
224
     * @param   Interfaces\StorageLayerInterface    $persistence
225
     * @return  self
226
     */
227
    public function setPersistence(Interfaces\StorageLayerInterface $persistence)
228
    {
229
        $this->persistence = $persistence;
230
        return $this;
231
    }
232
233
    /**
234
     * Sets this metadata as representing a polymorphic class.
235
     *
236
     * @param   bool    $bit
237
     * @return  self
238
     */
239
    public function setPolymorphic($bit = true)
240
    {
241
        $this->polymorphic = (Boolean) $bit;
242
        return $this;
243
    }
244
245
    /**
246
     * Sets the search metadata for this entity.
247
     *
248
     * @param   Interfaces\StorageLayerInterface    $search
249
     * @return  self
250
     */
251
    public function setSearch(Interfaces\StorageLayerInterface $search)
252
    {
253
        $this->search = $search;
254
        return $this;
255
    }
256
257
    /**
258
     * Sets the entity type.
259
     *
260
     * @param   string  $type
261
     * @return  self
262
     * @throws  MetadataException   If the type is not a string or is empty.
263
     */
264
    public function setType($type)
265
    {
266
        if (!is_string($type) || empty($type)) {
267
            throw MetadataException::invalidEntityType($type);
268
        }
269
        $this->type = $type;
270
        return $this;
271
    }
272
273
    /**
274
     * {@inheritdoc}
275
     */
276 View Code Duplication
    protected function applyMixinProperties(MixinMetadata $mixin)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
277
    {
278
        foreach ($mixin->getAttributes() as $attribute) {
279
            if (true === $this->hasAttribute($attribute->key)) {
280
                throw MetadataException::mixinPropertyExists($this->type, $mixin->name, 'attribute', $attribute->key);
281
            }
282
            $this->addAttribute($attribute);
283
        }
284
        foreach ($mixin->getRelationships() as $relationship) {
285
            if (true === $this->hasRelationship($relationship->key)) {
286
                throw MetadataException::mixinPropertyExists($this->type, $mixin->name, 'relationship', $relationship->key);
287
            }
288
            $this->addRelationship($relationship);
289
        }
290
        foreach ($mixin->getEmbeds() as $embed) {
291
            if (true === $this->hasEmbed($embed->key)) {
292
                throw MetadataException::mixinPropertyExists($this->type, $mixin->name, 'embed', $embed->key);
293
            }
294
            $this->addEmbed($embed);
295
        }
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301 View Code Duplication
    protected function validateAttribute(AttributeMetadata $attribute)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
302
    {
303
        if (true === $this->hasRelationship($attribute->getKey())) {
304
            throw MetadataException::fieldKeyInUse('attribute', 'relationship', $attribute->getKey(), $this->type);
305
        }
306
        if (true === $this->hasEmbed($attribute->getKey())) {
307
            throw MetadataException::fieldKeyInUse('attribute', 'embed', $attribute->getKey(), $this->type);
308
        }
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314 View Code Duplication
    protected function validateEmbed(EmbeddedPropMetadata $embed)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
315
    {
316
        if (true === $this->hasAttribute($embed->getKey())) {
317
            throw MetadataException::fieldKeyInUse('embed', 'attribute', $embed->getKey(), $this->type);
318
        }
319
        if (true === $this->hasRelationship($embed->getKey())) {
320
            throw MetadataException::fieldKeyInUse('embed', 'relationship', $embed->getKey(), $this->type);
321
        }
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327 View Code Duplication
    protected function validateRelationship(RelationshipMetadata $relationship)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
328
    {
329
        if (true === $this->hasAttribute($relationship->getKey())) {
330
            throw MetadataException::fieldKeyInUse('relationship', 'attribute', $relationship->getKey(), $this->type);
331
        }
332
        if (true === $this->hasEmbed($relationship->getKey())) {
333
            throw MetadataException::fieldKeyInUse('relationship', 'embed', $relationship->getKey(), $this->type);
334
        }
335
    }
336
337
    /**
338
     * Merges attributes with this instance's attributes.
339
     *
340
     * @param   AttributeMetadata[]     $toAdd
341
     * @return  self
342
     */
343
    private function mergeAttributes(array $toAdd)
344
    {
345
        foreach ($toAdd as $attribute) {
346
            $this->addAttribute($attribute);
347
        }
348
        return $this;
349
    }
350
351
    /**
352
     * Merges embeds with this instance's embeds.
353
     *
354
     * @param   EmbeddedPropMetadata[]  $toAdd
355
     * @return  self
356
     */
357
    private function mergeEmbeds(array $toAdd)
358
    {
359
        foreach ($toAdd as $embed) {
360
            $this->addEmbed($embed);
361
        }
362
        return $this;
363
    }
364
365
    /**
366
     * Merges mixins with this instance's mixins.
367
     *
368
     * @param   MixinMetadata[]     $toAdd
369
     * @return  self
370
     */
371
    private function mergeMixins(array $toAdd)
372
    {
373
        foreach ($toAdd as $mixin) {
374
            if (!isset($this->mixins[$mixin->name])) {
375
                $this->mixins[$mixin->name] = $mixin;
376
            }
377
        }
378
        return $this;
379
    }
380
381
    /**
382
     * Merges relationships with this instance's relationships.
383
     *
384
     * @param   RelationshipMetadata[]  $toAdd
385
     * @return  self
386
     */
387
    private function mergeRelationships(array $toAdd)
388
    {
389
        foreach ($toAdd as $relationship) {
390
            $this->addRelationship($relationship);
391
        }
392
        return $this;
393
    }
394
}
395