Skip to content

Commit 680e4b4

Browse files
mbabkerfranmomu
authored andcommitted
Make the annotation/attribute reader optional in the extension metadata factory
1 parent 2ba8f94 commit 680e4b4

File tree

3 files changed

+45
-24
lines changed

3 files changed

+45
-24
lines changed

rector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
$rectorConfig->skip([
2828
TypedPropertyFromAssignsRector::class => [
29+
__DIR__.'/src/Mapping/MappedEventSubscriber.php', // Rector is trying to set a type on the $annotationReader property which requires a union type, not supported on PHP 7.4
2930
__DIR__.'/tests/Gedmo/Wrapper/Fixture/Entity/CompositeRelation.php', // @todo: remove this when https://github.com/doctrine/orm/issues/8255 is solved
3031
],
3132
]);

src/Mapping/ExtensionMetadataFactory.php

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,20 @@ class ExtensionMetadataFactory
6161
protected $extensionNamespace;
6262

6363
/**
64-
* Custom annotation reader
64+
* Metadata annotation reader
6565
*
66-
* @var Reader|AttributeReader|object
66+
* @var Reader|AttributeReader|object|null
6767
*/
6868
protected $annotationReader;
6969

7070
private ?CacheItemPoolInterface $cacheItemPool = null;
7171

