diff --git a/Event/Subscriber/AbstractDoctrineSubscriber.php b/Event/Subscriber/AbstractDoctrineSubscriber.php index 6e160aa..1ab8734 100644 --- a/Event/Subscriber/AbstractDoctrineSubscriber.php +++ b/Event/Subscriber/AbstractDoctrineSubscriber.php @@ -232,15 +232,23 @@ public function filterNumberRange(GetFilterConditionEvent $event) */ public function filterText(GetFilterConditionEvent $event) { - $expr = $event->getFilterQuery()->getExpressionBuilder(); + $expr = $event->getFilterQuery()->getExpr(); + $exprBuilder = $event->getFilterQuery()->getExpressionBuilder(); + $expression = $expr->andX(); $values = $event->getValues(); if ('' !== $values['value'] && null !== $values['value']) { + $paramName = $this->generateParameterName($event->getField()); + if (isset($values['condition_pattern'])) { - $event->setCondition($expr->stringLike($event->getField(), $values['value'], $values['condition_pattern'])); + $expression->add($expr->like($event->getField(), ':' . $paramName, $values['condition_pattern'])); + $value = $exprBuilder->convertTypeToMask($values['value'], $values['condition_pattern']); } else { - $event->setCondition($expr->stringLike($event->getField(), $values['value'])); + $expression->add($expr->like($event->getField(), ':' . $paramName)); + $value = $values['value']; } + + $event->setCondition($expression, [$paramName => $value]); } } diff --git a/Filter/Doctrine/Expression/ExpressionBuilder.php b/Filter/Doctrine/Expression/ExpressionBuilder.php index 98a816b..795df35 100644 --- a/Filter/Doctrine/Expression/ExpressionBuilder.php +++ b/Filter/Doctrine/Expression/ExpressionBuilder.php @@ -236,7 +236,7 @@ protected function convertToSqlDateTime($date) * * @throws \InvalidArgumentException */ - protected function convertTypeToMask($value, $type) + public function convertTypeToMask($value, $type) { if ($this->forceCaseInsensitivity) { $value = $this->encoding ? mb_strtolower($value, $this->encoding) : mb_strtolower($value); diff --git a/Tests/Filter/Doctrine/DBALQueryBuilderUpdaterTest.php b/Tests/Filter/Doctrine/DBALQueryBuilderUpdaterTest.php index bab3e53..300e180 100644 --- a/Tests/Filter/Doctrine/DBALQueryBuilderUpdaterTest.php +++ b/Tests/Filter/Doctrine/DBALQueryBuilderUpdaterTest.php @@ -22,12 +22,12 @@ public function testBuildQuery() { parent::createBuildQueryTest('getSQL', [ 'SELECT i FROM item i', - 'SELECT i FROM item i WHERE i.name LIKE \'blabla\'', - 'SELECT i FROM item i WHERE (i.name LIKE \'blabla\') AND (i.position > :p_i_position)', - 'SELECT i FROM item i WHERE (i.name LIKE \'blabla\') AND (i.position > :p_i_position) AND (i.enabled = :p_i_enabled)', - 'SELECT i FROM item i WHERE (i.name LIKE \'blabla\') AND (i.position > :p_i_position) AND (i.enabled = :p_i_enabled)', - 'SELECT i FROM item i WHERE (i.name LIKE \'%blabla\') AND (i.position <= :p_i_position) AND (i.createdAt = :p_i_createdAt)', - 'SELECT i FROM item i WHERE (i.name LIKE \'%blabla\') AND (i.position <= :p_i_position) AND (i.createdAt = :p_i_createdAt)', + 'SELECT i FROM item i WHERE i.name LIKE :p_i_name ESCAPE 3', + 'SELECT i FROM item i WHERE (i.name LIKE :p_i_name ESCAPE 3) AND (i.position > :p_i_position)', + 'SELECT i FROM item i WHERE (i.name LIKE :p_i_name ESCAPE 3) AND (i.position > :p_i_position) AND (i.enabled = :p_i_enabled)', + 'SELECT i FROM item i WHERE (i.name LIKE :p_i_name ESCAPE 3) AND (i.position > :p_i_position) AND (i.enabled = :p_i_enabled)', + 'SELECT i FROM item i WHERE (i.name LIKE :p_i_name ESCAPE 2) AND (i.position <= :p_i_position) AND (i.createdAt = :p_i_createdAt)', + 'SELECT i FROM item i WHERE (i.name LIKE :p_i_name ESCAPE 2) AND (i.position <= :p_i_position) AND (i.createdAt = :p_i_createdAt)', ] ); } @@ -74,7 +74,7 @@ public function testDateTimeRange() public function testFilterStandardType() { - parent::createFilterStandardTypeTest('getSQL', ['SELECT i FROM item i WHERE (i.name LIKE \'%hey dude%\') AND (i.position = 99)']); + parent::createFilterStandardTypeTest('getSQL', ['SELECT i FROM item i WHERE (i.name LIKE :p_i_name) AND (i.position = 99)']); } protected function createDoctrineQueryBuilder() diff --git a/Tests/Filter/Doctrine/DoctrineQueryBuilderUpdater.php b/Tests/Filter/Doctrine/DoctrineQueryBuilderUpdater.php index cfeae38..b335bed 100644 --- a/Tests/Filter/Doctrine/DoctrineQueryBuilderUpdater.php +++ b/Tests/Filter/Doctrine/DoctrineQueryBuilderUpdater.php @@ -85,6 +85,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[0], $doctrineQueryBuilder->{$method}()); + $this->assertEquals([], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // bind a request to the form - 1 params $doctrineQueryBuilder = $this->createDoctrineQueryBuilder(); @@ -92,6 +93,8 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[1], $doctrineQueryBuilder->{$method}()); + $this->assertEquals(['p_i_name' => 'blabla'], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + // bind a request to the form - 2 params $form = $this->formFactory->create(ItemFilterType::class); @@ -101,7 +104,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[2], $doctrineQueryBuilder->{$method}()); - $this->assertEquals(['p_i_position' => 2], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'blabla', 'p_i_position' => 2.0], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // bind a request to the form - 3 params $form = $this->formFactory->create(ItemFilterType::class); @@ -111,7 +114,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[3], $doctrineQueryBuilder->{$method}()); - $this->assertEquals(['p_i_position' => 2, 'p_i_enabled' => true], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'blabla', 'p_i_position' => 2.0, 'p_i_enabled' => 1], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // bind a request to the form - 3 params (use checkbox for enabled field) $form = $this->formFactory->create(ItemFilterType::class, null, ['checkbox' => true]); @@ -121,7 +124,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[4], $doctrineQueryBuilder->{$method}()); - $this->assertEquals(['p_i_position' => 2, 'p_i_enabled' => 1], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'blabla', 'p_i_position' => 2, 'p_i_enabled' => 1], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // bind a request to the form - date + pattern selector $year = \date('Y'); @@ -148,7 +151,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[5], $doctrineQueryBuilder->{$method}()); - $this->assertEquals(['p_i_position' => 2, 'p_i_createdAt' => new \DateTime("{$year}-09-27")], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => '%blabla', 'p_i_position' => 2.0, 'p_i_createdAt' => new \DateTime("{$year}-09-27")], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // bind a request to the form - datetime + pattern selector $form = $this->formFactory->create(ItemFilterType::class, null, ['with_selector' => true, 'datetime' => true]); @@ -158,7 +161,7 @@ protected function createBuildQueryTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[6], $doctrineQueryBuilder->{$method}()); - $this->assertEquals(['p_i_position' => 2, 'p_i_createdAt' => new \DateTime("{$year}-09-27 13:21:00")], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => '%blabla', 'p_i_position' => 2.0, 'p_i_createdAt' => new \DateTime("{$year}-09-27 13:21:00")], $this->getQueryBuilderParameters($doctrineQueryBuilder)); } protected function createDisabledFieldTest($method, array $dqls) @@ -304,5 +307,6 @@ public function createFilterStandardTypeTest($method, array $dqls) $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($dqls[0], $doctrineQueryBuilder->{$method}()); + $this->assertEquals(['p_i_name' => 'hey dude'], $this->getQueryBuilderParameters($doctrineQueryBuilder)); } } diff --git a/Tests/Filter/Doctrine/ORMQueryBuilderUpdaterTest.php b/Tests/Filter/Doctrine/ORMQueryBuilderUpdaterTest.php index 564d1be..4799e87 100644 --- a/Tests/Filter/Doctrine/ORMQueryBuilderUpdaterTest.php +++ b/Tests/Filter/Doctrine/ORMQueryBuilderUpdaterTest.php @@ -24,7 +24,7 @@ class ORMQueryBuilderUpdaterTest extends DoctrineQueryBuilderUpdater { public function testBuildQuery() { - parent::createBuildQueryTest('getDQL', ['SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'blabla\'', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'blabla\' AND i.position > :p_i_position', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'blabla\' AND i.position > :p_i_position AND i.enabled = :p_i_enabled', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'blabla\' AND i.position > :p_i_position AND i.enabled = :p_i_enabled', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'%blabla\' AND i.position <= :p_i_position AND i.createdAt = :p_i_createdAt', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'%blabla\' AND i.position <= :p_i_position AND i.createdAt = :p_i_createdAt']); + parent::createBuildQueryTest('getDQL', ['SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position > :p_i_position', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position > :p_i_position AND i.enabled = :p_i_enabled', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position > :p_i_position AND i.enabled = :p_i_enabled', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position <= :p_i_position AND i.createdAt = :p_i_createdAt', 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position <= :p_i_position AND i.createdAt = :p_i_createdAt']); } public function testDisabledFieldQuery() @@ -69,7 +69,7 @@ public function testDateTimeRange() public function testFilterStandardType() { - parent::createFilterStandardTypeTest('getDQL', ['SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE \'%hey dude%\' AND i.position = 99']); + parent::createFilterStandardTypeTest('getDQL', ['SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i WHERE i.name LIKE :p_i_name AND i.position = 99']); } public function testEmbedFormFilter() @@ -82,11 +82,11 @@ public function testEmbedFormFilter() $form->submit(['name' => 'dude', 'options' => [['label' => 'color', 'rank' => 3]]]); $expectedDql = 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i'; - $expectedDql .= ' LEFT JOIN i.options opt WHERE i.name LIKE \'dude\' AND (opt.label LIKE \'color\' AND opt.rank = :p_opt_rank)'; + $expectedDql .= ' LEFT JOIN i.options opt WHERE i.name LIKE :p_i_name AND (opt.label LIKE :p_opt_label AND opt.rank = :p_opt_rank)'; $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql()); - $this->assertEquals(['p_opt_rank' => 3], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'dude', 'p_opt_label' => 'color', 'p_opt_rank' => 3], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // doctrine query builder with joins $form = $this->formFactory->create(ItemEmbeddedOptionsFilterType::class); @@ -97,13 +97,13 @@ public function testEmbedFormFilter() $form->submit(['name' => 'dude', 'options' => [['label' => 'size', 'rank' => 5]]]); $expectedDql = 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i'; - $expectedDql .= ' LEFT JOIN i.options o WHERE i.name LIKE \'dude\' AND (o.label LIKE \'size\' AND o.rank = :p_o_rank)'; + $expectedDql .= ' LEFT JOIN i.options o WHERE i.name LIKE :p_i_name AND (o.label LIKE :p_o_label AND o.rank = :p_o_rank)'; $filterQueryBuilder->setParts(['i.options' => 'o']); $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql()); - $this->assertEquals(['p_o_rank' => 5], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'dude', 'p_o_label' => 'size', 'p_o_rank' => 5], $this->getQueryBuilderParameters($doctrineQueryBuilder)); } public function testCustomConditionBuilder() @@ -126,11 +126,11 @@ public function testCustomConditionBuilder() $form->submit(['name' => 'dude', 'options' => [['label' => 'color', 'rank' => 6]]]); $expectedDql = 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i'; - $expectedDql .= ' LEFT JOIN i.options opt WHERE opt.label LIKE \'color\' OR (opt.rank = :p_opt_rank AND i.name LIKE \'dude\')'; + $expectedDql .= ' LEFT JOIN i.options opt WHERE opt.label LIKE :p_opt_label OR (opt.rank = :p_opt_rank AND i.name LIKE :p_i_name)'; $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql()); - $this->assertEquals(['p_opt_rank' => 6], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'dude', 'p_opt_label' => 'color', 'p_opt_rank' => 6], $this->getQueryBuilderParameters($doctrineQueryBuilder)); // doctrine query builder without any joins + custom condition builder $form = $this->formFactory->create(ItemEmbeddedOptionsFilterType::class, null, ['filter_condition_builder' => function (ConditionBuilderInterface $builder) { @@ -153,11 +153,11 @@ public function testCustomConditionBuilder() $form->submit(['name' => 'dude', 'position' => 1, 'options' => [['label' => 'color', 'rank' => 6]]]); $expectedDql = 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i'; - $expectedDql .= ' LEFT JOIN i.options opt WHERE (i.name LIKE \'dude\' OR opt.label LIKE \'color\') AND (opt.rank = :p_opt_rank OR i.position = :p_i_position)'; + $expectedDql .= ' LEFT JOIN i.options opt WHERE (i.name LIKE :p_i_name OR opt.label LIKE :p_opt_label) AND (opt.rank = :p_opt_rank OR i.position = :p_i_position)'; $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql()); - $this->assertEquals(['p_opt_rank' => 6, 'p_i_position' => 1], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'dude', 'p_opt_label' => 'color', 'p_opt_rank' => 6, 'p_i_position' => 1], $this->getQueryBuilderParameters($doctrineQueryBuilder)); } public function testWithDataClass() @@ -170,11 +170,11 @@ public function testWithDataClass() $form->submit(['name' => 'dude', 'options' => [['label' => 'color', 'rank' => 6]]]); $expectedDql = 'SELECT i FROM Spiriit\Bundle\FormFilterBundle\Tests\Fixtures\Entity\Item i'; - $expectedDql .= ' LEFT JOIN i.options opt WHERE i.name LIKE \'dude\' AND (opt.label LIKE \'color\' AND opt.rank = :p_opt_rank)'; + $expectedDql .= ' LEFT JOIN i.options opt WHERE i.name LIKE :p_i_name AND (opt.label LIKE :p_opt_label AND opt.rank = :p_opt_rank)'; $filterQueryBuilder->addFilterConditions($form, $doctrineQueryBuilder); $this->assertEquals($expectedDql, $doctrineQueryBuilder->getDql()); - $this->assertEquals(['p_opt_rank' => 6], $this->getQueryBuilderParameters($doctrineQueryBuilder)); + $this->assertEquals(['p_i_name' => 'dude', 'p_opt_label' => 'color', 'p_opt_rank' => 6], $this->getQueryBuilderParameters($doctrineQueryBuilder)); } protected function createDoctrineQueryBuilder()