Skip to content

Commit

Permalink
Make the annotation/attribute reader optional in the extension metada…
Browse files Browse the repository at this point in the history
…ta factory
  • Loading branch information
mbabker authored and franmomu committed Dec 5, 2023
1 parent 2ba8f94 commit 680e4b4
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 24 deletions.
1 change: 1 addition & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

$rectorConfig->skip([
TypedPropertyFromAssignsRector::class => [
__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
__DIR__.'/tests/Gedmo/Wrapper/Fixture/Entity/CompositeRelation.php', // @todo: remove this when https://github.com/doctrine/orm/issues/8255 is solved
],
]);
Expand Down
44 changes: 31 additions & 13 deletions src/Mapping/ExtensionMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,20 @@ class ExtensionMetadataFactory
protected $extensionNamespace;

/**
* Custom annotation reader
* Metadata annotation reader
*
* @var Reader|AttributeReader|object
* @var Reader|AttributeReader|object|null
*/
protected $annotationReader;

private ?CacheItemPoolInterface $cacheItemPool = null;

/**
* @param Reader|AttributeReader|object $annotationReader
* @param Reader|AttributeReader|object|null $annotationReader
*/
public function __construct(ObjectManager $objectManager, string $extensionNamespace, object $annotationReader, ?CacheItemPoolInterface $cacheItemPool = null)
public function __construct(ObjectManager $objectManager, string $extensionNamespace, ?object $annotationReader = null, ?CacheItemPoolInterface $cacheItemPool = null)
{
if (!$annotationReader instanceof Reader && !$annotationReader instanceof AttributeReader) {
if (null !== $annotationReader && !$annotationReader instanceof Reader && !$annotationReader instanceof AttributeReader) {
trigger_deprecation(
'gedmo/doctrine-extensions',
'3.11',
Expand All @@ -98,7 +98,7 @@ public function __construct(ObjectManager $objectManager, string $extensionNames
*
* @param ClassMetadata&(DocumentClassMetadata|EntityClassMetadata|LegacyEntityClassMetadata) $meta
*
* @return array<string, mixed> the metatada configuration
* @return array<string, mixed> the metadata configuration
*/
public function getExtensionMetadata($meta)
{
Expand Down Expand Up @@ -209,8 +209,20 @@ protected function getDriver($omDriver)
// create driver instance
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\\'.$driverName;
if (!class_exists($driverClassName)) {
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Annotation';
$originalDriverClassName = $driverClassName;

// try to fall back to either an annotation or attribute driver depending on the available dependencies
if (interface_exists(Reader::class)) {
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Annotation';
} elseif (\PHP_VERSION_ID >= 80000) {
$driverClassName = $this->extensionNamespace.'\Mapping\Driver\Attribute';
}

if (!class_exists($driverClassName)) {
if ($originalDriverClassName !== $driverClassName) {
throw new RuntimeException("Failed to create mapping driver: ({$originalDriverClassName}), the extension driver nor a fallback annotation or attribute driver could be found.");
}

throw new RuntimeException("Failed to fallback to annotation driver: ({$driverClassName}), extension driver was not found.");
}
}
Expand All @@ -227,14 +239,20 @@ protected function getDriver($omDriver)
}
}

if ($driver instanceof AttributeDriverInterface) {
if ($this->annotationReader instanceof AttributeReader) {
$driver->setAnnotationReader($this->annotationReader);
if ($driver instanceof AnnotationDriverInterface) {
if (null === $this->annotationReader) {
throw new RuntimeException("Cannot use metadata driver ({$driverClassName}), an annotation or attribute reader was not provided.");
}

if ($driver instanceof AttributeDriverInterface) {
if ($this->annotationReader instanceof AttributeReader) {
$driver->setAnnotationReader($this->annotationReader);
} else {
$driver->setAnnotationReader(new AttributeAnnotationReader(new AttributeReader(), $this->annotationReader));
}
} else {
$driver->setAnnotationReader(new AttributeAnnotationReader(new AttributeReader(), $this->annotationReader));
$driver->setAnnotationReader($this->annotationReader);
}
} elseif ($driver instanceof AnnotationDriverInterface) {
$driver->setAnnotationReader($this->annotationReader);
}
}

Expand Down
24 changes: 13 additions & 11 deletions src/Mapping/MappedEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use Doctrine\Persistence\Mapping\ClassMetadata;
use Doctrine\Persistence\ObjectManager;
use Gedmo\Exception\InvalidArgumentException;
use Gedmo\Exception\RuntimeException;
use Gedmo\Mapping\Driver\AttributeReader;
use Gedmo\Mapping\Event\AdapterInterface;
use Gedmo\ReferenceIntegrity\Mapping\Validator as ReferenceIntegrityValidator;
Expand Down Expand Up @@ -81,14 +80,14 @@ abstract class MappedEventSubscriber implements EventSubscriber
/**
* Custom annotation reader
*
* @var Reader|AttributeReader|object|null
* @var Reader|AttributeReader|object|false|null
*/
private $annotationReader;
private $annotationReader = false;

/**
* @var Reader|AttributeReader|null
* @var Reader|AttributeReader|false|null
*/
private static $defaultAnnotationReader;
private static $defaultAnnotationReader = false;

/**
* @var CacheItemPoolInterface|null
Expand Down Expand Up @@ -171,8 +170,8 @@ public function getExtensionMetadataFactory(ObjectManager $objectManager)
{
$oid = spl_object_id($objectManager);
if (!isset($this->extensionMetadataFactory[$oid])) {
if (null === $this->annotationReader) {
// create default annotation reader for extensions
if (false === $this->annotationReader) {
// create default annotation/attribute reader for extensions
$this->annotationReader = $this->getDefaultAnnotationReader();
}
$this->extensionMetadataFactory[$oid] = new ExtensionMetadataFactory(
Expand Down Expand Up @@ -307,19 +306,22 @@ protected function setFieldValue(AdapterInterface $adapter, $object, $field, $ol
}

/**
* Create default annotation reader for extensions
* Get the default annotation or attribute reader for extensions, creating it if necessary.
*
* @return Reader|AttributeReader
* 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,
* and the {@see ExtensionMetadataFactory} can handle raising an error if it tries to create a mapping driver that requires this reader.
*
* @return Reader|AttributeReader|null
*/
private function getDefaultAnnotationReader()
{
if (null === self::$defaultAnnotationReader) {
if (false === self::$defaultAnnotationReader) {
if (class_exists(PsrCachedReader::class)) {
self::$defaultAnnotationReader = new PsrCachedReader(new AnnotationReader(), new ArrayAdapter());
} elseif (\PHP_VERSION_ID >= 80000) {
self::$defaultAnnotationReader = new AttributeReader();
} else {
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));
self::$defaultAnnotationReader = null;
}
}

Expand Down

0 comments on commit 680e4b4

Please sign in to comment.