From 126ff8f06a63188d5e6bb987f0f5fdb1abd2bf05 Mon Sep 17 00:00:00 2001
From: Sascha Nowak <sascha.nowak@netlogix.de>
Date: Wed, 21 Feb 2024 07:00:44 +0100
Subject: [PATCH] [TASK] Clean up legacy cache_treelist leftovers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Using cache_treelist has been avoided with #103139
since it was broken. v13 now goes ahead and removes
the clearing logic and the table itself.

Note the PageRepository method that formerlly used
that cache would be a great target for a (first) CTE
to structurally enhance performance. v13 may see
patches in this area.

Resolves: #103165
Related: #103139
Releases: main
Change-Id: I2bcee1befa08b8dc81f39c7ef4b9e8a005fad0c8
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83051
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
---
 .../Classes/Command/CacheFlushCommand.php     |  21 -
 .../core/Classes/DataHandling/DataHandler.php |   1 -
 ...Important-103165-Remove-treelist-cache.rst |  21 +
 .../Domain/Repository/PageRepositoryTest.php  |  16 +-
 .../Hooks/TreelistCacheUpdateHooks.php        | 381 ------------------
 typo3/sysext/frontend/ext_localconf.php       |   6 -
 typo3/sysext/frontend/ext_tables.sql          |  13 -
 .../Classes/Service/ClearCacheService.php     |  17 +-
 8 files changed, 24 insertions(+), 452 deletions(-)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/13.1/Important-103165-Remove-treelist-cache.rst
 delete mode 100644 typo3/sysext/frontend/Classes/Hooks/TreelistCacheUpdateHooks.php

