Skip to content

Commit 1f08478

Browse files
[HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup
1 parent f751ac9 commit 1f08478

File tree

6 files changed

+98
-30
lines changed

6 files changed

+98
-30
lines changed

UPGRADE-3.4.md

+3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ HttpKernel
143143
tags: ['console.command']
144144
```
145145
146+
* The `getCacheDir()` method of your kernel should not be called directly in your code.
147+
Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command.
148+
146149
Process
147150
-------
148151

UPGRADE-4.0.md

+3
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ HttpKernel
510510
by Symfony. Use the `%env()%` syntax to get the value of any environment
511511
variable from configuration files instead.
512512

513+
* The `getCacheDir()` method of your kernel should not be called directly in your code.
514+
Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command.
515+
513516
Ldap
514517
----
515518

src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

+38-20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Filesystem\Filesystem;
2020
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
2121
use Symfony\Component\HttpKernel\KernelInterface;
22+
use Symfony\Component\HttpKernel\RebootableInterface;
2223
use Symfony\Component\Finder\Finder;
2324

2425
/**
@@ -33,6 +34,7 @@ class CacheClearCommand extends ContainerAwareCommand
3334
{
3435
private $cacheClearer;
3536
private $filesystem;
37+
private $warning;
3638

3739
/**
3840
* @param CacheClearerInterface $cacheClearer
@@ -112,6 +114,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
112114
$this->filesystem->rename($realCacheDir, $oldCacheDir);
113115
} else {
114116
$this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
117+
118+
if ($this->warning) {
119+
@trigger_error($this->warning, E_USER_DEPRECATED);
120+
$io->warning($this->warning);
121+
$this->warning = null;
122+
}
115123
}
116124

117125
if ($output->isVerbose()) {
@@ -167,17 +175,23 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
167175
{
168176
// create a temporary kernel
169177
$realKernel = $this->getApplication()->getKernel();
170-
$realKernelClass = get_class($realKernel);
171-
$namespace = '';
172-
if (false !== $pos = strrpos($realKernelClass, '\\')) {
173-
$namespace = substr($realKernelClass, 0, $pos);
174-
$realKernelClass = substr($realKernelClass, $pos + 1);
175-
}
176-
$tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir);
177-
$tempKernel->boot();
178+
if ($realKernel instanceof RebootableInterface) {
179+
$realKernel->reboot($warmupDir);
180+
$tempKernel = $realKernel;
181+
} else {
182+
$this->warning = 'Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is deprecated since version 3.4 and will be unsupported in 4.0.';
183+
$realKernelClass = get_class($realKernel);
184+
$namespace = '';
185+
if (false !== $pos = strrpos($realKernelClass, '\\')) {
186+
$namespace = substr($realKernelClass, 0, $pos);
187+
$realKernelClass = substr($realKernelClass, $pos + 1);
188+
}
189+
$tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir);
190+
$tempKernel->boot();
178191

179-
$tempKernelReflection = new \ReflectionObject($tempKernel);
180-
$tempKernelFile = $tempKernelReflection->getFileName();
192+
$tempKernelReflection = new \ReflectionObject($tempKernel);
193+
$tempKernelFile = $tempKernelReflection->getFileName();
194+
}
181195

182196
// warmup temporary dir
183197
$warmer = $tempKernel->getContainer()->get('cache_warmer');
@@ -186,6 +200,20 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
186200
}
187201
$warmer->warmUp($warmupDir);
188202

203+
// fix references to cached files with the real cache directory name
204+
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
205+
$replace = str_replace('\\', '/', $realCacheDir);
206+
foreach (Finder::create()->files()->in($warmupDir) as $file) {
207+
$content = str_replace($search, $replace, file_get_contents($file), $count);
208+
if ($count) {
209+
file_put_contents($file, $content);
210+
}
211+
}
212+
213+
if ($realKernel instanceof RebootableInterface) {
214+
return;
215+
}
216+
189217
// fix references to the Kernel in .meta files
190218
$safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel));
191219
$realKernelFQN = get_class($realKernel);
@@ -198,16 +226,6 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
198226
));
199227
}
200228

201-
// fix references to cached files with the real cache directory name
202-
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
203-
$replace = str_replace('\\', '/', $realCacheDir);
204-
foreach (Finder::create()->files()->in($warmupDir) as $file) {
205-
$content = str_replace($search, $replace, file_get_contents($file), $count);
206-
if ($count) {
207-
file_put_contents($file, $content);
208-
}
209-
}
210-
211229
// fix references to container's class
212230
$tempContainerClass = $tempKernel->getContainerClass();
213231
$realContainerClass = $tempKernel->getRealContainerClass();

src/Symfony/Component/HttpKernel/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
3.4.0
55
-----
66

7+
* added `RebootableInterface` and implemented it in `Kernel`
78
* deprecated commands auto registration
89
* added `AddCacheClearerPass`
910
* added `AddCacheWarmerPass`

src/Symfony/Component/HttpKernel/Kernel.php

+23-10
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
*
4444
* @author Fabien Potencier <fabien@symfony.com>
4545
*/
46-
abstract class Kernel implements KernelInterface, TerminableInterface
46+
abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface
4747
{
4848
/**
4949
* @var BundleInterface[]
@@ -61,6 +61,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
6161
protected $loadClassCache;
6262

6363
private $projectDir;
64+
private $warmupDir;
6465

6566
const VERSION = '3.4.0-DEV';
6667
const VERSION_ID = 30400;
@@ -127,6 +128,16 @@ public function boot()
127128
$this->booted = true;
128129
}
129130

131+
/**
132+
* {@inheritdoc}
133+
*/
134+
public function reboot($warmupDir)
135+
{
136+
$this->shutdown();
137+
$this->warmupDir = $warmupDir;
138+
$this->boot();
139+
}
140+
130141
/**
131142
* {@inheritdoc}
132143
*/
@@ -373,15 +384,15 @@ public function setClassCache(array $classes)
373384
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
374385
}
375386

376-
file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
387+
file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
377388
}
378389

379390
/**
380391
* @internal
381392
*/
382393
public function setAnnotatedClassCache(array $annotatedClasses)
383394
{
384-
file_put_contents($this->getCacheDir().'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true)));
395+
file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true)));
385396
}
386397

387398
/**
@@ -424,9 +435,10 @@ protected function doLoadClassCache($name, $extension)
424435
if (\PHP_VERSION_ID >= 70000) {
425436
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
426437
}
438+
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
427439

428-
if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
429-
ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
440+
if (!$this->booted && is_file($cacheDir.'/classes.map')) {
441+
ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension);
430442
}
431443
}
432444

@@ -536,7 +548,8 @@ protected function getContainerBaseClass()
536548
protected function initializeContainer()
537549
{
538550
$class = $this->getContainerClass();
539-
$cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
551+
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
552+
$cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug);
540553
$fresh = true;
541554
if (!$cache->isFresh()) {
542555
if ($this->debug) {
@@ -580,8 +593,8 @@ protected function initializeContainer()
580593
if ($this->debug) {
581594
restore_error_handler();
582595

583-
file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
584-
file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
596+
file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
597+
file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
585598
}
586599
}
587600

@@ -636,7 +649,7 @@ protected function getKernelParameters()
636649
'kernel.environment' => $this->environment,
637650
'kernel.debug' => $this->debug,
638651
'kernel.name' => $this->name,
639-
'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
652+
'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir,
640653
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
641654
'kernel.bundles' => $bundles,
642655
'kernel.bundles_metadata' => $bundlesMetadata,
@@ -682,7 +695,7 @@ protected function getEnvParameters()
682695
*/
683696
protected function buildContainer()
684697
{
685-
foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
698+
foreach (array('cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
686699
if (!is_dir($dir)) {
687700
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
688701
throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel;
13+
14+
/**
15+
* Rebotable extends the Kernel to allow it to reboot using a temporary cache directory.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
interface RebootableInterface
20+
{
21+
/**
22+
* Reboots a kernel.
23+
*
24+
* The getCacheDir() method of a rebootable kernel should not be called
25+
* in your code. Use the %kernel.cache_dir% parameter instead.
26+
*
27+
* @param string|null $warmupDir
28+
*/
29+
public function reboot($warmupDir);
30+
}

0 commit comments

Comments
 (0)