From ad593702411f9e54d77bf3ff17fb40ca6d04466f Mon Sep 17 00:00:00 2001 From: David Maicher Date: Mon, 20 Feb 2017 11:38:35 +0100 Subject: [PATCH] [DoctrineBridge] Fixed validating custom doctrine type columns --- .../SingleIntIdStringWrapperNameEntity.php | 33 +++++++++++++++ .../Tests/Fixtures/Type/StringWrapper.php | 36 ++++++++++++++++ .../Tests/Fixtures/Type/StringWrapperType.php | 42 +++++++++++++++++++ .../Constraints/UniqueEntityValidatorTest.php | 35 ++++++++++++++++ .../Constraints/UniqueEntityValidator.php | 10 ++++- 5 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdStringWrapperNameEntity.php create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapper.php create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapperType.php diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdStringWrapperNameEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdStringWrapperNameEntity.php new file mode 100644 index 0000000000..d69d3de4b6 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/SingleIntIdStringWrapperNameEntity.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures; + +use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; +use Symfony\Bridge\Doctrine\Tests\Fixtures\Type\StringWrapper; + +/** @Entity */ +class SingleIntIdStringWrapperNameEntity +{ + /** @Id @Column(type="integer") */ + protected $id; + + /** @Column(type="string_wrapper", nullable=true) */ + public $name; + + public function __construct($id, $name) + { + $this->id = $id; + $this->name = $name; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapper.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapper.php new file mode 100644 index 0000000000..13bb3703d7 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapper.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures\Type; + +class StringWrapper +{ + /** + * @var string + */ + private $string; + + /** + * @param string $string + */ + public function __construct($string = null) + { + $this->string = $string; + } + + /** + * @return string + */ + public function getString() + { + return $this->string; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapperType.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapperType.php new file mode 100644 index 0000000000..0af4271ba7 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/Type/StringWrapperType.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures\Type; + +use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Types\StringType; + +class StringWrapperType extends StringType +{ + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return $value instanceof StringWrapper ? $value->getString() : null; + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return new StringWrapper($value); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'string_wrapper'; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index aa2ecc7a3a..0045e76cbc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -15,6 +15,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Persistence\ManagerRegistry; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectRepository; +use Doctrine\DBAL\Types\Type; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Symfony\Bridge\Doctrine\Test\TestRepositoryFactory; use Symfony\Bridge\Doctrine\Tests\Fixtures\Employee; @@ -26,6 +27,8 @@ use Symfony\Bridge\Doctrine\Tests\Fixtures\DoubleNullableNameEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity2; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity; +use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdStringWrapperNameEntity; +use Symfony\Bridge\Doctrine\Tests\Fixtures\Type\StringWrapper; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator; use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; @@ -64,6 +67,10 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $config = DoctrineTestHelper::createTestConfiguration(); $config->setRepositoryFactory($this->repositoryFactory); + if (!Type::hasType('string_wrapper')) { + Type::addType('string_wrapper', 'Symfony\Bridge\Doctrine\Tests\Fixtures\Type\StringWrapperType'); + } + $this->em = DoctrineTestHelper::createTestEntityManager($config); $this->registry = $this->createRegistryMock($this->em); $this->createSchema($this->em); @@ -150,6 +157,7 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\Person'), $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\Employee'), $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeObjectNoToStringIdEntity'), + $em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdStringWrapperNameEntity'), )); } @@ -700,4 +708,31 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } + + public function testValidateUniquenessWithCustomDoctrineTypeValue() + { + $constraint = new UniqueEntity(array( + 'message' => 'myMessage', + 'fields' => array('name'), + 'em' => self::EM_NAME, + )); + + $existingEntity = new SingleIntIdStringWrapperNameEntity(1, new StringWrapper('foo')); + + $this->em->persist($existingEntity); + $this->em->flush(); + + $newEntity = new SingleIntIdStringWrapperNameEntity(2, new StringWrapper('foo')); + + $this->validator->validate($newEntity, $constraint); + + $expectedValue = 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\Type\StringWrapper")'; + + $this->buildViolation('myMessage') + ->atPath('property.path.name') + ->setParameter('{{ value }}', $expectedValue) + ->setInvalidValue($existingEntity->name) + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->assertRaised(); + } } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 454111c238..c2fcb520e1 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -176,9 +176,15 @@ class UniqueEntityValidator extends ConstraintValidator 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); + // non unique value might be a composite PK that consists of other entity objects + if ($em->getMetadataFactory()->hasMetadataFor($idClass)) { + $identifiers = $em->getClassMetadata($idClass)->getIdentifierValues($value); + } else { + // this case might happen if the non unique column has a custom doctrine type and its value is an object + // in which case we cannot get any identifiers for it + $identifiers = array(); + } } else { $identifiers = $class->getIdentifierValues($value); }