diff --git a/typo3/sysext/core/Classes/Command/CacheFlushCommand.php b/typo3/sysext/core/Classes/Command/CacheFlushCommand.php
index 2c04011c71bd..3393f2695aca 100644
--- a/typo3/sysext/core/Classes/Command/CacheFlushCommand.php
+++ b/typo3/sysext/core/Classes/Command/CacheFlushCommand.php
@@ -27,9 +27,7 @@ use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Event\CacheFlushEvent;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Core\BootService;
-use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\DependencyInjection\Cache\ContainerBackend;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 class CacheFlushCommand extends Command
 {
@@ -59,7 +57,6 @@ class CacheFlushCommand extends Command
     {
         $group = $input->getOption('group') ?? 'all';
 
-        $this->flushLegacyDatabaseCacheTables($group);
         $this->flushDependencyInjectionCaches($group);
         if ($group === 'di') {
             return Command::SUCCESS;
@@ -105,22 +102,4 @@ class CacheFlushCommand extends Command
 
         $container->get('cache.core')->flush();
     }
-
-    protected function flushLegacyDatabaseCacheTables($group): void
-    {
-        if ($group !== 'all') {
-            return;
-        }
-
-        $legacyDatabaseCacheTables = [
-            'cache_treelist',
-        ];
-
-        // Low level flush of legacy database cache tables
-        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
-        foreach ($legacyDatabaseCacheTables as $tableName) {
-            $connection = $connectionPool->getConnectionForTable($tableName);
-            $connection->truncate($tableName);
-        }
-    }
 }
diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 5ebca8379914..6ce9b4719384 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -9037,7 +9037,6 @@ class DataHandler implements LoggerAwareInterface
                     || ($this->admin && (bool)($userTsConfig['options.']['clearCache.']['all'] ?? true))
                 ) {
                     $this->cacheManager->flushCaches();
-                    $this->connectionPool->getConnectionForTable('cache_treelist')->truncate('cache_treelist');
 
                     // Delete Opcode Cache
                     GeneralUtility::makeInstance(OpcodeCacheService::class)->clearAllActive();
diff --git a/typo3/sysext/core/Documentation/Changelog/13.1/Important-103165-Remove-treelist-cache.rst b/typo3/sysext/core/Documentation/Changelog/13.1/Important-103165-Remove-treelist-cache.rst
new file mode 100644
index 000000000000..f128c0f602a8
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/13.1/Important-103165-Remove-treelist-cache.rst
@@ -0,0 +1,21 @@
+.. include:: /Includes.rst.txt
+
+.. _important-103165-1708508519:
+
+==========================================================
+Important: #103165 - Database table cache_treelist removed
+==========================================================
+
+See :issue:`103165`
+
+Description
+===========
+
+Database table :sql:`cache_treelist` has been removed, the database
+analyzer will suggest to drop it if it exists.
+
+That cache table was unused since a TYPO3 v12 patch level release, v13
+removed left over handling throughout the core and removed the table itself.
+
+
+.. index:: Database, ext:frontend
diff --git a/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php b/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
index 9376239f3b2e..72811185aef1 100644
--- a/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
+++ b/typo3/sysext/core/Tests/Functional/Domain/Repository/PageRepositoryTest.php
@@ -18,10 +18,8 @@ declare(strict_types=1);
 namespace TYPO3\CMS\Core\Tests\Functional\Domain\Repository;
 
 use Symfony\Component\DependencyInjection\Container;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\LanguageAspect;
-use TYPO3\CMS\Core\Context\UserAspect;
 use TYPO3\CMS\Core\Context\WorkspaceAspect;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Expression\CompositeExpression;
@@ -544,12 +542,7 @@ final class PageRepositoryTest extends FunctionalTestCase
      */
     public function getPageIdsRecursiveTest(): void
     {
-        // do not use cache_treelist
-        $user = new BackendUserAuthentication();
-        $user->user = ['uid' => PHP_INT_MAX];
-        $context = new Context();
-        $context->setAspect('backend.user', new UserAspect($user));
-        $subject = new PageRepository($context);
+        $subject = new PageRepository();
         // empty array does not do anything
         $result = $subject->getPageIdsRecursive([], 1);
         self::assertEquals([], $result);
@@ -572,12 +565,7 @@ final class PageRepositoryTest extends FunctionalTestCase
      */
     public function getDescendantPageIdsRecursiveTest(): void
     {
-        // do not use cache_treelist
-        $user = new BackendUserAuthentication();
-        $user->user = ['uid' => PHP_INT_MAX];
-        $context = new Context();
-        $context->setAspect('backend.user', new UserAspect($user));
-        $subject = new PageRepository($context);
+        $subject = new PageRepository();
         // Negative numbers or "0" do not return anything
         $result = $subject->getDescendantPageIdsRecursive(-1, 1);
         self::assertEquals([], $result);
diff --git a/typo3/sysext/frontend/Classes/Hooks/TreelistCacheUpdateHooks.php b/typo3/sysext/frontend/Classes/Hooks/TreelistCacheUpdateHooks.php
deleted file mode 100644
index 610e67f8464a..000000000000
--- a/typo3/sysext/frontend/Classes/Hooks/TreelistCacheUpdateHooks.php
+++ /dev/null
@@ -1,381 +0,0 @@
-<?php
-
-/*
- * 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\Hooks;
-
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Database\Connection;
-use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\DataHandling\DataHandler;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * Class that hooks into DataHandler and listens for updates to pages to update the
- * treelist cache
- * @internal this is a concrete TYPO3 hook implementation and solely used for EXT:frontend and not part of TYPO3's Core API.
- */
-class TreelistCacheUpdateHooks
-{
-    /**
-     * Should not be manipulated from others except through the
-     * configuration provided @see __construct()
-     *
-     * @var array
-     */
-    private $updateRequiringFields = [
-        'pid',
-        'php_tree_stop',
-        'extendToSubpages',
-    ];
-
-    /**
-     * Constructor, adds update requiring fields to the default ones
-     */
-    public function __construct()
-    {
-        // As enableFields can be set dynamically we add them here
-        $pagesEnableFields = $GLOBALS['TCA']['pages']['ctrl']['enablecolumns'];
-        foreach ($pagesEnableFields as $pagesEnableField) {
-            $this->updateRequiringFields[] = $pagesEnableField;
-        }
-        $this->updateRequiringFields[] = $GLOBALS['TCA']['pages']['ctrl']['delete'];
-        // Extension can add fields to the pages table that require an
-        // update of the treelist cache, too; so we also add those
-        // example: $TYPO3_CONF_VARS['BE']['additionalTreelistUpdateFields'] .= ',my_field';
-        if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['additionalTreelistUpdateFields'])) {
-            $additionalTreelistUpdateFields = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['BE']['additionalTreelistUpdateFields'], true);
-            $this->updateRequiringFields = array_merge($this->updateRequiringFields, $additionalTreelistUpdateFields);
-        }
-    }
-
-    /**
-     * waits for DataHandler commands and looks for changed pages, if found further
-     * changes take place to determine whether the cache needs to be updated
-     *
-     * @param string $status DataHandler operation status, either 'new' or 'update'
-     * @param string $table The DB table the operation was carried out on
-     * @param mixed $recordId The record's uid for update records, a string to look the record's uid up after it has been created
-     * @param array $updatedFields Array of changed fields and their new values
-     * @param DataHandler $dataHandler DataHandler parent object
-     */
-    public function processDatamap_afterDatabaseOperations($status, $table, $recordId, array $updatedFields, DataHandler $dataHandler)
-    {
-        if ($table === 'pages' && $this->requiresUpdate($updatedFields)) {
-            $affectedPagePid = 0;
-            $affectedPageUid = 0;
-            if ($status === 'new') {
-                // Detect new pages
-                // Resolve the uid
-                $affectedPageUid = $dataHandler->substNEWwithIDs[$recordId];
-                $affectedPagePid = $updatedFields['pid'];
-            } elseif ($status === 'update') {
-                // Detect updated pages
-                $affectedPageUid = $recordId;
-                // When updating a page the pid is not directly available so we
-                // need to retrieve it ourselves.
-                $fullPageRecord = BackendUtility::getRecord($table, $recordId);
-                $affectedPagePid = $fullPageRecord['pid'];
-            }
-            $clearCacheActions = $this->determineClearCacheActions($status, $updatedFields);
-            $this->processClearCacheActions($affectedPageUid, $affectedPagePid, $updatedFields, $clearCacheActions);
-        }
-    }
-
-    /**
-     * Waits for DataHandler commands and looks for deleted pages or published pages, if found
-     * further changes take place to determine whether the cache needs to be updated
-     *
-     * @param string $command The TCE command
-     * @param string $table The record's table
-     * @param int $recordId The record's uid
-     * @param array $commandValue The commands value, typically an array with more detailed command information
-     * @param DataHandler $dataHandler The DataHandler parent object
-     */
-    public function processCmdmap_postProcess($command, $table, $recordId, $commandValue, DataHandler $dataHandler)
-    {
-        $action = (is_array($commandValue) && isset($commandValue['action'])) ? (string)$commandValue['action'] : '';
-        if ($table === 'pages' && ($command === 'delete' || ($command === 'version' && $action === 'publish'))) {
-            $affectedRecord = BackendUtility::getRecord($table, $recordId, '*', '', false);
-            if (!is_array($affectedRecord)) {
-                return;
-            }
-            $affectedPageUid = $affectedRecord['uid'];
-            $affectedPagePid = $affectedRecord['pid'];
-
-            // Faking the updated fields
-            $updatedFields = [];
-            if ($command === 'delete') {
-                $updatedFields['deleted'] = 1;
-            } else {
-                // page was published to live
-                $updatedFields['t3ver_wsid'] = 0;
-            }
-            $clearCacheActions = $this->determineClearCacheActions(
-                'update',
-                $updatedFields
-            );
-
-            $this->processClearCacheActions($affectedPageUid, $affectedPagePid, $updatedFields, $clearCacheActions);
-        }
-    }
-
-    /**
-     * waits for DataHandler commands and looks for moved pages, if found further
-     * changes take place to determine whether the cache needs to be updated
-     *
-     * @param string $table Table name of the moved record
-     * @param int $recordId The record's uid
-     * @param int $destinationPid The record's destination page id
-     * @param array $movedRecord The record that moved
-     * @param array $updatedFields Array of changed fields
-     * @param DataHandler $dataHandler DataHandler parent object
-     */
-    public function moveRecord_firstElementPostProcess($table, $recordId, $destinationPid, array $movedRecord, array $updatedFields, DataHandler $dataHandler)
-    {
-        if ($table === 'pages' && $this->requiresUpdate($updatedFields)) {
-            $affectedPageUid = $recordId;
-            $affectedPageOldPid = $movedRecord['pid'];
-            $affectedPageNewPid = $updatedFields['pid'];
-            $clearCacheActions = $this->determineClearCacheActions('update', $updatedFields);
-            // Clear treelist entries for old parent page
-            $this->processClearCacheActions($affectedPageUid, $affectedPageOldPid, $updatedFields, $clearCacheActions);
-            // Clear treelist entries for new parent page
-            $this->processClearCacheActions($affectedPageUid, $affectedPageNewPid, $updatedFields, $clearCacheActions);
-        }
-    }
-
-    /**
-     * Waits for DataHandler commands and looks for moved pages, if found further
-     * changes take place to determine whether the cache needs to be updated
-     *
-     * @param string $table Table name of the moved record
-     * @param int $recordId The record's uid
-     * @param int $destinationPid The record's destination page id
-     * @param int $originalDestinationPid (negative) page id th page has been moved after
-     * @param array $movedRecord The record that moved
-     * @param array $updatedFields Array of changed fields
-     * @param DataHandler $dataHandler DataHandler parent object
-     */
-    public function moveRecord_afterAnotherElementPostProcess($table, $recordId, $destinationPid, $originalDestinationPid, array $movedRecord, array $updatedFields, DataHandler $dataHandler)
-    {
-        if ($table === 'pages' && $this->requiresUpdate($updatedFields)) {
-            $affectedPageUid = $recordId;
-            $affectedPageOldPid = $movedRecord['pid'];
-            $affectedPageNewPid = $updatedFields['pid'];
-            $clearCacheActions = $this->determineClearCacheActions('update', $updatedFields);
-            // Clear treelist entries for old parent page
-            $this->processClearCacheActions($affectedPageUid, $affectedPageOldPid, $updatedFields, $clearCacheActions);
-            // Clear treelist entries for new parent page
-            $this->processClearCacheActions($affectedPageUid, $affectedPageNewPid, $updatedFields, $clearCacheActions);
-        }
-    }
-
-    /**
-     * Checks whether the change requires an update of the treelist cache
-     *
-     * @param array $updatedFields Array of changed fields
-     * @return bool TRUE if the treelist cache needs to be updated, FALSE if no update to the cache is required
-     */
-    protected function requiresUpdate(array $updatedFields)
-    {
-        $requiresUpdate = false;
-        $updatedFieldNames = array_keys($updatedFields);
-        foreach ($updatedFieldNames as $updatedFieldName) {
-            if (in_array($updatedFieldName, $this->updateRequiringFields, true)) {
-                $requiresUpdate = true;
-                break;
-            }
-        }
-        return $requiresUpdate;
-    }
-
-    /**
-     * Calls the cache maintenance functions according to the determined actions
-     *
-     * @param int $affectedPage uid of the affected page
-     * @param int $affectedParentPage parent uid of the affected page
-     * @param array $updatedFields Array of updated fields and their new values
-     * @param array $actions Array of actions to carry out
-     */
-    protected function processClearCacheActions($affectedPage, $affectedParentPage, $updatedFields, array $actions)
-    {
-        $actionNames = array_keys($actions);
-        foreach ($actionNames as $actionName) {
-            switch ($actionName) {
-                case 'allParents':
-                    $this->clearCacheForAllParents($affectedParentPage);
-                    break;
-                case 'setExpiration':
-                    // Only used when setting an end time for a page
-                    $expirationTime = $updatedFields['endtime'];
-                    $this->setCacheExpiration($affectedPage, $expirationTime);
-                    break;
-                case 'uidInTreelist':
-                    $this->clearCacheWhereUidInTreelist($affectedPage);
-                    break;
-            }
-        }
-        // From time to time clean the cache from expired entries
-        // (theoretically every 1000 calls)
-        $randomNumber = random_int(1, 1000);
-        if ($randomNumber === 500) {
-            $this->removeExpiredCacheEntries();
-        }
-    }
-
-    /**
-     * Clears the treelist cache for all parents of a changed page.
-     * gets called after creating a new page and after moving a page
-     *
-     * @param int $affectedParentPage Parent page id of the changed page, the page to start clearing from
-     */
-    protected function clearCacheForAllParents($affectedParentPage)
-    {
-        $rootLine = BackendUtility::BEgetRootLine($affectedParentPage);
-        $rootLineIds = [];
-        foreach ($rootLine as $page) {
-            if ($page['uid'] != 0) {
-                $rootLineIds[] = $page['uid'];
-            }
-        }
-        if (!empty($rootLineIds)) {
-            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-                ->getQueryBuilderForTable('cache_treelist');
-            $queryBuilder
-                ->delete('cache_treelist')
-                ->where(
-                    $queryBuilder->expr()->in(
-                        'pid',
-                        $queryBuilder->createNamedParameter($rootLineIds, Connection::PARAM_INT_ARRAY)
-                    )
-                )
-                ->executeStatement();
-        }
-    }
-
-    /**
-     * Clears the treelist cache for all pages where the affected page is found
-     * in the treelist
-     *
-     * @param int $affectedPage ID of the changed page
-     */
-    protected function clearCacheWhereUidInTreelist($affectedPage)
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getQueryBuilderForTable('cache_treelist');
-        $queryBuilder
-            ->delete('cache_treelist')
-            ->where(
-                $queryBuilder->expr()->inSet('treelist', $queryBuilder->quote((string)$affectedPage))
-            )
-            ->executeStatement();
-    }
-
-    /**
-     * Sets an expiration time for all cache entries having the changed page in
-     * the treelist.
-     *
-     * @param int $affectedPage Uid of the changed page
-     * @param int $expirationTime
-     */
-    protected function setCacheExpiration($affectedPage, $expirationTime)
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getQueryBuilderForTable('cache_treelist');
-        $queryBuilder
-            ->update('cache_treelist')
-            ->where(
-                $queryBuilder->expr()->inSet('treelist', $queryBuilder->quote((string)$affectedPage))
-            )
-            ->set('expires', $expirationTime)
-            ->executeStatement();
-    }
-
-    /**
-     * Removes all expired treelist cache entries
-     */
-    protected function removeExpiredCacheEntries()
-    {
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getQueryBuilderForTable('cache_treelist');
-        $queryBuilder
-            ->delete('cache_treelist')
-            ->where(
-                $queryBuilder->expr()->lte(
-                    'expires',
-                    $queryBuilder->createNamedParameter($GLOBALS['EXEC_TIME'], Connection::PARAM_INT)
-                )
-            )
-            ->executeStatement();
-    }
-
-    /**
-     * Determines what happened to the page record, this is necessary to clear
-     * as less cache entries as needed later
-     *
-     * @param string $status DataHandler operation status, either 'new' or 'update'
-     * @param array $updatedFields Array of updated fields
-     * @return array List of actions that happened to the page record
-     */
-    protected function determineClearCacheActions($status, $updatedFields): array
-    {
-        $actions = [];
-        if ($status === 'new') {
-            // New page
-            $actions['allParents'] = true;
-        } elseif ($status === 'update') {
-            $updatedFieldNames = array_keys($updatedFields);
-            foreach ($updatedFieldNames as $updatedFieldName) {
-                switch ($updatedFieldName) {
-                    case 'pid':
-
-                    case $GLOBALS['TCA']['pages']['ctrl']['enablecolumns']['disabled']:
-
-                    case $GLOBALS['TCA']['pages']['ctrl']['delete']:
-
-                    case $GLOBALS['TCA']['pages']['ctrl']['enablecolumns']['starttime']:
-
-                    case $GLOBALS['TCA']['pages']['ctrl']['enablecolumns']['fe_group']:
-
-                    case 'extendToSubpages':
-
-                    case 't3ver_wsid':
-
-                    case 'php_tree_stop':
-                        // php_tree_stop
-                        $actions['allParents'] = true;
-                        $actions['uidInTreelist'] = true;
-                        break;
-                    case $GLOBALS['TCA']['pages']['ctrl']['enablecolumns']['endtime']:
-                        // end time set/unset
-                        // When setting an end time the cache entry needs an
-                        // expiration time. When unsetting the end time the
-                        // page must become listed in the treelist again.
-                        if ($updatedFields['endtime'] > 0) {
-                            $actions['setExpiration'] = true;
-                        } else {
-                            $actions['uidInTreelist'] = true;
-                        }
-                        break;
-                    default:
-                        if (in_array($updatedFieldName, $this->updateRequiringFields, true)) {
-                            $actions['uidInTreelist'] = true;
-                        }
-                }
-            }
-        }
-        return $actions;
-    }
-}
diff --git a/typo3/sysext/frontend/ext_localconf.php b/typo3/sysext/frontend/ext_localconf.php
index b2262a2217a9..f9bd7646d84f 100644
--- a/typo3/sysext/frontend/ext_localconf.php
+++ b/typo3/sysext/frontend/ext_localconf.php
@@ -4,7 +4,6 @@ declare(strict_types=1);
 
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Frontend\Controller\ShowImageController;
-use TYPO3\CMS\Frontend\Hooks\TreelistCacheUpdateHooks;
 
 defined('TYPO3') or die();
 
