From dfa3a35d40cbecf17a18bff2b0fccce18e07856c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dimitri=20K=C3=B6nig?= <typo3@dimitrikoenig.net>
Date: Mon, 22 Jan 2024 16:34:44 +0100
Subject: [PATCH] [BUGFIX] Reverse rootline for PageLayoutResolver calls
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

There have been quite a lot of patches around the pagelayout
condition, which was introduced in early TYPO3 v11. It was
broken in the beginning and got fixed with #98044.
Soon after, a major refactoring of the ConditionMatcher
has been applied with #100047, which re-introduced bugs
regarding the pagelayout TypoScript condition. These have
partially fixed with #100764 and #100921.

The affected code is a bit messy due to a weird sorted
array returned by the 'rootline' methods and classes,
which we can't resolve right now.

The fix itself revolves a last issue by reversing the
rootline again. This was already done in the old backend
ConditionMatcher. The frontend ConditionMatcher received
the fullRootline, which is already reversed (deepest first).

With the introduction of IncludeTreeConditionMatcherVisitor
this has been unified, but the array_reverse was forgotten.

In addition, the fullRootline from the frontend controller
and BackendUtility::getPagesTSconfig() calls are sorted with
`ksort` before passed over, meaning we always receive a
top-down (root-first) rootline. Hence, the array_reverse is
a viable fix for both backend and frontend.

The patch covers BE pageTS, FE TypoScript and FE getData
with tests to cover the situation once and for all.

Resolves: #102268
Related: #100047
Related: #100764
Related: #100921
Related: #98044
Related: #97816
Releases: main, 12.4
Change-Id: Ibec77f3cf63073e40e4a711d69f584b9265b1ad6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/82743
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Stefan Bürk <stefan@buerk.tech>
---
 .../IncludeTreeConditionMatcherVisitor.php    |   8 +-
 .../backendLayoutAndNextLevelOnRoot.csv       |   4 +
 ...ndLayoutAndNextLevelOnRootSetup.typoscript |   6 +
 ...ndLayoutAndNextLevelOnRootSubOverride1.csv |   5 +
 ...extLevelOnRootSubOverride1Setup.typoscript |   6 +
 ...ndLayoutAndNextLevelOnRootSubOverride2.csv |   6 +
 ...extLevelOnRootSubOverride2Setup.typoscript |   6 +
 ...ndLayoutAndNextLevelOnRootSubOverride3.csv |   6 +
 ...extLevelOnRootSubOverride3Setup.typoscript |   6 +
 .../backendLayoutNextLevelOnRoot.csv          |   3 +
 ...ckendLayoutNextLevelOnRootSetup.typoscript |   7 +
 .../backendLayoutOnRoot.csv                   |   3 +
 .../backendLayoutOnRootSetup.typoscript       |   6 +
 .../backendLayoutAndNextLevelOnRootPage.csv   |   7 +
 ...youtAndNextLevelOnRootPageSubOverride1.csv |   8 +
 ...youtAndNextLevelOnRootPageSubOverride2.csv |   9 ++
 ...youtAndNextLevelOnRootPageSubOverride3.csv |   9 ++
 .../backendLayoutNextLevelOnRootPage.csv      |   6 +
 .../backendLayoutOnRootPage.csv               |   6 +
 ...poScriptFactoryPageLayoutConditionTest.php | 140 ++++++++++++++++++
 ...TsConfigFactoryPageLayoutConditionTest.php | 131 ++++++++++++++++
 ...entObjectRendererGetDataPageLayoutTest.php | 140 ++++++++++++++++++
 .../backendLayoutAndNextLevelOnRootPage.csv   |   4 +
 ...youtAndNextLevelOnRootPageSubOverride1.csv |   5 +
 ...youtAndNextLevelOnRootPageSubOverride2.csv |   6 +
 ...youtAndNextLevelOnRootPageSubOverride3.csv |   6 +
 .../backendLayoutNextLevelOnRootPage.csv      |   3 +
 .../backendLayoutOnRootPage.csv               |   3 +
 .../setup.typoscript                          |   3 +
 29 files changed, 555 insertions(+), 3 deletions(-)
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRoot.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSetup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1Setup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2Setup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3Setup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRoot.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRootSetup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRoot.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRootSetup.typoscript
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPage.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutNextLevelOnRootPage.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutOnRootPage.csv
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/FrontendTypoScriptFactoryPageLayoutConditionTest.php
 create mode 100644 typo3/sysext/core/Tests/Functional/TypoScript/PageTsConfigFactoryPageLayoutConditionTest.php
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/ContentObjectRendererGetDataPageLayoutTest.php
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPage.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutNextLevelOnRootPage.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutOnRootPage.csv
 create mode 100644 typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript

