Skip to content

Commit 648bcc2

Browse files
committed
Extract annotations-agnostic code in its own class
1 parent d1c22c8 commit 648bcc2

File tree

9 files changed

+289
-252
lines changed

9 files changed

+289
-252
lines changed

UPGRADE.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ awareness about deprecated code.
66
- Use of our low-overhead runtime deprecation API, details:
77
https://github.com/doctrine/deprecations/
88

9+
# Upgrade to 2.4
10+
11+
## Deprecated `AnnotationDriver`
12+
13+
Since attributes were introduced in PHP 8.0, annotations are deprecated. Extend
14+
`ColocatedMappingDriver` directly instead. This will involve
15+
implementing `isTransient()` as well as `__construct()` and `getReader()` to
16+
retain backward compatibility.
17+
918
# Upgrade to 2.3
1019

1120
## Deprecated using short namespace alias syntax in favor of `::class` syntax.

docs/en/reference/index.rst

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Mapping Driver
159159

160160
In order to load ``ClassMetadata`` instances you can use the ``Doctrine\Persistence\Mapping\Driver\MappingDriver``
161161
interface. This is the interface that does the core loading of mapping information from wherever they are stored.
162-
That may be in files, annotations, yaml, xml, etc.
162+
That may be in files, attributes, yaml, xml, etc.
163163

164164
.. code-block:: php
165165
@@ -174,8 +174,8 @@ That may be in files, annotations, yaml, xml, etc.
174174
public function isTransient($className);
175175
}
176176
177-
The Doctrine Persistence project offers a few base implementations that make it easy to implement your own XML,
178-
Annotations or YAML drivers.
177+
The Doctrine Persistence project offers a few base implementations that
178+
make it easy to implement your own XML, Attributes or YAML drivers.
179179

180180
FileDriver
181181
----------
@@ -233,45 +233,9 @@ AnnotationDriver
233233

234234
.. note::
235235

236-
This driver requires the ``doctrine/annotations`` project. You can install it with composer.
236+
This driver requires the ``doctrine/annotations`` project and is
237+
deprecated because of that.
237238

238-
.. code-block:: php
239-
240-
composer require doctrine/annotations
241-
242-
The AnnotationDriver reads the mapping metadata from docblock annotations.
243-
244-
.. code-block:: php
245-
246-
final class MyAnnotationDriver extends AnnotationDriver
247-
{
248-
public function loadMetadataForClass($className, ClassMetadata $metadata)
249-
{
250-
/** @var ClassMetadata $class */
251-
$reflClass = $class->getReflectionClass();
252-
253-
$classAnnotations = $this->reader->getClassAnnotations($reflClass);
254-
255-
// Use the reader to read annotations from your classes to then populate the $metadata instance.
256-
}
257-
}
258-
259-
Now you can use it like the following:
260-
261-
.. code-block:: php
262-
263-
use App\Model\User;
264-
use Doctrine\Annotations\AnnotationReader;
265-
use Doctrine\Persistence\Mapping\ClassMetadata;
266-
267-
$annotationReader = new AnnotationReader();
268-
269-
$annotationDriver = new AnnotationDriver($annotationReader, '/path/to/classes/with/annotations');
270-
271-
$classMetadata = new ClassMetadata();
272-
273-
// looks for a PHP file at /path/to/classes/with/annotations/App/Model/User.php
274-
$annotationDriver->loadMetadataForClass(User::class, $classMetadata);
275239

276240
PHPDriver
277241
---------

lib/Doctrine/Persistence/Mapping/Driver/AnnotationDriver.php

Lines changed: 4 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,16 @@
33
namespace Doctrine\Persistence\Mapping\Driver;
44

55
use Doctrine\Common\Annotations\Reader;
6-
use Doctrine\Persistence\Mapping\MappingException;
7-
use FilesystemIterator;
8-
use RecursiveDirectoryIterator;
9-
use RecursiveIteratorIterator;
10-
use RecursiveRegexIterator;
116
use ReflectionClass;
12-
use RegexIterator;
137

14-
use function array_merge;
15-
use function array_unique;
16-
use function assert;
178
use function get_class;
18-
use function get_declared_classes;
19-
use function in_array;
20-
use function is_dir;
21-
use function preg_match;
22-
use function preg_quote;
23-
use function realpath;
24-
use function str_replace;
25-
use function strpos;
269

