diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index abe31d474dfab..93fb0e897d92a 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -951,6 +951,40 @@ public function rewind(): void } public function testValidateDTOUniqueness() + { + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['name'], + em: self::EM_NAME, + entityClass: Person::class, + ); + + $entity = new Person(1, 'Foo'); + $dto = new HireAnEmployee('Foo'); + + $this->validator->validate($entity, $constraint); + + $this->assertNoViolation(); + + $this->em->persist($entity); + $this->em->flush(); + + $this->validator->validate($entity, $constraint); + + $this->assertNoViolation(); + + $this->validator->validate($dto, $constraint); + + $this->buildViolation('myMessage') + ->atPath('property.path.name') + ->setInvalidValue('Foo') + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->setCause([$entity]) + ->setParameters(['{{ value }}' => '"Foo"']) + ->assertRaised(); + } + + public function testValidateDTOUniquenessDoctrineStyle() { $constraint = new UniqueEntity([ 'message' => 'myMessage', @@ -985,6 +1019,32 @@ public function testValidateDTOUniqueness() } public function testValidateMappingOfFieldNames() + { + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['primaryName' => 'name', 'secondaryName' => 'name2'], + em: self::EM_NAME, + entityClass: DoubleNameEntity::class, + ); + + $entity = new DoubleNameEntity(1, 'Foo', 'Bar'); + $dto = new CreateDoubleNameEntity('Foo', 'Bar'); + + $this->em->persist($entity); + $this->em->flush(); + + $this->validator->validate($dto, $constraint); + + $this->buildViolation('myMessage') + ->atPath('property.path.name') + ->setParameter('{{ value }}', '"Foo"') + ->setInvalidValue('Foo') + ->setCause([$entity]) + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->assertRaised(); + } + + public function testValidateMappingOfFieldNamesDoctrineStyle() { $constraint = new UniqueEntity([ 'message' => 'myMessage', @@ -1011,6 +1071,21 @@ public function testValidateMappingOfFieldNames() } public function testInvalidateDTOFieldName() + { + $this->expectException(ConstraintDefinitionException::class); + $this->expectExceptionMessage('The field "primaryName" is not a property of class "Symfony\Bridge\Doctrine\Tests\Fixtures\HireAnEmployee".'); + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['primaryName' => 'name'], + em: self::EM_NAME, + entityClass: SingleStringIdEntity::class, + ); + + $dto = new HireAnEmployee('Foo'); + $this->validator->validate($dto, $constraint); + } + + public function testInvalidateDTOFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); $this->expectExceptionMessage('The field "primaryName" is not a property of class "Symfony\Bridge\Doctrine\Tests\Fixtures\HireAnEmployee".'); @@ -1026,6 +1101,21 @@ public function testInvalidateDTOFieldName() } public function testInvalidateEntityFieldName() + { + $this->expectException(ConstraintDefinitionException::class); + $this->expectExceptionMessage('The field "name2" is not mapped by Doctrine, so it cannot be validated for uniqueness.'); + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['name2'], + em: self::EM_NAME, + entityClass: SingleStringIdEntity::class, + ); + + $dto = new HireAnEmployee('Foo'); + $this->validator->validate($dto, $constraint); + } + + public function testInvalidateEntityFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); $this->expectExceptionMessage('The field "name2" is not mapped by Doctrine, so it cannot be validated for uniqueness.'); @@ -1041,6 +1131,36 @@ public function testInvalidateEntityFieldName() } public function testValidateDTOUniquenessWhenUpdatingEntity() + { + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['name'], + em: self::EM_NAME, + entityClass: Person::class, + identifierFieldNames: ['id'], + ); + + $entity1 = new Person(1, 'Foo'); + $entity2 = new Person(2, 'Bar'); + + $this->em->persist($entity1); + $this->em->persist($entity2); + $this->em->flush(); + + $dto = new UpdateEmployeeProfile(2, 'Foo'); + + $this->validator->validate($dto, $constraint); + + $this->buildViolation('myMessage') + ->atPath('property.path.name') + ->setInvalidValue('Foo') + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->setCause([$entity1]) + ->setParameters(['{{ value }}' => '"Foo"']) + ->assertRaised(); + } + + public function testValidateDTOUniquenessWhenUpdatingEntityDoctrineStyle() { $constraint = new UniqueEntity([ 'message' => 'myMessage', @@ -1071,6 +1191,28 @@ public function testValidateDTOUniquenessWhenUpdatingEntity() } public function testValidateDTOUniquenessWhenUpdatingEntityWithTheSameValue() + { + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['name'], + em: self::EM_NAME, + entityClass: CompositeIntIdEntity::class, + identifierFieldNames: ['id1', 'id2'], + ); + + $entity = new CompositeIntIdEntity(1, 2, 'Foo'); + + $this->em->persist($entity); + $this->em->flush(); + + $dto = new UpdateCompositeIntIdEntity(1, 2, 'Foo'); + + $this->validator->validate($dto, $constraint); + + $this->assertNoViolation(); + } + + public function testValidateDTOUniquenessWhenUpdatingEntityWithTheSameValueDoctrineStyle() { $constraint = new UniqueEntity([ 'message' => 'myMessage', @@ -1093,6 +1235,35 @@ public function testValidateDTOUniquenessWhenUpdatingEntityWithTheSameValue() } public function testValidateIdentifierMappingOfFieldNames() + { + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['object1' => 'objectOne', 'object2' => 'objectTwo'], + em: self::EM_NAME, + entityClass: CompositeObjectNoToStringIdEntity::class, + identifierFieldNames: ['object1' => 'objectOne', 'object2' => 'objectTwo'], + ); + + $objectOne = new SingleIntIdNoToStringEntity(1, 'foo'); + $objectTwo = new SingleIntIdNoToStringEntity(2, 'bar'); + + $this->em->persist($objectOne); + $this->em->persist($objectTwo); + $this->em->flush(); + + $entity = new CompositeObjectNoToStringIdEntity($objectOne, $objectTwo); + + $this->em->persist($entity); + $this->em->flush(); + + $dto = new UpdateCompositeObjectNoToStringIdEntity($objectOne, $objectTwo, 'Foo'); + + $this->validator->validate($dto, $constraint); + + $this->assertNoViolation(); + } + + public function testValidateIdentifierMappingOfFieldNamesDoctrineStyle() { $constraint = new UniqueEntity([ 'message' => 'myMessage', @@ -1122,6 +1293,34 @@ public function testValidateIdentifierMappingOfFieldNames() } public function testInvalidateMissingIdentifierFieldName() + { + $this->expectException(ConstraintDefinitionException::class); + $this->expectExceptionMessage('The "Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeObjectNoToStringIdEntity" entity identifier field names should be "objectOne, objectTwo", not "objectTwo".'); + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['object1' => 'objectOne', 'object2' => 'objectTwo'], + em: self::EM_NAME, + entityClass: CompositeObjectNoToStringIdEntity::class, + identifierFieldNames: ['object2' => 'objectTwo'], + ); + + $objectOne = new SingleIntIdNoToStringEntity(1, 'foo'); + $objectTwo = new SingleIntIdNoToStringEntity(2, 'bar'); + + $this->em->persist($objectOne); + $this->em->persist($objectTwo); + $this->em->flush(); + + $entity = new CompositeObjectNoToStringIdEntity($objectOne, $objectTwo); + + $this->em->persist($entity); + $this->em->flush(); + + $dto = new UpdateCompositeObjectNoToStringIdEntity($objectOne, $objectTwo, 'Foo'); + $this->validator->validate($dto, $constraint); + } + + public function testInvalidateMissingIdentifierFieldNameDoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); $this->expectExceptionMessage('The "Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeObjectNoToStringIdEntity" entity identifier field names should be "objectOne, objectTwo", not "objectTwo".'); @@ -1150,6 +1349,25 @@ public function testInvalidateMissingIdentifierFieldName() } public function testUninitializedValueThrowException() + { + $this->expectExceptionMessage('Typed property Symfony\Bridge\Doctrine\Tests\Fixtures\Dto::$foo must not be accessed before initialization'); + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['foo' => 'name'], + em: self::EM_NAME, + entityClass: DoubleNameEntity::class, + ); + + $entity = new DoubleNameEntity(1, 'Foo', 'Bar'); + $dto = new Dto(); + + $this->em->persist($entity); + $this->em->flush(); + + $this->validator->validate($dto, $constraint); + } + + public function testUninitializedValueThrowExceptionDoctrineStyle() { $this->expectExceptionMessage('Typed property Symfony\Bridge\Doctrine\Tests\Fixtures\Dto::$foo must not be accessed before initialization'); $constraint = new UniqueEntity([ @@ -1169,6 +1387,27 @@ public function testUninitializedValueThrowException() } public function testEntityManagerNullObjectWhenDTO() + { + $this->expectException(ConstraintDefinitionException::class); + $this->expectExceptionMessage('Unable to find the object manager associated with an entity of class "Symfony\Bridge\Doctrine\Tests\Fixtures\Person"'); + $constraint = new UniqueEntity( + message: 'myMessage', + fields: ['name'], + entityClass: Person::class, + // no "em" option set + ); + + $this->em = null; + $this->registry = $this->createRegistryMock($this->em); + $this->validator = $this->createValidator(); + $this->validator->initialize($this->context); + + $dto = new HireAnEmployee('Foo'); + + $this->validator->validate($dto, $constraint); + } + + public function testEntityManagerNullObjectWhenDTODoctrineStyle() { $this->expectException(ConstraintDefinitionException::class); $this->expectExceptionMessage('Unable to find the object manager associated with an entity of class "Symfony\Bridge\Doctrine\Tests\Fixtures\Person"'); diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php index 5786d4c224fce..edc9011b27ea1 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php @@ -60,9 +60,9 @@ public function __construct( $payload = null, array $options = [], ) { - if (\is_array($fields) && \is_string(key($fields))) { + if (\is_array($fields) && \is_string(key($fields)) && [] === array_diff(array_keys($fields), array_keys(get_class_vars(static::class)))) { $options = array_merge($fields, $options); - } elseif (null !== $fields) { + } else { $options['fields'] = $fields; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy