[BUGFIX] Skip special doktype parent pages in slug generation 73/58473/4
authorBenni Mack <benni@typo3.org>
Sat, 29 Sep 2018 18:57:24 +0000 (20:57 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Sun, 30 Sep 2018 17:37:30 +0000 (19:37 +0200)
When checking the parent page for an existing slug, the parent page
should not be used if the parent page is a sys folder, spacer or
recycler (pages.doktype), but the traversal goes up.

This makes it a bit easier for editors to work with better-speaking
URLs and keep the rootline traversal as best practice.

Resolves: #86456
Releases: master
Change-Id: I2c46d096e41fb3a325fd42bf86b8968b79d6305b
Reviewed-on: https://review.typo3.org/58473
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
typo3/sysext/core/Classes/DataHandling/SlugHelper.php
typo3/sysext/core/Tests/Unit/DataHandling/SlugHelperTest.php

index 397063a..4c4fa37 100644 (file)
@@ -164,14 +164,7 @@ class SlugHelper
         if ($this->configuration['generatorOptions']['prefixParentPageSlug'] ?? false) {
             $languageFieldName = $GLOBALS['TCA'][$this->tableName]['ctrl']['languageField'] ?? null;
             $languageId = (int)($recordData[$languageFieldName] ?? 0);
-            $rootLine = $this->resolveRootLine($pid);
-            $parentPageRecord = reset($rootLine);
-            if ($languageId > 0) {
-                $localizedParentPageRecord = BackendUtility::getRecordLocalization('pages', $parentPageRecord['uid'], $languageId);
-                if (!empty($localizedParentPageRecord)) {
-                    $parentPageRecord = reset($localizedParentPageRecord);
-                }
-            }
+            $parentPageRecord = $this->resolveParentPageRecord($pid, $languageId);
             if (is_array($parentPageRecord)) {
                 // If the parent page has a slug, use that instead of "re-generating" the slug from the parents' page title
                 if (!empty($parentPageRecord['slug'])) {
@@ -535,11 +528,25 @@ class SlugHelper
     }
 
     /**
+     * Fetch a parent page, but exclude spacers, recyclers and sys-folders and all doktypes > 200
      * @param int $pid
-     * @return array
+     * @param int $languageId
+     * @return array|null
      */
-    protected function resolveRootLine(int $pid): array
+    protected function resolveParentPageRecord(int $pid, int $languageId): ?array
     {
-        return BackendUtility::BEgetRootLine($pid, '', true, ['nav_title']);
+        $parentPageRecord = null;
+        $rootLine = BackendUtility::BEgetRootLine($pid, '', true, ['nav_title']);
+        do {
+            $parentPageRecord = array_shift($rootLine);
+            // do not use spacers (199), recyclers and folders and everything else
+        } while (!empty($rootLine) && (int)$parentPageRecord['doktype'] >= 199);
+        if ($languageId > 0) {
+            $localizedParentPageRecord = BackendUtility::getRecordLocalization('pages', $parentPageRecord['uid'], $languageId);
+            if (!empty($localizedParentPageRecord)) {
+                $parentPageRecord = reset($localizedParentPageRecord);
+            }
+        }
+        return $parentPageRecord;
     }
 }
index e72b4d6..0f364d3 100644 (file)
@@ -379,16 +379,14 @@ class SlugHelperTest extends UnitTestCase
     public function generatePrependsSlugsForPages(string $input, string $expected)
     {
         $GLOBALS['dummyTable']['ctrl'] = [];
-        $rootLine = [
-            [
-                'uid' => '13',
-                'pid' => '10',
-                'title' => 'Parent Page',
-            ]
+        $parentPage = [
+            'uid' => '13',
+            'pid' => '10',
+            'title' => 'Parent Page',
         ];
         $subject = $this->getAccessibleMock(
             SlugHelper::class,
-            ['resolveRootLine'],
+            ['resolveParentPageRecord'],
             [
                 'pages',
                 'slug',
@@ -401,9 +399,9 @@ class SlugHelperTest extends UnitTestCase
             ]
         );
         $subject->expects(static::at(0))
-            ->method('resolveRootLine')->with(13)->willReturn($rootLine);
+            ->method('resolveParentPageRecord')->with(13)->willReturn($parentPage);
         $subject->expects(static::at(1))
-            ->method('resolveRootLine')->with(10)->willReturn([]);
+            ->method('resolveParentPageRecord')->with(10)->willReturn(null);
         static::assertEquals(
             $expected,
             $subject->generate(['title' => $input, 'uid' => 13], 13)