@@ -41,10 +40,5 @@ tt_content {
     '
 );
 
-// Registering hooks for the tree list cache
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass'][] = TreelistCacheUpdateHooks::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass'][] = TreelistCacheUpdateHooks::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['moveRecordClass'][] = TreelistCacheUpdateHooks::class;
-
 // Register search key shortcuts
 $GLOBALS['TYPO3_CONF_VARS']['SYS']['livesearch']['content'] = 'tt_content';
diff --git a/typo3/sysext/frontend/ext_tables.sql b/typo3/sysext/frontend/ext_tables.sql
index 022aba727575..54c9a88c70f7 100644
--- a/typo3/sysext/frontend/ext_tables.sql
+++ b/typo3/sysext/frontend/ext_tables.sql
@@ -1,16 +1,3 @@
-#
-# Table structure for table 'cache_treelist'
-#
-CREATE TABLE cache_treelist (
-	md5hash char(32) DEFAULT '' NOT NULL,
-	pid int(11) DEFAULT '0' NOT NULL,
-	treelist mediumtext,
-	tstamp int(11) DEFAULT '0' NOT NULL,
-	expires int(11) unsigned  DEFAULT '0' NOT NULL,
-
-	PRIMARY KEY (md5hash)
-) ENGINE=InnoDB;
-
 #
 # Table structure for table 'fe_groups'
 #