diff --git a/typo3/sysext/core/Classes/TypoScript/IncludeTree/Visitor/IncludeTreeConditionMatcherVisitor.php b/typo3/sysext/core/Classes/TypoScript/IncludeTree/Visitor/IncludeTreeConditionMatcherVisitor.php
index e3acb82120e6..ebf959c667b4 100644
--- a/typo3/sysext/core/Classes/TypoScript/IncludeTree/Visitor/IncludeTreeConditionMatcherVisitor.php
+++ b/typo3/sysext/core/Classes/TypoScript/IncludeTree/Visitor/IncludeTreeConditionMatcherVisitor.php
@@ -118,9 +118,11 @@ final class IncludeTreeConditionMatcherVisitor implements IncludeTreeVisitorInte
             $tree->rootLineParentIds = array_slice(array_column($localRootLine, 'pid'), 1);
             // We're feeding the "full" RootLine here, not the "local" one that stops at sys_template record having 'root' set.
             // This is to be in-line with backend here: A 'backend_layout_next_level' on a page above sys_template 'root' page should
-            // still be considered. Additionally, $fullRootLine is "deepest page first, then up" for getLayoutForPage() to find
-            // the 'nearest' parent.
-            $tree->pagelayout = $this->pageLayoutResolver->getLayoutForPage($variables['page'], $fullRootLine);
+            // still be considered. Normally, $fullRootLine is "deepest page first, then up". This is needed for getLayoutForPage() to find
+            // the 'nearest' parent. However, here it is always passed sorted, so it is a top-down rootLine. Hence, this needs to be once
+            // again reversed at this point.
+            $bottomUpFullRootLine = array_reverse($fullRootLine);
+            $tree->pagelayout = $this->pageLayoutResolver->getLayoutForPage($variables['page'], $bottomUpFullRootLine);
             $enrichedVariables['tree'] = $tree;
         }
 
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRoot.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRoot.csv
new file mode 100644
index 000000000000..c770d5dc0a8c
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRoot.csv
@@ -0,0 +1,4 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSetup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSetup.typoscript
new file mode 100644
index 000000000000..06531b4c7703
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSetup.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+
+[tree.pagelayout == 'pagets__inherit']
+  page.10 = TEXT
+  page.10.value = Inherited Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1.csv
new file mode 100644
index 000000000000..6e2b5dda51ad
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1.csv
@@ -0,0 +1,5 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","pagets__default",""
+,3,2,"Subpage 2","","pagets__default"
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1Setup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1Setup.typoscript
new file mode 100644
index 000000000000..06531b4c7703
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1Setup.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+
+[tree.pagelayout == 'pagets__inherit']
+  page.10 = TEXT
+  page.10.value = Inherited Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2.csv
new file mode 100644
index 000000000000..3fe19e230c07
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","","pagets__foo"
+,3,2,"Subpage 2","","pagets__extra"
+,4,3,"Subpage 3","pagets__extra",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2Setup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2Setup.typoscript
new file mode 100644
index 000000000000..fb7d06951d49
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2Setup.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+
+[tree.pagelayout == 'pagets__extra']
+  page.10 = TEXT
+  page.10.value = Extra Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3.csv
new file mode 100644
index 000000000000..470c499e91bd
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","","pagets__foo"
+,3,2,"Subpage 2","","pagets__extra"
+,4,3,"Subpage 3","",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3Setup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3Setup.typoscript
new file mode 100644
index 000000000000..fb7d06951d49
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3Setup.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+
+[tree.pagelayout == 'pagets__extra']
+  page.10 = TEXT
+  page.10.value = Extra Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRoot.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRoot.csv
new file mode 100644
index 000000000000..ccfec6c03a8b
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRoot.csv
@@ -0,0 +1,3 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","","pagets__default"
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRootSetup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRootSetup.typoscript
new file mode 100644
index 000000000000..b5c5391eec4f
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRootSetup.typoscript
@@ -0,0 +1,7 @@
+page = PAGE
+page.typeNum = 0
+
+[tree.pagelayout == 'pagets__default']
+  page.10 = TEXT
+  page.10.value = Default Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRoot.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRoot.csv
new file mode 100644
index 000000000000..746f7be25170
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRoot.csv
@@ -0,0 +1,3 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRootSetup.typoscript b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRootSetup.typoscript
new file mode 100644
index 000000000000..95c2a2e3d873
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRootSetup.typoscript
@@ -0,0 +1,6 @@
+page = PAGE
+
+[tree.pagelayout == 'pagets__default']
+  page.10 = TEXT
+  page.10.value = Default Layout
+[end]
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPage.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPage.csv
new file mode 100644
index 000000000000..e93e4a731f37
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPage.csv
@@ -0,0 +1,7 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","pagets__default","pagets__inherit","
+[tree.pagelayout == 'pagets__inherit']
+    layout = Inherited Layout
+[end]"
+,2,1,"Subpage","","",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride1.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
new file mode 100644
index 000000000000..c7c283bfa3f4
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
@@ -0,0 +1,8 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","pagets__default","pagets__inherit","
+[tree.pagelayout == 'pagets__inherit']
+    layout = Inherited Layout
+[end]"
+,2,1,"Subpage","pagets__default","",""
+,3,2,"Subpage 2","","pagets__default",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride2.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
new file mode 100644
index 000000000000..611119ecf65e
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
@@ -0,0 +1,9 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","pagets__default","pagets__inherit","
+[tree.pagelayout == 'pagets__extra']
+    layout = Extra Layout
+[end]"
+,2,1,"Subpage","","pagets__foo",""
+,3,2,"Subpage 2","","pagets__extra",""
+,4,3,"Subpage 3","pagets__extra","",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride3.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
new file mode 100644
index 000000000000..923d014efd53
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
@@ -0,0 +1,9 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","pagets__default","pagets__inherit","
+[tree.pagelayout == 'pagets__extra']
+    layout = Extra Layout
+[end]"
+,2,1,"Subpage","","pagets__foo",""
+,3,2,"Subpage 2","","pagets__extra",""
+,4,3,"Subpage 3","","",""
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutNextLevelOnRootPage.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutNextLevelOnRootPage.csv
new file mode 100644
index 000000000000..97279bb72089
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutNextLevelOnRootPage.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","","pagets__default","
+[tree.pagelayout == 'pagets__default']
+    layout = Default Layout
+[end]"
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutOnRootPage.csv b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutOnRootPage.csv
new file mode 100644
index 000000000000..991898e0abb0
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutOnRootPage.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level","TSconfig"
+,1,0,"Homepage","pagets__default","","
+[tree.pagelayout == 'pagets__default']
+    layout = Default Layout
+[end]"
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/FrontendTypoScriptFactoryPageLayoutConditionTest.php b/typo3/sysext/core/Tests/Functional/TypoScript/FrontendTypoScriptFactoryPageLayoutConditionTest.php
new file mode 100644
index 000000000000..b217e6bd60e2
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/FrontendTypoScriptFactoryPageLayoutConditionTest.php
@@ -0,0 +1,140 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * 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!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Functional\TypoScript;
+
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+/**
+ * Test Frontend TypoScript 'tree.pagelayout' related condition matching.
+ */
+final class FrontendTypoScriptFactoryPageLayoutConditionTest extends FunctionalTestCase
+{
+    use SiteBasedTestTrait;
+
+    protected const LANGUAGE_PRESETS = [
+        'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
+    ];
+    private const ROOT_PAGE_ID = 1;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->writeSiteConfiguration(
+            'tree_page_layout_test',
+            $this->buildSiteConfiguration(self::ROOT_PAGE_ID, '/'),
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRoot.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutOnRootSetup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('Default Layout', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionNotMetForBackendLayoutNextLevelOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRoot.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutNextLevelOnRootSetup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringNotContainsString('Default Layout', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelInheritedOnSubpageLevel1(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRoot.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSetup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(2));
+        self::assertStringContainsString('Inherited Layout', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelInheritedOnSubpageLevel2(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride1Setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(3));
+        self::assertStringContainsString('Inherited Layout', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride2Setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(4));
+        self::assertStringContainsString('Extra Layout', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelOverrideOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:core/Tests/Functional/TypoScript/Fixtures/FrontendTypoScriptFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootSubOverride3Setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(4));
+        self::assertStringContainsString('Extra Layout', (string)$response->getBody());
+    }
+}
diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/PageTsConfigFactoryPageLayoutConditionTest.php b/typo3/sysext/core/Tests/Functional/TypoScript/PageTsConfigFactoryPageLayoutConditionTest.php
new file mode 100644
index 000000000000..b082be92a3b8
--- /dev/null
+++ b/typo3/sysext/core/Tests/Functional/TypoScript/PageTsConfigFactoryPageLayoutConditionTest.php
@@ -0,0 +1,131 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * 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!
+ */
+
+namespace TYPO3\CMS\Core\Tests\Functional\TypoScript;
+
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Site\Entity\NullSite;
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\CMS\Core\TypoScript\PageTsConfigFactory;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+/**
+ * Test pageTS 'tree.pagelayout' related condition matching.
+ */
+final class PageTsConfigFactoryPageLayoutConditionTest extends FunctionalTestCase
+{
+    use SiteBasedTestTrait;
+
+    protected const LANGUAGE_PRESETS = [
+        'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
+    ];
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->writeSiteConfiguration(
+            'tree_page_layout_test',
+            $this->buildSiteConfiguration(1, '/'),
+        );
+        $this->importCSVDataSet(__DIR__ . '/../Fixtures/be_users.csv');
+        $this->setUpBackendUser(1);
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutOnRootPage.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(1, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringContainsString('Default Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionNotMetForBackendLayoutNextLevelOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutNextLevelOnRootPage.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(1, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringNotContainsString('Default Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelInheritedOnSubpageLevel1(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPage.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(2, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringContainsString('Inherited Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelInheritedOnSubpageLevel2(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride1.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(3, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringContainsString('Inherited Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride2.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(4, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringContainsString('Extra Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+
+    /**
+     * @test
+     */
+    public function treePageLayoutConditionMetForBackendLayoutNextLevelOverrideOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/PageTsConfigFactoryPageLayoutCondition/backendLayoutAndNextLevelOnRootPageSubOverride3.csv');
+        $fullRootLine = BackendUtility::BEgetRootLine(4, '', true);
+        ksort($fullRootLine);
+        $subject = $this->get(PageTsConfigFactory::class);
+        $pageTsConfig = $subject->create($fullRootLine, new NullSite());
+        $pageTsConfigArray = $pageTsConfig->getPageTsConfigArray();
+        self::assertStringContainsString('Extra Layout', $pageTsConfigArray['layout'] ?? '');
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/ContentObjectRendererGetDataPageLayoutTest.php b/typo3/sysext/frontend/Tests/Functional/ContentObject/ContentObjectRendererGetDataPageLayoutTest.php
new file mode 100644
index 000000000000..bd5bd97ac3a4
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/ContentObjectRendererGetDataPageLayoutTest.php
@@ -0,0 +1,140 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * 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!
+ */
+
+namespace TYPO3\CMS\Frontend\Tests\Functional\ContentObject;
+
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+/**
+ * Tests for COR->getData() with pagelayout.
+ */
+final class ContentObjectRendererGetDataPageLayoutTest extends FunctionalTestCase
+{
+    use SiteBasedTestTrait;
+
+    protected const LANGUAGE_PRESETS = [
+        'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
+    ];
+    private const ROOT_PAGE_ID = 1;
+
+    public function setUp(): void
+    {
+        parent::setUp();
+        $this->writeSiteConfiguration(
+            'tree_page_layout_test',
+            $this->buildSiteConfiguration(self::ROOT_PAGE_ID, '/'),
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutResolvedForBackendLayoutOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutOnRootPage.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringContainsString('pagets__default', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutNotResolvedForBackendLayoutNextLevelOnRootPage(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutNextLevelOnRootPage.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(self::ROOT_PAGE_ID));
+        self::assertStringNotContainsString('pagets__default', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutResolvedForBackendLayoutNextLevelInheritedOnSubpageLevel1(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPage.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(2));
+        self::assertStringContainsString('pagets__inherit', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutResolvedForBackendLayoutNextLevelInheritedOnSubpageLevel2(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride1.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(3));
+        self::assertStringContainsString('pagets__inherit', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutResolvedForBackendLayoutOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride2.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(4));
+        self::assertStringContainsString('pagets__bar', (string)$response->getBody());
+    }
+
+    /**
+     * @test
+     */
+    public function pageLayoutResolvedForBackendLayoutNextLevelOverrideOnSubpageLevel3(): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride3.csv');
+        $this->setUpFrontendRootPage(
+            self::ROOT_PAGE_ID,
+            [
+                'EXT:frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript',
+            ]
+        );
+        $response = $this->executeFrontendSubRequest((new InternalRequest())->withPageId(4));
+        self::assertStringContainsString('pagets__extra', (string)$response->getBody());
+    }
+}
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPage.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPage.csv
new file mode 100644
index 000000000000..c770d5dc0a8c
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPage.csv
@@ -0,0 +1,4 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","",""
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride1.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
new file mode 100644
index 000000000000..6e2b5dda51ad
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride1.csv
@@ -0,0 +1,5 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","pagets__default",""
+,3,2,"Subpage 2","","pagets__default"
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride2.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
new file mode 100644
index 000000000000..168511f7ddbd
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride2.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","","pagets__foo"
+,3,2,"Subpage 2","","pagets__extra"
+,4,3,"Subpage 3","pagets__bar",""
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride3.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
new file mode 100644
index 000000000000..470c499e91bd
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutAndNextLevelOnRootPageSubOverride3.csv
@@ -0,0 +1,6 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default","pagets__inherit"
+,2,1,"Subpage","","pagets__foo"
+,3,2,"Subpage 2","","pagets__extra"
+,4,3,"Subpage 3","",""
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutNextLevelOnRootPage.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutNextLevelOnRootPage.csv
new file mode 100644
index 000000000000..ccfec6c03a8b
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutNextLevelOnRootPage.csv
@@ -0,0 +1,3 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","","pagets__default"
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutOnRootPage.csv b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutOnRootPage.csv
new file mode 100644
index 000000000000..746f7be25170
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/backendLayoutOnRootPage.csv
@@ -0,0 +1,3 @@
+"pages"
+,"uid","pid","title","backend_layout","backend_layout_next_level"
+,1,0,"Homepage","pagets__default",""
diff --git a/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript
new file mode 100644
index 000000000000..afffbfbac21f
--- /dev/null
+++ b/typo3/sysext/frontend/Tests/Functional/ContentObject/Fixtures/ContentObjectRendererGetDataPageLayout/setup.typoscript
@@ -0,0 +1,3 @@
+page = PAGE
+page.10 = TEXT
+page.10.data = pagelayout
-- 
GitLab