bug #21656 [DoctrineBridge] Fixed validating custom doctrine type columns (dmaicher)
This PR was merged into the 3.2 branch.
Discussion
----------
[DoctrineBridge] Fixed validating custom doctrine type columns
| Q | A
| ------------- | ---
| Branch? | 3.1
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #21619
| License | MIT
| Doc PR | -
This fixes #21619 by not assuming the invalid `$value` is a Doctrine entity if its an object
Commits
-------
ad59370241
[DoctrineBridge] Fixed validating custom doctrine type columns
This commit is contained in:
commit
fbcd227763
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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';
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
|||||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||||
use Doctrine\Common\Persistence\ObjectManager;
|
use Doctrine\Common\Persistence\ObjectManager;
|
||||||
use Doctrine\Common\Persistence\ObjectRepository;
|
use Doctrine\Common\Persistence\ObjectRepository;
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
|
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
|
||||||
use Symfony\Bridge\Doctrine\Test\TestRepositoryFactory;
|
use Symfony\Bridge\Doctrine\Test\TestRepositoryFactory;
|
||||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\Employee;
|
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\AssociationEntity;
|
||||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity2;
|
use Symfony\Bridge\Doctrine\Tests\Fixtures\AssociationEntity2;
|
||||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity;
|
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\UniqueEntity;
|
||||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator;
|
||||||
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
|
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
|
||||||
@ -64,6 +67,10 @@ class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest
|
|||||||
$config = DoctrineTestHelper::createTestConfiguration();
|
$config = DoctrineTestHelper::createTestConfiguration();
|
||||||
$config->setRepositoryFactory($this->repositoryFactory);
|
$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->em = DoctrineTestHelper::createTestEntityManager($config);
|
||||||
$this->registry = $this->createRegistryMock($this->em);
|
$this->registry = $this->createRegistryMock($this->em);
|
||||||
$this->createSchema($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\Person'),
|
||||||
$em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\Employee'),
|
$em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\Employee'),
|
||||||
$em->getClassMetadata('Symfony\Bridge\Doctrine\Tests\Fixtures\CompositeObjectNoToStringIdEntity'),
|
$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)
|
->setCode(UniqueEntity::NOT_UNIQUE_ERROR)
|
||||||
->assertRaised();
|
->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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,9 +176,15 @@ class UniqueEntityValidator extends ConstraintValidator
|
|||||||
return $this->formatValue($value, self::PRETTY_DATE);
|
return $this->formatValue($value, self::PRETTY_DATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// non unique value is a composite PK
|
|
||||||
if ($class->getName() !== $idClass = get_class($value)) {
|
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 {
|
} else {
|
||||||
$identifiers = $class->getIdentifierValues($value);
|
$identifiers = $class->getIdentifierValues($value);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user