diff --git a/typo3/sysext/install/Classes/Service/ClearCacheService.php b/typo3/sysext/install/Classes/Service/ClearCacheService.php
index ed073dbc652a..3adfce909387 100644
--- a/typo3/sysext/install/Classes/Service/ClearCacheService.php
+++ b/typo3/sysext/install/Classes/Service/ClearCacheService.php
@@ -17,9 +17,7 @@ namespace TYPO3\CMS\Install\Service;
 
 use TYPO3\CMS\Core\Cache\CacheManager;
 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\DependencyInjection\Cache\ContainerBackend;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Basic service to clear caches within the install tool.
@@ -27,10 +25,6 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class ClearCacheService
 {
-    private const legacyDatabaseCacheTables = [
-        'cache_treelist',
-    ];
-
     public function __construct(
         private readonly LateBootService $lateBootService,
         private readonly FrontendInterface $dependencyInjectionCache
@@ -41,7 +35,7 @@ class ClearCacheService
      * Goal is to reliably get rid of cache entries, even if some broken
      * extension is loaded that would kill the backend 'clear cache' action.
      *
-     * Therefore this method "knows" implementation details of the cache
+     * Therefore, this method "knows" implementation details of the cache
      * framework and uses them to clear all file based cache (typo3temp/Cache)
      * and database caches (tables prefixed with cf_) manually.
      *
@@ -51,15 +45,6 @@ class ClearCacheService
      */
     public function clearAll(): void
     {
-        // Low level flush of legacy database cache tables
-        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
-        foreach (self::legacyDatabaseCacheTables as $tableName) {
-            $connection = $connectionPool->getConnectionForTable($tableName);
-            if ($connection->createSchemaManager()->tablesExist([$tableName])) {
-                $connection->truncate($tableName);
-            }
-        }
-
         // Flush all caches defined in TYPO3_CONF_VARS, but not the ones defined by extensions in ext_localconf.php
         $baseCaches = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] ?? [];
         $this->flushCaches($baseCaches);
-- 
GitLab