Issues (353)

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.

ODM/MongoDB/Mapping/ClassMetadataFactory.php (3 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
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Mapping;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\ODM\MongoDB\Configuration;
9
use Doctrine\ODM\MongoDB\ConfigurationException;
10
use Doctrine\ODM\MongoDB\DocumentManager;
11
use Doctrine\ODM\MongoDB\Event\LoadClassMetadataEventArgs;
12
use Doctrine\ODM\MongoDB\Event\OnClassMetadataNotFoundEventArgs;
13
use Doctrine\ODM\MongoDB\Events;
14
use Doctrine\ODM\MongoDB\Id\AlnumGenerator;
15
use Doctrine\ODM\MongoDB\Id\AutoGenerator;
16
use Doctrine\ODM\MongoDB\Id\IdGenerator;
17
use Doctrine\ODM\MongoDB\Id\IncrementGenerator;
18
use Doctrine\ODM\MongoDB\Id\UuidGenerator;
19
use Doctrine\Persistence\Mapping\AbstractClassMetadataFactory;
20
use Doctrine\Persistence\Mapping\ClassMetadata as ClassMetadataInterface;
21
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
22
use Doctrine\Persistence\Mapping\ReflectionService;
23
use ReflectionException;
24
use function assert;
25
use function get_class;
26
use function get_class_methods;
27
use function in_array;
28
use function interface_exists;
29
use function ucfirst;
30
31
/**
32
 * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
33
 * metadata mapping informations of a class which describes how a class should be mapped
34
 * to a document database.
35
 *
36
 * @internal
37
 */
38
final class ClassMetadataFactory extends AbstractClassMetadataFactory
39
{
40
    /** @var string */
41
    protected $cacheSalt = '$MONGODBODMCLASSMETADATA';
42
43
    /** @var DocumentManager The DocumentManager instance */
44
    private $dm;
45
46
    /** @var Configuration The Configuration instance */
47
    private $config;
48
49
    /** @var MappingDriver The used metadata driver. */
50
    private $driver;
51
52
    /** @var EventManager The event manager instance */
53
    private $evm;
54
55 1832
    public function setDocumentManager(DocumentManager $dm) : void
56
    {
57 1832
        $this->dm = $dm;
58 1832
    }
59
60 1832
    public function setConfiguration(Configuration $config) : void
61
    {
62 1832
        $this->config = $config;
63 1832
    }
64
65 1607
    public function getMetadataFor($className)
66
    {
67 1607
        return parent::getMetadataFor($this->dm->getClassNameResolver()->getRealClass($className));
68
    }
69
70
    /**
71
     * Lazy initialization of this stuff, especially the metadata driver,
72
     * since these are not needed at all when a metadata cache is active.
73
     */
74 1606
    protected function initialize() : void
75
    {
76 1606
        $driver = $this->config->getMetadataDriverImpl();
77 1606
        if ($driver === null) {
78
            throw ConfigurationException::noMetadataDriverConfigured();
79
        }
80
81 1606
        $this->driver      = $driver;
82 1606
        $this->evm         = $this->dm->getEventManager();
83 1606
        $this->initialized = true;
84 1606
    }
85
86
    /**
87
     * {@inheritDoc}
88
     */
89 21
    protected function onNotFoundMetadata($className)
90
    {
91 21
        if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) {
92 19
            return null;
93
        }
94
95 2
        $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->dm);
96
97 2
        $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs);
98
99 2
        return $eventArgs->getFoundMetadata();
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) : string
106
    {
107
        return $this->config->getDocumentNamespace($namespaceAlias) . '\\' . $simpleClassName;
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113 1042
    protected function getDriver()
114
    {
115 1042
        return $this->driver;
116
    }
117
118
    /**
119
     * {@inheritDoc}
120
     */
121 1598
    protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService) : void
122
    {
123 1598
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128 1606
    protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService) : void
129
    {
130 1606
    }
131
132
    /**
133
     * {@inheritDoc}
134
     */
135 1598
    protected function isEntity(ClassMetadataInterface $class) : bool
136
    {
137 1598
        assert($class instanceof ClassMetadata);
138
139 1598
        return ! $class->isMappedSuperclass && ! $class->isEmbeddedDocument && ! $class->isQueryResultDocument && ! $class->isView();
140
    }
141
142
    /**
143
     * {@inheritDoc}
144
     */
145 1606
    protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents = []) : void
