diff --git a/src/Exception/EntityNotFoundException.php b/src/Exception/EntityNotFoundException.php new file mode 100644 index 0000000..e7a0be7 --- /dev/null +++ b/src/Exception/EntityNotFoundException.php @@ -0,0 +1,26 @@ +$methodName($queryParameterValue); - if ($queryField->getAccessor()) { + if (null !== $entity && $queryField->getAccessor()) { $accessMethodName = $queryField->getAccessor(); $entity = $entity->$accessMethodName(); } if (null === $entity) { - return $query; + throw new EntityNotFoundException($parameterName, (string) $queryParameterValue); } $setMethodName = $queryField->getMethodName(); diff --git a/tests/Factory/ValueAssigner/ValueAssignerTest.php b/tests/Factory/ValueAssigner/ValueAssignerTest.php index 54e335b..03aeea6 100644 --- a/tests/Factory/ValueAssigner/ValueAssignerTest.php +++ b/tests/Factory/ValueAssigner/ValueAssignerTest.php @@ -3,6 +3,8 @@ namespace MalteHuebner\DataQueryBundle\Tests\Factory\ValueAssigner; use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\ObjectRepository; +use MalteHuebner\DataQueryBundle\Exception\EntityNotFoundException; use MalteHuebner\DataQueryBundle\Factory\ValueAssigner\ValueAssigner; use MalteHuebner\DataQueryBundle\Factory\ValueAssigner\ValueAssignerInterface; use MalteHuebner\DataQueryBundle\Factory\ValueAssigner\ValueType; @@ -11,6 +13,10 @@ use MalteHuebner\DataQueryBundle\Query\BoundingBoxQuery; use MalteHuebner\DataQueryBundle\Parameter\SizeParameter; use MalteHuebner\DataQueryBundle\RequestParameterList\RequestParameterList; +use MalteHuebner\DataQueryBundle\Tests\Fixtures\SimpleEntity; +use MalteHuebner\DataQueryBundle\Tests\Fixtures\SimpleEntityContainer; +use MalteHuebner\DataQueryBundle\Tests\Fixtures\SimpleEntityContainerRepository; +use MalteHuebner\DataQueryBundle\Tests\Fixtures\SimpleEntityQuery; use PHPUnit\Framework\TestCase; class ValueAssignerTest extends TestCase @@ -309,4 +315,130 @@ public function testConvertToIntTrimsWhitespaceForParameter(): void $this->assertTrue(true); } + + public function testAssignQueryEntityValueAssignsEntityFromRepository(): void + { + $entity = new SimpleEntity(); + + $repository = $this->createMock(ObjectRepository::class); + $repository->method('find')->with('42')->willReturn($entity); + + $this->managerRegistry->method('getRepository')->with(SimpleEntity::class)->willReturn($repository); + + $list = new RequestParameterList(); + $list->add('simpleEntityId', '42'); + + $query = new SimpleEntityQuery(); + + $queryField = new QueryField(); + $queryField + ->setMethodName('setSimpleEntity') + ->setParameterName('simpleEntityId') + ->setType(SimpleEntity::class); + + $this->valueAssigner->assignQueryPropertyValueFromRequest($list, $query, $queryField); + + $this->assertSame($entity, $query->getSimpleEntity()); + } + + public function testAssignQueryEntityValueThrowsWhenEntityNotFound(): void + { + $repository = $this->createMock(ObjectRepository::class); + $repository->method('find')->willReturn(null); + + $this->managerRegistry->method('getRepository')->willReturn($repository); + + $list = new RequestParameterList(); + $list->add('simpleEntityId', '42'); + + $query = new SimpleEntityQuery(); + + $queryField = new QueryField(); + $queryField + ->setMethodName('setSimpleEntity') + ->setParameterName('simpleEntityId') + ->setType(SimpleEntity::class); + + $this->expectException(EntityNotFoundException::class); + $this->expectExceptionMessage('Could not find entity for query parameter "simpleEntityId" with value "42"'); + + $this->valueAssigner->assignQueryPropertyValueFromRequest($list, $query, $queryField); + } + + public function testAssignQueryEntityValueWithAccessorAssignsAccessedEntity(): void + { + $entity = new SimpleEntity(); + $repository = new SimpleEntityContainerRepository(new SimpleEntityContainer($entity)); + + $this->managerRegistry->method('getRepository')->with(SimpleEntityContainer::class)->willReturn($repository); + + $list = new RequestParameterList(); + $list->add('simpleEntitySlug', 'some-slug'); + + $query = new SimpleEntityQuery(); + + $queryField = new QueryField(); + $queryField + ->setMethodName('setSimpleEntity') + ->setParameterName('simpleEntitySlug') + ->setType(SimpleEntity::class) + ->setRepository(SimpleEntityContainer::class) + ->setRepositoryMethod('findOneBySlug') + ->setAccessor('getSimpleEntity'); + + $this->valueAssigner->assignQueryPropertyValueFromRequest($list, $query, $queryField); + + $this->assertSame($entity, $query->getSimpleEntity()); + } + + public function testAssignQueryEntityValueWithAccessorThrowsWhenLookupReturnsNull(): void + { + $repository = new SimpleEntityContainerRepository(null); + + $this->managerRegistry->method('getRepository')->willReturn($repository); + + $list = new RequestParameterList(); + $list->add('simpleEntitySlug', 'unknown-slug'); + + $query = new SimpleEntityQuery(); + + $queryField = new QueryField(); + $queryField + ->setMethodName('setSimpleEntity') + ->setParameterName('simpleEntitySlug') + ->setType(SimpleEntity::class) + ->setRepository(SimpleEntityContainer::class) + ->setRepositoryMethod('findOneBySlug') + ->setAccessor('getSimpleEntity'); + + $this->expectException(EntityNotFoundException::class); + $this->expectExceptionMessage('Could not find entity for query parameter "simpleEntitySlug" with value "unknown-slug"'); + + $this->valueAssigner->assignQueryPropertyValueFromRequest($list, $query, $queryField); + } + + public function testAssignQueryEntityValueThrowsWhenAccessorReturnsNull(): void + { + $repository = new SimpleEntityContainerRepository(new SimpleEntityContainer(null)); + + $this->managerRegistry->method('getRepository')->willReturn($repository); + + $list = new RequestParameterList(); + $list->add('simpleEntitySlug', 'some-slug'); + + $query = new SimpleEntityQuery(); + + $queryField = new QueryField(); + $queryField + ->setMethodName('setSimpleEntity') + ->setParameterName('simpleEntitySlug') + ->setType(SimpleEntity::class) + ->setRepository(SimpleEntityContainer::class) + ->setRepositoryMethod('findOneBySlug') + ->setAccessor('getSimpleEntity'); + + $this->expectException(EntityNotFoundException::class); + + $this->valueAssigner->assignQueryPropertyValueFromRequest($list, $query, $queryField); + } } diff --git a/tests/Fixtures/SimpleEntityContainer.php b/tests/Fixtures/SimpleEntityContainer.php new file mode 100644 index 0000000..a8bcb55 --- /dev/null +++ b/tests/Fixtures/SimpleEntityContainer.php @@ -0,0 +1,18 @@ +simpleEntity; + } +} diff --git a/tests/Fixtures/SimpleEntityContainerRepository.php b/tests/Fixtures/SimpleEntityContainerRepository.php new file mode 100644 index 0000000..3edfdd2 --- /dev/null +++ b/tests/Fixtures/SimpleEntityContainerRepository.php @@ -0,0 +1,48 @@ + + */ +class SimpleEntityContainerRepository implements ObjectRepository +{ + public function __construct( + private readonly ?SimpleEntityContainer $simpleEntityContainer = null + ) + { + + } + + public function findOneBySlug(string $slug): ?SimpleEntityContainer + { + return $this->simpleEntityContainer; + } + + public function find(mixed $id): ?object + { + return null; + } + + public function findAll(): array + { + return []; + } + + public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array + { + return []; + } + + public function findOneBy(array $criteria): ?object + { + return null; + } + + public function getClassName(): string + { + return SimpleEntityContainer::class; + } +} diff --git a/tests/Fixtures/SimpleEntityQuery.php b/tests/Fixtures/SimpleEntityQuery.php new file mode 100644 index 0000000..e911284 --- /dev/null +++ b/tests/Fixtures/SimpleEntityQuery.php @@ -0,0 +1,22 @@ +simpleEntity = $simpleEntity; + + return $this; + } + + public function getSimpleEntity(): ?SimpleEntity + { + return $this->simpleEntity; + } +}