CacheClearCommand.php 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\FrameworkBundle\Command;
  11. use Symfony\Component\Console\Input\InputInterface;
  12. use Symfony\Component\Console\Input\InputOption;
  13. use Symfony\Component\Console\Output\OutputInterface;
  14. use Symfony\Component\HttpKernel\KernelInterface;
  15. use Symfony\Component\Finder\Finder;
  16. /**
  17. * Clear and Warmup the cache.
  18. *
  19. * @author Francis Besset <francis.besset@gmail.com>
  20. * @author Fabien Potencier <fabien@symfony.com>
  21. */
  22. class CacheClearCommand extends ContainerAwareCommand
  23. {
  24. protected $name;
  25. /**
  26. * @see Command
  27. */
  28. protected function configure()
  29. {
  30. $this
  31. ->setName('cache:clear')
  32. ->setDefinition(array(
  33. new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'),
  34. ))
  35. ->setDescription('Clears the cache')
  36. ->setHelp(<<<EOF
  37. The <info>cache:clear</info> command clears the application cache for a given environment
  38. and debug mode:
  39. <info>php app/console cache:clear --env=dev</info>
  40. <info>php app/console cache:clear --env=prod --no-debug</info>
  41. EOF
  42. )
  43. ;
  44. }
  45. /**
  46. * {@inheritdoc}
  47. */
  48. protected function execute(InputInterface $input, OutputInterface $output)
  49. {
  50. $realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
  51. $oldCacheDir = $realCacheDir.'_old';
  52. if (!is_writable($realCacheDir)) {
  53. throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir));
  54. }
  55. $kernel = $this->getContainer()->get('kernel');
  56. $output->writeln(sprintf('Clearing the cache for the <info>%s</info> environment with debug <info>%s</info>', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
  57. if ($input->getOption('no-warmup')) {
  58. rename($realCacheDir, $oldCacheDir);
  59. } else {
  60. $warmupDir = $realCacheDir.'_new';
  61. $this->warmup($warmupDir);
  62. rename($realCacheDir, $oldCacheDir);
  63. rename($warmupDir, $realCacheDir);
  64. }
  65. $this->getContainer()->get('filesystem')->remove($oldCacheDir);
  66. }
  67. protected function warmup($warmupDir)
  68. {
  69. $this->getContainer()->get('filesystem')->remove($warmupDir);
  70. $parent = $this->getContainer()->get('kernel');
  71. $class = get_class($parent);
  72. $namespace = '';
  73. if (false !== $pos = strrpos($class, '\\')) {
  74. $namespace = substr($class, 0, $pos);
  75. $class = substr($class, $pos + 1);
  76. }
  77. $kernel = $this->getTempKernel($parent, $namespace, $class, $warmupDir);
  78. $kernel->boot();
  79. $warmer = $kernel->getContainer()->get('cache_warmer');
  80. $warmer->enableOptionalWarmers();
  81. $warmer->warmUp($warmupDir);
  82. // fix container files and classes
  83. $regex = '/'.preg_quote($this->getTempKernelSuffix(), '/').'/';
  84. $finder = new Finder();
  85. foreach ($finder->files()->name(get_class($kernel->getContainer()).'*')->in($warmupDir) as $file) {
  86. $content = file_get_contents($file);
  87. $content = preg_replace($regex, '', $content);
  88. // fix absolute paths to the cache directory
  89. $content = preg_replace('/'.preg_quote($warmupDir, '/').'/', preg_replace('/_new$/', '', $warmupDir), $content);
  90. file_put_contents(preg_replace($regex, '', $file), $content);
  91. unlink($file);
  92. }
  93. // fix meta references to the Kernel
  94. foreach ($finder->files()->name('*.meta')->in($warmupDir) as $file) {
  95. $content = preg_replace(
  96. '/C\:\d+\:"'.preg_quote($class.$this->getTempKernelSuffix(), '"/').'"/',
  97. sprintf('C:%s:"%s"', strlen($class), $class),
  98. file_get_contents($file)
  99. );
  100. file_put_contents($file, $content);
  101. }
  102. }
  103. protected function getTempKernelSuffix()
  104. {
  105. if (null === $this->name) {
  106. $this->name = '__'.uniqid().'__';
  107. }
  108. return $this->name;
  109. }
  110. protected function getTempKernel(KernelInterface $parent, $namespace, $class, $warmupDir)
  111. {
  112. $suffix = $this->getTempKernelSuffix();
  113. $rootDir = $parent->getRootDir();
  114. $code = <<<EOF
  115. <?php
  116. namespace $namespace
  117. {
  118. class $class$suffix extends $class
  119. {
  120. public function getCacheDir()
  121. {
  122. return '$warmupDir';
  123. }
  124. public function getRootDir()
  125. {
  126. return '$rootDir';
  127. }
  128. protected function getContainerClass()
  129. {
  130. return parent::getContainerClass().'$suffix';
  131. }
  132. }
  133. }
  134. EOF;
  135. $this->getContainer()->get('filesystem')->mkdir($warmupDir);
  136. file_put_contents($file = $warmupDir.'/kernel.tmp', $code);
  137. require_once $file;
  138. @unlink($file);
  139. $class = "$namespace\\$class$suffix";
  140. return new $class($parent->getEnvironment(), $parent->isDebug());
  141. }
  142. }