Skip to content

[FrameworkBundle] Added cache:clear command #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 21, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?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\Bundle\FrameworkBundle\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Clear and Warmup the cache.
*
* @author Francis Besset <francis.besset@gmail.com>
*/
class CacheClearCommand extends CacheWarmupCommand
{
/**
* @see Command
*/
protected function configure()
{
$this
->setName('cache:clear')
->setDefinition(array(
new InputOption('warmup', '', InputOption::VALUE_NONE, 'Warms up the cache')
))
->setDescription('Clear the cache')
->setHelp(<<<EOF
The <info>cache:clear</info> command clear the cache.

<info>./app/console cache:clear --warmup</info>

Warmup option, warms up the cache.
EOF
)
;
}

protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);

$this->cacheDir = $this->container->getParameter('kernel.environment').'_tmp';
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$realCacheDir = $this->container->getParameter('kernel.cache_dir');
$oldCacheDir = $realCacheDir.'_old';

if (!is_writable($realCacheDir)) {
throw new \RuntimeException(sprintf('Unable to write %s directory', $this->realCacheDir));
}

$this->clearDir($oldCacheDir);

if (!$input->getOption('warmup')) {
$output->writeln('Clear cache');

rename($realCacheDir, $oldCacheDir);
$this->clearDir($oldCacheDir);
} else {
parent::execute($input, $output);

$output->writeln('Move cache directories');
rename($realCacheDir, $oldCacheDir);
rename($this->kernelTmp->getCacheDir(), $realCacheDir);

$output->writeln('Clear the old cache');
$this->clearDir($oldCacheDir);
}
}
}
82 changes: 78 additions & 4 deletions src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@
namespace Symfony\Bundle\FrameworkBundle\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Finder\Finder;

/**
* Warmup the cache.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Francis Besset <francis.besset@gmail.com>
*/
class CacheWarmupCommand extends Command
{
protected $cacheDir;
protected $kernelTmp;

/**
* @see Command
*/
Expand All @@ -29,24 +36,91 @@ protected function configure()
$this
->setName('cache:warmup')
->setDescription('Warms up an empty cache')
->setDefinition(array(
new InputOption('warmup-dir', '', InputOption::VALUE_OPTIONAL, 'Warms up the cache in a specific directory')
))
->setHelp(<<<EOF
The <info>cache:warmup</info> command warms up the cache.
The <info>cache:warmup --warmup-dir=new_cache</info> command warms up the cache.

Before running this command, the cache must be empty.
Before running this command, the cache must be empty if not use warmup-dir option.
EOF
)
;
}

protected function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);

if ($input->hasOption('warmup-dir')) {
$this->cacheDir = $input->getOption('warmup-dir');
}
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Warming up the cache');

$warmer = $this->container->get('cache_warmer');
if (!$this->cacheDir) {
$this->warmUp($this->container);
} else {
$this->kernelTmp = new \AppKernel(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work if an application uses a different class name for their kernel.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm there is already some black magic in the WebTestCase for this, but obviously we want people to easily change the position and name for their kernel. does this require some generic solution? then again i would guess from inside a running kernel instance it should be no problem to properly locate the actual kernel class name

$this->container->getParameter('kernel.environment'),
$this->container->getParameter('kernel.debug'),
$this->cacheDir
);

$this->clearDir($this->kernelTmp->getCacheDir());

$this->kernelTmp->boot();
unlink($this->kernelTmp->getCacheDir().DIRECTORY_SEPARATOR.$this->kernelTmp->getContainerClass().'.php');

$this->warmUp($this->kernelTmp->getContainer());
}
}

protected function warmUp(ContainerInterface $container)
{
$warmer = $container->get('cache_warmer');
$warmer->enableOptionalWarmers();
$warmer->warmUp($this->container->getParameter('kernel.cache_dir'));
$warmer->warmUp($container->getParameter('kernel.cache_dir'));
}

protected function clearDir($dir)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use this instead:

$fs = new Filesystem();
$fs->remove($dir);

{
if (is_dir($dir)) {
$finder = new Finder();
$files = $finder
->in($dir)
->getIterator()
;

$array = iterator_to_array($files);

foreach (array_reverse($array) as $file) {
if ($file->isFile()) {
if (!is_writable($file->getPathname())) {
throw new \RuntimeException(sprintf('Unable to delete %s file', $file->getPathname()));
}

unlink($file->getPathname());
} else {
if (!is_writable($file->getPathname())) {
throw new \RuntimeException(sprintf('Unable to delete %s directory', $file->getPathname()));
}

rmdir($file->getPathname());
}
}

if (!is_writable($dir)) {
throw new \RuntimeException(sprintf('Unable to delete %s directory', $dir));
}

rmdir($dir);
}
}
}
9 changes: 9 additions & 0 deletions src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ abstract class CacheWarmer implements CacheWarmerInterface
{
protected function writeCacheFile($file, $content)
{
$dir = dirname($file);
if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true)) {
throw new \RuntimeException(sprintf('Unable to create the %s directory', $dir));
}
} elseif (!is_writable($dir)) {
throw new \RuntimeException(sprintf('Unable to write in the %s directory', $dir));
}

$tmpFile = tempnam(dirname($file), basename($file));
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
chmod($file, 0644);
Expand Down
29 changes: 26 additions & 3 deletions src/Symfony/Component/HttpKernel/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ abstract class Kernel implements KernelInterface
protected $rootDir;
protected $environment;
protected $debug;
protected $cacheDir;
protected $booted;
protected $name;
protected $startTime;
Expand All @@ -56,10 +57,11 @@ abstract class Kernel implements KernelInterface
* @param string $environment The environment
* @param Boolean $debug Whether to enable debugging or not
*/
public function __construct($environment, $debug)
public function __construct($environment, $debug, $cacheDir = null)
{
$this->environment = $environment;
$this->debug = (Boolean) $debug;
$this->cacheDir = $cacheDir;
$this->booted = false;
$this->rootDir = realpath($this->registerRootDir());
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
Expand Down Expand Up @@ -308,6 +310,14 @@ public function getContainer()
return $this->container;
}

/**
* @return string The container classname
*/
public function getContainerClass()
{
return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'.($this->cacheDir ? 'Tmp' : '');
}

/**
* Gets the request start time (not available if debug is disabled).
*
Expand All @@ -325,7 +335,7 @@ public function getStartTime()
*/
public function getCacheDir()
{
return $this->rootDir.'/cache/'.$this->environment;
return $this->rootDir.'/cache/'.($this->cacheDir ?: $this->environment);
}

/**
Expand Down Expand Up @@ -399,7 +409,7 @@ protected function initializeBundles()

protected function initializeContainer()
{
$class = $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
$class = $this->getContainerClass();
$cache = new ConfigCache($this->getCacheDir(), $class, $this->debug);
$fresh = false;
if (!$cache->isFresh()) {
Expand All @@ -417,6 +427,19 @@ protected function initializeContainer()
if ($fresh && 'cli' !== php_sapi_name()) {
$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
}

if ($cacheDir = $this->cacheDir) {
$realCacheDir = $this->getCacheDir();
$this->cacheDir = null;

$class = $this->getContainerClass();
$cache = new ConfigCache($realCacheDir, $class, $this->debug);

$container = $this->buildContainer();
$this->dumpContainer($cache, $container, $class);

$this->cacheDir = $cacheDir;
}
}

protected function getKernelParameters()
Expand Down