Browse Source

[FrameworkBundle] Added cache:clear command with warmup option

Francis Besset 14 years ago
parent
commit
bb7986e221

+ 84 - 0
src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

@@ -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);
+        }
+    }
+}

+ 78 - 4
src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php

@@ -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
      */
@@ -29,15 +36,27 @@ class CacheWarmupCommand extends Command
         $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}
      */
@@ -45,8 +64,63 @@ EOF
     {
         $output->writeln('Warming up the cache');
 
-        $warmer = $this->container->get('cache_warmer');
+        if (!$this->cacheDir) {
+            $this->warmUp($this->container);
+        } else {
+            $this->kernelTmp = new \AppKernel(
+                $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)
+    {
+        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 - 0
src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmer.php

@@ -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);

+ 26 - 3
src/Symfony/Component/HttpKernel/Kernel.php

@@ -44,6 +44,7 @@ abstract class Kernel implements KernelInterface
     protected $rootDir;
     protected $environment;
     protected $debug;
+    protected $cacheDir;
     protected $booted;
     protected $name;
     protected $startTime;
@@ -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));
@@ -308,6 +310,14 @@ abstract class Kernel implements KernelInterface
         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).
      *
@@ -325,7 +335,7 @@ abstract class Kernel implements KernelInterface
      */
     public function getCacheDir()
     {
-        return $this->rootDir.'/cache/'.$this->environment;
+        return $this->rootDir.'/cache/'.($this->cacheDir ?: $this->environment);
     }
 
     /**
@@ -399,7 +409,7 @@ abstract class Kernel implements KernelInterface
 
     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()) {
@@ -417,6 +427,19 @@ abstract class Kernel implements KernelInterface
         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()