7272
/**
73-
* @param Reader|AttributeReader|object $annotationReader
73+
* @param Reader|AttributeReader|object|null $annotationReader
7474
*/
75-
public function __construct(ObjectManager $objectManager, string $extensionNamespace, object $annotationReader, ?CacheItemPoolInterface $cacheItemPool = null)
75+
public function __construct(ObjectManager $objectManager, string $extensionNamespace, ?object $annotationReader = null, ?CacheItemPoolInterface $cacheItemPool = null)
7676
{
77-
if (!$annotationReader instanceof Reader && !$annotationReader instanceof AttributeReader) {
77+
if (null !== $annotationReader && !$annotationReader instanceof Reader && !$annotationReader instanceof AttributeReader) {
7878
trigger_deprecation(
7979
'gedmo/doctrine-extensions',
8080
'3.11',
@@ -98,7 +98,7 @@ public function __construct(ObjectManager $objectManager, string $extensionNames
9898
*
9999
* @param ClassMetadata&(DocumentClassMetadata|EntityClassMetadata|LegacyEntityClassMetadata) $meta
100100
*
101-
* @return array<string, mixed> the metatada configuration
101+
* @return array<string, mixed> the metadata configuration
102102
*/
103103
public function getExtensionMetadata($meta)
104104
{
@@ -209,8 +209,20 @@ protected function getDriver($omDriver)
209209
// create driver instance
210210
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\\'.$driverName;
211211
if (!class_exists($driverClassName)) {
212-
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Annotation';
212+
$originalDriverClassName = $driverClassName;
213+
214+
// try to fall back to either an annotation or attribute driver depending on the available dependencies
215+
if (interface_exists(Reader::class)) {
216+
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Annotation';
217+
} elseif (\PHP_VERSION_ID >= 80000) {
218+
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Attribute';
219+
}
220+
213221
if (!class_exists($driverClassName)) {
222+
if ($originalDriverClassName !== $driverClassName) {
223+
throw new RuntimeException("Failed to create mapping driver: ({$originalDriverClassName}), the extension driver nor a fallback annotation or attribute driver could be found.");
224+
}
225+
214226
throw new RuntimeException("Failed to fallback to annotation driver: ({$driverClassName}), extension driver was not found.");
215227
}
216228
}
@@ -227,14 +239,20 @@ protected function getDriver($omDriver)
227239
}
228240
}
229241

230-
if ($driver instanceof AttributeDriverInterface) {
231-
if ($this->annotationReader instanceof AttributeReader) {
232-
$driver->setAnnotationReader($this->annotationReader);
242+
if ($driver instanceof AnnotationDriverInterface) {
243+
if (null === $this->annotationReader) {
244+
throw new RuntimeException("Cannot use metadata driver ({$driverClassName}), an annotation or attribute reader was not provided.");
245+
}
246+
247+
if ($driver instanceof AttributeDriverInterface) {
248+
if ($this->annotationReader instanceof AttributeReader) {
249+
$driver->setAnnotationReader($this->annotationReader);
250+
} else {
251+
$driver->setAnnotationReader(new AttributeAnnotationReader(new AttributeReader(), $this->annotationReader));
252+
}
233253
} else {
234-
$driver->setAnnotationReader(new AttributeAnnotationReader(new AttributeReader(), $this->annotationReader));
254+
$driver->setAnnotationReader($this->annotationReader);
235255
}
236-
} elseif ($driver instanceof AnnotationDriverInterface) {
237-
$driver->setAnnotationReader($this->annotationReader);
238256
}
239257
}
240258

src/Mapping/MappedEventSubscriber.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use Doctrine\Persistence\Mapping\ClassMetadata;
2424
use Doctrine\Persistence\ObjectManager;
2525
use Gedmo\Exception\InvalidArgumentException;
26-
use Gedmo\Exception\RuntimeException;
2726
use Gedmo\Mapping\Driver\AttributeReader;
2827
use Gedmo\Mapping\Event\AdapterInterface;
2928
use Gedmo\ReferenceIntegrity\Mapping\Validator as ReferenceIntegrityValidator;
@@ -81,14 +80,14 @@ abstract class MappedEventSubscriber implements EventSubscriber
8180
/**
8281
* Custom annotation reader
8382
*
84-
* @var Reader|AttributeReader|object|null
83+
* @var Reader|AttributeReader|object|false|null
8584
*/
86-
private $annotationReader;
85+
private $annotationReader = false;
8786

8887
/**
89-
* @var Reader|AttributeReader|null
88+
* @var Reader|AttributeReader|false|null
9089
*/
91-
private static $defaultAnnotationReader;
90+
private static $defaultAnnotationReader = false;
9291

9392
/**
9493
* @var CacheItemPoolInterface|null
@@ -171,8 +170,8 @@ public function getExtensionMetadataFactory(ObjectManager $objectManager)
171170
{
172171
$oid = spl_object_id($objectManager);
173172
if (!isset($this->extensionMetadataFactory[$oid])) {
174-
if (null === $this->annotationReader) {
175-
// create default annotation reader for extensions
173+
if (false === $this->annotationReader) {
174+
// create default annotation/attribute reader for extensions
176175
$this->annotationReader = $this->getDefaultAnnotationReader();
177176
}
178177
$this->extensionMetadataFactory[$oid] = new ExtensionMetadataFactory(
@@ -307,19 +306,22 @@ protected function setFieldValue(AdapterInterface $adapter, $object, $field, $ol
307306
}
308307

309308
/**
310-
* Create default annotation reader for extensions
309+
* Get the default annotation or attribute reader for extensions, creating it if necessary.
311310
*
312-
* @return Reader|AttributeReader
311+
* If a reader cannot be created due to missing requirements, no default will be set as the reader is only required for annotation or attribute metadata,
312+
* and the {@see ExtensionMetadataFactory} can handle raising an error if it tries to create a mapping driver that requires this reader.
313+
*
314+
* @return Reader|AttributeReader|null
313315
*/
314316
private function getDefaultAnnotationReader()
315317
{
316-
if (null === self::$defaultAnnotationReader) {
318+
if (false === self::$defaultAnnotationReader) {
317319
if (class_exists(PsrCachedReader::class)) {
318320
self::$defaultAnnotationReader = new PsrCachedReader(new AnnotationReader(), new ArrayAdapter());
319321
} elseif (\PHP_VERSION_ID >= 80000) {
320322
self::$defaultAnnotationReader = new AttributeReader();
321323
} else {
322-
throw new RuntimeException(sprintf('Cannot create a default annotation reader in "%1$s". Ensure you are running PHP 8 to use attributes, have installed the "doctrine/annotations" package, or call "%1$s::setAnnotationReader()" with a configured reader.', self::class));
324+
self::$defaultAnnotationReader = null;
323325
}
324326
}
325327

0 commit comments

Comments
 (0)