diff --git a/src/lib/Gateway/ExpressionVisitor.php b/src/lib/Gateway/ExpressionVisitor.php index 9aabf6b..0fa4a40 100644 --- a/src/lib/Gateway/ExpressionVisitor.php +++ b/src/lib/Gateway/ExpressionVisitor.php @@ -118,65 +118,7 @@ public function walkComparison(Comparison $comparison) } $parameter = new Parameter($parameterName, $value, $type); - switch ($comparison->getOperator()) { - case Comparison::IN: - $this->parameters[] = $parameter; - - return $this->expr()->in($fullColumnName, $placeholder); - - case Comparison::NIN: - $this->parameters[] = $parameter; - - return $this->expr()->notIn($fullColumnName, $placeholder); - - case Comparison::EQ: - case Comparison::IS: - if ($this->walkValue($comparison->getValue()) === null) { - return $this->expr()->isNull($fullColumnName); - } - - $this->parameters[] = $parameter; - - return $this->expr()->eq($fullColumnName, $placeholder); - - case Comparison::NEQ: - if ($this->walkValue($comparison->getValue()) === null) { - return $this->expr()->isNotNull($fullColumnName); - } - - $this->parameters[] = $parameter; - - return $this->expr()->neq($fullColumnName, $placeholder); - - case Comparison::CONTAINS: - $parameter->setValue('%' . $this->escapeSpecialSQLValues($parameter) . '%'); - $this->parameters[] = $parameter; - - return $this->expr()->like($fullColumnName, $placeholder); - - case Comparison::STARTS_WITH: - $parameter->setValue($this->escapeSpecialSQLValues($parameter) . '%'); - $this->parameters[] = $parameter; - - return $this->expr()->like($fullColumnName, $placeholder); - - case Comparison::ENDS_WITH: - $parameter->setValue('%' . $this->escapeSpecialSQLValues($parameter)); - $this->parameters[] = $parameter; - - return $this->expr()->like($fullColumnName, $placeholder); - - case Comparison::GT: - case Comparison::GTE: - case Comparison::LT: - case Comparison::LTE: - $this->parameters[] = $parameter; - - return $this->expr()->comparison($fullColumnName, $comparison->getOperator(), $placeholder); - - default: - throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()); - } + return $this->handleComparison($comparison, $parameter, $fullColumnName, $placeholder); } /** @@ -300,13 +242,14 @@ private function handleJoinQuery( } $parameter = new Parameter($parameterName, $value, $type); - $this->parameters[] = $parameter; if (is_array($value)) { + $this->parameters[] = $parameter; + return $this->expr()->in($tableName . '.' . $field, $placeholder); } - return $this->expr()->comparison($tableName . '.' . $field, $comparison->getOperator(), $placeholder); + return $this->handleComparison($comparison, $parameter, $tableName . '.' . $field, $placeholder); } private function handleSubSelectQuery( @@ -379,4 +322,71 @@ private function isInheritedColumn(string $column): bool return $this->schemaMetadata->getIdentifierColumn() !== $column && $this->schemaMetadata->isInheritedColumn($column); } + + private function handleComparison( + Comparison $comparison, + Parameter $parameter, + string $fullColumnName, + string $placeholder + ): string { + switch ($comparison->getOperator()) { + case Comparison::IN: + $this->parameters[] = $parameter; + + return $this->expr()->in($fullColumnName, $placeholder); + + case Comparison::NIN: + $this->parameters[] = $parameter; + + return $this->expr()->notIn($fullColumnName, $placeholder); + + case Comparison::EQ: + case Comparison::IS: + if ($this->walkValue($comparison->getValue()) === null) { + return $this->expr()->isNull($fullColumnName); + } + + $this->parameters[] = $parameter; + + return $this->expr()->eq($fullColumnName, $placeholder); + + case Comparison::NEQ: + if ($this->walkValue($comparison->getValue()) === null) { + return $this->expr()->isNotNull($fullColumnName); + } + + $this->parameters[] = $parameter; + + return $this->expr()->neq($fullColumnName, $placeholder); + + case Comparison::CONTAINS: + $parameter->setValue('%' . $this->escapeSpecialSQLValues($parameter) . '%'); + $this->parameters[] = $parameter; + + return $this->expr()->like($fullColumnName, $placeholder); + + case Comparison::STARTS_WITH: + $parameter->setValue($this->escapeSpecialSQLValues($parameter) . '%'); + $this->parameters[] = $parameter; + + return $this->expr()->like($fullColumnName, $placeholder); + + case Comparison::ENDS_WITH: + $parameter->setValue('%' . $this->escapeSpecialSQLValues($parameter)); + $this->parameters[] = $parameter; + + return $this->expr()->like($fullColumnName, $placeholder); + + case Comparison::GT: + case Comparison::GTE: + case Comparison::LT: + case Comparison::LTE: + $this->parameters[] = $parameter; + + return $this->expr()->comparison($fullColumnName, $comparison->getOperator(), $placeholder); + + default: + throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()); + } + } } diff --git a/tests/bundle/Gateway/ExpressionVisitorTest.php b/tests/bundle/Gateway/ExpressionVisitorTest.php index 8ac33bb..7e9fc27 100644 --- a/tests/bundle/Gateway/ExpressionVisitorTest.php +++ b/tests/bundle/Gateway/ExpressionVisitorTest.php @@ -224,9 +224,14 @@ public function testFieldFromSubSelectRelationship(): void /** * @dataProvider provideForFieldFromInheritedRelationship + * + * @phpstan-param array<\Ibexa\CorePersistence\Gateway\Parameter> $parameters */ - public function testFieldFromInheritedRelationship(Comparison $comparison, string $expectedResult): void - { + public function testFieldFromInheritedRelationship( + Comparison $comparison, + string $expectedResult, + array $parameters + ): void { /** @var class-string $relationshipClass pretend it's a class-string */ $relationshipClass = 'relationship_class'; $doctrineRelationship = new DoctrineOneToManyRelationship( @@ -254,26 +259,53 @@ public function testFieldFromInheritedRelationship(Comparison $comparison, strin $expectedResult, $result, ); + + self::assertEquals($parameters, $this->expressionVisitor->getParameters()); } /** - * @return iterable + * @return iterable, + * }> */ public static function provideForFieldFromInheritedRelationship(): iterable { yield [ new Comparison('relationship_1.field', '=', 'value'), 'relationship_table_name.field = :field_0', + [new Parameter('field_0', 'value', 0)], ]; yield [ new Comparison('relationship_1.field', 'IN', ['value', 'value_2']), 'relationship_table_name.field IN (:field_0)', + [new Parameter('field_0', ['value', 'value_2'], 100)], ]; yield [ new Comparison('relationship_1.field', '=', ['value', 'value_2']), 'relationship_table_name.field IN (:field_0)', + [new Parameter('field_0', ['value', 'value_2'], 100)], + ]; + + yield [ + new Comparison('relationship_1.field', 'STARTS_WITH', 'value'), + 'relationship_table_name.field LIKE :field_0', + [new Parameter('field_0', 'value%', 0)], + ]; + + yield [ + new Comparison('relationship_1.field', 'ENDS_WITH', 'value'), + 'relationship_table_name.field LIKE :field_0', + [new Parameter('field_0', '%value', 0)], + ]; + + yield [ + new Comparison('relationship_1.field', 'CONTAINS', 'value'), + 'relationship_table_name.field LIKE :field_0', + [new Parameter('field_0', '%value%', 0)], ]; } diff --git a/tests/integration/Gateway/ExpressionVisitorTest.php b/tests/integration/Gateway/ExpressionVisitorTest.php index 6e6dd28..3a8f2af 100644 --- a/tests/integration/Gateway/ExpressionVisitorTest.php +++ b/tests/integration/Gateway/ExpressionVisitorTest.php @@ -69,7 +69,7 @@ public static function provideForTraversingRelationships(): iterable 'IN', 'bar', ), - 'relationship_2_table_name.relationship_2_foo IN :relationship_2_foo_0', + 'relationship_2_table_name.relationship_2_foo IN (:relationship_2_foo_0)', ]; yield [