[HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup
This commit is contained in:
parent
f751ac9ac1
commit
a4fc49294e
|
@ -143,6 +143,9 @@ HttpKernel
|
||||||
tags: ['console.command']
|
tags: ['console.command']
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* The `getCacheDir()` method of your kernel should not be called while building the container.
|
||||||
|
Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command.
|
||||||
|
|
||||||
Process
|
Process
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -510,6 +510,9 @@ HttpKernel
|
||||||
by Symfony. Use the `%env()%` syntax to get the value of any environment
|
by Symfony. Use the `%env()%` syntax to get the value of any environment
|
||||||
variable from configuration files instead.
|
variable from configuration files instead.
|
||||||
|
|
||||||
|
* The `getCacheDir()` method of your kernel should not be called while building the container.
|
||||||
|
Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command.
|
||||||
|
|
||||||
Ldap
|
Ldap
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\Filesystem\Filesystem;
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
|
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
|
||||||
use Symfony\Component\HttpKernel\KernelInterface;
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
|
use Symfony\Component\HttpKernel\RebootableInterface;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +34,7 @@ class CacheClearCommand extends ContainerAwareCommand
|
||||||
{
|
{
|
||||||
private $cacheClearer;
|
private $cacheClearer;
|
||||||
private $filesystem;
|
private $filesystem;
|
||||||
|
private $warning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CacheClearerInterface $cacheClearer
|
* @param CacheClearerInterface $cacheClearer
|
||||||
|
@ -112,6 +114,12 @@ EOF
|
||||||
$this->filesystem->rename($realCacheDir, $oldCacheDir);
|
$this->filesystem->rename($realCacheDir, $oldCacheDir);
|
||||||
} else {
|
} else {
|
||||||
$this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
|
$this->warmupCache($input, $output, $realCacheDir, $oldCacheDir);
|
||||||
|
|
||||||
|
if ($this->warning) {
|
||||||
|
@trigger_error($this->warning, E_USER_DEPRECATED);
|
||||||
|
$io->warning($this->warning);
|
||||||
|
$this->warning = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($output->isVerbose()) {
|
if ($output->isVerbose()) {
|
||||||
|
@ -167,17 +175,23 @@ EOF
|
||||||
{
|
{
|
||||||
// create a temporary kernel
|
// create a temporary kernel
|
||||||
$realKernel = $this->getApplication()->getKernel();
|
$realKernel = $this->getApplication()->getKernel();
|
||||||
$realKernelClass = get_class($realKernel);
|
if ($realKernel instanceof RebootableInterface) {
|
||||||
$namespace = '';
|
$realKernel->reboot($warmupDir);
|
||||||
if (false !== $pos = strrpos($realKernelClass, '\\')) {
|
$tempKernel = $realKernel;
|
||||||
$namespace = substr($realKernelClass, 0, $pos);
|
} else {
|
||||||
$realKernelClass = substr($realKernelClass, $pos + 1);
|
$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.';
|
||||||
}
|
$realKernelClass = get_class($realKernel);
|
||||||
$tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir);
|
$namespace = '';
|
||||||
$tempKernel->boot();
|
if (false !== $pos = strrpos($realKernelClass, '\\')) {
|
||||||
|
$namespace = substr($realKernelClass, 0, $pos);
|
||||||
|
$realKernelClass = substr($realKernelClass, $pos + 1);
|
||||||
|
}
|
||||||
|
$tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir);
|
||||||
|
$tempKernel->boot();
|
||||||
|
|
||||||
$tempKernelReflection = new \ReflectionObject($tempKernel);
|
$tempKernelReflection = new \ReflectionObject($tempKernel);
|
||||||
$tempKernelFile = $tempKernelReflection->getFileName();
|
$tempKernelFile = $tempKernelReflection->getFileName();
|
||||||
|
}
|
||||||
|
|
||||||
// warmup temporary dir
|
// warmup temporary dir
|
||||||
$warmer = $tempKernel->getContainer()->get('cache_warmer');
|
$warmer = $tempKernel->getContainer()->get('cache_warmer');
|
||||||
|
@ -186,6 +200,20 @@ EOF
|
||||||
}
|
}
|
||||||
$warmer->warmUp($warmupDir);
|
$warmer->warmUp($warmupDir);
|
||||||
|
|
||||||
|
// fix references to cached files with the real cache directory name
|
||||||
|
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
|
||||||
|
$replace = str_replace('\\', '/', $realCacheDir);
|
||||||
|
foreach (Finder::create()->files()->in($warmupDir) as $file) {
|
||||||
|
$content = str_replace($search, $replace, file_get_contents($file), $count);
|
||||||
|
if ($count) {
|
||||||
|
file_put_contents($file, $content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($realKernel instanceof RebootableInterface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// fix references to the Kernel in .meta files
|
// fix references to the Kernel in .meta files
|
||||||
$safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel));
|
$safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel));
|
||||||
$realKernelFQN = get_class($realKernel);
|
$realKernelFQN = get_class($realKernel);
|
||||||
|
@ -198,16 +226,6 @@ EOF
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix references to cached files with the real cache directory name
|
|
||||||
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
|
|
||||||
$replace = str_replace('\\', '/', $realCacheDir);
|
|
||||||
foreach (Finder::create()->files()->in($warmupDir) as $file) {
|
|
||||||
$content = str_replace($search, $replace, file_get_contents($file), $count);
|
|
||||||
if ($count) {
|
|
||||||
file_put_contents($file, $content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix references to container's class
|
// fix references to container's class
|
||||||
$tempContainerClass = $tempKernel->getContainerClass();
|
$tempContainerClass = $tempKernel->getContainerClass();
|
||||||
$realContainerClass = $tempKernel->getRealContainerClass();
|
$realContainerClass = $tempKernel->getRealContainerClass();
|
||||||
|
|
|
@ -4,6 +4,7 @@ CHANGELOG
|
||||||
3.4.0
|
3.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* added `RebootableInterface` and implemented it in `Kernel`
|
||||||
* deprecated commands auto registration
|
* deprecated commands auto registration
|
||||||
* added `AddCacheClearerPass`
|
* added `AddCacheClearerPass`
|
||||||
* added `AddCacheWarmerPass`
|
* added `AddCacheWarmerPass`
|
||||||
|
|
|
@ -43,7 +43,7 @@ use Symfony\Component\ClassLoader\ClassCollectionLoader;
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
abstract class Kernel implements KernelInterface, TerminableInterface
|
abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var BundleInterface[]
|
* @var BundleInterface[]
|
||||||
|
@ -61,6 +61,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
protected $loadClassCache;
|
protected $loadClassCache;
|
||||||
|
|
||||||
private $projectDir;
|
private $projectDir;
|
||||||
|
private $warmupDir;
|
||||||
|
|
||||||
const VERSION = '3.4.0-DEV';
|
const VERSION = '3.4.0-DEV';
|
||||||
const VERSION_ID = 30400;
|
const VERSION_ID = 30400;
|
||||||
|
@ -127,6 +128,16 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
$this->booted = true;
|
$this->booted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function reboot($warmupDir)
|
||||||
|
{
|
||||||
|
$this->shutdown();
|
||||||
|
$this->warmupDir = $warmupDir;
|
||||||
|
$this->boot();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -373,7 +384,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
|
file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -381,7 +392,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
*/
|
*/
|
||||||
public function setAnnotatedClassCache(array $annotatedClasses)
|
public function setAnnotatedClassCache(array $annotatedClasses)
|
||||||
{
|
{
|
||||||
file_put_contents($this->getCacheDir().'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true)));
|
file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -424,9 +435,10 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
if (\PHP_VERSION_ID >= 70000) {
|
if (\PHP_VERSION_ID >= 70000) {
|
||||||
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
|
||||||
|
|
||||||
if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
|
if (!$this->booted && is_file($cacheDir.'/classes.map')) {
|
||||||
ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
|
ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,7 +548,8 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
protected function initializeContainer()
|
protected function initializeContainer()
|
||||||
{
|
{
|
||||||
$class = $this->getContainerClass();
|
$class = $this->getContainerClass();
|
||||||
$cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
|
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
|
||||||
|
$cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug);
|
||||||
$fresh = true;
|
$fresh = true;
|
||||||
if (!$cache->isFresh()) {
|
if (!$cache->isFresh()) {
|
||||||
if ($this->debug) {
|
if ($this->debug) {
|
||||||
|
@ -580,8 +593,8 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
if ($this->debug) {
|
if ($this->debug) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
|
|
||||||
file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
|
file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
|
||||||
file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
|
file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +649,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
'kernel.environment' => $this->environment,
|
'kernel.environment' => $this->environment,
|
||||||
'kernel.debug' => $this->debug,
|
'kernel.debug' => $this->debug,
|
||||||
'kernel.name' => $this->name,
|
'kernel.name' => $this->name,
|
||||||
'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(),
|
'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir,
|
||||||
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
|
'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(),
|
||||||
'kernel.bundles' => $bundles,
|
'kernel.bundles' => $bundles,
|
||||||
'kernel.bundles_metadata' => $bundlesMetadata,
|
'kernel.bundles_metadata' => $bundlesMetadata,
|
||||||
|
@ -682,7 +695,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
*/
|
*/
|
||||||
protected function buildContainer()
|
protected function buildContainer()
|
||||||
{
|
{
|
||||||
foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
|
foreach (array('cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
|
||||||
if (!is_dir($dir)) {
|
if (!is_dir($dir)) {
|
||||||
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
|
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
|
||||||
throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
|
throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
|
||||||
|
@ -786,9 +799,6 @@ abstract class Kernel implements KernelInterface, TerminableInterface
|
||||||
@chmod($dir.$file, 0666 & ~umask());
|
@chmod($dir.$file, 0666 & ~umask());
|
||||||
}
|
}
|
||||||
|
|
||||||
// track changes made to the container directory
|
|
||||||
$container->fileExists(dirname($dir.$file));
|
|
||||||
|
|
||||||
$cache->write($rootCode, $container->getResources());
|
$cache->write($rootCode, $container->getResources());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\HttpKernel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the Kernel to be rebooted using a temporary cache directory.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
interface RebootableInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Reboots a kernel.
|
||||||
|
*
|
||||||
|
* The getCacheDir() method of a rebootable kernel should not be called
|
||||||
|
* while building the container. Use the %kernel.cache_dir% parameter instead.
|
||||||
|
*
|
||||||
|
* @param string|null $warmupDir pass null to reboot in the regular cache directory
|
||||||
|
*/
|
||||||
|
public function reboot($warmupDir);
|
||||||
|
}
|
Reference in New Issue