From 45579fd7cd792eca9e4fdc90b34dd18523441137 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Jun 2015 17:49:33 +0200 Subject: [PATCH 1/2] [Form] Fixed: Filter non-integers when selecting entities by int ID --- .../Form/ChoiceList/ORMQueryBuilderLoader.php | 6 +++ .../ChoiceList/ORMQueryBuilderLoaderTest.php | 38 +++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 872e77affe..60aece4400 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -86,6 +86,12 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface $metadata = $qb->getEntityManager()->getClassMetadata($entity); if (in_array($metadata->getTypeOfField($identifier), array('integer', 'bigint', 'smallint'))) { $parameterType = Connection::PARAM_INT_ARRAY; + + // Filter out non-integer values (e.g. ""). If we don't, some + // databases such as PostgreSQL fail. + $values = array_values(array_filter($values, function ($v) { + return (string) $v === (string) (int) $v; + })); } else { $parameterType = Connection::PARAM_STR_ARRAY; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index bbad668250..7b68fda055 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -15,7 +15,7 @@ use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper; use Doctrine\DBAL\Connection; -class ORMQueryBuilderLoaderTest extends DoctrineTestHelper +class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException @@ -27,6 +27,7 @@ class ORMQueryBuilderLoaderTest extends DoctrineTestHelper /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + * @group legacy */ public function testClosureRequiresTheEntityManager() { @@ -47,7 +48,7 @@ class ORMQueryBuilderLoaderTest extends DoctrineTestHelper protected function checkIdentifierType($classname, $expectedType) { - $em = $this->createTestEntityManager(); + $em = DoctrineTestHelper::createTestEntityManager(); $query = $this->getMockBuilder('QueryMock') ->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute')) @@ -56,7 +57,7 @@ class ORMQueryBuilderLoaderTest extends DoctrineTestHelper $query->expects($this->once()) ->method('setParameter') ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(), $expectedType) - ->will($this->returnValue($query)); + ->willReturn($query); $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') ->setConstructorArgs(array($em)) @@ -65,7 +66,7 @@ class ORMQueryBuilderLoaderTest extends DoctrineTestHelper $qb->expects($this->once()) ->method('getQuery') - ->will($this->returnValue($query)); + ->willReturn($query); $qb->select('e') ->from($classname, 'e'); @@ -73,4 +74,33 @@ class ORMQueryBuilderLoaderTest extends DoctrineTestHelper $loader = new ORMQueryBuilderLoader($qb); $loader->getEntitiesByIds('id', array()); } + + public function testFilterNonIntegerValues() + { + $em = DoctrineTestHelper::createTestEntityManager(); + + $query = $this->getMockBuilder('QueryMock') + ->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute')) + ->getMock(); + + $query->expects($this->once()) + ->method('setParameter') + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(1, 2, 3), Connection::PARAM_INT_ARRAY) + ->willReturn($query); + + $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') + ->setConstructorArgs(array($em)) + ->setMethods(array('getQuery')) + ->getMock(); + + $qb->expects($this->once()) + ->method('getQuery') + ->willReturn($query); + + $qb->select('e') + ->from('Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity', 'e'); + + $loader = new ORMQueryBuilderLoader($qb); + $loader->getEntitiesByIds('id', array(1, '', 2, 3, 'foo')); + } } From 086c58c716ad1a676f34dcb3f930f343b38820ef Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 Jun 2015 17:17:34 +0200 Subject: [PATCH 2/2] [DoctrineBridge] Bypass the db when no valid identifier is provided in ORMQueryBuilderLoader --- .../Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php | 3 +++ .../Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 60aece4400..8f135d6258 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -95,6 +95,9 @@ class ORMQueryBuilderLoader implements EntityLoaderInterface } else { $parameterType = Connection::PARAM_STR_ARRAY; } + if (!$values) { + return array(); + } return $qb->andWhere($where) ->getQuery() diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index 7b68fda055..8fec7584e4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -56,7 +56,7 @@ class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase $query->expects($this->once()) ->method('setParameter') - ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(), $expectedType) + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array(1, 2), $expectedType) ->willReturn($query); $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') @@ -72,7 +72,7 @@ class ORMQueryBuilderLoaderTest extends \PHPUnit_Framework_TestCase ->from($classname, 'e'); $loader = new ORMQueryBuilderLoader($qb); - $loader->getEntitiesByIds('id', array()); + $loader->getEntitiesByIds('id', array(1, 2)); } public function testFilterNonIntegerValues()