diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a0a0cebe..dc9dac0a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5,6 +5,11 @@ parameters: count: 1 path: src/Persistence/Mapping/Driver/StaticPHPDriver.php + - + message: "#^Call to function method_exists\\(\\) with TObjectManager of Doctrine\\\\Persistence\\\\ObjectManager and 'isUninitializedObje…' will always evaluate to true\\.$#" + count: 1 + path: src/Persistence/ObjectManagerDecorator.php + - message: "#^Doctrine\\\\Persistence\\\\Reflection\\\\EnumReflectionProperty\\:\\:__construct\\(\\) does not call parent constructor from ReflectionProperty\\.$#" count: 1 diff --git a/src/Persistence/ObjectManagerDecorator.php b/src/Persistence/ObjectManagerDecorator.php index 1b78ec1f..b628f9d8 100644 --- a/src/Persistence/ObjectManagerDecorator.php +++ b/src/Persistence/ObjectManagerDecorator.php @@ -4,9 +4,14 @@ namespace Doctrine\Persistence; +use BadMethodCallException; use Doctrine\Persistence\Mapping\ClassMetadata; use Doctrine\Persistence\Mapping\ClassMetadataFactory; +use function get_class; +use function method_exists; +use function sprintf; + /** * Base class to simplify ObjectManager decorators * @@ -76,6 +81,28 @@ public function initializeObject(object $obj): void $this->wrapped->initializeObject($obj); } + public function isUninitializedObject(mixed $value): bool + { + if (! method_exists($this->wrapped, 'isUninitializedObject')) { + $wrappedClass = get_class($this->wrapped); + + throw new BadMethodCallException(sprintf( + <<<'EXCEPTION' +Context: Trying to call %s +Problem: The wrapped ObjectManager, an instance of %s does not implement this method. +Solution: Implement %s::isUninitializedObject() with a signature compatible with this one: + public function isUninitializedObject(mixed $value): bool +EXCEPTION + , + __METHOD__, + $wrappedClass, + $wrappedClass, + )); + } + + return $this->wrapped->isUninitializedObject($value); + } + public function contains(object $object): bool { return $this->wrapped->contains($object); diff --git a/tests/Persistence/ObjectManagerDecoratorTest.php b/tests/Persistence/ObjectManagerDecoratorTest.php index e8219680..97c38e9e 100644 --- a/tests/Persistence/ObjectManagerDecoratorTest.php +++ b/tests/Persistence/ObjectManagerDecoratorTest.php @@ -4,6 +4,7 @@ namespace Doctrine\Tests\Persistence; +use BadMethodCallException; use Doctrine\Persistence\Mapping\ClassMetadata; use Doctrine\Persistence\Mapping\ClassMetadataFactory; use Doctrine\Persistence\ObjectManager; @@ -153,6 +154,37 @@ public function testContains(): void self::assertTrue($this->decorated->contains($object)); } + + /** @requires PHP 8.0 */ + public function testIsUninitializedObject(): void + { + $object = new TestObject(); + + $wrapped = $this->createMock(ObjectManagerV4::class); + $decorated = new NullObjectManagerDecorator($wrapped); + $wrapped->expects(self::once()) + ->method('isUninitializedObject') + ->with($object) + ->willReturn(false); + + self::assertFalse($decorated->isUninitializedObject($object)); + } + + /** @requires PHP 8.0 */ + public function testIsThrowsWhenTheWrappedObjectManagerDoesNotImplementObjectManagerV4(): void + { + $object = new TestObject(); + + $this->expectException(BadMethodCallException::class); + $decorated = new NullObjectManagerDecorator($this->createMock(ObjectManager::class)); + + self::assertFalse($decorated->isUninitializedObject($object)); + } +} + +interface ObjectManagerV4 extends ObjectManager +{ + public function isUninitializedObject(mixed $object): bool; } /** @extends ObjectManagerDecorator */