146
    {
147 1606
        assert($class instanceof ClassMetadata);
148 1606
        if ($parent instanceof ClassMetadata) {
149 1037
            $class->setInheritanceType($parent->inheritanceType);
150 1037
            $class->setDiscriminatorField($parent->discriminatorField);
151 1037
            $class->setDiscriminatorMap($parent->discriminatorMap);
152 1037
            $class->setDefaultDiscriminatorValue($parent->defaultDiscriminatorValue);
153 1037
            $class->setIdGeneratorType($parent->generatorType);
154 1037
            $this->addInheritedFields($class, $parent);
155 1037
            $this->addInheritedRelations($class, $parent);
156 1037
            $this->addInheritedIndexes($class, $parent);
157 1037
            $this->setInheritedShardKey($class, $parent);
158 1037
            $class->setIdentifier($parent->identifier);
159 1037
            $class->setVersioned($parent->isVersioned);
160 1037
            $class->setVersionField($parent->versionField);
161 1037
            $class->setLifecycleCallbacks($parent->lifecycleCallbacks);
162 1037
            $class->setAlsoLoadMethods($parent->alsoLoadMethods);
163 1037
            $class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
164 1037
            $class->setReadPreference($parent->readPreference, $parent->readPreferenceTags);
165 1037
            $class->setWriteConcern($parent->writeConcern);
166
167 1037
            if ($parent->isMappedSuperclass) {
168 970
                $class->setCustomRepositoryClass($parent->customRepositoryClassName);
169
            }
170
171 1037
            if ($parent->isFile) {
172 1
                $class->isFile = true;
173 1
                $class->setBucketName($parent->bucketName);
174
175 1
                if ($parent->chunkSizeBytes !== null) {
176 1
                    $class->setChunkSizeBytes($parent->chunkSizeBytes);
177
                }
178
            }
179
        }
180
181
        // Invoke driver
182
        try {
183 1606
            $this->driver->loadMetadataForClass($class->getName(), $class);
0 ignored issues
show
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
184 13
        } catch (ReflectionException $e) {
185
            throw MappingException::reflectionFailure($class->getName(), $e);
0 ignored issues
show
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
186
        }
187
188 1598
        $this->validateIdentifier($class);
189
190 1598
        if ($parent instanceof ClassMetadata && $rootEntityFound && $parent->generatorType === $class->generatorType) {
191 185
            if ($parent->generatorType) {
192 185
                $class->setIdGeneratorType($parent->generatorType);
193
            }
194 185
            if ($parent->generatorOptions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parent->generatorOptions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
195
                $class->setIdGeneratorOptions($parent->generatorOptions);
196
            }
197 185
            if ($parent->idGenerator) {
198 185
                $class->setIdGenerator($parent->idGenerator);
199
            }
200
        } else {
201 1598
            $this->completeIdGeneratorMapping($class);
202
        }
203
204 1598
        if ($parent instanceof ClassMetadata && $parent->isInheritanceTypeSingleCollection()) {
205 174
            $class->setDatabase($parent->getDatabase());
206 174
            $class->setCollection($parent->getCollection());
207
        }
208
209 1598
        $class->setParentClasses($nonSuperclassParents);
210
211 1598
        if (! $this->evm->hasListeners(Events::loadClassMetadata)) {
212 1594
            return;
213
        }
214
215 4
        $eventArgs = new LoadClassMetadataEventArgs($class, $this->dm);
216 4
        $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
217 4
    }
218
219
    /**
220
     * Validates the identifier mapping.
221
     *
222
     * @throws MappingException
223
     */
224 1598
    protected function validateIdentifier(ClassMetadata $class) : void
225
    {
226 1598
        if (! $class->identifier && $this->isEntity($class)) {
227
            throw MappingException::identifierRequired($class->name);
228
        }
229 1598
    }
230
231
    /**
232
     * {@inheritdoc}
233
     */
234 1606
    protected function newClassMetadataInstance($className) : ClassMetadata
235
    {
236 1606
        return new ClassMetadata($className);
237
    }
238
239 1598
    private function completeIdGeneratorMapping(ClassMetadata $class) : void
