diff --git a/src/lib/Gateway/ExpressionVisitor.php b/src/lib/Gateway/ExpressionVisitor.php index 0c47d43..9dbd942 100644 --- a/src/lib/Gateway/ExpressionVisitor.php +++ b/src/lib/Gateway/ExpressionVisitor.php @@ -13,7 +13,6 @@ use Doctrine\Common\Collections\Expr\ExpressionVisitor as BaseExpressionVisitor; use Doctrine\Common\Collections\Expr\Value; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Query\Expression\CompositeExpression as DBALCompositeExpression; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; use Ibexa\Contracts\CorePersistence\Gateway\DoctrineOneToManyRelationship; @@ -197,7 +196,7 @@ public function walkValue(Value $value) return $value->getValue(); } - public function walkCompositeExpression(CompositeExpression $expr): DBALCompositeExpression + public function walkCompositeExpression(CompositeExpression $expr): string { $expressionList = []; foreach ($expr->getExpressionList() as $child) { @@ -206,10 +205,13 @@ public function walkCompositeExpression(CompositeExpression $expr): DBALComposit switch ($expr->getType()) { case CompositeExpression::TYPE_AND: - return $this->expr()->and(...$expressionList); + return (string)$this->expr()->and(...$expressionList); case CompositeExpression::TYPE_OR: - return $this->expr()->or(...$expressionList); + return (string)$this->expr()->or(...$expressionList); + + case 'NOT': + return $this->queryBuilder->getConnection()->getDatabasePlatform()->getNotExpression($expressionList[0]); default: throw new RuntimeException('Unknown composite ' . $expr->getType()); diff --git a/tests/bundle/Gateway/ExpressionVisitorTest.php b/tests/bundle/Gateway/ExpressionVisitorTest.php new file mode 100644 index 0000000..3bc13bb --- /dev/null +++ b/tests/bundle/Gateway/ExpressionVisitorTest.php @@ -0,0 +1,104 @@ +createMock(Connection::class); + + $connection->method('getExpressionBuilder') + ->willReturn(new ExpressionBuilder($connection)); + + $platform = $this->getMockBuilder(AbstractPlatform::class) + ->getMockForAbstractClass(); + + $connection->method('getDatabasePlatform') + ->willReturn($platform); + + $this->expressionVisitor = new ExpressionVisitor( + new QueryBuilder($connection), + $this->createMock(DoctrineSchemaMetadataRegistryInterface::class), + 'table_name', + 'table_alias', + ); + } + + public function testWalkComparison(): void + { + $result = $this->expressionVisitor->dispatch(new Comparison('field', '=', 'value')); + + self::assertSame('table_alias.field = :field_0', $result); + self::assertEquals([ + new Parameter( + 'field_0', + 'value', + 0, + ), + ], $this->expressionVisitor->getParameters()); + } + + public function testLogicalNot(): void + { + $result = $this->expressionVisitor->dispatch( + new CompositeExpression('NOT', [new Comparison('field', '=', 'value')]), + ); + + self::assertSame('NOT(table_alias.field = :field_0)', $result); + self::assertEquals([ + new Parameter( + 'field_0', + 'value', + 0, + ), + ], $this->expressionVisitor->getParameters()); + } + + public function testLogicalAnd(): void + { + $result = $this->expressionVisitor->dispatch( + new CompositeExpression('AND', [ + new Comparison('field', '=', 'value'), + new Comparison('field_2', 'IN', 'value_2'), + ]), + ); + + self::assertSame( + '(table_alias.field = :field_0) AND (table_alias.field_2 IN (:field_2_1))', + $result, + ); + + self::assertEquals([ + new Parameter( + 'field_0', + 'value', + 0, + ), + new Parameter( + 'field_2_1', + 'value_2', + 0, + ), + ], $this->expressionVisitor->getParameters()); + } +}