[BUGFIX] Make Extbase pagination work with QueryBuilder queries 09/53409/12
authorTymoteusz Motylewski <t.motylewski@gmail.com>
Mon, 14 Aug 2017 14:27:22 +0000 (16:27 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 9 Sep 2017 11:46:56 +0000 (13:46 +0200)
Now you can pass a query built by QueryBuilder to $query->statement(),
and use the QueryResult for pagination.

So inside repository you can create custom query like:

$queryBuilder->select('*')->...
$query = $this->createQuery();
$query->statement($queryBuilder);
return $query->execute();

and pass the result to paginate ViewHelper.

Resolves: #81887
Releases: master, 8.7
Change-Id: Ia00f673039362afaa8ef7232ba4bc89c520d5a46
Reviewed-on: https://review.typo3.org/53409
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Joerg Kummer <typo3@enobe.de>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Storage/Typo3DbQueryParserTest.php

index 2c420d8..a7457a3 100644 (file)
@@ -353,12 +353,19 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
     public function getObjectDataByQuery(QueryInterface $query)
     {
         $statement = $query->getStatement();
-        if ($statement instanceof Qom\Statement) {
+        if ($statement instanceof Qom\Statement
+            && !$statement->getStatement() instanceof QueryBuilder
+        ) {
             $rows = $this->getObjectDataByRawQuery($statement);
         } else {
             $queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
-            $queryBuilder = $queryParser
-                ->convertQueryToDoctrineQueryBuilder($query);
+            if ($statement instanceof Qom\Statement
+                && $statement->getStatement() instanceof QueryBuilder
+            ) {
+                $queryBuilder = $statement->getStatement();
+            } else {
+                $queryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
+            }
             $selectParts = $queryBuilder->getQueryPart('select');
             if ($queryParser->isDistinctQuerySuggested() && !empty($selectParts)) {
                 $selectParts[0] = 'DISTINCT ' . $selectParts[0];
index 444b6cd..db00a25 100644 (file)
@@ -138,6 +138,11 @@ class Typo3DbQueryParser
         $this->tableAliasMap = [];
         $this->unionTableAliasCache = [];
         $this->tableName = '';
+
+        if ($query->getStatement() && $query->getStatement()->getStatement() instanceof QueryBuilder) {
+            $this->queryBuilder = clone $query->getStatement()->getStatement();
+            return $this->queryBuilder;
+        }
         // Find the right table name
         $source = $query->getSource();
         $this->initializeQueryBuilder($source);
index 6314c19..430e60e 100644 (file)
@@ -76,6 +76,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         // Test part: getConstraint returns no constraint object, andWhere() should not be called
         $queryProphecy->getConstraint()->willReturn(null);
@@ -102,6 +103,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         // Test part: getConstraint returns not implemented object
         $constraintProphecy = $this->prophesize(ConstraintInterface::class);
@@ -130,6 +132,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         // Test part: getConstraint returns simple constraint, and should push to andWhere()
         $constraintProphecy = $this->prophesize(ComparisonInterface::class);
@@ -158,6 +161,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         $constraintProphecy = $this->prophesize(NotInterface::class);
         $subConstraintProphecy = $this->prophesize(ComparisonInterface::class);
@@ -187,6 +191,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         $constraintProphecy = $this->prophesize(AndInterface::class);
         $queryProphecy->getConstraint()->willReturn($constraintProphecy->reveal());
@@ -224,6 +229,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         $constraintProphecy = $this->prophesize(AndInterface::class);
         $queryProphecy->getConstraint()->willReturn($constraintProphecy->reveal());
@@ -256,6 +262,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         $constraintProphecy = $this->prophesize(OrInterface::class);
         $queryProphecy->getConstraint()->willReturn($constraintProphecy->reveal());
@@ -293,6 +300,7 @@ class Typo3DbQueryParserTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestC
         $sourceProphecy = $this->prophesize(SourceInterface::class);
         $queryProphecy->getSource()->willReturn($sourceProphecy->reveal());
         $queryProphecy->getOrderings()->willReturn([]);
+        $queryProphecy->getStatement()->willReturn(null);
 
         $constraintProphecy = $this->prophesize(OrInterface::class);
         $queryProphecy->getConstraint()->willReturn($constraintProphecy->reveal());