From 58042b06373ea7d40ae05d5dd417f517950666c1 Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@networkteam.com>
Date: Sun, 30 May 2021 17:23:42 +0200
Subject: [PATCH] [FEATURE] Add excludePagesRecursive option to XML sitemap
 generation

With this option pages can be excluded recursive in the XML sitemap:

    plugin.tx_seo.config.xmlSitemap.sitemaps.pages.config {
        # comma-separated list of page uids which should be excluded recursive
        excludePagesRecursive = 10,24
    }

Resolves: #94206
Releases: master
Change-Id: Ibcf543050c7892df9f768d27e4cb425ee7005a14
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/69328
Tested-by: core-ci <typo3@b13.com>
Tested-by: Riny van Tiggelen <info@online-gamer.nl>
Tested-by: Richard Haeser <richard@richardhaeser.com>
Reviewed-by: Riny van Tiggelen <info@online-gamer.nl>
Reviewed-by: Richard Haeser <richard@richardhaeser.com>
---
 ...agesRecursiveOptionToSitemapGeneration.rst | 36 ++++++++++++++++
 .../PagesXmlSitemapDataProvider.php           |  8 +++-
 .../XmlSitemap/constants.typoscript           |  2 +
 .../TypoScript/XmlSitemap/setup.typoscript    |  2 +
 .../Fixtures/excludePagesRecursive.typoscript | 11 +++++
 .../XmlSitemap/XmlSitemapPagesTest.php        | 41 +++++++++++++++++++
 6 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-94206-AddExcludePagesRecursiveOptionToSitemapGeneration.rst
 create mode 100644 typo3/sysext/seo/Tests/Functional/Fixtures/excludePagesRecursive.typoscript

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-94206-AddExcludePagesRecursiveOptionToSitemapGeneration.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-94206-AddExcludePagesRecursiveOptionToSitemapGeneration.rst
new file mode 100644
index 000000000000..c8051223deb0
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-94206-AddExcludePagesRecursiveOptionToSitemapGeneration.rst
@@ -0,0 +1,36 @@
+.. include:: ../../Includes.txt
+
+============================================================================
+Feature: #94206 - Add excludePagesRecursive option to XML sitemap generation
+============================================================================
+
+See :issue:`94206`
+
+Description
+===========
+
+With this option you can exclude pages recursively in the XML sitemap:
+
+.. code-block:: typoscript
+
+   plugin.tx_seo {
+       config {
+           xmlSitemap {
+               sitemaps {
+                   pages {
+                       config {
+                           # comma-separated list of page uids which should be excluded recursive
+                           excludePagesRecursive = 2,3
+                       }
+                   }
+               }
+           }
+       }
+   }
+
+Impact
+======
+
+The new option enables integrators to easily exclude pages recursively in the XML sitemap
+
+.. index:: ext:seo
diff --git a/typo3/sysext/seo/Classes/XmlSitemap/PagesXmlSitemapDataProvider.php b/typo3/sysext/seo/Classes/XmlSitemap/PagesXmlSitemapDataProvider.php
index 8ee0b6e81716..f66518ffb342 100644
--- a/typo3/sysext/seo/Classes/XmlSitemap/PagesXmlSitemapDataProvider.php
+++ b/typo3/sysext/seo/Classes/XmlSitemap/PagesXmlSitemapDataProvider.php
@@ -70,8 +70,14 @@ class PagesXmlSitemapDataProvider extends AbstractXmlSitemapDataProvider
             $rootPageId = $site->getRootPageId();
         }
 
+        $excludePagesRecursive = GeneralUtility::intExplode(',', $this->config['excludePagesRecursive'] ?? '', true);
+        $excludePagesRecursiveWhereClause = '';
+        if ($excludePagesRecursive !== []) {
+            $excludePagesRecursiveWhereClause = sprintf('uid NOT IN (%s)', implode(',', $excludePagesRecursive));
+        }
+
         $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