2710
/**
2811
* The AnnotationDriver reads the mapping metadata from docblock annotations.
12+
*
13+
* @deprecated extend ColocatedMappingDriver directly instead.
2914
*/
30-
abstract class AnnotationDriver implements MappingDriver
15+
abstract class AnnotationDriver extends ColocatedMappingDriver implements MappingDriver
3116
{
3217
/**
3318
* The annotation reader.
@@ -36,35 +21,6 @@ abstract class AnnotationDriver implements MappingDriver
3621
*/
3722
protected $reader;
3823

39-
/**
40-
* The paths where to look for mapping files.
41-
*
42-
* @var string[]
43-
*/
44-
protected $paths = [];
45-
46-
/**
47-
* The paths excluded from path where to look for mapping files.
48-
*
49-
* @var string[]
50-
*/
51-
protected $excludePaths = [];
52-
53-
/**
54-
* The file extension of mapping documents.
55-
*
56-
* @var string
57-
*/
58-
protected $fileExtension = '.php';
59-
60-
/**
61-
* Cache for AnnotationDriver#getAllClassNames().
62-
*
63-
* @var string[]|null
64-
* @psalm-var list<class-string>|null
65-
*/
66-
protected $classNames;
67-
6824
/**
6925
* Name of the entity annotations as keys.
7026
*
@@ -82,55 +38,8 @@ abstract class AnnotationDriver implements MappingDriver
8238
public function __construct($reader, $paths = null)
8339
{
8440
$this->reader = $reader;
85-
if (! $paths) {
86-
return;
87-
}
8841

89-
$this->addPaths((array) $paths);
90-
}
91-
92-
/**
93-
* Appends lookup paths to metadata driver.
94-
*
95-
* @param string[] $paths
96-
*
97-
* @return void
98-
*/
99-
public function addPaths(array $paths)
100-
{
101-
$this->paths = array_unique(array_merge($this->paths, $paths));
102-
}
103-
104-
/**
105-
* Retrieves the defined metadata lookup paths.
106-
*
107-
* @return string[]
108-
*/
109-
public function getPaths()
110-
{
111-
return $this->paths;
112-
}
113-
114-
/**
115-
* Append exclude lookup paths to metadata driver.
116-
*
117-
* @param string[] $paths
118-
*
119-
* @return void
120-
*/
121-
public function addExcludePaths(array $paths)
122-
{
123-
$this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
124-
}
125-
126-
/**
127-
* Retrieve the defined metadata lookup exclude paths.
128-
*
129-
* @return string[]
130-
*/
131-
public function getExcludePaths()
132-
{
133-
return $this->excludePaths;
42+
parent::__construct(...(array) $paths);
13443
}
13544

13645
/**
@@ -144,34 +53,6 @@ public function getReader()
14453
}
14554

14655
/**
147-
* Gets the file extension used to look for mapping files under.
148-
*
149-
* @return string
150-
*/
151-
public function getFileExtension()
152-
{
153-
return $this->fileExtension;
154-
}
155-
156-
/**
157-
* Sets the file extension used to look for mapping files under.
158-
*
159-
* @param string $fileExtension The file extension to set.
160-
*
161-
* @return void
162-
*/
163-
public function setFileExtension($fileExtension)
164-
{
165-
$this->fileExtension = $fileExtension;
166-
}
167-
168-
/**
169-
* Returns whether the class with the specified name is transient. Only non-transient
170-
* classes, that is entities and mapped superclasses, should have their metadata loaded.
171-
*
172-
* A class is non-transient if it is annotated with an annotation
173-
* from the {@see AnnotationDriver::entityAnnotationClasses}.
174-
*
17556
* {@inheritDoc}
17657
*/
17758
public function isTransient($className)
@@ -186,75 +67,4 @@ public function isTransient($className)
18667

18768
return true;
18869
}
189-
190-
/**
191-
* {@inheritDoc}
192-
*/
193-
public function getAllClassNames()
194-
{
195-
if ($this->classNames !== null) {
196-
return $this->classNames;
197-
}
198-
199-
if (! $this->paths) {
200-
throw MappingException::pathRequired();
201-
}
202-
203-
$classes = [];
204-
$includedFiles = [];
205-
206-
foreach ($this->paths as $path) {
207-
if (! is_dir($path)) {
208-
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
209-
}
210-
211-
$iterator = new RegexIterator(
212-
new RecursiveIteratorIterator(
213-
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
214-
RecursiveIteratorIterator::LEAVES_ONLY
215-
),
216-
'/^.+' . preg_quote($this->fileExtension) . '$/i',
217-
RecursiveRegexIterator::GET_MATCH
218-
);
219-
220-
foreach ($iterator as $file) {
221-
$sourceFile = $file[0];
222-
223-
if (preg_match('(^phar:)i', $sourceFile) === 0) {
224-
$sourceFile = realpath($sourceFile);
225-
}
226-
227-
foreach ($this->excludePaths as $excludePath) {
228-
$realExcludePath = realpath($excludePath);
229-
assert($realExcludePath !== false);
230-
$exclude = str_replace('\\', '/', $realExcludePath);
231-
$current = str_replace('\\', '/', $sourceFile);
232-
233-
if (strpos($current, $exclude) !== false) {
234-
continue 2;
235-
}
236-
}
237-
238-
require_once $sourceFile;
239-
240-
$includedFiles[] = $sourceFile;
241-
}
242-
}
243-
244-
$declared = get_declared_classes();
245-
246-
foreach ($declared as $className) {
247-
$rc = new ReflectionClass($className);
248-
$sourceFile = $rc->getFileName();
249-
if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) {
250-
continue;
251-
}
252-
253-
$classes[] = $className;
254-
}
255-
256-
$this->classNames = $classes;
257-
258-
return $classes;
259-
}
26070
}

0 commit comments

Comments
 (0)