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\Driver; |
||
6 | |||
7 | use Doctrine\Common\Annotations\AnnotationReader; |
||
8 | use Doctrine\Common\Annotations\Reader; |
||
9 | use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver; |
||
10 | use Doctrine\ODM\MongoDB\Events; |
||
11 | use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; |
||
12 | use Doctrine\ODM\MongoDB\Mapping\Annotations\AbstractIndex; |
||
13 | use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; |
||
14 | use Doctrine\ODM\MongoDB\Mapping\MappingException; |
||
15 | use ReflectionClass; |
||
16 | use ReflectionMethod; |
||
17 | use const E_USER_DEPRECATED; |
||
18 | use function array_merge; |
||
19 | use function array_replace; |
||
20 | use function constant; |
||
21 | use function get_class; |
||
22 | use function is_array; |
||
23 | use function trigger_error; |
||
24 | |||
25 | /** |
||
26 | * The AnnotationDriver reads the mapping metadata from docblock annotations. |
||
27 | */ |
||
28 | class AnnotationDriver extends AbstractAnnotationDriver |
||
29 | { |
||
30 | 918 | public function isTransient($className) |
|
31 | { |
||
32 | 918 | $classAnnotations = $this->reader->getClassAnnotations(new ReflectionClass($className)); |
|
33 | |||
34 | 918 | foreach ($classAnnotations as $annot) { |
|
35 | 917 | if ($annot instanceof ODM\AbstractDocument) { |
|
36 | 917 | return false; |
|
37 | } |
||
38 | } |
||
39 | 69 | return true; |
|
40 | } |
||
41 | |||
42 | /** |
||
43 | * {@inheritdoc} |
||
44 | */ |
||
45 | 1448 | public function loadMetadataForClass($className, \Doctrine\Common\Persistence\Mapping\ClassMetadata $class) : void |
|
46 | { |
||
47 | /** @var ClassMetadata $class */ |
||
48 | 1448 | $reflClass = $class->getReflectionClass(); |
|
49 | |||
50 | 1448 | $classAnnotations = $this->reader->getClassAnnotations($reflClass); |
|
51 | |||
52 | 1448 | $documentAnnot = null; |
|
53 | 1448 | foreach ($classAnnotations as $annot) { |
|
54 | 1446 | $classAnnotations[get_class($annot)] = $annot; |
|
55 | |||
56 | 1446 | if ($annot instanceof ODM\AbstractDocument) { |
|
57 | 1446 | if ($documentAnnot !== null) { |
|
58 | 5 | throw MappingException::classCanOnlyBeMappedByOneAbstractDocument($className, $documentAnnot, $annot); |
|
59 | } |
||
60 | 1446 | $documentAnnot = $annot; |
|
61 | } |
||
62 | |||
63 | // non-document class annotations |
||
64 | 1446 | if ($annot instanceof ODM\AbstractIndex) { |
|
65 | 6 | $this->addIndex($class, $annot); |
|
66 | } |
||
67 | 1446 | if ($annot instanceof ODM\Indexes) { |
|
68 | 94 | foreach (is_array($annot->value) ? $annot->value : [$annot->value] as $index) { |
|
69 | 94 | $this->addIndex($class, $index); |
|
70 | } |
||
71 | 1446 | } elseif ($annot instanceof ODM\InheritanceType) { |
|
72 | 859 | $class->setInheritanceType(constant(ClassMetadata::class . '::INHERITANCE_TYPE_' . $annot->value)); |
|
73 | 1446 | } elseif ($annot instanceof ODM\DiscriminatorField) { |
|
74 | 132 | $class->setDiscriminatorField($annot->value); |
|
75 | 1446 | } elseif ($annot instanceof ODM\DiscriminatorMap) { |
|
76 | 131 | $class->setDiscriminatorMap($annot->value); |
|
77 | 1446 | } elseif ($annot instanceof ODM\DiscriminatorValue) { |
|
78 | $class->setDiscriminatorValue($annot->value); |
||
79 | 1446 | } elseif ($annot instanceof ODM\ChangeTrackingPolicy) { |
|
80 | 66 | $class->setChangeTrackingPolicy(constant(ClassMetadata::class . '::CHANGETRACKING_' . $annot->value)); |
|
81 | 1446 | } elseif ($annot instanceof ODM\DefaultDiscriminatorValue) { |
|
82 | 68 | $class->setDefaultDiscriminatorValue($annot->value); |
|
83 | 1446 | } elseif ($annot instanceof ODM\ReadPreference) { |
|
84 | 1446 | $class->setReadPreference($annot->value, $annot->tags); |
|
85 | } |
||
86 | } |
||
87 | |||
88 | 1443 | if ($documentAnnot === null) { |
|
89 | 3 | throw MappingException::classIsNotAValidDocument($className); |
|
90 | } |
||
91 | |||
92 | 1441 | if ($documentAnnot instanceof ODM\MappedSuperclass) { |
|
93 | 849 | $class->isMappedSuperclass = true; |
|
94 | 1440 | } elseif ($documentAnnot instanceof ODM\EmbeddedDocument) { |
|
95 | 287 | $class->isEmbeddedDocument = true; |
|
96 | 1433 | } elseif ($documentAnnot instanceof ODM\QueryResultDocument) { |
|
97 | 67 | $class->isQueryResultDocument = true; |
|
98 | 1433 | } elseif ($documentAnnot instanceof ODM\File) { |
|
99 | 79 | $class->isFile = true; |
|
100 | |||
101 | 79 | if ($documentAnnot->chunkSizeBytes !== null) { |
|
102 | 78 | $class->setChunkSizeBytes($documentAnnot->chunkSizeBytes); |
|
103 | } |
||
104 | } |
||
105 | |||
106 | 1441 | if (isset($documentAnnot->db)) { |
|
107 | 1 | $class->setDatabase($documentAnnot->db); |
|
108 | } |
||
109 | 1441 | if (isset($documentAnnot->collection)) { |
|
110 | 911 | $class->setCollection($documentAnnot->collection); |
|
111 | } |
||
112 | // Store bucketName as collection name for GridFS files |
||
113 | 1441 | if (isset($documentAnnot->bucketName)) { |
|
114 | 1 | $class->setBucketName($documentAnnot->bucketName); |
|
115 | } |
||
116 | 1441 | if (isset($documentAnnot->repositoryClass)) { |
|
117 | 77 | $class->setCustomRepositoryClass($documentAnnot->repositoryClass); |
|
118 | } |
||
119 | 1441 | if (isset($documentAnnot->writeConcern)) { |
|
120 | 10 | $class->setWriteConcern($documentAnnot->writeConcern); |
|
121 | } |
||
122 | 1441 | if (isset($documentAnnot->indexes)) { |
|
123 | 1440 | foreach ($documentAnnot->indexes as $index) { |
|
124 | $this->addIndex($class, $index); |
||
125 | } |
||
126 | } |
||
127 | 1441 | if (! empty($documentAnnot->readOnly)) { |
|
128 | 5 | $class->markReadOnly(); |
|
129 | } |
||
130 | |||
131 | 1441 | foreach ($reflClass->getProperties() as $property) { |
|
132 | 1440 | if (($class->isMappedSuperclass && ! $property->isPrivate()) |
|
133 | || |
||
134 | 1440 | ($class->isInheritedField($property->name) && $property->getDeclaringClass()->name !== $class->name)) { |
|
135 | 891 | continue; |
|
136 | } |
||
137 | |||
138 | 1439 | $indexes = []; |
|
139 | 1439 | $mapping = ['fieldName' => $property->getName()]; |
|
140 | 1439 | $fieldAnnot = null; |
|
141 | |||
142 | 1439 | foreach ($this->reader->getPropertyAnnotations($property) as $annot) { |
|
143 | 1439 | if ($annot instanceof ODM\AbstractField) { |
|
144 | 1439 | $fieldAnnot = $annot; |
|
145 | 1439 | if ($annot->isDeprecated()) { |
|
146 | @trigger_error($annot->getDeprecationMessage(), E_USER_DEPRECATED); |
||
0 ignored issues
–
show
|
|||
147 | } |
||
148 | } |
||
149 | 1439 | if ($annot instanceof ODM\AbstractIndex) { |
|
150 | 182 | $indexes[] = $annot; |
|
151 | } |
||
152 | 1439 | if ($annot instanceof ODM\Indexes) { |
|
153 | foreach (is_array($annot->value) ? $annot->value : [$annot->value] as $index) { |
||
154 | $indexes[] = $index; |
||
155 | } |
||
156 | 1439 | } elseif ($annot instanceof ODM\AlsoLoad) { |
|
157 | 15 | $mapping['alsoLoadFields'] = (array) $annot->value; |
|
158 | 1439 | } elseif ($annot instanceof ODM\Version) { |
|
159 | 108 | $mapping['version'] = true; |
|
160 | 1439 | } elseif ($annot instanceof ODM\Lock) { |
|
161 | 1439 | $mapping['lock'] = true; |
|
162 | } |
||
163 | } |
||
164 | |||
165 | 1439 | if ($fieldAnnot) { |
|
166 | 1439 | $mapping = array_replace($mapping, (array) $fieldAnnot); |
|
167 | 1439 | $class->mapField($mapping); |
|
168 | } |
||
169 | |||
170 | 1439 | if (! $indexes) { |
|
0 ignored issues
–
show
The expression
$indexes 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 ![]() |
|||
171 | 1439 | continue; |
|
172 | } |
||
173 | |||
174 | 182 | foreach ($indexes as $index) { |
|
175 | 182 | $name = $mapping['name'] ?? $mapping['fieldName']; |
|
176 | 182 | $keys = [$name => $index->order ?: 'asc']; |
|
177 | 182 | $this->addIndex($class, $index, $keys); |
|
178 | } |
||
179 | } |
||
180 | |||
181 | // Set shard key after all fields to ensure we mapped all its keys |
||
182 | 1438 | if (isset($classAnnotations['Doctrine\ODM\MongoDB\Mapping\Annotations\ShardKey'])) { |
|
183 | 88 | $this->setShardKey($class, $classAnnotations['Doctrine\ODM\MongoDB\Mapping\Annotations\ShardKey']); |
|
184 | } |
||
185 | |||
186 | /** @var ReflectionMethod $method */ |
||
187 | 1437 | foreach ($reflClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { |
|
188 | /* Filter for the declaring class only. Callbacks from parent |
||
189 | * classes will already be registered. |
||
190 | */ |
||
191 | 1185 | if ($method->getDeclaringClass()->name !== $reflClass->name) { |
|
192 | 856 | continue; |
|
193 | } |
||
194 | |||
195 | 1185 | foreach ($this->reader->getMethodAnnotations($method) as $annot) { |
|
196 | 850 | if ($annot instanceof ODM\AlsoLoad) { |
|
197 | 13 | $class->registerAlsoLoadMethod($method->getName(), $annot->value); |
|
198 | } |
||
199 | |||
200 | 850 | if (! isset($classAnnotations[ODM\HasLifecycleCallbacks::class])) { |
|
201 | 84 | continue; |
|
202 | } |
||
203 | |||
204 | 831 | if ($annot instanceof ODM\PrePersist) { |
|
205 | 812 | $class->addLifecycleCallback($method->getName(), Events::prePersist); |
|
206 | 95 | } elseif ($annot instanceof ODM\PostPersist) { |
|
207 | 10 | $class->addLifecycleCallback($method->getName(), Events::postPersist); |
|
208 | 95 | } elseif ($annot instanceof ODM\PreUpdate) { |
|
209 | 15 | $class->addLifecycleCallback($method->getName(), Events::preUpdate); |
|
210 | 90 | } elseif ($annot instanceof ODM\PostUpdate) { |
|
211 | 79 | $class->addLifecycleCallback($method->getName(), Events::postUpdate); |
|
212 | 84 | } elseif ($annot instanceof ODM\PreRemove) { |
|
213 | 82 | $class->addLifecycleCallback($method->getName(), Events::preRemove); |
|
214 | 84 | } elseif ($annot instanceof ODM\PostRemove) { |
|
215 | 82 | $class->addLifecycleCallback($method->getName(), Events::postRemove); |
|
216 | 84 | } elseif ($annot instanceof ODM\PreLoad) { |
|
217 | 83 | $class->addLifecycleCallback($method->getName(), Events::preLoad); |
|
218 | 83 | } elseif ($annot instanceof ODM\PostLoad) { |
|
219 | 82 | $class->addLifecycleCallback($method->getName(), Events::postLoad); |
|
220 | 11 | } elseif ($annot instanceof ODM\PreFlush) { |
|
221 | 1185 | $class->addLifecycleCallback($method->getName(), Events::preFlush); |
|
222 | } |
||
223 | } |
||
224 | } |
||
225 | 1437 | } |
|
226 | |||
227 | 214 | private function addIndex(ClassMetadata $class, AbstractIndex $index, array $keys = []) : void |
|
228 | { |
||
229 | 214 | $keys = array_merge($keys, $index->keys); |
|
230 | 214 | $options = []; |
|
231 | 214 | $allowed = ['name', 'dropDups', 'background', 'unique', 'sparse', 'expireAfterSeconds']; |
|
232 | 214 | foreach ($allowed as $name) { |
|
233 | 214 | if (! isset($index->$name)) { |
|
234 | 214 | continue; |
|
235 | } |
||
236 | |||
237 | 214 | $options[$name] = $index->$name; |
|
238 | } |
||
239 | 214 | if (! empty($index->partialFilterExpression)) { |
|
240 | 2 | $options['partialFilterExpression'] = $index->partialFilterExpression; |
|
241 | } |
||
242 | 214 | $options = array_merge($options, $index->options); |
|
243 | 214 | $class->addIndex($keys, $options); |
|
244 | 214 | } |
|
245 | |||
246 | /** |
||
247 | * @throws MappingException |
||
248 | */ |
||
249 | 88 | private function setShardKey(ClassMetadata $class, ODM\ShardKey $shardKey) : void |
|
250 | { |
||
251 | 88 | $options = []; |
|
252 | 88 | $allowed = ['unique', 'numInitialChunks']; |
|
253 | 88 | foreach ($allowed as $name) { |
|
254 | 88 | if (! isset($shardKey->$name)) { |
|
255 | 88 | continue; |
|
256 | } |
||
257 | |||
258 | $options[$name] = $shardKey->$name; |
||
259 | } |
||
260 | |||
261 | 88 | $class->setShardKey($shardKey->keys, $options); |
|
262 | 87 | } |
|
263 | |||
264 | /** |
||
265 | * Factory method for the Annotation Driver |
||
266 | * |
||
267 | * @param array|string $paths |
||
268 | */ |
||
269 | 1711 | public static function create($paths = [], ?Reader $reader = null) : AnnotationDriver |
|
270 | { |
||
271 | 1711 | if ($reader === null) { |
|
272 | 1711 | $reader = new AnnotationReader(); |
|
273 | } |
||
274 | 1711 | return new self($reader, $paths); |
|
275 | } |
||
276 | } |
||
277 |
If you suppress an error, we recommend checking for the error condition explicitly: