From aeca66f840f6e89646d969e1db6728829a089a72 Mon Sep 17 00:00:00 2001 From: Tomas Hermanek Date: Wed, 10 Dec 2025 11:52:43 +0100 Subject: [PATCH 1/2] Add support for configurable user entity class in validators. --- .../AnzuSystemsCommonExtension.php | 10 ++++++++++ src/Resources/config/services.php | 2 ++ src/Validator/Constraints/EntityExistsValidator.php | 12 +++++++++++- src/Validator/Constraints/UniqueEntityValidator.php | 13 ++++++++++++- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/DependencyInjection/AnzuSystemsCommonExtension.php b/src/DependencyInjection/AnzuSystemsCommonExtension.php index 74eae20..3cdd190 100644 --- a/src/DependencyInjection/AnzuSystemsCommonExtension.php +++ b/src/DependencyInjection/AnzuSystemsCommonExtension.php @@ -81,7 +81,9 @@ use AnzuSystems\CommonBundle\Serializer\Handler\Handlers\ValueObjectHandler; use AnzuSystems\CommonBundle\Serializer\Service\BsonConverter; use AnzuSystems\CommonBundle\Util\ResourceLocker; +use AnzuSystems\CommonBundle\Validator\Constraints\EntityExistsValidator; use AnzuSystems\CommonBundle\Validator\Constraints\UniqueEntityDtoValidator; +use AnzuSystems\CommonBundle\Validator\Constraints\UniqueEntityValidator; use AnzuSystems\CommonBundle\Validator\Validator; use AnzuSystems\SerializerBundle\Metadata\MetadataRegistry; use AnzuSystems\SerializerBundle\Serializer; @@ -270,6 +272,14 @@ private function loadSettings(ContainerBuilder $container): void ->getDefinition(UniqueEntityDtoValidator::class) ->replaceArgument('$userEntityClass', $settings['user_entity_class']); + $container + ->getDefinition(UniqueEntityValidator::class) + ->replaceArgument('$userEntityClass', $settings['user_entity_class']); + + $container + ->getDefinition(EntityExistsValidator::class) + ->replaceArgument('$userEntityClass', $settings['user_entity_class']); + if ($settings['send_context_id_with_response']) { $container->register(ContextIdOnResponseListener::class) ->addTag('kernel.event_listener', ['event' => KernelEvents::RESPONSE]) diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index 1b16529..c2cc7b2 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -150,12 +150,14 @@ $services->set(EntityExistsValidator::class) ->arg('$entityManager', service(EntityManagerInterface::class)) + ->arg('$userEntityClass', null) ->tag('validator.constraint_validator') ; $services->set(UniqueEntityValidator::class) ->arg('$propertyAccessor', service(PropertyAccessorInterface::class)) ->arg('$entityManager', service(EntityManagerInterface::class)) + ->arg('$userEntityClass', null) ->tag('validator.constraint_validator') ; diff --git a/src/Validator/Constraints/EntityExistsValidator.php b/src/Validator/Constraints/EntityExistsValidator.php index c9941fd..7dc4dbb 100644 --- a/src/Validator/Constraints/EntityExistsValidator.php +++ b/src/Validator/Constraints/EntityExistsValidator.php @@ -5,6 +5,7 @@ namespace AnzuSystems\CommonBundle\Validator\Constraints; use AnzuSystems\CommonBundle\Repository\AnzuRepositoryInterface; +use AnzuSystems\Contracts\Entity\AnzuUser; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -12,8 +13,12 @@ final class EntityExistsValidator extends ConstraintValidator { + /** + * @param class-string $userEntityClass + */ public function __construct( private readonly EntityManagerInterface $entityManager, + private readonly string $userEntityClass, ) { } @@ -30,8 +35,13 @@ public function validate(mixed $value, Constraint $constraint): void throw new UnexpectedTypeException($value, 'string|integer'); } + $entityClass = $constraint->entity; + if ($entityClass === AnzuUser::class) { + $entityClass = $this->userEntityClass; + } + /** @var AnzuRepositoryInterface $repo */ - $repo = $this->entityManager->getRepository($constraint->entity); + $repo = $this->entityManager->getRepository($entityClass); if ($repo->exists(is_numeric($value) ? (int) $value : $value)) { return; } diff --git a/src/Validator/Constraints/UniqueEntityValidator.php b/src/Validator/Constraints/UniqueEntityValidator.php index 5c4454a..aa0eb5c 100644 --- a/src/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Validator/Constraints/UniqueEntityValidator.php @@ -4,7 +4,9 @@ namespace AnzuSystems\CommonBundle\Validator\Constraints; +use AnzuSystems\Contracts\Entity\AnzuUser; use AnzuSystems\Contracts\Entity\Interfaces\BaseIdentifiableInterface; +use Doctrine\Common\Util\ClassUtils; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraint; @@ -13,9 +15,13 @@ final class UniqueEntityValidator extends ConstraintValidator { + /** + * @param class-string $userEntityClass + */ public function __construct( private readonly PropertyAccessorInterface $propertyAccessor, private readonly EntityManagerInterface $entityManager, + private readonly string $userEntityClass, ) { } @@ -34,8 +40,13 @@ public function validate(mixed $value, Constraint $constraint): void $fields[$fieldName] = $this->propertyAccessor->getValue($value, $fieldName); } + $entityClass = ClassUtils::getRealClass($value::class); + if ($entityClass === AnzuUser::class) { + $entityClass = $this->userEntityClass; + } + /** @var BaseIdentifiableInterface|null $existingEntity */ - $existingEntity = $this->entityManager->getRepository($value::class)->findOneBy($fields); + $existingEntity = $this->entityManager->getRepository($entityClass)->findOneBy($fields); if (null === $existingEntity) { return; } From 76ef9e6b5a9f69308f9295aa197b0585a07bea39 Mon Sep 17 00:00:00 2001 From: Tomas Hermanek Date: Wed, 10 Dec 2025 13:12:22 +0100 Subject: [PATCH 2/2] Refactor --- .../Constraints/EntityExistsValidator.php | 12 ++++---- .../Constraints/UniqueEntityDtoValidator.php | 17 ++++++----- .../Constraints/UniqueEntityValidator.php | 12 ++++---- .../Traits/EntityClassResolverTrait.php | 29 +++++++++++++++++++ 4 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 src/Validator/Traits/EntityClassResolverTrait.php diff --git a/src/Validator/Constraints/EntityExistsValidator.php b/src/Validator/Constraints/EntityExistsValidator.php index 7dc4dbb..ebeeea6 100644 --- a/src/Validator/Constraints/EntityExistsValidator.php +++ b/src/Validator/Constraints/EntityExistsValidator.php @@ -5,7 +5,7 @@ namespace AnzuSystems\CommonBundle\Validator\Constraints; use AnzuSystems\CommonBundle\Repository\AnzuRepositoryInterface; -use AnzuSystems\Contracts\Entity\AnzuUser; +use AnzuSystems\CommonBundle\Validator\Traits\EntityClassResolverTrait; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -13,13 +13,16 @@ final class EntityExistsValidator extends ConstraintValidator { + use EntityClassResolverTrait; + /** * @param class-string $userEntityClass */ public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly string $userEntityClass, + string $userEntityClass, ) { + $this->userEntityClass = $userEntityClass; } /** @@ -35,10 +38,7 @@ public function validate(mixed $value, Constraint $constraint): void throw new UnexpectedTypeException($value, 'string|integer'); } - $entityClass = $constraint->entity; - if ($entityClass === AnzuUser::class) { - $entityClass = $this->userEntityClass; - } + $entityClass = $this->resolveEntityClass($constraint->entity); /** @var AnzuRepositoryInterface $repo */ $repo = $this->entityManager->getRepository($entityClass); diff --git a/src/Validator/Constraints/UniqueEntityDtoValidator.php b/src/Validator/Constraints/UniqueEntityDtoValidator.php index 1427021..d6e5de6 100644 --- a/src/Validator/Constraints/UniqueEntityDtoValidator.php +++ b/src/Validator/Constraints/UniqueEntityDtoValidator.php @@ -4,7 +4,7 @@ namespace AnzuSystems\CommonBundle\Validator\Constraints; -use AnzuSystems\Contracts\Entity\AnzuUser; +use AnzuSystems\CommonBundle\Validator\Traits\EntityClassResolverTrait; use AnzuSystems\Contracts\Entity\Interfaces\BaseIdentifiableInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; @@ -14,11 +14,17 @@ final class UniqueEntityDtoValidator extends ConstraintValidator { + use EntityClassResolverTrait; + + /** + * @param class-string $userEntityClass + */ public function __construct( private readonly PropertyAccessorInterface $propertyAccessor, private readonly EntityManagerInterface $entityManager, - private readonly string $userEntityClass, + string $userEntityClass, ) { + $this->userEntityClass = $userEntityClass; } /** @@ -33,12 +39,7 @@ public function validate(mixed $value, Constraint $constraint): void throw new UnexpectedTypeException($constraint->entity, BaseIdentifiableInterface::class); } - /** @var class-string $entityClass */ - $entityClass = $constraint->entity; - if ($entityClass === AnzuUser::class) { - /** @var class-string $entityClass */ - $entityClass = $this->userEntityClass; - } + $entityClass = $this->resolveEntityClass($constraint->entity); $fieldsNames = $constraint->fields; $fields = []; diff --git a/src/Validator/Constraints/UniqueEntityValidator.php b/src/Validator/Constraints/UniqueEntityValidator.php index aa0eb5c..2e1213e 100644 --- a/src/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Validator/Constraints/UniqueEntityValidator.php @@ -4,7 +4,7 @@ namespace AnzuSystems\CommonBundle\Validator\Constraints; -use AnzuSystems\Contracts\Entity\AnzuUser; +use AnzuSystems\CommonBundle\Validator\Traits\EntityClassResolverTrait; use AnzuSystems\Contracts\Entity\Interfaces\BaseIdentifiableInterface; use Doctrine\Common\Util\ClassUtils; use Doctrine\ORM\EntityManagerInterface; @@ -15,14 +15,17 @@ final class UniqueEntityValidator extends ConstraintValidator { + use EntityClassResolverTrait; + /** * @param class-string $userEntityClass */ public function __construct( private readonly PropertyAccessorInterface $propertyAccessor, private readonly EntityManagerInterface $entityManager, - private readonly string $userEntityClass, + string $userEntityClass, ) { + $this->userEntityClass = $userEntityClass; } /** @@ -40,10 +43,7 @@ public function validate(mixed $value, Constraint $constraint): void $fields[$fieldName] = $this->propertyAccessor->getValue($value, $fieldName); } - $entityClass = ClassUtils::getRealClass($value::class); - if ($entityClass === AnzuUser::class) { - $entityClass = $this->userEntityClass; - } + $entityClass = $this->resolveEntityClass(ClassUtils::getRealClass($value::class)); /** @var BaseIdentifiableInterface|null $existingEntity */ $existingEntity = $this->entityManager->getRepository($entityClass)->findOneBy($fields); diff --git a/src/Validator/Traits/EntityClassResolverTrait.php b/src/Validator/Traits/EntityClassResolverTrait.php new file mode 100644 index 0000000..1ff92f2 --- /dev/null +++ b/src/Validator/Traits/EntityClassResolverTrait.php @@ -0,0 +1,29 @@ +userEntityClass; + } + + return $entityClass; + } +}