From 1c16df58e544d05e723459445a1c8e3aeae52431 Mon Sep 17 00:00:00 2001 From: Yevhen Sidelnyk Date: Thu, 21 Aug 2025 11:47:55 +0300 Subject: [PATCH 1/2] Make signatures forward-comaptible with doctrine/persistence 4.x These changes are the first of migration toward doctrine/persistence 4.0. Most of the signatures that could've been made compatible have been made compatible. There are some other, which require more in-depth knowledge of repository to adjust / rework. --- .../ODM/PHPCR/Decorator/DocumentManagerDecorator.php | 7 +++++++ lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php | 8 +++----- lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php | 4 ++-- lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php | 2 +- lib/Doctrine/ODM/PHPCR/Mapping/Driver/YamlDriver.php | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/Doctrine/ODM/PHPCR/Decorator/DocumentManagerDecorator.php b/lib/Doctrine/ODM/PHPCR/Decorator/DocumentManagerDecorator.php index 98a6ca877..ace7e8628 100644 --- a/lib/Doctrine/ODM/PHPCR/Decorator/DocumentManagerDecorator.php +++ b/lib/Doctrine/ODM/PHPCR/Decorator/DocumentManagerDecorator.php @@ -7,6 +7,7 @@ use Doctrine\ODM\PHPCR\ChildrenCollection; use Doctrine\ODM\PHPCR\Configuration; use Doctrine\ODM\PHPCR\DocumentManagerInterface; +use Doctrine\ODM\PHPCR\Mapping\ClassMetadata as PhpcrClassMetadata; use Doctrine\ODM\PHPCR\Proxy\ProxyFactory; use Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder; use Doctrine\ODM\PHPCR\Query\Query; @@ -38,6 +39,12 @@ public function __construct(DocumentManagerInterface $wrapped) $this->wrapped = $wrapped; } + /** @noinspection SenselessMethodDuplicationInspection - return type is made more specific to match {@see DocumentManagerInterface::getClassMetadata()} */ + public function getClassMetadata(string $className): PhpcrClassMetadata + { + return $this->wrapped->getClassMetadata($className); + } + public function setTranslationStrategy(string $key, TranslationStrategyInterface $strategy): void { $this->wrapped->setTranslationStrategy($key, $strategy); diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php b/lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php index 42bee4bcc..b158a6761 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManagerInterface.php @@ -45,13 +45,11 @@ interface DocumentManagerInterface extends ObjectManager { /** - * @{@inheritDoc} - * - * Overwritten to tighten return type. We can't tighten the return type declaration because of Doctrine\Persistence\ObjectManagerDecorator. + * {@inheritdoc} * - * @return PhpcrClassMetadata + * Overwritten to tighten the return type. */ - public function getClassMetadata(string $className); + public function getClassMetadata(string $className): PhpcrClassMetadata; /** * Add or replace a translation strategy. diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php index df152de10..e57ad171d 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php @@ -1317,7 +1317,7 @@ public function getAssociationTargetClass($fieldName): ?string return $this->mappings[$fieldName]['targetDocument']; } - public function getAssociationMappedByTargetField($assocName) + public function getAssociationMappedByTargetField($assocName): string { throw new BadMethodCallException(sprintf( '%s not yet implemented in "%s"', @@ -1326,7 +1326,7 @@ public function getAssociationMappedByTargetField($assocName) )); } - public function isAssociationInverseSide($assocName) + public function isAssociationInverseSide($assocName): bool { throw new BadMethodCallException(sprintf( '%s not yet implemented in "%s"', diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php index e435cd1f2..d709d989b 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php @@ -63,7 +63,7 @@ public function __construct(array $paths) $this->addPaths($paths); } - public function isTransient($className) + public function isTransient($className): bool { $classAttributes = $this->reader->getClassAttributes(new \ReflectionClass($className)); diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/YamlDriver.php index a60d43170..d3c44e230 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/YamlDriver.php @@ -262,7 +262,7 @@ private function addMappingFromReference(ClassMetadata $class, string $fieldName } } - protected function loadMappingFile($file) + protected function loadMappingFile($file): array { if (!is_file($file)) { throw new InvalidArgumentException(sprintf('File "%s" not found', $file)); From dc1b028406a72f75f746b095a083a666ce210c9f Mon Sep 17 00:00:00 2001 From: Yevhen Sidelnyk Date: Thu, 21 Aug 2025 11:51:44 +0300 Subject: [PATCH 2/2] Feature: add support for `ClassLocator` from doctrine/persistence 4.1 These changes integrate https://github.com/doctrine/persistence/pull/433 `ClassLocator` allows clients to pass any iterable of classes they might want. --- .phpstan/phpstan-baseline.neon | 21 +++++++++++++++++++ .../PHPCR/Mapping/Driver/AttributeDriver.php | 12 ++++++++--- .../ODM/PHPCR/Mapping/AttributeDriverTest.php | 16 ++++++++------ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/.phpstan/phpstan-baseline.neon b/.phpstan/phpstan-baseline.neon index eea5fd279..ecd09e698 100644 --- a/.phpstan/phpstan-baseline.neon +++ b/.phpstan/phpstan-baseline.neon @@ -40,3 +40,24 @@ parameters: message: "#^Call to an undefined method Doctrine\\\\ODM\\\\PHPCR\\\\Query\\\\Builder\\\\AbstractNode\\:\\:setConverter\\(\\)\\.$#" count: 1 path: ../tests/Doctrine/Tests/ODM/PHPCR/Query/Builder/QueryBuilderTest.php + + - + message: '#^Access to an undefined property Doctrine\\ODM\\PHPCR\\Mapping\\Driver\\AttributeDriver\:\:\$classLocator\.$#' + identifier: property.notFound + count: 1 + path: ../lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php + reportUnmatched: false + + - + message: '#^Class Doctrine\\Persistence\\Mapping\\Driver\\ClassLocator not found\.$#' + identifier: class.notFound + count: 1 + path: ../lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php + reportUnmatched: false + + - + message: '#^Parameter \$paths of method Doctrine\\ODM\\PHPCR\\Mapping\\Driver\\AttributeDriver\:\:__construct\(\) has invalid type Doctrine\\Persistence\\Mapping\\Driver\\ClassLocator\.$#' + identifier: class.notFound + count: 2 + path: ../lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php + reportUnmatched: false diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php index d709d989b..b015b69dd 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/Driver/AttributeDriver.php @@ -27,6 +27,7 @@ use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; use Doctrine\ODM\PHPCR\Mapping\MappingException; use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata; +use Doctrine\Persistence\Mapping\Driver\ClassLocator; use Doctrine\Persistence\Mapping\Driver\ColocatedMappingDriver; use Doctrine\Persistence\Mapping\Driver\MappingDriver; @@ -55,12 +56,17 @@ class AttributeDriver implements MappingDriver private AttributeReader $reader; /** - * @param array $paths + * @param array|ClassLocator $paths directory paths or class locator */ - public function __construct(array $paths) + public function __construct(array|ClassLocator $paths) { $this->reader = new AttributeReader(); - $this->addPaths($paths); + + if ($paths instanceof ClassLocator) { + $this->classLocator = $paths; + } else { + $this->addPaths($paths); + } } public function isTransient($className): bool diff --git a/tests/Doctrine/Tests/ODM/PHPCR/Mapping/AttributeDriverTest.php b/tests/Doctrine/Tests/ODM/PHPCR/Mapping/AttributeDriverTest.php index b60132d0d..e391e85bb 100644 --- a/tests/Doctrine/Tests/ODM/PHPCR/Mapping/AttributeDriverTest.php +++ b/tests/Doctrine/Tests/ODM/PHPCR/Mapping/AttributeDriverTest.php @@ -3,6 +3,7 @@ namespace Doctrine\Tests\ODM\PHPCR\Mapping; use Doctrine\ODM\PHPCR\Mapping\Driver\AttributeDriver; +use Doctrine\Persistence\Mapping\Driver\FileClassLocator; use Doctrine\Persistence\Mapping\Driver\MappingDriver; /** @@ -10,17 +11,20 @@ */ class AttributeDriverTest extends AbstractMappingDriverTest { - protected function loadDriver(): AttributeDriver + /** @param list $paths */ + protected function loadDriver(array $paths = []): AttributeDriver { - return new AttributeDriver([]); + // Available in Doctrine Persistence 4.1+ + if (class_exists(FileClassLocator::class)) { + $paths = FileClassLocator::createFromDirectories($paths); + } + + return new AttributeDriver($paths); } protected function loadDriverForTestMappingDocuments(): MappingDriver { - $attributeDriver = $this->loadDriver(); - $attributeDriver->addPaths([__DIR__.'/Model']); - - return $attributeDriver; + return $this->loadDriver([__DIR__.'/Model']); } /**