From 56269a975cb2d71bada701796f2c20f2fc68b86e Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Sat, 2 May 2020 21:13:26 +0200
Subject: [PATCH] [BUGFIX] Use correct slug for access restricted translated
 pages

Access restricted, translated pages currently always have the slug from the
default language instead of their translated slug in the frontend.
To generate correct urls, while using the "linkAccessRestrictedPages"
option, the $disableGroupAccessCheck parameter needs to also take into
account for
 * PageRepository::getPageOverlay()
when setting the option in PageRepository::getPage().

This "hack" is currently similar to what HMENU is doing, however
this public property should not be used with the Context API instead.

This change however needs more refactoring on the Context API,
which is why this solution is chosen for the time being (and also
for v9 backport).

Resolves: #90842
Resolves: #87969
Resolves: #91185
Releases: master, 9.5
Change-Id: I99a34ca7fceacba7218c6b7132781805a6b59ac9
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63963
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Jonas Eberle <flightvision@googlemail.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Jonas Eberle <flightvision@googlemail.com>
Reviewed-by: Helmut Hummel <typo3@helhum.io>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../Domain/Repository/PageRepository.php      | 13 +++++
 .../SiteHandling/Fixtures/SlugScenario.yaml   |  9 +++
 .../SiteHandling/SlugLinkGeneratorTest.php    | 58 +++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
index aa7c252f078e..b50f20698880 100644
--- a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
+++ b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
@@ -27,6 +27,7 @@ use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\QueryHelper;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
+use TYPO3\CMS\Core\Database\Query\Restriction\FrontendGroupRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
 use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\QueryRestrictionContainerInterface;
@@ -269,8 +270,12 @@ class PageRepository implements LoggerAwareInterface
                 QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del)
             );
 
+        $originalWhereGroupAccess = '';
         if (!$disableGroupAccessCheck) {
             $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess));
+        } else {
+            $originalWhereGroupAccess = $this->where_groupAccess;
+            $this->where_groupAccess = '';
         }
 
         $row = $queryBuilder->execute()->fetch();
@@ -280,6 +285,11 @@ class PageRepository implements LoggerAwareInterface
                 $result = $this->getPageOverlay($row);
             }
         }
+
+        if ($disableGroupAccessCheck) {
+            $this->where_groupAccess = $originalWhereGroupAccess;
+        }
+
         $cache->set($cacheIdentifier, $result);
         return $result;
     }
@@ -511,6 +521,9 @@ class PageRepository implements LoggerAwareInterface
 
             $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
             $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class, $this->context));
+            if (empty($this->where_groupAccess)) {
+                $queryBuilder->getRestrictions()->removeByType(FrontendGroupRestriction::class);
+            }
             $result = $queryBuilder->select('*')
                 ->from('pages')
                 ->where(
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml
index ef728f830924..b1217d4574db 100644
--- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml
+++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml
@@ -86,10 +86,19 @@ entities:
         - self: {id: 1500, title: 'Internal', slug: '/my-acme'}
           children:
             - self: {id: 1510, title: 'Whitepapers', visitorGroups: -2, extendToSubpages: true, slug: '/my-acme/whitepapers'}
+              languageVariants:
+                - self: {id: 1513, title: 'FR: Whitepapers', language: 1, slug: '/my-acme/papiersblanc'}
+                - self: {id: 1514, title: 'FR-CA: Whitepapers', language: 2, slug: '/my-acme-ca/papiersblanc'}
               children:
                 - self: {id: 1511, title: 'Products', slug: '/my-acme/whitepapers/products'}
                 - self: {id: 1512, title: 'Solutions', visitorGroups: 10, slug: '/my-acme/whitepapers/solutions'}
+                  languageVariants:
+                    - self: {id: 1516, title: 'FR: La Solutions', language: 1, slug: '/my-acme/papiersblanc/la-solutions'}
+                    - self: {id: 1517, title: 'FR-CA: La Solutions', language: 2, slug: '/my-acme-ca/papiersblanc/la-solutions'}
                 - self: {id: 1515, title: 'Research', visitorGroups: 20, slug: '/my-acme/whitepapers/research'}
+                  languageVariants:
+                    - self: {id: 1518, title: 'FR: Research', language: 1, slug: '/my-acme/papiersblanc/recherche'}
+                    - self: {id: 1519, title: 'FR-CA: Research', language: 2, slug: '/my-acme-ca/papiersblanc/recherche'}
             - self: {id: 1520, title: 'Forecasts', visitorGroups: 20, extendToSubpages: true, slug: '/my-acme/forecasts'}
               children:
                 - self: {id: 1521, title: 'Current Year', slug: '/my-acme/forecasts/current-year'}
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php
index 853a94e5d913..8c84b322125e 100644
--- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php
@@ -566,6 +566,64 @@ class SlugLinkGeneratorTest extends AbstractTestCase
         self::assertSame($expectation, (string)$response->getBody());
     }
 
+    /**
+     * @return array
+     */
+    public function linkIsGeneratedForRestrictedPageForGuestsUsingTypolinkLinkAccessRestrictedPagesDataProvider(): array
+    {
+        $instructions = [
+            // default language (0)
+            ['https://acme.us/', 1100, 1510, 0, '/my-acme/whitepapers'],
+            ['https://acme.us/', 1100, 1512, 0, '/my-acme/whitepapers/solutions'],
+            ['https://acme.us/', 1100, 1515, 0, '/my-acme/whitepapers/research'],
+            // french language (1)
+            ['https://acme.fr/', 1100, 1510, 1, '/my-acme/papiersblanc'],
+            ['https://acme.fr/', 1100, 1512, 1, '/my-acme/papiersblanc/la-solutions'],
+            ['https://acme.fr/', 1100, 1515, 1, '/my-acme/papiersblanc/recherche'],
+            // canadian french language (2)
+            ['https://acme.ca/', 1100, 1510, 2, '/my-acme-ca/papiersblanc'],
+            ['https://acme.ca/', 1100, 1512, 2, '/my-acme-ca/papiersblanc/la-solutions'],
+            ['https://acme.ca/', 1100, 1515, 2, '/my-acme-ca/papiersblanc/recherche'],
+        ];
+
+        return $this->keysFromTemplate(
+            $instructions,
+            '%2$d->%3$d (language: %4$d)'
+        );
+    }
+
+    /**
+     * @param string $hostPrefix
+     * @param int $sourcePageId
+     * @param int $targetPageId
+     * @param int $languageId
+     * @param string $expectation
+     *
+     * @test
+     * @dataProvider linkIsGeneratedForRestrictedPageForGuestsUsingTypolinkLinkAccessRestrictedPagesDataProvider
+     */
+    public function linkIsGeneratedForRestrictedPageForGuestsUsingTypolinkLinkAccessRestrictedPages(string $hostPrefix, int $sourcePageId, int $targetPageId, int $languageId, string $expectation)
+    {
+        $response = $this->executeFrontendRequest(
+            (new InternalRequest($hostPrefix))
+                ->withPageId($sourcePageId)
+                ->withInstructions([
+                    (new TypoScriptInstruction(TemplateService::class))
+                        ->withTypoScript([
+                            'config.' => [
+                                'typolinkLinkAccessRestrictedPages' => 'NONE',
+                            ],
+                        ]),
+                    $this->createTypoLinkUrlInstruction([
+                        'parameter' => $targetPageId,
+                    ])
+                ]),
+            $this->internalRequestContext
+        );
+
+        self::assertSame($expectation, (string)$response->getBody());
+    }
+
     /**
      * @return array
      */
-- 
GitLab