From c7289fa39a50782644ea28063508f7b4bba45c8c Mon Sep 17 00:00:00 2001
From: Manuel Selbach <manuel_selbach@yahoo.de>
Date: Sat, 16 Mar 2019 22:36:01 +0100
Subject: [PATCH] [BUGFIX] Use single instance of
 DocumentTypeExclusionRestriction

With this change, the DocumentTypeExclusionRestrictionTest will use
NOT IN instead of <>. This will allow to have only one instance of that
restriction.

Additionally multiple casts to integer have been removed.

Resolves: #87938
Releases: master, 9.5
Change-Id: I3c1c5cc47800dae3f13afc654f55236634ad5bc5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60275
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Dennis Prinse <dennis@dennisprinse.com>
Tested-by: Richard Haeser <richard@maxserv.com>
Reviewed-by: Dennis Prinse <dennis@dennisprinse.com>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Claus Due <claus@phpmind.net>
Reviewed-by: Richard Haeser <richard@maxserv.com>
---
 .../Controller/Page/TreeController.php        | 26 ++++++++--
 .../DocumentTypeExclusionRestriction.php      | 16 +++---
 .../DocumentTypeExclusionRestrictionTest.php  | 51 +++++++++++++++++++
 3 files changed, 82 insertions(+), 11 deletions(-)
 create mode 100644 typo3/sysext/core/Tests/Unit/Database/Query/Restriction/DocumentTypeExclusionRestrictionTest.php

diff --git a/typo3/sysext/backend/Classes/Controller/Page/TreeController.php b/typo3/sysext/backend/Classes/Controller/Page/TreeController.php
index 7294418d3b86..685305ed91ac 100644
--- a/typo3/sysext/backend/Classes/Controller/Page/TreeController.php
+++ b/typo3/sysext/backend/Classes/Controller/Page/TreeController.php
@@ -357,14 +357,17 @@ class TreeController
         $userTsConfig = $this->getBackendUser()->getTSConfig();
         $excludedDocumentTypes = GeneralUtility::intExplode(',', $userTsConfig['options.']['pageTree.']['excludeDoktypes'] ?? '', true);
 
-        $additionalPageTreeQueryRestrictions = [];
+        $additionalQueryRestrictions = [];
         if (!empty($excludedDocumentTypes)) {
-            foreach ($excludedDocumentTypes as $excludedDocumentType) {
-                $additionalPageTreeQueryRestrictions[] = new DocumentTypeExclusionRestriction((int)$excludedDocumentType);
-            }
+            $additionalQueryRestrictions[] = $this->retrieveDocumentTypeExclusionRestriction($excludedDocumentTypes);
         }
 
-        $repository = GeneralUtility::makeInstance(PageTreeRepository::class, (int)$backendUser->workspace, [], $additionalPageTreeQueryRestrictions);
+        $repository = GeneralUtility::makeInstance(
+            PageTreeRepository::class,
+            (int)$backendUser->workspace,
+            [],
+            $additionalQueryRestrictions
+        );
 
         $entryPoints = (int)($backendUser->uc['pageTree_temporaryMountPoint'] ?? 0);
         if ($entryPoints > 0) {
@@ -415,6 +418,19 @@ class TreeController
         return $entryPoints;
     }
 
+    /**
+     * @param int[] $excludedDocumentTypes
+     * @return DocumentTypeExclusionRestriction|null
+     */
+    protected function retrieveDocumentTypeExclusionRestriction(array $excludedDocumentTypes): ?DocumentTypeExclusionRestriction
+    {
+        if (empty($excludedDocumentTypes)) {
+            return null;
+        }
+
+        return GeneralUtility::makeInstance(DocumentTypeExclusionRestriction::class, $excludedDocumentTypes);
+    }
+
     /**
      * Returns the first configured domain name for a page
      *
diff --git a/typo3/sysext/core/Classes/Database/Query/Restriction/DocumentTypeExclusionRestriction.php b/typo3/sysext/core/Classes/Database/Query/Restriction/DocumentTypeExclusionRestriction.php
index ade165f0c647..438745869343 100644
--- a/typo3/sysext/core/Classes/Database/Query/Restriction/DocumentTypeExclusionRestriction.php
+++ b/typo3/sysext/core/Classes/Database/Query/Restriction/DocumentTypeExclusionRestriction.php
@@ -24,16 +24,20 @@ use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
 class DocumentTypeExclusionRestriction implements QueryRestrictionInterface
 {
     /**
-     * @var int
+     * @var int[]
      */
-    protected $doktype;
+    protected $doktypes;
 
     /**
-     * @param int $doktype
+     * @param int[]|int $doktype
      */
-    public function __construct(int $doktype)
+    public function __construct($doktype)
     {
-        $this->doktype = (int)$doktype;
+        if (is_array($doktype)) {
+            $this->doktypes = $doktype;
+        } else {
+            $this->doktypes = [$doktype];
+        }
     }
 
     /**
@@ -52,7 +56,7 @@ class DocumentTypeExclusionRestriction implements QueryRestrictionInterface
                 continue;
             }
 
-            $constraints[] = $expressionBuilder->neq($tableAlias . '.doktype', $this->doktype);
+            $constraints[] = $expressionBuilder->notIn($tableAlias . '.doktype', $this->doktypes);
         }
 
         return $expressionBuilder->andX(...$constraints);
diff --git a/typo3/sysext/core/Tests/Unit/Database/Query/Restriction/DocumentTypeExclusionRestrictionTest.php b/typo3/sysext/core/Tests/Unit/Database/Query/Restriction/DocumentTypeExclusionRestrictionTest.php
new file mode 100644
index 000000000000..69d21aecb78d
--- /dev/null
+++ b/typo3/sysext/core/Tests/Unit/Database/Query/Restriction/DocumentTypeExclusionRestrictionTest.php
@@ -0,0 +1,51 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Core\Tests\Unit\Database\Query\Restriction;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Database\Query\Restriction\DocumentTypeExclusionRestriction;
+
+class DocumentTypeExclusionRestrictionTest extends AbstractRestrictionTestCase
+{
+    public function buildRestrictionsAddsDoktypeWhereClauseDataProvider(): array
+    {
+        return [
+            'build with one parameter' => [
+                [1],
+                '"pages"."doktype" NOT IN (1)',
+            ],
+            'build with multiple parameter' => [
+                [1, 4, 100],
+                '"pages"."doktype" NOT IN (1, 4, 100)',
+            ],
+            'build with int parameter' => [
+                1,
+                '"pages"."doktype" NOT IN (1)',
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     *
+     * @dataProvider buildRestrictionsAddsDoktypeWhereClauseDataProvider
+     */
+    public function buildRestrictionsAddsDoktypeWhereClause($excludedDocumentTypes, string $expected): void
+    {
+        $subject = new DocumentTypeExclusionRestriction($excludedDocumentTypes);
+        $expression = $subject->buildExpression(['pages' => 'pages'], $this->expressionBuilder);
+        self::assertSame($expected, (string)$expression);
+    }
+}
-- 
GitLab