diff --git a/Classes/Compatibility/TYPO3v87/Service/CacheLowLevelCleaner.php b/Classes/Compatibility/TYPO3v87/Service/CacheLowLevelCleaner.php
index b7cc7c917..d10aeb02f 100644
--- a/Classes/Compatibility/TYPO3v87/Service/CacheLowLevelCleaner.php
+++ b/Classes/Compatibility/TYPO3v87/Service/CacheLowLevelCleaner.php
@@ -45,7 +45,7 @@ public function forceFlushDatabaseCacheTables()
$connection->truncate($tableName);
}
}
- // check tables on other connections
+ // Check tables on other connections
$remappedTables = isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
? array_keys((array)$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
: [];
diff --git a/Classes/Console/Command/Cache/CacheFlushCommand.php b/Classes/Console/Command/Cache/CacheFlushCommand.php
new file mode 100644
index 000000000..4ed9dbe99
--- /dev/null
+++ b/Classes/Console/Command/Cache/CacheFlushCommand.php
@@ -0,0 +1,126 @@
+setDescription('Flush all caches');
+ $this->setHelp(
+ <<<'EOH'
+Flushes TYPO3 core caches first and after that, flushes caches from extensions.
+EOH
+ );
+
+ $this->setDefinition($this->createCompleteInputDefinition());
+ }
+
+ protected function createNativeDefinition(): array
+ {
+ return [
+ new InputOption(
+ 'files-only',
+ null,
+ InputOption::VALUE_NONE,
+ 'Only file caches are flushed'
+ ),
+ ];
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $filesOnly = $input->getOption('files-only');
+ $application = $this->getApplication();
+ if (!$application instanceof Application) {
+ throw new \RuntimeException('Fatal error. Application is not properly initialized.', 1546617606);
+ }
+ $filesOnly = $filesOnly || !$application->isFullyCapable();
+
+ $io = new SymfonyStyle($input, $output);
+
+ $lowLevelCleaner = new CacheLowLevelCleaner();
+ $lowLevelCleaner->forceFlushCachesFiles();
+ if ($filesOnly) {
+ $io->writeln('Flushed all file caches.');
+ // No need to proceed, as files only flush is requested
+ return;
+ }
+
+ $lowLevelCleaner->forceFlushDatabaseCacheTables();
+ $application->boot(RunLevel::LEVEL_FULL);
+
+ $cacheService = new CacheService();
+ $cacheService->flush();
+ $cacheService->flushCachesWithDataHandler();
+
+ $io->writeln('Flushed all caches.');
+ }
+
+ /**
+ * @deprecated will be removed with 6.0
+ *
+ * @return array
+ */
+ protected function createDeprecatedDefinition(): array
+ {
+ return [
+ new InputOption(
+ 'force',
+ null,
+ InputOption::VALUE_NONE,
+ 'Cache is forcibly flushed (low level operations are performed)'
+ ),
+ new InputArgument(
+ 'force',
+ null,
+ 'Cache is forcibly flushed (low level operations are performed)',
+ false
+ ),
+ new InputArgument(
+ 'filesOnly',
+ null,
+ 'Only file caches are flushed',
+ false
+ ),
+ ];
+ }
+
+ /**
+ * @deprecated will be removed with 6.0
+ */
+ protected function handleDeprecatedArgumentsAndOptions(InputInterface $input, OutputInterface $output)
+ {
+ if ($input->getArgument('force')
+ || $input->getArgument('filesOnly')
+ || $input->getOption('files-only')
+ || $input->getOption('force')
+ ) {
+ $io = new SymfonyStyle($input, $output);
+ $io->getErrorStyle()->writeln('All options and arguments are deprecated and have no effect any more.');
+ }
+ }
+}
diff --git a/Classes/Console/Command/CacheCommandController.php b/Classes/Console/Command/CacheCommandController.php
index dce799e0e..7d7f301be 100644
--- a/Classes/Console/Command/CacheCommandController.php
+++ b/Classes/Console/Command/CacheCommandController.php
@@ -14,8 +14,6 @@
*
*/
-use Helhum\Typo3Console\Mvc\Cli\CommandDispatcher;
-use Helhum\Typo3Console\Mvc\Cli\FailedSubProcessCommandException;
use Helhum\Typo3Console\Mvc\Controller\CommandController;
use Helhum\Typo3Console\Service\CacheService;
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException;
@@ -30,86 +28,9 @@ class CacheCommandController extends CommandController
*/
private $cacheService;
- /**
- * @var CommandDispatcher
- */
- private $commandDispatcher;
-
- /**
- * @param CacheService $cacheService
- * @param CommandDispatcher $commandDispatcher
- */
- public function __construct(CacheService $cacheService, CommandDispatcher $commandDispatcher = null)
+ public function __construct(CacheService $cacheService)
{
$this->cacheService = $cacheService;
- $this->commandDispatcher = $commandDispatcher ?: CommandDispatcher::createFromCommandRun();
- }
-
- /**
- * Flush all caches
- *
- * Flushes TYPO3 core caches first and after that, flushes caches from extensions.
- *
- * @param bool $force Cache is forcibly flushed (low level operations are performed)
- * @param bool $filesOnly Only file caches are flushed
- * @throws FailedSubProcessCommandException
- */
- public function flushCommand($force = false, $filesOnly = false)
- {
- $exitCode = 0;
- $isApplicationFullyCapable = $this->isApplicationFullyCapable();
- if (!$isApplicationFullyCapable) {
- $filesOnly = true;
- }
- if ($filesOnly) {
- $this->cacheService->flushFileCaches($force);
- try {
- $this->commandDispatcher->executeCommand('cache:flushcomplete', ['--files-only']);
- } catch (FailedSubProcessCommandException $e) {
- if ($isApplicationFullyCapable) {
- throw $e;
- }
- $this->output->getSymfonyConsoleOutput()->getErrorOutput()->writeln('Could not load extension configuration.');
- $this->output->getSymfonyConsoleOutput()->getErrorOutput()->writeln('Some caches might not have been flushed.');
- }
- } else {
- $this->cacheService->flush($force);
- $this->commandDispatcher->executeCommand('cache:flushcomplete');
- }
-
- $this->outputLine('%slushed all %scaches.', [$force ? 'Force f' : 'F', $filesOnly ? 'file ' : '']);
- $this->quit($exitCode);
- }
-
- /**
- * Check if we have all mandatory files to assume we have a fully configured / installed TYPO3
- *
- * @return bool
- * @deprecated can be removed once this is converted into a native Symfony command. We can use the Application API then.
- */
- private function isApplicationFullyCapable(): bool
- {
- return file_exists(PATH_site . 'typo3conf/PackageStates.php') && file_exists(PATH_site . 'typo3conf/LocalConfiguration.php');
- }
-
- /**
- * Called only internally in a sub process of the cache:flush command
- *
- * This command will then use the full TYPO3 bootstrap.
- *
- * @param bool $filesOnly Only file caches are flushed
- * @internal
- */
- public function flushCompleteCommand($filesOnly = false)
- {
- // Flush a second time to have extension caches and previously disabled core caches cleared when clearing not forced
- if ($filesOnly) {
- $this->cacheService->flushFileCaches();
- } else {
- $this->cacheService->flush();
- // Also call the data handler API to cover legacy hook subscriber code
- $this->cacheService->flushCachesWithDataHandler();
- }
}
/**
@@ -118,7 +39,6 @@ public function flushCompleteCommand($filesOnly = false)
* Flushes all caches in specified groups.
* Valid group names are by default:
*
- * - all
* - lowlevel
* - pages
* - system
@@ -175,7 +95,7 @@ public function listGroupsCommand()
switch (count($groups)) {
case 0:
- $this->outputLine('No cache group is registered.');
+ $this->outputLine('No cache groups are registered.');
break;
case 1:
$this->outputLine('The following cache group is registered: "' . implode('", "', $groups) . '".');
diff --git a/Classes/Console/Mvc/Cli/Symfony/Application.php b/Classes/Console/Mvc/Cli/Symfony/Application.php
index 2a46358d9..3f98a05f0 100644
--- a/Classes/Console/Mvc/Cli/Symfony/Application.php
+++ b/Classes/Console/Mvc/Cli/Symfony/Application.php
@@ -15,6 +15,7 @@
*/
use Helhum\Typo3Console\Core\Booting\RunLevel;
+use Helhum\Typo3Console\Core\Booting\StepFailedException;
use Helhum\Typo3Console\Error\ExceptionRenderer;
use Helhum\Typo3Console\Exception\CommandNotAvailableException;
use Helhum\Typo3Console\Mvc\Cli\Symfony\Command\HelpCommand;
@@ -79,6 +80,15 @@ public function hasErrors(): bool
return $this->runLevel->getError() !== null;
}
+ /**
+ * @param string $runLevel
+ * @throws StepFailedException
+ */
+ public function boot(string $runLevel)
+ {
+ $this->runLevel->runSequence($runLevel);
+ }
+
/**
* Whether this application is composer managed.
* Can be used to enable or disable commands or arguments/ options
diff --git a/Classes/Console/Service/CacheLowLevelCleaner.php b/Classes/Console/Service/CacheLowLevelCleaner.php
index 58ec0d6f0..c45126b60 100644
--- a/Classes/Console/Service/CacheLowLevelCleaner.php
+++ b/Classes/Console/Service/CacheLowLevelCleaner.php
@@ -28,8 +28,7 @@ class CacheLowLevelCleaner
*/
public function forceFlushCachesFiles()
{
- // Delete typo3temp/Cache
- GeneralUtility::flushDirectory(Environment::getVarPath() . '/cache', true, true);
+ GeneralUtility::flushDirectory(Environment::getVarPath() . '/cache', true);
}
/**
@@ -46,7 +45,7 @@ public function forceFlushDatabaseCacheTables()
$connection->truncate($tableName);
}
}
- // check tables on other connections
+ // Check tables on other connections
$remappedTables = isset($GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
? array_keys((array)$GLOBALS['TYPO3_CONF_VARS']['DB']['TableMapping'])
: [];
diff --git a/Classes/Console/Service/CacheService.php b/Classes/Console/Service/CacheService.php
index 36803243b..49e6cbbd0 100644
--- a/Classes/Console/Service/CacheService.php
+++ b/Classes/Console/Service/CacheService.php
@@ -14,16 +14,8 @@
*
*/
-use Helhum\Typo3Console\Core\Booting\CompatibilityScripts;
-use Helhum\Typo3Console\Core\Booting\Scripts;
-use Helhum\Typo3Console\Service\Configuration\ConfigurationService;
-use Symfony\Component\Console\Exception\RuntimeException;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheGroupException;
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -39,67 +31,28 @@ class CacheService implements SingletonInterface
protected $cacheManager;
/**
- * @var ConfigurationService
+ * @var array
*/
- protected $configurationService;
+ protected $cacheConfiguration;
- /**
- * @var Bootstrap
- */
- private $bootstrap;
-
- /**
- * @var CacheLowLevelCleaner
- */
- private $lowLevelCleaner;
-
- /**
- * Builds the dependencies correctly
- *
- * @param ConfigurationService $configurationService
- */
- public function __construct(ConfigurationService $configurationService, Bootstrap $bootstrap = null, CacheLowLevelCleaner $lowLevelCleaner = null)
+ public function __construct()
{
// We need a new instance here to get the real caches instead of the disabled ones
$this->cacheManager = new CacheManager();
- $this->cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
- $this->configurationService = $configurationService;
- $this->bootstrap = $bootstrap ?: Bootstrap::getInstance();
- $this->lowLevelCleaner = $lowLevelCleaner ?: new CacheLowLevelCleaner();
+ $this->cacheConfiguration = $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'];
+ $this->cacheManager->setCacheConfigurations($this->cacheConfiguration);
}
/**
* Flushes all caches
- *
- * @param bool $force
*/
- public function flush($force = false)
+ public function flush()
{
- $this->ensureDatabaseIsInitialized();
- if ($force) {
- $this->lowLevelCleaner->forceFlushCachesFiles();
- $this->lowLevelCleaner->forceFlushDatabaseCacheTables();
- }
$this->cacheManager->flushCaches();
}
/**
- * Flushes all file based caches
- *
- * @param bool $force
- */
- public function flushFileCaches($force = false)
- {
- if ($force) {
- $this->lowLevelCleaner->forceFlushCachesFiles();
- }
- foreach ($this->getFileCaches() as $cache) {
- $cache->flush();
- }
- }
-
- /**
- * Flushes caches using the data handler. This should not be necessary any more in the future.
+ * Flushes caches using the data handler.
* Although we trigger the cache flush API here, the real intention is to trigger
* hook subscribers, so that they can do their job (flushing "other" caches when cache is flushed.
* For example realurl subscribes to these hooks.
@@ -111,18 +64,12 @@ public function flushFileCaches($force = false)
* However if you find a valid use case for us to also call "pages" here, then please create
* a pull request and describe this case. "system" or "temp_cached" will not be added however
* because these are deprecated since TYPO3 8.x
- *
- * Besides that, this DataHandler API is probably something to be removed in TYPO3,
- * so we deprecate and mark this method as internal at the same time.
- *
- * @deprecated Will be removed once DataHandler cache flush methods are removed in supported TYPO3 versions
- * @internal
*/
public function flushCachesWithDataHandler()
{
- $this->ensureDatabaseIsInitialized();
- $this->ensureBackendUserIsInitialized();
- self::createDataHandlerFromGlobals()->clear_cacheCmd('all');
+ $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
+ $dataHandler->start([], []);
+ $dataHandler->clear_cacheCmd('all');
}
/**
@@ -134,7 +81,6 @@ public function flushCachesWithDataHandler()
public function flushGroups(array $groups)
{
$this->ensureCacheGroupsExist($groups);
- $this->ensureDatabaseIsInitialized();
foreach ($groups as $group) {
$this->cacheManager->flushCachesInGroup($group);
}
@@ -148,7 +94,6 @@ public function flushGroups(array $groups)
*/
public function flushByTags(array $tags, $group = null)
{
- $this->ensureDatabaseIsInitialized();
foreach ($tags as $tag) {
if ($group === null) {
$this->cacheManager->flushCachesByTag($tag);
@@ -182,35 +127,13 @@ public function flushByTagsAndGroups(array $tags, array $groups = null)
public function getValidCacheGroups()
{
$validGroups = [];
- foreach ($this->configurationService->getActive('SYS/caching/cacheConfigurations') as $cacheConfiguration) {
+ foreach ($this->cacheConfiguration as $cacheConfiguration) {
if (isset($cacheConfiguration['groups']) && is_array($cacheConfiguration['groups'])) {
- $validGroups = array_merge($validGroups, $cacheConfiguration['groups']);
+ $validGroups[] = $cacheConfiguration['groups'];
}
}
- return array_unique($validGroups);
- }
-
- /**
- * @deprecated can be removed when TYPO3 8 support is removed
- */
- private function ensureDatabaseIsInitialized()
- {
- if (!empty($GLOBALS['TYPO3_DB'])) {
- // Already initialized
- return;
- }
- CompatibilityScripts::initializeDatabaseConnection($this->bootstrap);
- }
-
- private function ensureBackendUserIsInitialized()
- {
- if (!empty($GLOBALS['BE_USER'])) {
- // Already initialized
- return;
- }
- Scripts::initializePersistence($this->bootstrap);
- Scripts::initializeAuthenticatedOperations($this->bootstrap);
+ return array_unique(array_merge(...$validGroups));
}
/**
@@ -226,45 +149,4 @@ private function ensureCacheGroupsExist($groups)
throw new NoSuchCacheGroupException('Invalid cache groups "' . implode(', ', $invalidGroups) . '".', 1399630162);
}
}
-
- /**
- * @return FrontendInterface[]
- */
- private function getFileCaches()
- {
- $fileCaches = [];
- foreach ($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'] as $identifier => $cacheConfiguration) {
- if (
- isset($cacheConfiguration['backend'])
- && (
- $cacheConfiguration['backend'] === SimpleFileBackend::class
- || is_subclass_of($cacheConfiguration['backend'], SimpleFileBackend::class)
- )
- ) {
- $fileCaches[] = $this->cacheManager->getCache($identifier);
- }
- }
-
- return $fileCaches;
- }
-
- /**
- * Create a data handler instance from global state (with user being admin)
- *
- * @internal
- * @throws RuntimeException
- * @return DataHandler
- */
- private static function createDataHandlerFromGlobals()
- {
- if (empty($GLOBALS['BE_USER']) || !$GLOBALS['BE_USER'] instanceof BackendUserAuthentication) {
- throw new RuntimeException('No backend user initialized. flushCachesWithDataHandler needs fully initialized TYPO3', 1477066610);
- }
- $user = clone $GLOBALS['BE_USER'];
- $user->admin = 1;
- $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
- $dataHandler->start([], [], $user);
-
- return $dataHandler;
- }
}
diff --git a/Configuration/Commands.php b/Configuration/Commands.php
index 9c89d3d6d..f66adb4f2 100644
--- a/Configuration/Commands.php
+++ b/Configuration/Commands.php
@@ -56,20 +56,10 @@
],
'cache:flush' => [
'vendor' => 'typo3_console',
- 'class' => \Helhum\Typo3Console\Mvc\Cli\Symfony\Command\DummyCommand::class,
+ 'class' => \Helhum\Typo3Console\Command\Cache\CacheFlushCommand::class,
'schedulable' => false,
- 'controller' => \Helhum\Typo3Console\Command\CacheCommandController::class,
- 'controllerCommandName' => 'flush',
'runLevel' => \Helhum\Typo3Console\Core\Booting\RunLevel::LEVEL_COMPILE,
],
- 'cache:flushcomplete' => [
- 'vendor' => 'typo3_console',
- 'class' => \Helhum\Typo3Console\Mvc\Cli\Symfony\Command\DummyCommand::class,
- 'schedulable' => false,
- 'controller' => \Helhum\Typo3Console\Command\CacheCommandController::class,
- 'controllerCommandName' => 'flushComplete',
- 'runLevel' => \Helhum\Typo3Console\Core\Booting\RunLevel::LEVEL_MINIMAL,
- ],
'cache:flushgroups' => [
'vendor' => 'typo3_console',
'class' => \Helhum\Typo3Console\Mvc\Cli\Symfony\Command\DummyCommand::class,
diff --git a/Documentation/CommandReference/Index.rst b/Documentation/CommandReference/Index.rst
index 4dc90a902..6e1e38448 100644
--- a/Documentation/CommandReference/Index.rst
+++ b/Documentation/CommandReference/Index.rst
@@ -319,14 +319,6 @@ Flushes TYPO3 core caches first and after that, flushes caches from extensions.
Options
~~~~~~~
-`--force`
- Cache is forcibly flushed (low level operations are performed)
-
-- Accept value: no
-- Is value required: no
-- Is multiple: no
-- Default: false
-
`--files-only`
Only file caches are flushed
@@ -350,7 +342,6 @@ Options
Flushes all caches in specified groups.
Valid group names are by default:
-- all
- lowlevel
- pages
- system