240
    {
241 1598
        $idGenOptions = $class->generatorOptions;
242 1598
        switch ($class->generatorType) {
243
            case ClassMetadata::GENERATOR_TYPE_AUTO:
244 1532
                $class->setIdGenerator(new AutoGenerator());
245 1532
                break;
246 View Code Duplication
            case ClassMetadata::GENERATOR_TYPE_INCREMENT:
247 9
                $incrementGenerator = new IncrementGenerator();
248 9
                if (isset($idGenOptions['key'])) {
249
                    $incrementGenerator->setKey((string) $idGenOptions['key']);
250
                }
251 9
                if (isset($idGenOptions['collection'])) {
252
                    $incrementGenerator->setCollection((string) $idGenOptions['collection']);
253
                }
254 9
                if (isset($idGenOptions['startingId'])) {
255 1
                    $incrementGenerator->setStartingId((int) $idGenOptions['startingId']);
256
                }
257 9
                $class->setIdGenerator($incrementGenerator);
258 9
                break;
259
            case ClassMetadata::GENERATOR_TYPE_UUID:
260 4
                $uuidGenerator = new UuidGenerator();
261 4
                if (isset($idGenOptions['salt'])) {
262 2
                    $uuidGenerator->setSalt((string) $idGenOptions['salt']);
263
                }
264 4
                $class->setIdGenerator($uuidGenerator);
265 4
                break;
266 View Code Duplication
            case ClassMetadata::GENERATOR_TYPE_ALNUM:
267 1
                $alnumGenerator = new AlnumGenerator();
268 1
                if (isset($idGenOptions['pad'])) {
269
                    $alnumGenerator->setPad((int) $idGenOptions['pad']);
270
                }
271 1
                if (isset($idGenOptions['chars'])) {
272 1
                    $alnumGenerator->setChars((string) $idGenOptions['chars']);
273
                } elseif (isset($idGenOptions['awkwardSafe'])) {
274
                    $alnumGenerator->setAwkwardSafeMode((bool) $idGenOptions['awkwardSafe']);
275
                }
276
277 1
                $class->setIdGenerator($alnumGenerator);
278 1
                break;
279
            case ClassMetadata::GENERATOR_TYPE_CUSTOM:
280
                if (empty($idGenOptions['class'])) {
281
                    throw MappingException::missingIdGeneratorClass($class->name);
282
                }
283
284
                $customGenerator = new $idGenOptions['class']();
285
                unset($idGenOptions['class']);
286
                if (! $customGenerator instanceof IdGenerator) {
287
                    throw MappingException::classIsNotAValidGenerator(get_class($customGenerator));
288
                }
289
290
                $methods = get_class_methods($customGenerator);
291
                foreach ($idGenOptions as $name => $value) {
292
                    $method = 'set' . ucfirst($name);
293
                    if (! in_array($method, $methods)) {
294
                        throw MappingException::missingGeneratorSetter(get_class($customGenerator), $name);
295
                    }
296
297
                    $customGenerator->$method($value);
298
                }
299
                $class->setIdGenerator($customGenerator);
300
                break;
301
            case ClassMetadata::GENERATOR_TYPE_NONE:
302 215
                break;
303
            default:
304
                throw new MappingException('Unknown generator type: ' . $class->generatorType);
305
        }
306 1598
    }
307
308
    /**
309
     * Adds inherited fields to the subclass mapping.
310
     */
311 1037
    private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass) : void
312
    {
313 1037
        foreach ($parentClass->fieldMappings as $fieldName => $mapping) {
314 205 View Code Duplication
            if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
315 197
                $mapping['inherited'] = $parentClass->name;
316
            }
317 205
            if (! isset($mapping['declared'])) {
318 205
                $mapping['declared'] = $parentClass->name;
319
            }
320 205
            $subClass->addInheritedFieldMapping($mapping);
321
        }
322 1037
        foreach ($parentClass->reflFields as $name => $field) {
323 205
            $subClass->reflFields[$name] = $field;
324
        }
325 1037
    }
326
327
    /**
328
     * Adds inherited association mappings to the subclass mapping.
329
     *
330
     * @throws MappingException
331
     */
332 1037
    private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass) : void
333
    {
334 1037
        foreach ($parentClass->associationMappings as $field => $mapping) {
335 153
            if ($parentClass->isMappedSuperclass) {
336 4
                $mapping['sourceDocument'] = $subClass->name;
337
            }
338
339 153 View Code Duplication
            if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
340 149
                $mapping['inherited'] = $parentClass->name;
341
            }
342 153
            if (! isset($mapping['declared'])) {
343 153
                $mapping['declared'] = $parentClass->name;
344
            }
345 153
            $subClass->addInheritedAssociationMapping($mapping);
346
        }
347 1037
    }
348
349
    /**
350
     * Adds inherited indexes to the subclass mapping.
351
     */
352 1037
    private function addInheritedIndexes(ClassMetadata $subClass, ClassMetadata $parentClass) : void
353
    {
354 1037
        foreach ($parentClass->indexes as $index) {
355 126
            $subClass->addIndex($index['keys'], $index['options']);
356
        }
357 1037
    }
358
359
    /**
360
     * Adds inherited shard key to the subclass mapping.
361
     */
362 1037
    private function setInheritedShardKey(ClassMetadata $subClass, ClassMetadata $parentClass) : void
363
    {
364 1037
        if (! $parentClass->isSharded()) {
365 1032
            return;
366
        }
367
368 5
        $subClass->setShardKey(
369 5
            $parentClass->shardKey['keys'],
370 5
            $parentClass->shardKey['options']
371
        );
372 5
    }
373
}
374
375 1
interface_exists(ClassMetadataInterface::class);
376
interface_exists(ReflectionService::class);
377