Skip to content

Commit

Permalink
bug #54835 [DoctrineBridge]  fix setting validated fields not using t…
Browse files Browse the repository at this point in the history
…he options array (xabbuh)

This PR was merged into the 7.1 branch.

Discussion
----------

[DoctrineBridge]  fix setting validated fields not using the options array

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        |
| License       | MIT

Commits
-------

d19dfaf fix setting validated fields not using the options array
  • Loading branch information
xabbuh committed May 15, 2024
2 parents 14a104a + d19dfaf commit 744e54b
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand All @@ -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".');
Expand All @@ -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.');
Expand All @@ -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',
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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".');
Expand Down Expand Up @@ -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([
Expand All @@ -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"');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 744e54b

Please sign in to comment.