From 4074faaef32a55c44ee74b91e0e549f45ce6071f Mon Sep 17 00:00:00 2001 From: abluchet Date: Thu, 12 Jan 2017 11:35:37 +0100 Subject: [PATCH 1/2] Move normalizeIdentifiers method to a new Util class IdentifierManager --- src/Bridge/Doctrine/Orm/ItemDataProvider.php | 73 ++----------- .../Doctrine/Orm/Util/IdentifierManager.php | 71 ++++++++++++ .../Orm/Util/IdentifierManagerInterface.php | 30 ++++++ .../Compiler/DoctrineQueryExtensionPass.php | 2 +- .../Bundle/Resources/config/doctrine_orm.xml | 10 +- .../Doctrine/Orm/ItemDataProviderTest.php | 101 ++++-------------- .../Doctrine/Util/IdentifierManagerTest.php | 94 ++++++++++++++++ .../ApiPlatformExtensionTest.php | 2 +- .../DoctrineQueryExtensionPassTest.php | 2 +- 9 files changed, 236 insertions(+), 149 deletions(-) create mode 100644 src/Bridge/Doctrine/Orm/Util/IdentifierManager.php create mode 100644 src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php create mode 100644 tests/Bridge/Doctrine/Util/IdentifierManagerTest.php diff --git a/src/Bridge/Doctrine/Orm/ItemDataProvider.php b/src/Bridge/Doctrine/Orm/ItemDataProvider.php index 0d820f9ac98..69bc500057c 100644 --- a/src/Bridge/Doctrine/Orm/ItemDataProvider.php +++ b/src/Bridge/Doctrine/Orm/ItemDataProvider.php @@ -13,15 +13,12 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; +use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; -use ApiPlatform\Core\Exception\PropertyNotFoundException; use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; use ApiPlatform\Core\Exception\RuntimeException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use Doctrine\Common\Persistence\ManagerRegistry; -use Doctrine\Common\Persistence\ObjectManager; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; @@ -34,21 +31,18 @@ class ItemDataProvider implements ItemDataProviderInterface { private $managerRegistry; - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; + private $identifierManager; private $itemExtensions; /** - * @param ManagerRegistry $managerRegistry - * @param PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory - * @param PropertyMetadataFactoryInterface $propertyMetadataFactory - * @param QueryItemExtensionInterface[] $itemExtensions + * @param ManagerRegistry $managerRegistry + * @param IdentifierManagerInterface $identifierManager + * @param QueryItemExtensionInterface[] $itemExtensions */ - public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, array $itemExtensions = []) + public function __construct(ManagerRegistry $managerRegistry, IdentifierManagerInterface $identifierManager, array $itemExtensions = []) { $this->managerRegistry = $managerRegistry; - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; + $this->identifierManager = $identifierManager; $this->itemExtensions = $itemExtensions; } @@ -66,7 +60,7 @@ public function getItem(string $resourceClass, $id, string $operationName = null throw new ResourceClassNotSupportedException(); } - $identifiers = $this->normalizeIdentifiers($id, $manager, $resourceClass); + $identifiers = $this->identifierManager->normalizeIdentifiers($id, $manager, $resourceClass); $fetchData = $context['fetch_data'] ?? true; if (!$fetchData && $manager instanceof EntityManagerInterface) { @@ -114,55 +108,4 @@ private function addWhereForIdentifiers(array $identifiers, QueryBuilder $queryB $queryBuilder->setParameter($placeholder, $value); } } - - /** - * Transform and check the identifier, composite or not. - * - * @param int|string $id - * @param ObjectManager $manager - * @param string $resourceClass - * - * @throws PropertyNotFoundException - * - * @return array - */ - private function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array - { - $identifierValues = [$id]; - $doctrineMetadataIdentifier = $manager->getClassMetadata($resourceClass)->getIdentifier(); - - if (count($doctrineMetadataIdentifier) >= 2) { - $identifiers = explode(';', $id); - $identifiersMap = []; - - // first transform identifiers to a proper key/value array - foreach ($identifiers as $identifier) { - $keyValue = explode('=', $identifier); - $identifiersMap[$keyValue[0]] = $keyValue[1]; - } - } - - $identifiers = []; - $i = 0; - - foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); - - $identifier = $propertyMetadata->isIdentifier(); - if (null === $identifier || false === $identifier) { - continue; - } - - $identifier = !isset($identifiersMap) ? $identifierValues[$i] ?? null : $identifiersMap[$propertyName] ?? null; - - if (null === $identifier) { - throw new PropertyNotFoundException(sprintf('Invalid identifier "%s", "%s" has not been found.', $id, $propertyName)); - } - - $identifiers[$propertyName] = $identifier; - ++$i; - } - - return $identifiers; - } } diff --git a/src/Bridge/Doctrine/Orm/Util/IdentifierManager.php b/src/Bridge/Doctrine/Orm/Util/IdentifierManager.php new file mode 100644 index 00000000000..7cf3446b8ee --- /dev/null +++ b/src/Bridge/Doctrine/Orm/Util/IdentifierManager.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; + +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use Doctrine\Common\Persistence\ObjectManager; + +class IdentifierManager implements IdentifierManagerInterface +{ + private $propertyNameCollectionFactory; + private $propertyMetadataFactory; + + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory) + { + $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; + $this->propertyMetadataFactory = $propertyMetadataFactory; + } + + /** + * {@inheritdoc} + */ + public function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array + { + $identifierValues = [$id]; + $doctrineMetadataIdentifier = $manager->getClassMetadata($resourceClass)->getIdentifier(); + + if (2 <= count($doctrineMetadataIdentifier)) { + $identifiers = explode(';', $id); + $identifiersMap = []; + + // first transform identifiers to a proper key/value array + foreach ($identifiers as $identifier) { + $keyValue = explode('=', $identifier); + $identifiersMap[$keyValue[0]] = $keyValue[1]; + } + } + + $identifiers = []; + $i = 0; + + foreach ($this->propertyNameCollectionFactory->create($resourceClass) as $propertyName) { + $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName); + + $identifier = $propertyMetadata->isIdentifier(); + if (null === $identifier || false === $identifier) { + continue; + } + + $identifier = !isset($identifiersMap) ? $identifierValues[$i] ?? null : $identifiersMap[$propertyName] ?? null; + if (null === $identifier) { + throw new PropertyNotFoundException(sprintf('Invalid identifier "%s", "%s" has not been found.', $id, $propertyName)); + } + + $identifiers[$propertyName] = $identifier; + ++$i; + } + + return $identifiers; + } +} diff --git a/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php b/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php new file mode 100644 index 00000000000..daed64a8c3d --- /dev/null +++ b/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; + +use Doctrine\Common\Persistence\ObjectManager; + +interface IdentifierManagerInterface +{ + /** + * Transform and check the identifier, composite or not. + * + * @param int|string $id + * @param ObjectManager $manager + * @param string $resourceClass + * + * @throws PropertyNotFoundException + * + * @return array + */ + public function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array; +} diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php index 3add3fa0595..fd43792f35f 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php @@ -39,7 +39,7 @@ public function process(ContainerBuilder $container) $itemDataProviderDefinition = $container->getDefinition('api_platform.doctrine.orm.item_data_provider'); $collectionDataProviderDefinition->replaceArgument(1, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.collection')); - $itemDataProviderDefinition->replaceArgument(3, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.item')); + $itemDataProviderDefinition->replaceArgument(2, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.item')); } /** diff --git a/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml index ca72c60149c..a5fd944d672 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -16,8 +16,7 @@ - - + @@ -85,6 +84,13 @@ + + + + + + + diff --git a/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php index f008f20de51..e860ea2f3ff 100644 --- a/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php +++ b/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php @@ -14,18 +14,14 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; +use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; -use ApiPlatform\Core\Metadata\Property\PropertyMetadata; -use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr\Comparison; use Doctrine\ORM\QueryBuilder; @@ -36,6 +32,15 @@ */ class ItemDataProviderTest extends \PHPUnit_Framework_TestCase { + private function getIdentifierManagerProphecy($input, $resourceClass, $output) + { + $objectManager = Argument::type(ObjectManager::class); + $identifierManagerProphecy = $this->prophesize(IdentifierManagerInterface::class); + $identifierManagerProphecy->normalizeIdentifiers($input, $objectManager, $resourceClass)->willReturn($output); + + return $identifierManagerProphecy->reveal(); + } + public function testGetItemSingleIdentifier() { $context = ['foo' => 'bar', 'fetch_data' => true]; @@ -61,9 +66,6 @@ public function testGetItemSingleIdentifier() $managerProphecy = $this->prophesize(ObjectManager::class); $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(['id'])->shouldBeCalled(); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal())->shouldBeCalled(); $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); @@ -71,14 +73,9 @@ public function testGetItemSingleIdentifier() $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn($metadata)->shouldBeCalled(); + $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 1, 'foo', $context)); } @@ -110,9 +107,6 @@ public function testGetItemDoubleIdentifier() $managerProphecy = $this->prophesize(ObjectManager::class); $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(['ida', 'idb'])->shouldBeCalled(); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal())->shouldBeCalled(); $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); @@ -120,46 +114,13 @@ public function testGetItemDoubleIdentifier() $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', [])->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['nonid', 'ida', 'idb']))->shouldBeCalled(); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'nonid')->willReturn(new PropertyMetadata())->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'ida')->willReturn($metadata)->shouldBeCalled(); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'idb')->willReturn($metadata)->shouldBeCalled(); + $identifierManagerProphecy = $this->getIdentifierManagerProphecy('ida=1;idb=2', Dummy::class, ['ida' => 1, 'idb' => 2]); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 'ida=1;idb=2', 'foo')); } - /** - * @expectedException \ApiPlatform\Core\Exception\PropertyNotFoundException - * @expectedExceptionMessage Invalid identifier "idbad=1;idb=2", "ida" has not been found. - */ - public function testInvalidIdentifier() - { - $managerProphecy = $this->prophesize(ObjectManager::class); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(['ida', 'idb'])->shouldBeCalled(); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['ida', 'idb']))->shouldBeCalled(); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'ida')->willReturn($metadata)->shouldBeCalled(); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), []); - - $this->assertEquals([], $dataProvider->getItem(Dummy::class, 'idbad=1;idb=2', 'foo')); - } - public function testQueryResultExtension() { $comparisonProphecy = $this->prophesize(Comparison::class); @@ -180,9 +141,6 @@ public function testQueryResultExtension() $managerProphecy = $this->prophesize(ObjectManager::class); $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(['id'])->shouldBeCalled(); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal())->shouldBeCalled(); $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); @@ -192,15 +150,9 @@ public function testQueryResultExtension() $extensionProphecy->supportsResult(Dummy::class, 'foo')->willReturn(true)->shouldBeCalled(); $extensionProphecy->getResult($queryBuilder)->willReturn([])->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - - $metadata = new PropertyMetadata(); - $metadata = $metadata->withIdentifier(true); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn($metadata)->shouldBeCalled(); + $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 1, 'foo')); } @@ -213,12 +165,11 @@ public function testThrowResourceClassNotSupportedException() $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn(null)->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]); + $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); + + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); $dataProvider->getItem(Dummy::class, 'foo'); } @@ -230,24 +181,16 @@ public function testCannotCreateQueryBuilder() { $repositoryProphecy = $this->prophesize(ObjectRepository::class); - $classMetadataProphecy = $this->prophesize(ClassMetadata::class); - $classMetadataProphecy->getIdentifier()->willReturn(['id'])->shouldBeCalled(); - $managerProphecy = $this->prophesize(ObjectManager::class); $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - $managerProphecy->getClassMetadata(Dummy::class)->willReturn($classMetadataProphecy->reveal())->shouldBeCalled(); $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); - $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); - $propertyNameCollectionFactoryProphecy->create(Dummy::class)->willReturn(new PropertyNameCollection(['id']))->shouldBeCalled(); - - $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create(Dummy::class, 'id')->willReturn((new PropertyMetadata())->withIdentifier(true))->shouldBeCalled(); - $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - (new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal(), [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo'); + $identifierManagerProphecy = $this->getIdentifierManagerProphecy('foo', Dummy::class, ['id' => 'foo']); + + (new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo'); } } diff --git a/tests/Bridge/Doctrine/Util/IdentifierManagerTest.php b/tests/Bridge/Doctrine/Util/IdentifierManagerTest.php new file mode 100644 index 00000000000..22d7a46b3e5 --- /dev/null +++ b/tests/Bridge/Doctrine/Util/IdentifierManagerTest.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace ApiPlatform\Core\Tests\Doctrine\Util; + +use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManager; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; +use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\Mapping\ClassMetadata; + +class IdentifierManagerTest extends \PHPUnit_Framework_TestCase +{ + private function getMetadataProphecies(array $identifiers, string $resourceClass) + { + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + + $nameCollection = ['foobar']; + + foreach ($identifiers as $identifier) { + $metadata = new PropertyMetadata(); + $metadata = $metadata->withIdentifier(true); + $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); + + $nameCollection[] = $identifier; + } + + //random property to prevent the use of non-identifiers metadata while looping + $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); + + $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection))->shouldBeCalled(); + + return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; + } + + private function getObjectManagerProphecy(array $output, string $resourceClass) + { + $classMetadataProphecy = $this->prophesize(ClassMetadata::class); + $classMetadataProphecy->getIdentifier()->willReturn($output)->shouldBeCalled(); + $managerProphecy = $this->prophesize(ObjectManager::class); + $managerProphecy->getClassMetadata($resourceClass)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); + + return $managerProphecy->reveal(); + } + + public function testSingleIdentifier() + { + $identifiers = ['id']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); + + $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + + $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, Dummy::class), ['id' => 1]); + } + + public function testCompositeIdentifier() + { + $identifiers = ['ida', 'idb']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); + + $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + + $this->assertEquals($identifierManager->normalizeIdentifiers('ida=1;idb=2', $objectManager, Dummy::class), ['ida' => 1, 'idb' => 2]); + } + + /** + * @expectedException \ApiPlatform\Core\Exception\PropertyNotFoundException + * @expectedExceptionMessage Invalid identifier "idbad=1;idb=2", "ida" has not been found. + */ + public function testInvalidIdentifier() + { + $identifiers = ['ida', 'idb']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); + + $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + + $identifierManager->normalizeIdentifiers('idbad=1;idb=2', $objectManager, Dummy::class); + } +} diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 737ccaaad8c..11ce5ae9679 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -236,13 +236,13 @@ private function getContainerBuilderProphecy() 'api_platform.cache.route_name_resolver', 'api_platform.collection_data_provider', 'api_platform.doctrine.listener.view.write', + 'api_platform.doctrine.orm.util.identifier_manager', 'api_platform.doctrine.metadata_factory', 'api_platform.doctrine.orm.boolean_filter', 'api_platform.doctrine.orm.collection_data_provider', 'api_platform.doctrine.orm.date_filter', 'api_platform.doctrine.orm.default.collection_data_provider', 'api_platform.doctrine.orm.default.item_data_provider', - 'api_platform.doctrine.orm.default.item_data_provider', 'api_platform.doctrine.orm.item_data_provider', 'api_platform.doctrine.orm.metadata.property.metadata_factory', 'api_platform.doctrine.orm.numeric_filter', diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php index df92a82d21e..ad63328d4c0 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php @@ -33,7 +33,7 @@ public function testProcess() $collectionDataProviderDefinition = $collectionDataProviderDefinitionProphecy->reveal(); $itemDataProviderDefinitionProphecy = $this->prophesize(Definition::class); - $itemDataProviderDefinitionProphecy->replaceArgument(3, Argument::type('array'))->shouldBeCalled(); + $itemDataProviderDefinitionProphecy->replaceArgument(2, Argument::type('array'))->shouldBeCalled(); $itemDataProviderDefinition = $itemDataProviderDefinitionProphecy->reveal(); $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class); From 1f72a9b000859fb6eee6d6e6fb522226690e7da3 Mon Sep 17 00:00:00 2001 From: abluchet Date: Fri, 13 Jan 2017 10:24:13 +0100 Subject: [PATCH 2/2] Move IdentifierManager to a trait to avoid BC break --- src/Bridge/Doctrine/Orm/ItemDataProvider.php | 16 ++- .../Orm/Util/IdentifierManagerInterface.php | 30 ----- ...Manager.php => IdentifierManagerTrait.php} | 26 ++--- .../Compiler/DoctrineQueryExtensionPass.php | 2 +- .../Bundle/Resources/config/doctrine_orm.xml | 10 +- .../Doctrine/Orm/ItemDataProviderTest.php | 108 +++++++++++------- ...est.php => IdentifierManagerTraitTest.php} | 23 +++- .../ApiPlatformExtensionTest.php | 1 - .../DoctrineQueryExtensionPassTest.php | 2 +- 9 files changed, 110 insertions(+), 108 deletions(-) delete mode 100644 src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php rename src/Bridge/Doctrine/Orm/Util/{IdentifierManager.php => IdentifierManagerTrait.php} (74%) rename tests/Bridge/Doctrine/Util/{IdentifierManagerTest.php => IdentifierManagerTraitTest.php} (79%) diff --git a/src/Bridge/Doctrine/Orm/ItemDataProvider.php b/src/Bridge/Doctrine/Orm/ItemDataProvider.php index 69bc500057c..e51913ed15f 100644 --- a/src/Bridge/Doctrine/Orm/ItemDataProvider.php +++ b/src/Bridge/Doctrine/Orm/ItemDataProvider.php @@ -13,11 +13,13 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerInterface; +use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerTrait; use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGenerator; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; use ApiPlatform\Core\Exception\RuntimeException; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; @@ -31,18 +33,22 @@ class ItemDataProvider implements ItemDataProviderInterface { private $managerRegistry; - private $identifierManager; + private $propertyNameCollectionFactory; + private $propertyMetadataFactory; private $itemExtensions; + use IdentifierManagerTrait; + /** * @param ManagerRegistry $managerRegistry * @param IdentifierManagerInterface $identifierManager * @param QueryItemExtensionInterface[] $itemExtensions */ - public function __construct(ManagerRegistry $managerRegistry, IdentifierManagerInterface $identifierManager, array $itemExtensions = []) + public function __construct(ManagerRegistry $managerRegistry, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, array $itemExtensions = []) { $this->managerRegistry = $managerRegistry; - $this->identifierManager = $identifierManager; + $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; + $this->propertyMetadataFactory = $propertyMetadataFactory; $this->itemExtensions = $itemExtensions; } @@ -60,7 +66,7 @@ public function getItem(string $resourceClass, $id, string $operationName = null throw new ResourceClassNotSupportedException(); } - $identifiers = $this->identifierManager->normalizeIdentifiers($id, $manager, $resourceClass); + $identifiers = $this->normalizeIdentifiers($id, $manager, $resourceClass); $fetchData = $context['fetch_data'] ?? true; if (!$fetchData && $manager instanceof EntityManagerInterface) { diff --git a/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php b/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php deleted file mode 100644 index daed64a8c3d..00000000000 --- a/src/Bridge/Doctrine/Orm/Util/IdentifierManagerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; - -use Doctrine\Common\Persistence\ObjectManager; - -interface IdentifierManagerInterface -{ - /** - * Transform and check the identifier, composite or not. - * - * @param int|string $id - * @param ObjectManager $manager - * @param string $resourceClass - * - * @throws PropertyNotFoundException - * - * @return array - */ - public function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array; -} diff --git a/src/Bridge/Doctrine/Orm/Util/IdentifierManager.php b/src/Bridge/Doctrine/Orm/Util/IdentifierManagerTrait.php similarity index 74% rename from src/Bridge/Doctrine/Orm/Util/IdentifierManager.php rename to src/Bridge/Doctrine/Orm/Util/IdentifierManagerTrait.php index 7cf3446b8ee..9e741ee4ad2 100644 --- a/src/Bridge/Doctrine/Orm/Util/IdentifierManager.php +++ b/src/Bridge/Doctrine/Orm/Util/IdentifierManagerTrait.php @@ -12,23 +12,23 @@ namespace ApiPlatform\Core\Bridge\Doctrine\Orm\Util; use ApiPlatform\Core\Exception\PropertyNotFoundException; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; -use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use Doctrine\Common\Persistence\ObjectManager; -class IdentifierManager implements IdentifierManagerInterface +/** + * @internal + */ +trait IdentifierManagerTrait { - private $propertyNameCollectionFactory; - private $propertyMetadataFactory; - - public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory) - { - $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; - $this->propertyMetadataFactory = $propertyMetadataFactory; - } - /** - * {@inheritdoc} + * Transform and check the identifier, composite or not. + * + * @param int|string $id + * @param ObjectManager $manager + * @param string $resourceClass + * + * @throws PropertyNotFoundException + * + * @return array */ public function normalizeIdentifiers($id, ObjectManager $manager, string $resourceClass): array { diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php index fd43792f35f..3add3fa0595 100644 --- a/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php +++ b/src/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPass.php @@ -39,7 +39,7 @@ public function process(ContainerBuilder $container) $itemDataProviderDefinition = $container->getDefinition('api_platform.doctrine.orm.item_data_provider'); $collectionDataProviderDefinition->replaceArgument(1, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.collection')); - $itemDataProviderDefinition->replaceArgument(2, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.item')); + $itemDataProviderDefinition->replaceArgument(3, $this->findSortedServices($container, 'api_platform.doctrine.orm.query_extension.item')); } /** diff --git a/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml b/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml index a5fd944d672..ca72c60149c 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/doctrine_orm.xml @@ -16,7 +16,8 @@ - + + @@ -84,13 +85,6 @@ - - - - - - - diff --git a/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php b/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php index e860ea2f3ff..7ee30e33b2a 100644 --- a/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php +++ b/tests/Bridge/Doctrine/Orm/ItemDataProviderTest.php @@ -14,14 +14,18 @@ use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\QueryResultItemExtensionInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\ItemDataProvider; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerInterface; use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; +use ApiPlatform\Core\Metadata\Property\PropertyMetadata; +use ApiPlatform\Core\Metadata\Property\PropertyNameCollection; use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Dummy; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\ORM\AbstractQuery; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Query\Expr; use Doctrine\ORM\Query\Expr\Comparison; use Doctrine\ORM\QueryBuilder; @@ -32,13 +36,45 @@ */ class ItemDataProviderTest extends \PHPUnit_Framework_TestCase { - private function getIdentifierManagerProphecy($input, $resourceClass, $output) + private function getManagerRegistryProphecy(QueryBuilder $queryBuilder, array $identifiers, string $resourceClass) { - $objectManager = Argument::type(ObjectManager::class); - $identifierManagerProphecy = $this->prophesize(IdentifierManagerInterface::class); - $identifierManagerProphecy->normalizeIdentifiers($input, $objectManager, $resourceClass)->willReturn($output); + $classMetadataProphecy = $this->prophesize(ClassMetadata::class); + $classMetadataProphecy->getIdentifier()->willReturn($identifiers)->shouldBeCalled(); - return $identifierManagerProphecy->reveal(); + $repositoryProphecy = $this->prophesize(EntityRepository::class); + $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); + + $managerProphecy = $this->prophesize(ObjectManager::class); + $managerProphecy->getClassMetadata($resourceClass)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); + $managerProphecy->getRepository($resourceClass)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); + + $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); + $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + + return $managerRegistryProphecy->reveal(); + } + + private function getMetadataProphecies(array $identifiers, string $resourceClass) + { + $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); + $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); + + $nameCollection = ['foobar']; + + foreach ($identifiers as $identifier) { + $metadata = new PropertyMetadata(); + $metadata = $metadata->withIdentifier(true); + $propertyMetadataFactoryProphecy->create($resourceClass, $identifier)->willReturn($metadata); + + $nameCollection[] = $identifier; + } + + //random property to prevent the use of non-identifiers metadata while looping + $propertyMetadataFactoryProphecy->create($resourceClass, 'foobar')->willReturn(new PropertyMetadata()); + + $propertyNameCollectionFactoryProphecy->create($resourceClass)->willReturn(new PropertyNameCollection($nameCollection)); + + return [$propertyNameCollectionFactoryProphecy->reveal(), $propertyMetadataFactoryProphecy->reveal()]; } public function testGetItemSingleIdentifier() @@ -61,21 +97,14 @@ public function testGetItemSingleIdentifier() $queryBuilder = $queryBuilderProphecy->reveal(); - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + $identifiers = ['id']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $managerRegistry = $this->getManagerRegistryProphecy($queryBuilder, $identifiers, Dummy::class); $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', $context)->shouldBeCalled(); - $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 1, 'foo', $context)); } @@ -102,21 +131,14 @@ public function testGetItemDoubleIdentifier() $queryBuilder = $queryBuilderProphecy->reveal(); - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + $identifiers = ['ida', 'idb']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $managerRegistry = $this->getManagerRegistryProphecy($queryBuilder, $identifiers, Dummy::class); $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['ida' => 1, 'idb' => 2], 'foo', [])->shouldBeCalled(); - $identifierManagerProphecy = $this->getIdentifierManagerProphecy('ida=1;idb=2', Dummy::class, ['ida' => 1, 'idb' => 2]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 'ida=1;idb=2', 'foo')); } @@ -136,23 +158,16 @@ public function testQueryResultExtension() $queryBuilder = $queryBuilderProphecy->reveal(); - $repositoryProphecy = $this->prophesize(EntityRepository::class); - $repositoryProphecy->createQueryBuilder('o')->willReturn($queryBuilder)->shouldBeCalled(); - - $managerProphecy = $this->prophesize(ObjectManager::class); - $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); - - $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); - $managerRegistryProphecy->getManagerForClass(Dummy::class)->willReturn($managerProphecy->reveal())->shouldBeCalled(); + $identifiers = ['id']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); + $managerRegistry = $this->getManagerRegistryProphecy($queryBuilder, $identifiers, Dummy::class); $extensionProphecy = $this->prophesize(QueryResultItemExtensionInterface::class); $extensionProphecy->applyToItem($queryBuilder, Argument::type(QueryNameGeneratorInterface::class), Dummy::class, ['id' => 1], 'foo', [])->shouldBeCalled(); $extensionProphecy->supportsResult(Dummy::class, 'foo')->willReturn(true)->shouldBeCalled(); $extensionProphecy->getResult($queryBuilder)->willReturn([])->shouldBeCalled(); - $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); - - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistry, $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $this->assertEquals([], $dataProvider->getItem(Dummy::class, 1, 'foo')); } @@ -167,9 +182,10 @@ public function testThrowResourceClassNotSupportedException() $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $identifierManagerProphecy = $this->getIdentifierManagerProphecy(1, Dummy::class, ['id' => 1]); + $identifiers = ['id']; + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); - $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]); + $dataProvider = new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]); $dataProvider->getItem(Dummy::class, 'foo'); } @@ -179,9 +195,13 @@ public function testThrowResourceClassNotSupportedException() */ public function testCannotCreateQueryBuilder() { - $repositoryProphecy = $this->prophesize(ObjectRepository::class); + $identifiers = ['id']; + $repositoryProphecy = $this->prophesize(ObjectRepository::class); + $classMetadataProphecy = $this->prophesize(ClassMetadata::class); + $classMetadataProphecy->getIdentifier()->willReturn($identifiers)->shouldBeCalled(); $managerProphecy = $this->prophesize(ObjectManager::class); + $managerProphecy->getClassMetadata(Dummy::class)->shouldBeCalled()->willReturn($classMetadataProphecy->reveal()); $managerProphecy->getRepository(Dummy::class)->willReturn($repositoryProphecy->reveal())->shouldBeCalled(); $managerRegistryProphecy = $this->prophesize(ManagerRegistry::class); @@ -189,8 +209,8 @@ public function testCannotCreateQueryBuilder() $extensionProphecy = $this->prophesize(QueryItemExtensionInterface::class); - $identifierManagerProphecy = $this->getIdentifierManagerProphecy('foo', Dummy::class, ['id' => 'foo']); + list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); - (new ItemDataProvider($managerRegistryProphecy->reveal(), $identifierManagerProphecy, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo'); + (new ItemDataProvider($managerRegistryProphecy->reveal(), $propertyNameCollectionFactory, $propertyMetadataFactory, [$extensionProphecy->reveal()]))->getItem(Dummy::class, 'foo'); } } diff --git a/tests/Bridge/Doctrine/Util/IdentifierManagerTest.php b/tests/Bridge/Doctrine/Util/IdentifierManagerTraitTest.php similarity index 79% rename from tests/Bridge/Doctrine/Util/IdentifierManagerTest.php rename to tests/Bridge/Doctrine/Util/IdentifierManagerTraitTest.php index 22d7a46b3e5..b6116c148c0 100644 --- a/tests/Bridge/Doctrine/Util/IdentifierManagerTest.php +++ b/tests/Bridge/Doctrine/Util/IdentifierManagerTraitTest.php @@ -11,7 +11,7 @@ namespace ApiPlatform\Core\Tests\Doctrine\Util; -use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManager; +use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\IdentifierManagerTrait; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Property\PropertyMetadata; @@ -20,7 +20,20 @@ use Doctrine\Common\Persistence\ObjectManager; use Doctrine\ORM\Mapping\ClassMetadata; -class IdentifierManagerTest extends \PHPUnit_Framework_TestCase +class IdentifierManagerTraitImpl +{ + use IdentifierManagerTrait; + private $propertyNameCollectionFactory; + private $propertyMetadataFactory; + + public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory) + { + $this->propertyNameCollectionFactory = $propertyNameCollectionFactory; + $this->propertyMetadataFactory = $propertyMetadataFactory; + } +} + +class IdentifierManagerTraitTest extends \PHPUnit_Framework_TestCase { private function getMetadataProphecies(array $identifiers, string $resourceClass) { @@ -61,7 +74,7 @@ public function testSingleIdentifier() list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); - $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + $identifierManager = new IdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory); $this->assertEquals($identifierManager->normalizeIdentifiers(1, $objectManager, Dummy::class), ['id' => 1]); } @@ -72,7 +85,7 @@ public function testCompositeIdentifier() list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); - $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + $identifierManager = new IdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory); $this->assertEquals($identifierManager->normalizeIdentifiers('ida=1;idb=2', $objectManager, Dummy::class), ['ida' => 1, 'idb' => 2]); } @@ -87,7 +100,7 @@ public function testInvalidIdentifier() list($propertyNameCollectionFactory, $propertyMetadataFactory) = $this->getMetadataProphecies($identifiers, Dummy::class); $objectManager = $this->getObjectManagerProphecy($identifiers, Dummy::class); - $identifierManager = new IdentifierManager($propertyNameCollectionFactory, $propertyMetadataFactory); + $identifierManager = new IdentifierManagerTraitImpl($propertyNameCollectionFactory, $propertyMetadataFactory); $identifierManager->normalizeIdentifiers('idbad=1;idb=2', $objectManager, Dummy::class); } diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index 11ce5ae9679..2450a5f695e 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -236,7 +236,6 @@ private function getContainerBuilderProphecy() 'api_platform.cache.route_name_resolver', 'api_platform.collection_data_provider', 'api_platform.doctrine.listener.view.write', - 'api_platform.doctrine.orm.util.identifier_manager', 'api_platform.doctrine.metadata_factory', 'api_platform.doctrine.orm.boolean_filter', 'api_platform.doctrine.orm.collection_data_provider', diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php index ad63328d4c0..df92a82d21e 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/Compiler/DoctrineQueryExtensionPassTest.php @@ -33,7 +33,7 @@ public function testProcess() $collectionDataProviderDefinition = $collectionDataProviderDefinitionProphecy->reveal(); $itemDataProviderDefinitionProphecy = $this->prophesize(Definition::class); - $itemDataProviderDefinitionProphecy->replaceArgument(2, Argument::type('array'))->shouldBeCalled(); + $itemDataProviderDefinitionProphecy->replaceArgument(3, Argument::type('array'))->shouldBeCalled(); $itemDataProviderDefinition = $itemDataProviderDefinitionProphecy->reveal(); $containerBuilderProphecy = $this->prophesize(ContainerBuilder::class);