diff --git a/src/Metadata/Driver/AbstractDoctrineTypeDriver.php b/src/Metadata/Driver/AbstractDoctrineTypeDriver.php index 70320f78e..c0d0cbecc 100644 --- a/src/Metadata/Driver/AbstractDoctrineTypeDriver.php +++ b/src/Metadata/Driver/AbstractDoctrineTypeDriver.php @@ -89,7 +89,6 @@ public function loadMetadataForClass(\ReflectionClass $class): ?BaseClassMetadat } \assert($classMetadata instanceof ClassMetadata); - // Abort if the given class is not a mapped entity if (!$doctrineMetadata = $this->tryLoadingDoctrineMetadata($class->name)) { return $classMetadata; diff --git a/src/Metadata/Driver/DoctrineTypeDriver.php b/src/Metadata/Driver/DoctrineTypeDriver.php index e51f8d5c4..959fc92ff 100644 --- a/src/Metadata/Driver/DoctrineTypeDriver.php +++ b/src/Metadata/Driver/DoctrineTypeDriver.php @@ -4,7 +4,8 @@ namespace JMS\Serializer\Metadata\Driver; -use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ODM\PHPCR\Mapping\ClassMetadata as ORMClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadata as ODMClassMetadata; use Doctrine\Persistence\Mapping\ClassMetadata as DoctrineClassMetadata; use JMS\Serializer\Metadata\ClassMetadata; use JMS\Serializer\Metadata\PropertyMetadata; @@ -15,12 +16,9 @@ */ class DoctrineTypeDriver extends AbstractDoctrineTypeDriver { - /** - * @param ClassMetadataInfo $doctrineMetadata - * @param ClassMetadata $classMetadata - */ protected function setDiscriminator(DoctrineClassMetadata $doctrineMetadata, ClassMetadata $classMetadata): void { + assert($doctrineMetadata instanceof ORMClassMetadata || $doctrineMetadata instanceof ODMClassMetadata); if ( empty($classMetadata->discriminatorMap) && !$classMetadata->discriminatorDisabled && !empty($doctrineMetadata->discriminatorMap) && $doctrineMetadata->isRootEntity() @@ -51,7 +49,7 @@ protected function setPropertyType(DoctrineClassMetadata $doctrineMetadata, Prop // For inheritance schemes, we cannot add any type as we would only add the super-type of the hierarchy. // On serialization, this would lead to only the supertype being serialized, and properties of subtypes // being ignored. - if ($targetMetadata instanceof ClassMetadataInfo && !$targetMetadata->isInheritanceTypeNone()) { + if ($targetMetadata instanceof ODMClassMetadata && !$targetMetadata->isInheritanceTypeNone()) { return; } diff --git a/tests/Fixtures/Doctrine/Entity/BlogPost.php b/tests/Fixtures/Doctrine/Entity/BlogPost.php index 665c72fd4..5eb426b24 100644 --- a/tests/Fixtures/Doctrine/Entity/BlogPost.php +++ b/tests/Fixtures/Doctrine/Entity/BlogPost.php @@ -7,6 +7,9 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; +use Doctrine\ORM\Mapping\DiscriminatorColumn; +use Doctrine\ORM\Mapping\DiscriminatorMap; +use Doctrine\ORM\Mapping\InheritanceType; use JMS\Serializer\Annotation as Serializer; use JMS\Serializer\Annotation\Groups; use JMS\Serializer\Annotation\SerializedName; @@ -18,10 +21,16 @@ /** * @ORM\Entity * + * @InheritanceType("SINGLE_TABLE") + * @DiscriminatorColumn(name="discr", type="string") + * @DiscriminatorMap({"simple" = "BlogPost", "extended" = "ExtendedPost"}) * @XmlRoot("blog-post") */ #[ORM\Entity] +#[InheritanceType('SINGLE_TABLE')] #[XmlRoot(name: 'blog-post')] +#[DiscriminatorColumn(name: 'discr', type: 'string')] +#[DiscriminatorMap(['simple' => BlogPost::class, 'extended' => ExtendedPost::class])] class BlogPost { /** diff --git a/tests/Fixtures/Doctrine/Entity/ExtendedPost.php b/tests/Fixtures/Doctrine/Entity/ExtendedPost.php new file mode 100644 index 000000000..4bc011eda --- /dev/null +++ b/tests/Fixtures/Doctrine/Entity/ExtendedPost.php @@ -0,0 +1,15 @@ +getDoctrineDriver()->loadMetadataForClass($refClass); } @@ -50,7 +55,7 @@ public function testSingleValuedAssociationIsProperlyHinted() { $metadata = $this->getMetadata(); self::assertEquals( - ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Entity\Author', 'params' => []], + ['name' => Author::class, 'params' => []], $metadata->propertyMetadata['author']->type, ); } @@ -63,7 +68,7 @@ public function testMultiValuedAssociationIsProperlyHinted() [ 'name' => 'ArrayCollection', 'params' => [ - ['name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Entity\Comment', 'params' => []], + ['name' => Comment::class, 'params' => []], ], ], $metadata->propertyMetadata['comments']->type, @@ -91,7 +96,7 @@ public function testNonDoctrineEntityClassIsNotModified() { // Note: Using regular BlogPost fixture here instead of Doctrine fixture // because it has no Doctrine metadata. - $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'); + $refClass = new \ReflectionClass(BlogPost::class); $plainMetadata = $this->getMetadataDriver()->loadMetadataForClass($refClass); $doctrineMetadata = $this->getDoctrineDriver()->loadMetadataForClass($refClass); @@ -107,7 +112,7 @@ public function testNonDoctrineEntityClassIsNotModified() public function testExcludePropertyNoPublicAccessorException() { $first = $this->getMetadataDriver() - ->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ExcludePublicAccessor')); + ->loadMetadataForClass(new \ReflectionClass(ExcludePublicAccessor::class)); self::assertArrayHasKey('id', $first->propertyMetadata); self::assertArrayNotHasKey('iShallNotBeAccessed', $first->propertyMetadata); @@ -129,7 +134,7 @@ public function testGuidPropertyIsGivenStringType() ); } - protected function getEntityManager() + protected function getEntityManager(): EntityManager { $config = new Configuration(); $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies'); @@ -140,6 +145,7 @@ protected function getEntityManager() new DoctrineAttributeDriver([__DIR__ . '/../../Fixtures/Doctrine'], true), ); } else { + assert(class_exists(DoctrineAnnotationDriver::class)); $config->setMetadataDriverImpl( new DoctrineAnnotationDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/Doctrine'), ); diff --git a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php index 37c92e7a7..224dcb0d7 100644 --- a/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php +++ b/tests/Metadata/Driver/DoctrinePHPCRDriverTest.php @@ -101,6 +101,7 @@ protected function getDocumentManager() $config = new Configuration(); $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies'); $config->setProxyNamespace('JMS\Tests\Proxies'); + assert(class_exists(DoctrinePHPCRDriver::class)); $config->setMetadataDriverImpl( new DoctrinePHPCRDriver(new AnnotationReader(), __DIR__ . '/../../Fixtures/DoctrinePHPCR'), ); diff --git a/tests/Serializer/Doctrine/IntegrationTest.php b/tests/Serializer/Doctrine/IntegrationTest.php index fcee0228a..e36a37c42 100644 --- a/tests/Serializer/Doctrine/IntegrationTest.php +++ b/tests/Serializer/Doctrine/IntegrationTest.php @@ -12,7 +12,6 @@ use Doctrine\ORM\EntityManager; use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\Mapping\Driver\AttributeDriver; -use Doctrine\ORM\ORMException; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\Persistence\AbstractManagerRegistry; use Doctrine\Persistence\Proxy; @@ -143,6 +142,7 @@ private function createEntityManager(Connection $con) ])); AnnotationReader::addGlobalIgnoredNamespace('Doctrine\ORM\Mapping'); } else { + assert(class_exists(AnnotationDriver::class)); $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ __DIR__ . '/../../Fixtures/Doctrine/SingleTableInheritance', ])); @@ -158,10 +158,10 @@ private function createEntityManager(Connection $con) class SimpleManagerRegistry extends AbstractManagerRegistry { - private $services = []; - private $serviceCreator; + private array $services = []; + private \Closure $serviceCreator; - public function __construct($serviceCreator, $name = 'anonymous', array $connections = ['default' => 'default_connection'], array $managers = ['default' => 'default_manager'], $defaultConnection = null, $defaultManager = null, $proxyInterface = Proxy::class) + public function __construct(\Closure $serviceCreator, $name = 'anonymous', array $connections = ['default' => 'default_connection'], array $managers = ['default' => 'default_manager'], $defaultConnection = null, $defaultManager = null, $proxyInterface = Proxy::class) { if (null === $defaultConnection) { $defaultConnection = key($connections); @@ -173,20 +173,12 @@ public function __construct($serviceCreator, $name = 'anonymous', array $connect parent::__construct($name, $connections, $managers, $defaultConnection, $defaultManager, $proxyInterface); - if (!is_callable($serviceCreator)) { - throw new \InvalidArgumentException('$serviceCreator must be a valid callable.'); - } - $this->serviceCreator = $serviceCreator; } public function getService($name) { - if (isset($this->services[$name])) { - return $this->services[$name]; - } - - return $this->services[$name] = call_user_func($this->serviceCreator, $name); + return $this->services[$name] ??= call_user_func($this->serviceCreator, $name); } public function resetService($name) @@ -196,20 +188,6 @@ public function resetService($name) public function getAliasNamespace($alias) { - foreach (array_keys($this->getManagers()) as $name) { - $manager = $this->getManager($name); - - if ($manager instanceof EntityManager) { - try { - return $manager->getConfiguration()->getEntityNamespace($alias); - } catch (ORMException $ex) { - // Probably mapped by another entity manager, or invalid, just ignore this here. - } - } else { - throw new \LogicException(sprintf('Unsupported manager type "%s".', get_class($manager))); - } - } - - throw new \RuntimeException(sprintf('The namespace alias "%s" is not known to any manager.', $alias)); + return $alias; } } diff --git a/tests/Serializer/Doctrine/ObjectConstructorTest.php b/tests/Serializer/Doctrine/ObjectConstructorTest.php index fad75ccaf..dd9fd1edf 100644 --- a/tests/Serializer/Doctrine/ObjectConstructorTest.php +++ b/tests/Serializer/Doctrine/ObjectConstructorTest.php @@ -15,7 +15,6 @@ use Doctrine\ORM\Mapping\Driver\AnnotationDriver; use Doctrine\ORM\Mapping\Driver\AttributeDriver; use Doctrine\ORM\Mapping\Driver\XmlDriver; -use Doctrine\ORM\ORMException; use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\Tools\SchemaTool; use Doctrine\ORM\UnitOfWork; @@ -51,7 +50,6 @@ use JMS\Serializer\Tests\Fixtures\Doctrine\PersistendCollection\SmartPhone; use JMS\Serializer\Tests\Fixtures\DoctrinePHPCR\Author as DoctrinePHPCRAuthor; use JMS\Serializer\Visitor\DeserializationVisitorInterface; -use LogicException; use Metadata\Driver\AdvancedDriverInterface; use Metadata\MetadataFactoryInterface; use PHPUnit\Framework\Attributes\DataProvider; @@ -536,6 +534,7 @@ private function createEntityManager(Connection $con, ?Configuration $cfg = null __DIR__ . '/../../Fixtures/Doctrine/PersistendCollection', ])); } else { + assert(class_exists(AnnotationDriver::class)); $cfg->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader(), [ __DIR__ . '/../../Fixtures/Doctrine/Entity', __DIR__ . '/../../Fixtures/Doctrine/IdentityFields', @@ -597,10 +596,10 @@ private function createSerializerWithDoctrineObjectConstructor() class SimpleBaseManagerRegistry extends AbstractManagerRegistry { - private $services = []; - private $serviceCreator; + private array $services = []; + private \Closure $serviceCreator; - public function __construct($serviceCreator, $name = 'anonymous', array $connections = ['default' => 'default_connection'], array $managers = ['default' => 'default_manager'], $defaultConnection = null, $defaultManager = null, $proxyInterface = Proxy::class) + public function __construct(\Closure $serviceCreator, $name = 'anonymous', array $connections = ['default' => 'default_connection'], array $managers = ['default' => 'default_manager'], $defaultConnection = null, $defaultManager = null, $proxyInterface = Proxy::class) { if (null === $defaultConnection) { $defaultConnection = key($connections); @@ -612,20 +611,12 @@ public function __construct($serviceCreator, $name = 'anonymous', array $connect parent::__construct($name, $connections, $managers, $defaultConnection, $defaultManager, $proxyInterface); - if (!is_callable($serviceCreator)) { - throw new \InvalidArgumentException('$serviceCreator must be a valid callable.'); - } - $this->serviceCreator = $serviceCreator; } public function getService($name) { - if (isset($this->services[$name])) { - return $this->services[$name]; - } - - return $this->services[$name] = call_user_func($this->serviceCreator, $name); + return $this->services[$name] ??= call_user_func($this->serviceCreator, $name); } public function resetService($name) @@ -635,20 +626,6 @@ public function resetService($name) public function getAliasNamespace($alias) { - foreach (array_keys($this->getManagers()) as $name) { - $manager = $this->getManager($name); - - if ($manager instanceof EntityManager) { - try { - return $manager->getConfiguration()->getEntityNamespace($alias); - } catch (ORMException $ex) { - // Probably mapped by another entity manager, or invalid, just ignore this here. - } - } else { - throw new LogicException(sprintf('Unsupported manager type "%s".', get_class($manager))); - } - } - - throw new RuntimeException(sprintf('The namespace alias "%s" is not known to any manager.', $alias)); + return $alias; } }