[DoctrineBridge] Fixed invalid unique value as composite key

Fixed UniqueEntityValidator tests
This commit is contained in:
HeahDude 2017-01-14 19:07:55 +01:00 committed by dmaicher
parent 5aadce3989
commit b3ced8608b
2 changed files with 39 additions and 29 deletions

View File

@ -175,7 +175,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->buildViolation('myMessage')
->atPath('property.path.name')
->setParameter('{{ value }}', '"Foo"')
->setInvalidValue('Foo')
->setInvalidValue($entity2)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->assertRaised();
}
@ -200,7 +200,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->buildViolation('myMessage')
->atPath('property.path.bar')
->setParameter('{{ value }}', '"Foo"')
->setInvalidValue('Foo')
->setInvalidValue($entity2)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->assertRaised();
}
@ -419,7 +419,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->buildViolation('myMessage')
->atPath('property.path.single')
->setParameter('{{ value }}', $entity1)
->setParameter('{{ value }}', 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity") identified by (id => 1)')
->setInvalidValue($entity1)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->assertRaised();
@ -452,12 +452,12 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($associated2, $constraint);
$expectedValue = 'Object of class "Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity2" identified by "2"';
$expectedValue = 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity") identified by (id => 1)';
$this->buildViolation('myMessage')
->atPath('property.path.single')
->setParameter('{{ value }}', '"'.$expectedValue.'"')
->setInvalidValue($expectedValue)
->setParameter('{{ value }}', $expectedValue)
->setInvalidValue($entity1)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->assertRaised();
}
@ -574,6 +574,11 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$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);
@ -583,12 +588,12 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
$this->validator->validate($newEntity, $constraint);
$expectedValue = 'Object of class "Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeObjectNoToStringIdEntity" identified by "(Object of class "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity" identified by "1"), (Object of class "Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity" identified by "2")"';
$expectedValue = 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity") identified by (id => 1)';
$this->buildViolation('myMessage')
->atPath('property.path.objectOne')
->setParameter('{{ value }}', '"'.$expectedValue.'"')
->setInvalidValue($expectedValue)
->setParameter('{{ value }}', $expectedValue)
->setInvalidValue($objectOne)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->assertRaised();
}

View File

@ -129,36 +129,41 @@ class UniqueEntityValidator extends ConstraintValidator
$errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];
$invalidValue = isset($criteria[$errorPath]) ? $criteria[$errorPath] : $criteria[$fields[0]];
if (is_object($invalidValue) && !method_exists($invalidValue, '__toString')) {
$invalidValue = $this->buildInvalidValueString($em, $class, $entity);
}
$this->context->buildViolation($constraint->message)
->atPath($errorPath)
->setParameter('{{ value }}', $this->formatValue($invalidValue, static::OBJECT_TO_STRING | static::PRETTY_DATE))
->setParameter('{{ value }}', $this->formatWithIdentifiers($em, $class, $invalidValue))
->setInvalidValue($invalidValue)
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
->addViolation();
}
/**
* @param ObjectManager $em
* @param ClassMetadata $class
* @param object $entity
*
* @return string
*/
private function buildInvalidValueString(ObjectManager $em, ClassMetadata $class, $entity)
private function formatWithIdentifiers(ObjectManager $em, ClassMetadata $class, $value)
{
$identifiers = array_map(function ($identifier) use ($em) {
// identifiers can be objects (without any __toString method) if its a composite PK
if (is_object($identifier) && !method_exists($identifier, '__toString')) {
return sprintf('(%s)', $this->buildInvalidValueString($em, $em->getClassMetadata(get_class($identifier)), $identifier));
if (!is_object($value) || $value instanceof \DateTimeInterface) {
return $this->formatValue($value, self::PRETTY_DATE);
}
// non unique value is a composite PK
if ($class->getName() !== $idClass = get_class($value)) {
$identifiers = $em->getClassMetadata($idClass)->getIdentifierValues($value);
} else {
$identifiers = $class->getIdentifierValues($value);
}
if (!$identifiers) {
return sprintf('object("%s")', $idClass);
}
array_walk($identifiers, function (&$id, $field) {
if (!is_object($id) || $id instanceof \DateTimeInterface) {
$idAsString = $this->formatValue($id, self::PRETTY_DATE);
} else {
$idAsString = sprintf('object("%s")', get_class($id));
}
return $identifier;
}, $class->getIdentifierValues($entity));
$id = sprintf('%s => %s', $field, $idAsString);
});
return sprintf('Object of class "%s" identified by "%s"', get_class($entity), implode(', ', $identifiers));
return sprintf('object("%s") identified by (%s)', $idClass, implode(', ', $identifiers));
}
}