Translated using Weblate (Portuguese)
[phpmyadmin.git] / src / Command / CacheWarmupCommand.php
blob66bcf72f0c16404414f7357bbbd62c3a0a619f84
1 <?php
3 declare(strict_types=1);
5 namespace PhpMyAdmin\Command;
7 use PhpMyAdmin\Config;
8 use PhpMyAdmin\DatabaseInterface;
9 use PhpMyAdmin\Routing\Routing;
10 use PhpMyAdmin\Template;
11 use PhpMyAdmin\Tests\Stubs\DbiDummy;
12 use RecursiveDirectoryIterator;
13 use RecursiveIteratorIterator;
14 use SplFileInfo;
15 use Symfony\Component\Console\Attribute\AsCommand;
16 use Symfony\Component\Console\Command\Command;
17 use Symfony\Component\Console\Input\InputArgument;
18 use Symfony\Component\Console\Input\InputInterface;
19 use Symfony\Component\Console\Output\OutputInterface;
20 use Twig\Cache\CacheInterface;
22 use function file_put_contents;
23 use function is_file;
24 use function json_encode;
25 use function sprintf;
26 use function str_contains;
27 use function str_replace;
29 use const CACHE_DIR;
30 use const CONFIG_FILE;
32 #[AsCommand(name: 'cache:warmup', description: 'Warms up the Twig templates cache.')]
33 final class CacheWarmupCommand extends Command
35 protected function configure(): void
37 $this->addOption('twig', null, null, 'Warm up twig templates cache.');
38 $this->addOption('routing', null, null, 'Warm up routing cache.');
39 $this->addOption('twig-po', null, null, 'Warm up twig templates and write file mappings.');
40 $this->addOption(
41 'env',
42 null,
43 InputArgument::OPTIONAL,
44 'Defines the environment (production or development) for twig warmup',
45 'production',
47 $this->setHelp('The <info>%command.name%</info> command warms up the cache of the Twig templates.');
50 protected function execute(InputInterface $input, OutputInterface $output): int
52 /** @var string $env */
53 $env = $input->getOption('env');
55 if ($input->getOption('twig') === true && $input->getOption('routing') === true) {
56 $output->writeln('Please specify --twig or --routing');
58 return Command::FAILURE;
61 if ($input->getOption('twig') === true) {
62 return $this->warmUpTwigCache($output, $env, false);
65 if ($input->getOption('twig-po') === true) {
66 return $this->warmUpTwigCache($output, $env, true);
69 if ($input->getOption('routing') === true) {
70 return $this->warmUpRoutingCache($output);
73 $output->writeln('Warming up all caches.', OutputInterface::VERBOSITY_VERBOSE);
74 $twigCode = $this->warmUpTwigCache($output, $env, false);
75 if ($twigCode !== 0) {
76 $output->writeln('Twig cache generation had an error.');
78 return $twigCode;
81 $routingCode = $this->warmUpRoutingCache($output);
82 if ($routingCode !== 0) {
83 $output->writeln('Routing cache generation had an error.');
85 return $twigCode;
88 $output->writeln('Warm up of all caches done.', OutputInterface::VERBOSITY_VERBOSE);
90 return Command::SUCCESS;
93 private function warmUpRoutingCache(OutputInterface $output): int
95 $output->writeln('Warming up the routing cache', OutputInterface::VERBOSITY_VERBOSE);
96 Routing::getDispatcher();
98 if (is_file(Routing::ROUTES_CACHE_FILE)) {
99 $output->writeln('Warm up done.', OutputInterface::VERBOSITY_VERBOSE);
101 return Command::SUCCESS;
104 $output->writeln(
105 sprintf(
106 'Warm up did not work, the folder "%s" is probably not writable.',
107 CACHE_DIR,
109 OutputInterface::VERBOSITY_NORMAL,
112 return Command::FAILURE;
115 private function warmUpTwigCache(
116 OutputInterface $output,
117 string $environment,
118 bool $writeReplacements,
119 ): int {
120 $output->writeln('Warming up the twig cache', OutputInterface::VERBOSITY_VERBOSE);
121 $config = Config::getInstance();
122 $config->loadAndCheck(CONFIG_FILE);
123 $config->settings['environment'] = $environment;
124 $config->set('environment', $config->settings['environment']);
125 DatabaseInterface::$instance = new DatabaseInterface(new DbiDummy());
126 $tmpDir = ROOT_PATH . 'twig-templates';
127 $twig = Template::getTwigEnvironment($tmpDir, $config->config->environment === 'development');
129 $output->writeln('Searching for files...', OutputInterface::VERBOSITY_VERY_VERBOSE);
131 $templates = new RecursiveIteratorIterator(
132 new RecursiveDirectoryIterator(Template::TEMPLATES_FOLDER),
133 RecursiveIteratorIterator::LEAVES_ONLY,
136 /** @var CacheInterface $twigCache */
137 $twigCache = $twig->getCache(false);
138 $replacements = [];
139 $output->writeln(
140 'Twig debug is: ' . ($twig->isDebug() ? 'enabled' : 'disabled'),
141 OutputInterface::VERBOSITY_DEBUG,
144 $output->writeln('Warming templates', OutputInterface::VERBOSITY_VERY_VERBOSE);
145 /** @var SplFileInfo $file */
146 foreach ($templates as $file) {
147 // Skip test files
148 if (str_contains($file->getPathname(), '/tests/')) {
149 continue;
152 // force compilation
153 if (! $file->isFile() || $file->getExtension() !== 'twig') {
154 continue;
157 $name = str_replace(Template::TEMPLATES_FOLDER . '/', '', $file->getPathname());
158 $output->writeln('Loading: ' . $name, OutputInterface::VERBOSITY_DEBUG);
159 /** @psalm-suppress InternalMethod */
160 $template = $twig->loadTemplate($twig->getTemplateClass($name), $name);
162 if (! $writeReplacements) {
163 continue;
166 // Generate line map
167 /** @psalm-suppress InternalMethod */
168 $cacheFilename = $twigCache->generateKey($name, $twig->getTemplateClass($name));
169 $templateFile = 'resources/templates/' . $name;
170 $cacheFile = str_replace($tmpDir, 'twig-templates', $cacheFilename);
171 /** @psalm-suppress InternalMethod */
172 $replacements[$cacheFile] = [$templateFile, $template->getDebugInfo()];
175 if (! $writeReplacements) {
176 $output->writeln('Warm up done.', OutputInterface::VERBOSITY_VERBOSE);
178 return Command::SUCCESS;
181 $output->writeln('Writing replacements...', OutputInterface::VERBOSITY_VERY_VERBOSE);
183 // Store replacements in JSON
184 if (file_put_contents($tmpDir . '/replace.json', (string) json_encode($replacements)) === false) {
185 return Command::FAILURE;
188 $output->writeln('Replacements written done.', OutputInterface::VERBOSITY_VERBOSE);
189 $output->writeln('Warm up done.', OutputInterface::VERBOSITY_VERBOSE);
191 return Command::SUCCESS;