[BUGFIX] Extbase: correct handling of mm relations 82/51782/3
authorJohannes Kasberger <johannes.kasberger@reelworx.at>
Tue, 21 Feb 2017 13:27:56 +0000 (14:27 +0100)
committerGeorg Ringer <georg.ringer@gmail.com>
Tue, 21 Feb 2017 18:01:35 +0000 (19:01 +0100)
This change fixes a regression after the doctrine migration and additionally
fixes a wrong join condition which is also present in version 7

Resolves: #79931
Resolves: #79932
Releases: master
Change-Id: I04a4ce174fb1da3baca9af8ba771a7db70d9a884
Reviewed-on: https://review.typo3.org/51782
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbQueryParser.php
typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/Domain/Repository/PostRepository.php
typo3/sysext/extbase/Tests/Functional/Persistence/Fixtures/category-mm.xml
typo3/sysext/extbase/Tests/Functional/Persistence/RelationTest.php

index 9aba64c..51810ae 100644 (file)
@@ -954,9 +954,12 @@ class Typo3DbQueryParser
             $relationTableName = $columnMap->getRelationTableName();
             $relationTableAlias = $relationTableAlias = $this->getUniqueAlias($relationTableName, $fullPropertyPath . '_mm');
 
-            $joinConditionExpression = $this->queryBuilder->expr()->eq(
-                $tableName . '.uid',
-                $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()
+            $joinConditionExpression = $this->queryBuilder->expr()->andX(
+                $this->queryBuilder->expr()->eq(
+                    $tableName . '.uid',
+                    $relationTableAlias . '.' . $columnMap->getParentKeyFieldName()
+                ),
+                $this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)
             );
             $this->queryBuilder->leftJoin($tableName, $relationTableName, $relationTableAlias, $joinConditionExpression);
             $joinConditionExpression = $this->queryBuilder->expr()->eq(
@@ -964,9 +967,6 @@ class Typo3DbQueryParser
                 $childTableAlias . '.uid'
             );
             $this->queryBuilder->leftJoin($relationTableAlias, $childTableName, $childTableAlias, $joinConditionExpression);
-            $this->queryBuilder->andWhere(
-                $this->getAdditionalMatchFieldsStatement($this->queryBuilder->expr(), $columnMap, $relationTableAlias, $realTableName)
-            );
             $this->unionTableAliasCache[] = $childTableAlias;
             $this->queryBuilder->addGroupBy($this->tableName . '.uid');
         } else {
index 6ca57c0..f51a4e5 100644 (file)
@@ -14,6 +14,8 @@ namespace ExtbaseTeam\BlogExample\Domain\Repository;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Extbase\Persistence\QueryInterface;
+
 /**
  * A repository for blog posts
  *
@@ -148,4 +150,15 @@ class PostRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
             )
             ->execute();
     }
+
+    public function findAllSortedByCategory(array $uids)
+    {
+        $q = $this->createQuery();
+        $q->matching($q->in('uid', $uids));
+        $q->setOrderings([
+            'categories.title' => QueryInterface::ORDER_ASCENDING,
+            'uid' => QueryInterface::ORDER_ASCENDING,
+        ]);
+        return $q->execute();
+    }
 }
index a927275..785e287 100644 (file)
                <sorting_foreign>2</sorting_foreign>
        </sys_category_record_mm>
 
+       <!-- some bogus records to test MM_match_fields -->
+       <sys_category_record_mm>
+               <uid_local>4</uid_local>
+               <uid_foreign>5</uid_foreign>
+               <tablenames>tx_my_extension</tablenames>
+               <fieldname>categories</fieldname>
+               <sorting>1</sorting>
+               <sorting_foreign>2</sorting_foreign>
+       </sys_category_record_mm>
+
        <!-- blog 1 gets categories 1,2,3 -->
        <sys_category_record_mm>
                <uid_local>1</uid_local>
index 6cc153d..09aefcd 100644 (file)
@@ -14,6 +14,7 @@ namespace TYPO3\CMS\Extbase\Tests\Functional\Persistence;
  * The TYPO3 project - inspiring people to share!
  */
 
+use ExtbaseTeam\BlogExample\Domain\Model\Post;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -1009,4 +1010,42 @@ class RelationTest extends \TYPO3\TestingFramework\Core\Functional\FunctionalTes
         $blogRepository->update($this->blog);
         $this->persistentManager->persistAll();
     }
+
+    public function ensureCorrectPostOrderingByCategoryTitleDataProvider()
+    {
+        return [
+            'Post with no category and post with category' => [
+                [2, 3],
+                [3, 2]
+            ],
+            'Posts with category and Post with category and bogus category' => [
+                [2, 1],
+                [1, 2]
+            ],
+            'Posts bogus category and post with category' => [
+                [5, 2],
+                [5, 2]
+            ],
+        ];
+    }
+
+    /**
+     * This test covers the case when data is ordered by criteria that is MM related with matchFields involved
+     * on the relation table. (post <-> sys_category_mm <-> sys_category)
+     *
+     * @test
+     * @dataProvider ensureCorrectPostOrderingByCategoryTitleDataProvider
+     */
+    public function ensureCorrectPostOrderingByCategoryTitle(array $uids, array $expected)
+    {
+        /** @var \ExtbaseTeam\BlogExample\Domain\Repository\PostRepository $postRepository */
+        $postRepository = $this->objectManager->get(\ExtbaseTeam\BlogExample\Domain\Repository\PostRepository::class);
+        $posts = $postRepository->findAllSortedByCategory($uids)->toArray();
+        $result = [];
+        /** @var Post $post */
+        foreach ($posts as $post) {
+            $result[] = $post->getUid();
+        }
+        $this->assertSame($expected, $result);
+    }
 }