Skip to content

Commit 495b583

Browse files
authored
Decouple AttributeDriver from AnnotationDriver (#2502)
AttributeDriver no longer extends AnnotationDriver
1 parent 402a849 commit 495b583

File tree

7 files changed

+439
-428
lines changed

7 files changed

+439
-428
lines changed

UPGRADE-2.7.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# UPGRADE FROM 2.6 to 2.7
22

3+
## Backward compatibility breaks
4+
5+
* `Doctrine\ODM\MongoDB\Mapping\Driver\AttributeDriver` no longer extends
6+
`Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver`.
7+
38
## doctrine/persistence
49

510
* MongoDB ODM 2.7 requires `doctrine/persistence` 3.2 or newer.

lib/Doctrine/ODM/MongoDB/Mapping/Driver/AnnotationDriver.php

Lines changed: 1 addition & 345 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,12 @@
66

77
use Doctrine\Common\Annotations\AnnotationReader;
88
use Doctrine\Common\Annotations\Reader;
9-
use Doctrine\ODM\MongoDB\Events;
10-
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
11-
use Doctrine\ODM\MongoDB\Mapping\Annotations\AbstractIndex;
12-
use Doctrine\ODM\MongoDB\Mapping\Annotations\ShardKey;
13-
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
14-
use Doctrine\ODM\MongoDB\Mapping\MappingException;
15-
use Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver;
16-
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
17-
use MongoDB\Driver\Exception\UnexpectedValueException;
18-
use ReflectionClass;
19-
use ReflectionMethod;
20-
21-
use function array_merge;
22-
use function array_replace;
23-
use function assert;
24-
use function class_exists;
25-
use function constant;
26-
use function count;
27-
use function interface_exists;
28-
use function is_array;
29-
use function MongoDB\BSON\fromJSON;
30-
use function MongoDB\BSON\toPHP;
31-
use function trigger_deprecation;
329

3310
/**
3411
* The AnnotationDriver reads the mapping metadata from docblock annotations.
3512
*/
36-
class AnnotationDriver implements MappingDriver
13+
class AnnotationDriver extends AttributeDriver
3714
{
38-
use ColocatedMappingDriver;
39-
4015
/**
4116
* The annotation reader.
4217
*
@@ -60,323 +35,6 @@ public function __construct($reader, $paths = null)
6035
$this->addPaths((array) $paths);
6136
}
6237

63-
public function isTransient($className)
64-
{
65-
$classAnnotations = $this->reader->getClassAnnotations(new ReflectionClass($className));
66-
67-
foreach ($classAnnotations as $annot) {
68-
if ($annot instanceof ODM\AbstractDocument) {
69-
return false;
70-
}
71-
}
72-
73-
return true;
74-
}
75-
76-
public function loadMetadataForClass($className, \Doctrine\Persistence\Mapping\ClassMetadata $metadata): void
77-
{
78-
assert($metadata instanceof ClassMetadata);
79-
$reflClass = $metadata->getReflectionClass();
80-
81-
$classAnnotations = $this->reader->getClassAnnotations($reflClass);
82-
83-
$documentAnnot = null;
84-
foreach ($classAnnotations as $annot) {
85-
$classAnnotations[$annot::class] = $annot;
86-
87-
if ($annot instanceof ODM\AbstractDocument) {
88-
if ($documentAnnot !== null) {
89-
throw MappingException::classCanOnlyBeMappedByOneAbstractDocument($className, $documentAnnot, $annot);
90-
}
91-
92-
$documentAnnot = $annot;
93-
}
94-
95-
// non-document class annotations
96-
if ($annot instanceof ODM\AbstractIndex) {
97-
$this->addIndex($metadata, $annot);
98-
}
99-
100-
if ($annot instanceof ODM\Indexes) {
101-
trigger_deprecation(
102-
'doctrine/mongodb-odm',
103-
'2.2',
104-
'The "@Indexes" annotation used in class "%s" is deprecated. Specify all "@Index" and "@UniqueIndex" annotations on the class.',
105-
$className,
106-
);
107-
$value = $annot->value;
108-
foreach (is_array($value) ? $value : [$value] as $index) {
109-
$this->addIndex($metadata, $index);
110-
}
111-
} elseif ($annot instanceof ODM\InheritanceType) {
112-
$metadata->setInheritanceType(constant(ClassMetadata::class . '::INHERITANCE_TYPE_' . $annot->value));
113-
} elseif ($annot instanceof ODM\DiscriminatorField) {
114-
$metadata->setDiscriminatorField($annot->value);
115-
} elseif ($annot instanceof ODM\DiscriminatorMap) {
116-
$value = $annot->value;
117-
assert(is_array($value));
118-
$metadata->setDiscriminatorMap($value);
119-
} elseif ($annot instanceof ODM\DiscriminatorValue) {
120-
$metadata->setDiscriminatorValue($annot->value);
121-
} elseif ($annot instanceof ODM\ChangeTrackingPolicy) {
122-
$metadata->setChangeTrackingPolicy(constant(ClassMetadata::class . '::CHANGETRACKING_' . $annot->value));
123-
} elseif ($annot instanceof ODM\DefaultDiscriminatorValue) {
124-
$metadata->setDefaultDiscriminatorValue($annot->value);
125-
} elseif ($annot instanceof ODM\ReadPreference) {
126-
$metadata->setReadPreference($annot->value, $annot->tags ?? []);
127-
} elseif ($annot instanceof ODM\Validation) {
128-
if (isset($annot->validator)) {
129-
try {
130-
$validatorBson = fromJSON($annot->validator);
131-
} catch (UnexpectedValueException $e) {
132-
throw MappingException::schemaValidationError($e->getCode(), $e->getMessage(), $className, 'validator');
133-
}
134-
135-
$validator = toPHP($validatorBson, []);
136-
$metadata->setValidator($validator);
137-
}
138-
139-
if (isset($annot->action)) {
140-
$metadata->setValidationAction($annot->action);
141-
}
142-
143-
if (isset($annot->level)) {
144-
$metadata->setValidationLevel($annot->level);
145-
}
146-
}
147-
}
148-
149-
if ($documentAnnot === null) {
150-
throw MappingException::classIsNotAValidDocument($className);
151-
}
152-
153-
if ($documentAnnot instanceof ODM\MappedSuperclass) {
154-
$metadata->isMappedSuperclass = true;
155-
} elseif ($documentAnnot instanceof ODM\EmbeddedDocument) {
156-
$metadata->isEmbeddedDocument = true;
157-
} elseif ($documentAnnot instanceof ODM\QueryResultDocument) {
158-
$metadata->isQueryResultDocument = true;
159-
} elseif ($documentAnnot instanceof ODM\View) {
160-
if (! $documentAnnot->rootClass) {
161-
throw MappingException::viewWithoutRootClass($className);
162-
}
163-
164-
if (! class_exists($documentAnnot->rootClass)) {
165-
throw MappingException::viewRootClassNotFound($className, $documentAnnot->rootClass);
166-
}
167-
168-
$metadata->markViewOf($documentAnnot->rootClass);
169-
} elseif ($documentAnnot instanceof ODM\File) {
170-
$metadata->isFile = true;
171-
172-
if ($documentAnnot->chunkSizeBytes !== null) {
173-
$metadata->setChunkSizeBytes($documentAnnot->chunkSizeBytes);
174-
}
175-
}
176-
177-
if (isset($documentAnnot->db)) {
178-
$metadata->setDatabase($documentAnnot->db);
179-
}
180-
181-
if (isset($documentAnnot->collection)) {
182-
$metadata->setCollection($documentAnnot->collection);
183-
}
184-
185-
if (isset($documentAnnot->view)) {
186-
$metadata->setCollection($documentAnnot->view);
187-
}
188-
189-
// Store bucketName as collection name for GridFS files
190-
if (isset($documentAnnot->bucketName)) {
191-
$metadata->setBucketName($documentAnnot->bucketName);
192-
}
193-
194-
if (isset($documentAnnot->repositoryClass)) {
195-
$metadata->setCustomRepositoryClass($documentAnnot->repositoryClass);
196-
}
197-
198-
if (isset($documentAnnot->writeConcern)) {
199-
$metadata->setWriteConcern($documentAnnot->writeConcern);
200-
}
201-
202-
if (isset($documentAnnot->indexes) && count($documentAnnot->indexes)) {
203-
trigger_deprecation(
204-
'doctrine/mongodb-odm',
205-
'2.2',
206-
'The "indexes" parameter in the "%s" annotation for class "%s" is deprecated. Specify all "@Index" and "@UniqueIndex" annotations on the class.',
207-
$className,
208-
$documentAnnot::class,
209-
);
210-
211-
foreach ($documentAnnot->indexes as $index) {
212-
$this->addIndex($metadata, $index);
213-
}
214-
}
215-
216-
if (! empty($documentAnnot->readOnly)) {
217-
$metadata->markReadOnly();
218-
}
219-
220-
foreach ($reflClass->getProperties() as $property) {
221-
if (
222-
($metadata->isMappedSuperclass && ! $property->isPrivate())
223-
||
224-
($metadata->isInheritedField($property->name) && $property->getDeclaringClass()->name !== $metadata->name)
225-
) {
226-
continue;
227-
}
228-
229-
$indexes = [];
230-
$mapping = ['fieldName' => $property->getName()];
231-
$fieldAnnot = null;
232-
233-
foreach ($this->reader->getPropertyAnnotations($property) as $annot) {
234-
if ($annot instanceof ODM\AbstractField) {
235-
$fieldAnnot = $annot;
236-
}
237-
238-
if ($annot instanceof ODM\AbstractIndex) {
239-
$indexes[] = $annot;
240-
}
241-
242-
if ($annot instanceof ODM\Indexes) {
243-
$value = $annot->value;
244-
foreach (is_array($value) ? $value : [$value] as $index) {
245-
$indexes[] = $index;
246-
}
247-
} elseif ($annot instanceof ODM\AlsoLoad) {
248-
$mapping['alsoLoadFields'] = (array) $annot->value;
249-
} elseif ($annot instanceof ODM\Version) {
250-
$mapping['version'] = true;
251-
} elseif ($annot instanceof ODM\Lock) {
252-
$mapping['lock'] = true;
253-
}
254-
}
255-
256-
if ($fieldAnnot) {
257-
$mapping = array_replace($mapping, (array) $fieldAnnot);
258-
$metadata->mapField($mapping);
259-
}
260-
261-
if (! $indexes) {
262-
continue;
263-
}
264-
265-
foreach ($indexes as $index) {
266-
$name = $mapping['name'] ?? $mapping['fieldName'];
267-
$keys = [$name => $index->order ?: 'asc'];
268-
$this->addIndex($metadata, $index, $keys);
269-
}
270-
}
271-
272-
// Set shard key after all fields to ensure we mapped all its keys
273-
if (isset($classAnnotations[ShardKey::class])) {
274-
assert($classAnnotations[ShardKey::class] instanceof ShardKey);
275-
$this->setShardKey($metadata, $classAnnotations[ShardKey::class]);
276-
}
277-
278-
foreach ($reflClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
279-
/* Filter for the declaring class only. Callbacks from parent
280-
* classes will already be registered.
281-
*/
282-
if ($method->getDeclaringClass()->name !== $reflClass->name) {
283-
continue;
284-
}
285-
286-
foreach ($this->reader->getMethodAnnotations($method) as $annot) {
287-
if ($annot instanceof ODM\AlsoLoad) {
288-
$metadata->registerAlsoLoadMethod($method->getName(), $annot->value);
289-
}
290-
291-
if (! isset($classAnnotations[ODM\HasLifecycleCallbacks::class])) {
292-
continue;
293-
}
294-
295-
if ($annot instanceof ODM\PrePersist) {
296-
$metadata->addLifecycleCallback($method->getName(), Events::prePersist);
297-
} elseif ($annot instanceof ODM\PostPersist) {
298-
$metadata->addLifecycleCallback($method->getName(), Events::postPersist);
299-
} elseif ($annot instanceof ODM\PreUpdate) {
300-
$metadata->addLifecycleCallback($method->getName(), Events::preUpdate);
301-
} elseif ($annot instanceof ODM\PostUpdate) {
302-
$metadata->addLifecycleCallback($method->getName(), Events::postUpdate);
303-
} elseif ($annot instanceof ODM\PreRemove) {
304-
$metadata->addLifecycleCallback($method->getName(), Events::preRemove);
305-
} elseif ($annot instanceof ODM\PostRemove) {
306-
$metadata->addLifecycleCallback($method->getName(), Events::postRemove);
307-
} elseif ($annot instanceof ODM\PreLoad) {
308-
$metadata->addLifecycleCallback($method->getName(), Events::preLoad);
309-
} elseif ($annot instanceof ODM\PostLoad) {
310-
$metadata->addLifecycleCallback($method->getName(), Events::postLoad);
311-
} elseif ($annot instanceof ODM\PreFlush) {
312-
$metadata->addLifecycleCallback($method->getName(), Events::preFlush);
313-
}
314-
}
315-
}
316-
}
317-
318-
/**
319-
* @param ClassMetadata<object> $class
320-
* @param array<string, int|string> $keys
321-
*/
322-
private function addIndex(ClassMetadata $class, AbstractIndex $index, array $keys = []): void
323-
{
324-
$keys = array_merge($keys, $index->keys);
325-
$options = [];
326-
$allowed = ['name', 'background', 'unique', 'sparse', 'expireAfterSeconds'];
327-
foreach ($allowed as $name) {
328-
if (! isset($index->$name)) {
329-
continue;
330-
}
331-
332-
$options[$name] = $index->$name;
333-
}
334-
335-
if (! empty($index->partialFilterExpression)) {
336-
$options['partialFilterExpression'] = $index->partialFilterExpression;
337-
}
338-
339-
$options = array_merge($options, $index->options);
340-
$class->addIndex($keys, $options);
341-
}
342-
343-
/**
344-
* @param ClassMetadata<object> $class
345-
*
346-
* @throws MappingException
347-
*/
348-
private function setShardKey(ClassMetadata $class, ODM\ShardKey $shardKey): void
349-
{
350-
$options = [];
351-
$allowed = ['unique', 'numInitialChunks'];
352-
foreach ($allowed as $name) {
353-
if (! isset($shardKey->$name)) {
354-
continue;
355-
}
356-
357-
$options[$name] = $shardKey->$name;
358-
}
359-
360-
$class->setShardKey($shardKey->keys, $options);
361-
}
362-
363-
/**
364-
* Retrieve the current annotation reader
365-
*
366-
* @return Reader
367-
*/
368-
public function getReader()
369-
{
370-
trigger_deprecation(
371-
'doctrine/mongodb-odm',
372-
'2.4',
373-
'%s is deprecated with no replacement',
374-
__METHOD__,
375-
);
376-
377-
return $this->reader;
378-
}
379-
38038
/**
38139
* Factory method for the Annotation Driver
38240
*
@@ -387,5 +45,3 @@ public static function create($paths = [], ?Reader $reader = null): AnnotationDr
38745
return new self($reader ?? new AnnotationReader(), $paths);
38846
}
38947
}
390-
391-
interface_exists(\Doctrine\Persistence\Mapping\ClassMetadata::class);

0 commit comments

Comments
 (0)