Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
CacheClearCommand
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
4 / 4
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 clearDirectory
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
9
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Console\Command;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use Symfony\Component\Console\Command\Command;
12use Symfony\Component\Console\Input\InputInterface;
13use Symfony\Component\Console\Output\OutputInterface;
14
15/**
16 * Cache Clear Console Command.
17 *
18 * Clears runtime metadata cache, translation file cache, and compiled Twig
19 * template cache. Also invalidates OPcache entries for cleared translation files.
20 *
21 * @package App\Core\Console\Command
22 */
23final class CacheClearCommand extends Command
24{
25    /** @var string Command name identifier. */
26    private const COMMAND_NAME = 'cache:clear';
27
28    /**
29     * CacheClearCommand constructor.
30     *
31     * @param string $basePath Base application directory.
32     */
33    public function __construct(private readonly string $basePath)
34    {
35        parent::__construct(self::COMMAND_NAME);
36    }
37
38    /** {@inheritdoc} */
39    protected function configure(): void
40    {
41        $this->setDescription('Clears runtime metadata, translations, Twig template and file caches.');
42    }
43
44    /** {@inheritdoc} */
45    protected function execute(InputInterface $input, OutputInterface $output): int
46    {
47        $cleared = 0;
48        $cleared += $this->clearDirectory($this->basePath . '/storage/runtime/cache', $output, 'runtime', true);
49        $cleared += $this->clearDirectory($this->basePath . '/storage/cache/translations', $output, 'translations');
50        $cleared += $this->clearDirectory($this->basePath . '/storage/cache/twig', $output, 'twig', true);
51
52        $output->writeln(sprintf('<info>Cache cleared: %d files removed across all cache stores.</info>', $cleared));
53        return Command::SUCCESS;
54    }
55
56    /**
57     * Clears all files in a given cache directory.
58     *
59     * @param string          $directory   Absolute path to cache directory.
60     * @param OutputInterface $output      Console output instance.
61     * @param string          $label       Human-readable label for output messages.
62     * @param bool            $recursive   Whether to delete recursively (for Twig sub-dirs).
63     * @return int Number of files removed.
64     */
65    private function clearDirectory(
66        string $directory,
67        OutputInterface $output,
68        string $label,
69        bool $recursive = false
70    ): int {
71        if (!is_dir($directory)) {
72            $output->writeln(sprintf('<comment>%s cache directory not found, skipping.</comment>', ucfirst($label)));
73            return 0;
74        }
75
76        $count = 0;
77        $pattern = $recursive ? $directory . '/**' : $directory . '/*';
78        $files = (array)glob($pattern, GLOB_BRACE);
79
80        foreach ($files as $file) {
81            $filePath = (string)$file;
82            if (is_file($filePath)) {
83                if (unlink($filePath)) {
84                    $count++;
85                    if (function_exists('opcache_invalidate')) {
86                        opcache_invalidate($filePath, true);
87                    }
88                }
89            } elseif ($recursive && is_dir($filePath)) {
90                $count += $this->clearDirectory($filePath, $output, $label, true);
91                rmdir($filePath);
92            }
93        }
94
95        $output->writeln(sprintf('<info>%s cache cleared: %d files removed.</info>', ucfirst($label), $count));
96        return $count;
97    }
98}