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

View File

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