diff --git a/typo3/sysext/core/Classes/TypoScript/IncludeTree/TreeBuilder.php b/typo3/sysext/core/Classes/TypoScript/IncludeTree/TreeBuilder.php index bfb9e5d7e658fa04b7fde6da84df9e11163a9512..c26593baee9fcc06d161c9bba92ae8db3cb30ed4 100644 --- a/typo3/sysext/core/Classes/TypoScript/IncludeTree/TreeBuilder.php +++ b/typo3/sysext/core/Classes/TypoScript/IncludeTree/TreeBuilder.php @@ -24,7 +24,6 @@ use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer; use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction; -use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Package\PackageManager; use TYPO3\CMS\Core\Site\Entity\Site; @@ -603,8 +602,7 @@ final class TreeBuilder * one query per page. To handle the capabilities mentioned above, the query is a bit nifty, but * the implementation should scale nearly O(1) instead of O(n) with the rootline depth. * - * @todo: It's potentially possible to further optimize using a recursive CTE. This could - * implement the workspace overlay that is currently done separately in one go. Benefit + * @todo: It's potentially possible to further optimize using a recursive CTE. Benefit * won't be *that* huge though, and there are much more important CTE targets first. */ private function getRootlineSysTemplateRowsFromDatabase(array $rootline, int $templateUidOnDeepestRootline): array @@ -657,16 +655,13 @@ final class TreeBuilder $lastPid = null; $queryResult = $queryBuilder->executeQuery(); while ($sysTemplateRow = $queryResult->fetchAssociative()) { - $sysTemplateRow = $this->sysTemplateWorkspaceOverlay($sysTemplateRow); - if ($sysTemplateRow) { - // We're retrieving *all* templates per pid, but need the first one only. The - // order restriction above at least takes care they're after-each-other per pid. - if ($lastPid === (int)$sysTemplateRow['pid']) { - continue; - } - $lastPid = (int)$sysTemplateRow['pid']; - $sysTemplateRows[] = $sysTemplateRow; + // We're retrieving *all* templates per pid, but need the first one only. The + // order restriction above at least takes care they're after-each-other per pid. + if ($lastPid === (int)$sysTemplateRow['pid']) { + continue; } + $lastPid = (int)$sysTemplateRow['pid']; + $sysTemplateRows[] = $sysTemplateRow; } return $sysTemplateRows; } @@ -692,11 +687,7 @@ final class TreeBuilder ) ->executeQuery() ->fetchAllAssociative(); - $basedOnTemplateRows = array_combine(array_column($basedOnTemplateRows, 'uid'), $basedOnTemplateRows); - foreach ($basedOnTemplateRows as $uid => $sysTemplateRow) { - $basedOnTemplateRows[$uid] = $this->sysTemplateWorkspaceOverlay($sysTemplateRow); - } - return $basedOnTemplateRows; + return array_combine(array_column($basedOnTemplateRows, 'uid'), $basedOnTemplateRows); } /** @@ -728,27 +719,9 @@ final class TreeBuilder return 'return unserialize(\'' . addcslashes(serialize($node), '\'') . '\');'; } - /** - * Workspace aware sys_template records. - */ - private function sysTemplateWorkspaceOverlay(array $row): ?array - { - if ($this->context->getPropertyFromAspect('workspace', 'isOffline')) { - $pageRepository = GeneralUtility::makeInstance(PageRepository::class, $this->context); - /** @var $row array|null */ - $pageRepository->versionOL('sys_template', $row); - if ($row === false) { - $row = null; - } - } - return $row; - } - /** * Get sys_template record query builder restrictions. * Allows hidden records if enabled in context. - * - * @todo: This looks as if there is no workspace restriction? */ private function getSysTemplateQueryRestrictionContainer(): DefaultRestrictionContainer { diff --git a/typo3/sysext/core/Classes/TypoScript/TemplateService.php b/typo3/sysext/core/Classes/TypoScript/TemplateService.php index a2074a0c2fae5127b42e25fb8d295ce8ed8b0e3d..7cde066a00ecb32c5e6296214a9904f276dc837f 100644 --- a/typo3/sysext/core/Classes/TypoScript/TemplateService.php +++ b/typo3/sysext/core/Classes/TypoScript/TemplateService.php @@ -23,7 +23,6 @@ use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\Restriction\AbstractRestrictionContainer; use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer; use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction; -use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Package\PackageManager; use TYPO3\CMS\Core\Site\Entity\Site; @@ -580,10 +579,7 @@ class TemplateService ->setMaxResults(1) ->executeQuery(); if ($row = $queryResult->fetchAssociative()) { - $this->versionOL($row); - if (is_array($row)) { - $this->processTemplate($row, 'sys_' . $row['uid'], $this->absoluteRootLine[$a]['uid'], 'sys_' . $row['uid']); - } + $this->processTemplate($row, 'sys_' . $row['uid'], $this->absoluteRootLine[$a]['uid'], 'sys_' . $row['uid']); } $this->rootLine[] = $this->absoluteRootLine[$a]; } @@ -691,7 +687,6 @@ class TemplateService // Traversing list again to ensure the sorting of the templates foreach ($basedOnIds as $id) { if (is_array($subTemplates[$id] ?? false)) { - $this->versionOL($subTemplates[$id]); $this->processTemplate($subTemplates[$id], $idList . ',sys_' . $id, $pid, 'sys_' . $id, $templateID); } } @@ -908,19 +903,6 @@ class TemplateService return $subrow; } - /** - * Creating versioning overlay of a sys_template record. - * - * @param array $row Row to overlay (passed by reference) - */ - protected function versionOL(&$row) - { - if ($this->context->getPropertyFromAspect('workspace', 'isOffline')) { - $pageRepository = GeneralUtility::makeInstance(PageRepository::class, $this->context); - $pageRepository->versionOL('sys_template', $row); - } - } - /******************************************************************* * * Parsing TypoScript code text from Template Records into PHP array diff --git a/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98480-TCATableSys_templateIsNoLongerWorkspaceAware.rst b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98480-TCATableSys_templateIsNoLongerWorkspaceAware.rst new file mode 100644 index 0000000000000000000000000000000000000000..007c718444c8c79cd7d1c08781f4d3dd7da9b461 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.0/Breaking-98480-TCATableSys_templateIsNoLongerWorkspaceAware.rst @@ -0,0 +1,42 @@ +.. include:: /Includes.rst.txt + +.. _breaking-98480-1664546652: + +======================================================================== +Breaking: #98480 - TCA table "sys_template" is no longer workspace aware +======================================================================== + +See :issue:`98480` + +Description +=========== + +The TCA database table :php:`sys_template` is no longer workspace aware: +When changing sys_template records in a workspace in the Backend, this has +immediate effect on Live workspace. + +Impact +====== + +Records of the TypoScript table "sys_template" are not available for editors, +this change should not have impact on editors working on content related +workspace records. + + +Affected installations +====================== + +Instances with enabled workspaces extension may see an impact: Editing TypoScript +template records immediately affects live. This is a relatively seldom scenario, +an upgrade wizard is in place to set all workspace aware sys_template records to +deleted, preventing them to leak to live. + + +Migration +========= + +Do not change "sys_template" rows in workspaces anymore. Any changes will be published +to live on edit. + + +.. index:: Backend, Frontend, TCA, TypoScript, NotScanned, ext:core diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnAfterIncludeStatic.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnAfterIncludeStatic.csv index 340bab0624fd4f6ab6ce27128964a94ed0ab68b1..1f8b1489e47969d5d3de48d6c7e211dbc046bc50 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnAfterIncludeStatic.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnAfterIncludeStatic.csv @@ -3,6 +3,6 @@ ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" ,2,1,256,0,0,0,0,0,0,"Sub","/sub" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"EXT:core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate","foo=fooValue","","2",0,0 -,2,2,256,0,0,0,0,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"EXT:core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate","foo=fooValue","","2",0,0 +,2,2,256,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnBeforeIncludeStatic.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnBeforeIncludeStatic.csv index d965594b57080364f77dc63cfed5543413ad7bbf..3ea87774bbb86cc56cf010923d0a30f284e48fab 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnBeforeIncludeStatic.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnBeforeIncludeStatic.csv @@ -3,6 +3,6 @@ ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" ,2,1,256,0,0,0,0,0,0,"Sub","/sub" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"EXT:core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate","foo=fooValue","","2",1,0 -,2,2,256,0,0,0,0,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"EXT:core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate","foo=fooValue","","2",1,0 +,2,2,256,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnSimple.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnSimple.csv index 7c503af96fbb254fdada8c5d20ced10472d271e3..6340259abb5275e98aa17dc0b4417bcecc3de7c2 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnSimple.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/basedOnSimple.csv @@ -3,6 +3,6 @@ ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" ,2,1,256,0,0,0,0,0,0,"Sub","/sub" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"","foo=fooValue","","2",0,0 -,2,2,256,0,0,0,0,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"","foo=fooValue","","2",0,0 +,2,2,256,0,0,0,0,0,0,0,"","bar=loadedByBasedOn","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/singleRootTemplate.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/singleRootTemplate.csv index 25e6e760e3171d13f128a7fb6a17d575a73ff1e2..3043d064792845fde4623c066639ba7805ebc736 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/singleRootTemplate.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/singleRootTemplate.csv @@ -2,5 +2,5 @@ ,"uid","pid","sorting","deleted","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title","slug" ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplates.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplates.csv index 58dcf9aabc7521d74af9a930e660208770ec87c9..f69d241ac2d2669040902e491b4522b78aa72945 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplates.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplates.csv @@ -3,6 +3,6 @@ ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" ,2,1,256,0,0,0,0,0,0,"Sub","/sub" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 -,2,2,256,0,0,0,0,0,0,0,0,0,0,0,"","bar=barValue","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 +,2,2,256,0,0,0,0,0,0,0,"","bar=barValue","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplatesBothClear.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplatesBothClear.csv index 8ee5070b34f9d48f404e7b3998aa0a2a744987a0..e807e4a83cfdad03a871624cdf8f9b16b7d04cc4 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplatesBothClear.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoPagesTwoTemplatesBothClear.csv @@ -3,6 +3,6 @@ ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" ,2,1,256,0,0,0,0,0,0,"Sub","/sub" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 -,2,2,256,0,0,0,0,0,0,0,0,0,0,3,"","bar=barValue","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 +,2,2,256,0,0,0,0,0,0,3,"","bar=barValue","","",0,0 diff --git a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoTemplatesOnPage.csv b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoTemplatesOnPage.csv index ec71e40b2a3409012e334662b42d4aea58ad9caf..5c092d1e71f26c8de616b75e6bff889a9dba8487 100644 --- a/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoTemplatesOnPage.csv +++ b/typo3/sysext/core/Tests/Functional/TypoScript/IncludeTree/Fixtures/SysTemplate/twoTemplatesOnPage.csv @@ -2,6 +2,6 @@ ,"uid","pid","sorting","deleted","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title","slug" ,1,0,256,0,0,0,0,0,0,"FunctionalTest","/" "sys_template" -,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" -,1,1,256,0,0,0,0,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 -,2,1,512,0,0,0,0,0,0,0,0,0,1,3,"","bar=notSetFooTakesPrecedence","","",0,0 +,"uid","pid","sorting","deleted","hidden","starttime","endtime","t3_origuid","root","clear","include_static_file","constants","config","basedOn","includeStaticAfterBasedOn","static_file_mode" +,1,1,256,0,0,0,0,0,1,3,"","foo=fooValue","","",0,0 +,2,1,512,0,0,0,0,0,1,3,"","bar=notSetFooTakesPrecedence","","",0,0 diff --git a/typo3/sysext/frontend/Configuration/TCA/sys_template.php b/typo3/sysext/frontend/Configuration/TCA/sys_template.php index 373f4a2e542d1fe5ab81ac961766df78d9b059ab..7789d836054765021f5afa2b1847fb3cc2876875 100644 --- a/typo3/sysext/frontend/Configuration/TCA/sys_template.php +++ b/typo3/sysext/frontend/Configuration/TCA/sys_template.php @@ -8,7 +8,6 @@ return [ 'sortby' => 'sorting', 'prependAtCopy' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.prependAtCopy', 'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:sys_template', - 'versioningWS' => true, 'groupName' => 'system', 'origUid' => 't3_origuid', 'crdate' => 'crdate', diff --git a/typo3/sysext/install/Classes/Updates/SysTemplateNoWorkspaceMigration.php b/typo3/sysext/install/Classes/Updates/SysTemplateNoWorkspaceMigration.php new file mode 100644 index 0000000000000000000000000000000000000000..3d0188956a7ac32b2f024948364695431782889c --- /dev/null +++ b/typo3/sysext/install/Classes/Updates/SysTemplateNoWorkspaceMigration.php @@ -0,0 +1,121 @@ +<?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\Install\Updates; + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * @internal This class is only meant to be used within EXT:install and is not part of the TYPO3 Core API. + */ +final class SysTemplateNoWorkspaceMigration implements UpgradeWizardInterface +{ + private const TABLE_NAME = 'sys_template'; + + public function getIdentifier(): string + { + return 'sysTemplateNoWorkspaceMigration'; + } + + public function getTitle(): string + { + return 'Set workspace records in table "sys_template" to deleted.'; + } + + public function getDescription(): string + { + return 'Table "sys_template" is no longer workspace aware.' . + ' Existing database rows having field "t3ver_wsid" > 0 are set to "deleted" = 1 to not' . + ' leak into live when the workspace related columns are deleted.'; + } + + public function getPrerequisites(): array + { + return [ + DatabaseUpdatedPrerequisite::class, + ]; + } + + public function updateNecessary(): bool + { + if (!$this->sysTemplateTableExists() || !$this->sysTemplateT3verWsidFieldExists()) { + return false; + } + $queryBuilder = $this->getPreparedQueryBuilder(); + $numberOfNotDeletedWorkspaceRows = (int)$queryBuilder + ->count('uid') + ->from(self::TABLE_NAME) + ->where($queryBuilder->expr()->gt('t3ver_wsid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))) + ->executeQuery() + ->fetchOne(); + if ($numberOfNotDeletedWorkspaceRows > 0) { + return true; + } + return false; + } + + public function executeUpdate(): bool + { + if (!$this->sysTemplateTableExists() || !$this->sysTemplateT3verWsidFieldExists()) { + return true; + } + $queryBuilder = $this->getPreparedQueryBuilder(); + $queryBuilder->update(self::TABLE_NAME) + ->where( + $queryBuilder->expr()->gt('t3ver_wsid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), + ) + ->set('deleted', 1, true, \PDO::PARAM_INT) + ->executeStatement(); + return true; + } + + private function sysTemplateTableExists(): bool + { + $schemaManager = $this->getConnectionPool()->getConnectionForTable(self::TABLE_NAME)->createSchemaManager(); + return $schemaManager->tablesExist(self::TABLE_NAME); + } + + private function sysTemplateT3verWsidFieldExists(): bool + { + $schemaManager = $this->getConnectionPool()->getConnectionForTable(self::TABLE_NAME)->createSchemaManager(); + $tableColumns = $schemaManager->listTableColumns(self::TABLE_NAME); + $fieldExists = false; + foreach ($tableColumns as $column) { + if ($column->getName() === 't3ver_wsid') { + $fieldExists = true; + break; + } + } + return $fieldExists; + } + + private function getPreparedQueryBuilder(): QueryBuilder + { + $queryBuilder = $this->getConnectionPool()->getQueryBuilderForTable(self::TABLE_NAME); + $queryBuilder->getRestrictions()->removeAll()->add(new DeletedRestriction()); + return $queryBuilder; + } + + private function getConnectionPool(): ConnectionPool + { + return GeneralUtility::makeInstance(ConnectionPool::class); + } +} diff --git a/typo3/sysext/install/ext_localconf.php b/typo3/sysext/install/ext_localconf.php index f8e466caf703faac336c3624656677af72274273..7109819eb4974103f2165667f6abe462cf69a511 100644 --- a/typo3/sysext/install/ext_localconf.php +++ b/typo3/sysext/install/ext_localconf.php @@ -13,6 +13,7 @@ use TYPO3\CMS\Install\Updates\SvgFilesSanitization; use TYPO3\CMS\Install\Updates\SysFileMountIdentifierMigration; use TYPO3\CMS\Install\Updates\SysLogChannel; use TYPO3\CMS\Install\Updates\SysLogSerializationUpdate; +use TYPO3\CMS\Install\Updates\SysTemplateNoWorkspaceMigration; defined('TYPO3') or die(); @@ -32,3 +33,4 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sysLogSerial $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['backendGroupsExplicitAllowDenyMigration'] = BackendGroupsExplicitAllowDenyMigration::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sysFileMountIdentifierMigration'] = SysFileMountIdentifierMigration::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['backendModulePermission'] = BackendModulePermissionMigration::class; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sysTemplateNoWorkspaceMigration'] = SysTemplateNoWorkspaceMigration::class; diff --git a/typo3/sysext/tstemplate/Classes/Controller/AbstractTemplateModuleController.php b/typo3/sysext/tstemplate/Classes/Controller/AbstractTemplateModuleController.php index efde3e5fd98b28f43db1f1f78018e50b8346124e..2a733b5490be8fc5f243dc4438e05ffefe850f50 100644 --- a/typo3/sysext/tstemplate/Classes/Controller/AbstractTemplateModuleController.php +++ b/typo3/sysext/tstemplate/Classes/Controller/AbstractTemplateModuleController.php @@ -28,7 +28,6 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; -use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; use TYPO3\CMS\Core\DataHandling\DataHandler; use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Http\RedirectResponse; @@ -190,10 +189,7 @@ abstract class AbstractTemplateModuleController $result = $this->getTemplateQueryBuilder($pageId)->executeQuery(); $templateRows = []; while ($row = $result->fetchAssociative()) { - BackendUtility::workspaceOL('sys_template', $row); - if (is_array($row)) { - $templateRows[] = $row; - } + $templateRows[] = $row; } return $templateRows; } @@ -218,9 +214,7 @@ abstract class AbstractTemplateModuleController $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($templateUid, \PDO::PARAM_INT)) ); } - $row = $queryBuilder->executeQuery()->fetchAssociative(); - BackendUtility::workspaceOL('sys_template', $row); - return $row; + return $queryBuilder->executeQuery()->fetchAssociative(); } /** @@ -228,12 +222,10 @@ abstract class AbstractTemplateModuleController */ protected function getTemplateQueryBuilder(int $pid): QueryBuilder { - $backendUser = $this->getBackendUser(); $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template'); $queryBuilder->getRestrictions() ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $backendUser->workspace)); + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); return $queryBuilder->select('*') ->from('sys_template') ->where( diff --git a/typo3/sysext/tstemplate/Classes/Controller/TemplateRecordsOverviewController.php b/typo3/sysext/tstemplate/Classes/Controller/TemplateRecordsOverviewController.php index af360c78b48d5adfbe45ffb33b708edfb740f79a..e9a04671c6d470bc21873a4f4ae4b0f8e34f4fa3 100644 --- a/typo3/sysext/tstemplate/Classes/Controller/TemplateRecordsOverviewController.php +++ b/typo3/sysext/tstemplate/Classes/Controller/TemplateRecordsOverviewController.php @@ -22,10 +22,8 @@ use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Backend\Template\ModuleTemplateFactory; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; -use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Versioning\VersionState; /** * Overview of all sys_template records from site root @@ -45,7 +43,6 @@ class TemplateRecordsOverviewController extends AbstractTemplateModuleController $currentModule = $request->getAttribute('module'); $currentModuleIdentifier = $currentModule->getIdentifier(); $pageId = (int)($request->getQueryParams()['id'] ?? 0); - $workspaceId = $backendUser->workspace; $pageRecord = BackendUtility::readPageAccess($pageId, '1=1') ?: []; $moduleData = $request->getAttribute('moduleData'); @@ -55,20 +52,15 @@ class TemplateRecordsOverviewController extends AbstractTemplateModuleController $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_template'); $queryBuilder->getRestrictions()->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $workspaceId)); + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); $result = $queryBuilder - ->select('uid', 'pid', 'title', 'root', 'hidden', 'starttime', 'endtime', 't3ver_oid', 't3ver_wsid', 't3ver_state') + ->select('uid', 'pid', 'title', 'root', 'hidden', 'starttime', 'endtime') ->from('sys_template') ->orderBy('sys_template.pid') ->addOrderBy('sys_template.sorting') ->executeQuery(); $pagesWithTemplates = []; while ($record = $result->fetchAssociative()) { - BackendUtility::workspaceOL('sys_template', $record, $workspaceId, true); - if (empty($record) || VersionState::cast($record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) { - continue; - } $additionalFieldsForRootline = ['sorting', 'shortcut']; $rootline = array_reverse(BackendUtility::BEgetRootLine($record['pid'], '', true, $additionalFieldsForRootline)); $pagesWithTemplates = $this->setInPageArray($pagesWithTemplates, $rootline, $record); diff --git a/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php b/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php index da0eee0b05a526aa266113a901119359e5ecf00d..4556fc977219457aadb44812a83063cb0f2d88ce 100644 --- a/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php +++ b/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php @@ -161,7 +161,6 @@ class WorkspaceServiceTest extends FunctionalTestCase 'sys_file_metadata' => [], 'sys_file_reference' => [], 'backend_layout' => [], - 'sys_template' => [], 'tt_content' => [ 1 => true, 7 => true,