From b82af95b9868389c69f2da9807111f30f347c79a Mon Sep 17 00:00:00 2001 From: Alexander Rakushin Date: Thu, 27 Jul 2023 20:55:22 +0300 Subject: [PATCH] Add options in listeners: forceUseAttributeReader and separateXmlMapping --- CHANGELOG.md | 2 + src/Mapping/Driver/File.php | 52 ++++++++++++++++++++---- src/Mapping/ExtensionMetadataFactory.php | 35 +++++++++++++--- src/Mapping/MappedEventSubscriber.php | 28 ++++++++++++- 4 files changed, 102 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb2725a72e..8362df3fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ a release. --- ## [Unreleased] +### Fixed +- Mapping Driver: Configure usage separately with Doctrine `.orm.xml` -> `.gedmo.xml` files, also add an alternative option - force the use of AttributeReader and ignore the configuration of the Doctrine chain driver (#2613) ## [3.12.0] - 2023-07-08 ### Added diff --git a/src/Mapping/Driver/File.php b/src/Mapping/Driver/File.php index 495accfebc..40ca8f2ab4 100644 --- a/src/Mapping/Driver/File.php +++ b/src/Mapping/Driver/File.php @@ -116,20 +116,56 @@ abstract protected function _loadMappingFile($file); */ protected function _getMapping($className) { - // try loading mapping from original driver first $mapping = null; - if (null !== $this->_originalDriver) { - if ($this->_originalDriver instanceof FileDriver) { - $mapping = $this->_originalDriver->getElement($className); - } + $separatedFile = strpos($this->locator->getFileExtension(), '.gedmo') === 0; + + if($separatedFile){ + // try loading mapping from gedmo driver first + $mapping = $this->getMappingFromGedmoFileDriver($className); } - // if no mapping found try to load mapping file again + // if no mapping found try to load mapping file from original driver again if (null === $mapping) { - $yaml = $this->_loadMappingFile($this->locator->findMappingFile($className)); - $mapping = $yaml[$className]; + // read .orm.xml + $mapping = $this->getMappingFromOriginalDriver($className); + } + if (!$separatedFile && null === $mapping) { + // if no mapping found try to load mapping file again + $mapping = $this->getMappingFromGedmoFileDriver($className); + } + + return $mapping; + } + /** + * Tries to get a mapping for a given class from gedmo driver. + * + * @param string $className + * + * @return array|object|null + */ + private function getMappingFromGedmoFileDriver($className){ + if(!$this->locator->fileExists($className)){ + return null; } + $mapping = $this->_loadMappingFile($this->locator->findMappingFile($className)); + return $mapping[$className] ?? null; + } + + /** + * Tries to get a mapping for a given class from original doctrine driver. + * + * @param string $className + * + * @return array|object|null + */ + private function getMappingFromOriginalDriver($className){ + $mapping = null; + if (null !== $this->_originalDriver) { + if ($this->_originalDriver instanceof FileDriver) { + $mapping = $this->_originalDriver->getElement($className); + } + } return $mapping; } diff --git a/src/Mapping/ExtensionMetadataFactory.php b/src/Mapping/ExtensionMetadataFactory.php index 95909809a7..340399e3cb 100644 --- a/src/Mapping/ExtensionMetadataFactory.php +++ b/src/Mapping/ExtensionMetadataFactory.php @@ -13,6 +13,7 @@ use Doctrine\Common\Annotations\Reader; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as DocumentClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataInfo as EntityClassMetadata; +use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\Persistence\Mapping\ClassMetadata; use Doctrine\Persistence\Mapping\Driver\DefaultFileLocator; use Doctrine\Persistence\Mapping\Driver\MappingDriver; @@ -71,10 +72,22 @@ class ExtensionMetadataFactory */ private $cacheItemPool; + /** + * Ignore doctrine driver class and force use attribute reader for gedmo properties + * @var bool + */ + private $forceUseAttributeReader; + + /** + * Search mapping in .gedmo.xml and does not use doctrine *.orm.xml or *.dcm.xml file + * @var bool + */ + private $separateXmlMapping; + /** * @param Reader|AttributeReader|object $annotationReader */ - public function __construct(ObjectManager $objectManager, string $extensionNamespace, object $annotationReader, ?CacheItemPoolInterface $cacheItemPool = null) + public function __construct(ObjectManager $objectManager, string $extensionNamespace, object $annotationReader, ?CacheItemPoolInterface $cacheItemPool = null, $forceUseAttributeReader = false, $separateXmlMapping = false) { if (!$annotationReader instanceof Reader && !$annotationReader instanceof AttributeReader) { trigger_deprecation( @@ -90,6 +103,9 @@ public function __construct(ObjectManager $objectManager, string $extensionNames $this->objectManager = $objectManager; $this->annotationReader = $annotationReader; $this->extensionNamespace = $extensionNamespace; + $this->forceUseAttributeReader = $forceUseAttributeReader; + $this->separateXmlMapping = $separateXmlMapping; + $omDriver = $objectManager->getConfiguration()->getMetadataDriverImpl(); $this->driver = $this->getDriver($omDriver); $this->cacheItemPool = $cacheItemPool; @@ -155,6 +171,10 @@ public static function getCacheId($className, $extensionNamespace) return str_replace('\\', '_', $className).'_$'.strtoupper(str_replace('\\', '_', $extensionNamespace)).'_CLASSMETADATA'; } + private function getFileExtension($fileExtension) + { + return $this->separateXmlMapping ? str_replace(['.orm.','.dcm.'], '.gedmo.', $fileExtension) : $fileExtension; + } /** * Get the extended driver instance which will * read the metadata required by extension @@ -176,11 +196,12 @@ protected function getDriver($omDriver) $driverName = substr($className, strrpos($className, '\\') + 1); if ($omDriver instanceof MappingDriverChain || 'DriverChain' === $driverName) { $driver = new Chain(); + $attributeDriver = $this->forceUseAttributeReader ? new AttributeDriver([]) : null; foreach ($omDriver->getDrivers() as $namespace => $nestedOmDriver) { - $driver->addDriver($this->getDriver($nestedOmDriver), $namespace); + $driver->addDriver($this->getDriver($attributeDriver ?? $nestedOmDriver), $namespace); } if (null !== $omDriver->getDefaultDriver()) { - $driver->setDefaultDriver($this->getDriver($omDriver->getDefaultDriver())); + $driver->setDefaultDriver($this->getDriver($attributeDriver ?? $omDriver->getDefaultDriver())); } } else { $driverName = substr($driverName, 0, strpos($driverName, 'Driver')); @@ -202,12 +223,14 @@ protected function getDriver($omDriver) $driver->setOriginalDriver($omDriver); if ($driver instanceof FileDriver) { if ($omDriver instanceof MappingDriver) { - $driver->setLocator($omDriver->getLocator()); + $locator = clone $omDriver->getLocator(); + $locator->setFileExtension($this->getFileExtension( $locator->getFileExtension())); + $driver->setLocator($locator); // BC for Doctrine 2.2 } elseif ($isSimplified) { - $driver->setLocator(new SymfonyFileLocator($omDriver->getNamespacePrefixes(), $omDriver->getFileExtension())); + $driver->setLocator(new SymfonyFileLocator($omDriver->getNamespacePrefixes(), $this->getFileExtension( $omDriver->getFileExtension()))); } else { - $driver->setLocator(new DefaultFileLocator($omDriver->getPaths(), $omDriver->getFileExtension())); + $driver->setLocator(new DefaultFileLocator($omDriver->getPaths(), $this->getFileExtension( $omDriver->getFileExtension()))); } } diff --git a/src/Mapping/MappedEventSubscriber.php b/src/Mapping/MappedEventSubscriber.php index f28469dcef..f9da1a1d64 100644 --- a/src/Mapping/MappedEventSubscriber.php +++ b/src/Mapping/MappedEventSubscriber.php @@ -95,12 +95,36 @@ abstract class MappedEventSubscriber implements EventSubscriber */ private $cacheItemPool; + + /** + * Ignore doctrine driver class and force use attribute reader for gedmo properties + * @var bool + */ + private $forceUseAttributeReader = false; + + /** + * Search mapping in .gedmo.xml and does not use doctrine *.orm.xml or *.dcm.xml file + * @var bool + */ + private $separateXmlMapping = false; + + public function __construct() { $parts = explode('\\', $this->getNamespace()); $this->name = end($parts); } + + public function setForceUseAttributeReader(bool $forceUseAttributeReader) { + $this->forceUseAttributeReader = $forceUseAttributeReader; + } + public function setSeparateXmlMapping(bool $separateXmlMapping) { + $this->separateXmlMapping = $separateXmlMapping; + } + + + /** * Get the configuration for specific object class * if cache driver is present it scans it also @@ -179,7 +203,9 @@ public function getExtensionMetadataFactory(ObjectManager $objectManager) $objectManager, $this->getNamespace(), $this->annotationReader, - $this->getCacheItemPool($objectManager) + $this->getCacheItemPool($objectManager), + $this->forceUseAttributeReader, + $this->separateXmlMapping ); }