diff --git a/Readme.md b/Readme.md index 2fea809..7cde1b1 100644 --- a/Readme.md +++ b/Readme.md @@ -63,6 +63,112 @@ final class EmailUser // ... ``` +Sometimes we may also need to check not only whether the entity exists, but also the state (for example is an article published). +To do this need to create a new Constraint, which extends from EntityExist instead of the default Symfony Constraint class. + +```php +isPublished(); + } +} +``` + +Another example of validator with constructor injection: + +```php +salesChannelContext = $salesChannelContext; + } + + protected function checkEntity(object $entity): bool + { + if (!$entity instanceof Offer) { + throw new UnexpectedValueException($entity, Offer::class); + } + + return $entity->isVisible() + && $this->salesChannelContext->getCurrentSalesChannel()->equals($entity->getSalesChannel()); + } +} + +``` + +Finally, in your entity or DTO, use a new constraint instead of `EntityExist`. + +```php + */ -final class EntityExist extends Constraint +class EntityExist extends Constraint { public $message = 'Entity "%entity%" with property "%property%": "%value%" does not exist.'; public $property = 'id'; diff --git a/src/EntityExistValidator.php b/src/EntityExistValidator.php index 27852ea..ab055c4 100644 --- a/src/EntityExistValidator.php +++ b/src/EntityExistValidator.php @@ -11,8 +11,9 @@ /** * @author Tobias Nyholm * @author Radoje Albijanic + * @author Marcin Morawski */ -final class EntityExistValidator extends ConstraintValidator +class EntityExistValidator extends ConstraintValidator { private $entityManager; @@ -39,7 +40,7 @@ public function validate($value, Constraint $constraint): void $constraint->property => $value, ]); - if (null === $data) { + if (null === $data || !$this->checkEntity($data)) { $this->context->buildViolation($constraint->message) ->setParameter('%entity%', $constraint->entity) ->setParameter('%property%', $constraint->property) @@ -47,4 +48,9 @@ public function validate($value, Constraint $constraint): void ->addViolation(); } } + + protected function checkEntity(object $entity): bool + { + return true; + } } diff --git a/tests/EntityExistValidatorTest.php b/tests/EntityExistValidatorTest.php index 4f0e345..0c0e8de 100644 --- a/tests/EntityExistValidatorTest.php +++ b/tests/EntityExistValidatorTest.php @@ -62,7 +62,7 @@ public function testValidateValidEntity(): void ->expects($this->once()) ->method('findOneBy') ->with(['id' => 'foobar']) - ->willReturn('my_user'); + ->willReturn((object) ['username' => 'my_user']); $this->entityManager ->expects($this->once()) @@ -90,7 +90,7 @@ public function testValidateSkipsIfValueEmptyOrNull($value): void ->expects($this->exactly(0)) ->method('findOneBy') ->with(['id' => $value]) - ->willReturn('my_user'); + ->willReturn((object) ['username' => 'my_user']); $this->entityManager ->expects($this->exactly(0)) @@ -122,7 +122,7 @@ public function testValidateValidEntityWithCustomProperty(): void ->expects($this->once()) ->method('findOneBy') ->with(['uuid' => 'foobar']) - ->willReturn('my_user'); + ->willReturn((object) ['username' => 'my_user']); $this->entityManager ->expects($this->once()) @@ -158,4 +158,44 @@ public function testValidateInvalidEntity(): void $this->validator->validate(1, $constraint); } + + public function testCheckEntityCall(): void + { + $violationBuilder = $this->getMockBuilder(ConstraintViolationBuilderInterface::class)->getMock(); + $violationBuilder->method('setParameter')->will($this->returnSelf()); + $this->context->expects($this->once())->method('buildViolation')->willReturn($violationBuilder); + + $constraint = new EntityExist(); + $constraint->entity = 'App\Entity\User'; + + $repository = $this->getMockBuilder(EntityRepository::class) + ->disableOriginalConstructor() + ->getMock(); + + $repository + ->expects($this->once()) + ->method('findOneBy') + ->with(['id' => 'foobar']) + ->willReturn((object) ['username' => 'my_user']); + + $this->entityManager + ->expects($this->once()) + ->method('getRepository') + ->with('App\Entity\User') + ->willReturn($repository); + + $validator = $this->getValidatorWhichAlwaysReturnFalseForCheckEntity($this->entityManager); + $validator->initialize($this->context); + $validator->validate('foobar', $constraint); + } + + private function getValidatorWhichAlwaysReturnFalseForCheckEntity(EntityManagerInterface $entityManager): EntityExistValidator + { + return new class($entityManager) extends EntityExistValidator { + protected function checkEntity(object $entity): bool + { + return false; + } + }; + } }