-        $treeList = $cObj->getTreeList(-$rootPageId, 99);
+        $treeList = $cObj->getTreeList(-$rootPageId, 99, 0, false, '', $excludePagesRecursiveWhereClause);
         $treeListArray = GeneralUtility::intExplode(',', $treeList);
 
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
diff --git a/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/constants.typoscript b/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/constants.typoscript
index 111ec7a6ba8c..fabd73a8f9f4 100644
--- a/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/constants.typoscript
+++ b/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/constants.typoscript
@@ -16,6 +16,8 @@ plugin.tx_seo {
         pages {
           # cat=plugin.tx_seo/sitemap; type=string; label=Doktypes to exclude
           excludedDoktypes = 3, 4, 6, 7, 199, 254, 255
+          # cat=plugin.tx_seo/sitemap; type=string; label=List of page uids which should be excluded recursive
+          excludePagesRecursive =
           # cat=plugin.tx_seo/sitemap; type=string; label=Additional where clause
           additionalWhere = no_index = 0 AND canonical_link = ''
         }
diff --git a/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/setup.typoscript b/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/setup.typoscript
index 238c1f5bed63..12168fc45476 100644
--- a/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/setup.typoscript
+++ b/typo3/sysext/seo/Configuration/TypoScript/XmlSitemap/setup.typoscript
@@ -48,6 +48,8 @@ plugin.tx_seo {
             # Here you can override the xslFile for a single sitemap
             # xslFile = EXT:seo/Resources/Public/CSS/Sitemap.xsl
             excludedDoktypes = {$plugin.tx_seo.settings.xmlSitemap.sitemaps.pages.excludedDoktypes}
+            # comma-separated list of page uids which should be excluded recursive
+            excludePagesRecursive = {$plugin.tx_seo.settings.xmlSitemap.sitemaps.pages.excludePagesRecursive}
             additionalWhere = {$plugin.tx_seo.settings.xmlSitemap.sitemaps.pages.additionalWhere}
           }
         }
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/excludePagesRecursive.typoscript b/typo3/sysext/seo/Tests/Functional/Fixtures/excludePagesRecursive.typoscript
new file mode 100644
index 000000000000..cd6b2cb394c2
--- /dev/null
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/excludePagesRecursive.typoscript
@@ -0,0 +1,11 @@
+plugin.tx_seo {
+    settings {
+        xmlSitemap {
+            sitemaps {
+                pages {
+                    excludePagesRecursive = 2
+                }
+            }
+        }
+    }
+}
diff --git a/typo3/sysext/seo/Tests/Functional/XmlSitemap/XmlSitemapPagesTest.php b/typo3/sysext/seo/Tests/Functional/XmlSitemap/XmlSitemapPagesTest.php
index b5d0fc79304d..60c4cc415796 100644
--- a/typo3/sysext/seo/Tests/Functional/XmlSitemap/XmlSitemapPagesTest.php
+++ b/typo3/sysext/seo/Tests/Functional/XmlSitemap/XmlSitemapPagesTest.php
@@ -134,4 +134,45 @@ class XmlSitemapPagesTest extends AbstractXmlSitemapPagesTest
             (string)$this->getResponse('http://localhost/de/')->getBody()
         );
     }
+
+    /**
+     * @test
+     */
+    public function pagesSitemapDoesNotContainUrlsOfExcludedPages(): void
+    {
+        $this->setUpFrontendRootPage(
+            1,
+            [
+                'constants' => [
+                    'EXT:seo/Configuration/TypoScript/XmlSitemap/constants.typoscript',
+                    'EXT:seo/Tests/Functional/Fixtures/excludePagesRecursive.typoscript'
+                ],
+                'setup' => ['EXT:seo/Configuration/TypoScript/XmlSitemap/setup.typoscript']
+            ]
+        );
+
+        $xml = (string)$this->getResponse()->getBody();
+        self::assertStringNotContainsString(
+            '<loc>http://localhost/dummy-1-2</loc>',
+            $xml
+        );
+        self::assertStringNotContainsString(
+            '<loc>http://localhost/dummy-1-2-5</loc>',
+            $xml
+        );
+        self::assertStringNotContainsString(
+            '<loc>http://localhost/dummy-1-2-6</loc>',
+            $xml
+        );
+
+        self::assertStringContainsString(
+            '<loc>http://localhost/</loc>',
+            $xml
+        );
+
+        self::assertStringContainsString(
+            '<loc>http://localhost/dummy-1-3</loc>',
+            $xml
+        );
+    }
 }
-- 
GitLab