diff --git a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php index dc0b28d8ff..98d3bc28de 100644 --- a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php +++ b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php @@ -26,6 +26,9 @@ use Symfony\Component\Console\Output\OutputInterface; */ class DumpCommand extends Command { + private $basePath; + private $am; + protected function configure() { $this @@ -36,21 +39,29 @@ class DumpCommand extends Command ; } + protected function initialize(InputInterface $input, OutputInterface $output) + { + parent::initialize($input, $output); + + $this->basePath = $input->getArgument('write_to') ?: $this->container->getParameter('assetic.write_to'); + $this->am = $this->container->get('assetic.asset_manager'); + } + protected function execute(InputInterface $input, OutputInterface $output) { - if (!$basePath = $input->getArgument('write_to')) { - $basePath = $this->container->getParameter('assetic.write_to'); + if (!$input->getOption('watch')) { + foreach ($this->am->getNames() as $name) { + $this->dumpAsset($name, $output); + } + + return; } - $am = $this->container->get('assetic.asset_manager'); - - if ($input->getOption('watch')) { - return $this->watch($am, $basePath, $output, $this->container->getParameter('kernel.debug')); + if (!$this->am->isDebug()) { + throw new \RuntimeException('The --watch option is only available in debug mode.'); } - foreach ($am->getNames() as $name) { - $this->dumpAsset($am->get($name), $basePath, $output); - } + $this->watch($output); } /** @@ -59,22 +70,15 @@ class DumpCommand extends Command * This method includes an infinite loop the continuously polls the asset * manager for changes. * - * @param LazyAssetManager $am The asset manager - * @param string $basePath The base directory to write to - * @param OutputInterface $output The command output - * @param Boolean $debug Debug mode + * @param OutputInterface $output The command output */ - protected function watch(LazyAssetManager $am, $basePath, OutputInterface $output, $debug = false) + private function watch(OutputInterface $output) { - if (!$debug) { - throw new \RuntimeException('The --watch option is only available in debug mode.'); - } - $refl = new \ReflectionClass('Assetic\\AssetManager'); $prop = $refl->getProperty('assets'); $prop->setAccessible(true); - $cache = sys_get_temp_dir().'/assetic_watch_'.substr(sha1($basePath), 0, 7); + $cache = sys_get_temp_dir().'/assetic_watch_'.substr(sha1($this->basePath), 0, 7); if (file_exists($cache)) { $previously = unserialize(file_get_contents($cache)); } else { @@ -84,15 +88,15 @@ class DumpCommand extends Command $error = ''; while (true) { try { - foreach ($am->getNames() as $name) { - if ($asset = $this->checkAsset($am, $name, $previously)) { - $this->dumpAsset($asset, $basePath, $output); + foreach ($this->am->getNames() as $name) { + if ($asset = $this->checkAsset($name, $previously)) { + $this->dumpAsset($asset, $output); } } // reset the asset manager - $prop->setValue($am, array()); - $am->load(); + $prop->setValue($this->am, array()); + $this->am->load(); file_put_contents($cache, serialize($previously)); $error = ''; @@ -110,16 +114,15 @@ class DumpCommand extends Command /** * Checks if an asset should be dumped. * - * @param LazyAssetManager $am The asset manager - * @param string $name The asset name - * @param array &$previously An array of previous visits + * @param string $name The asset name + * @param array &$previously An array of previous visits * * @return AssetInterface|Boolean The asset if it should be dumped */ - protected function checkAsset(LazyAssetManager $am, $name, array &$previously) + private function checkAsset($name, array &$previously) { - $formula = $am->hasFormula($name) ? serialize($am->getFormula($name)) : null; - $asset = $am->get($name); + $formula = $this->am->hasFormula($name) ? serialize($this->am->getFormula($name)) : null; + $asset = $this->am->get($name); $mtime = $asset->getLastModified(); if (isset($previously[$name])) { @@ -136,15 +139,39 @@ class DumpCommand extends Command /** * Writes an asset. * - * @param AssetInterface $asset An asset - * @param string $basePath The base directory to write to - * @param OutputInterface $output The command output + * If the application or asset is in debug mode, each leaf asset will be + * dumped as well. + * + * @param string $name An asset name + * @param OutputInterface $output The command output + */ + private function dumpAsset($name, OutputInterface $output) + { + $asset = $this->am->get($name); + $formula = $this->am->getFormula($name); + + // start by dumping the main asset + $this->doDump($asset, $output); + + // dump each leaf if debug + if (isset($formula[2]['debug']) ? $formula[2]['debug'] : $this->am->isDebug()) { + foreach ($asset as $leaf) { + $this->doDump($leaf, $output); + } + } + } + + /** + * Performs the asset dump. + * + * @param AssetInterface $asset An asset + * @param OutputInterface $output The command output * * @throws RuntimeException If there is a problem writing the asset */ - protected function dumpAsset(AssetInterface $asset, $basePath, OutputInterface $output) + private function doDump(AssetInterface $asset, OutputInterface $output) { - $target = rtrim($basePath, '/').'/'.str_replace('_controller/', '', $asset->getTargetUrl()); + $target = rtrim($this->basePath, '/').'/'.str_replace('_controller/', '', $asset->getTargetUrl()); if (!is_dir($dir = dirname($target))) { $output->writeln('[dir+] '.$dir); if (false === @mkdir($dir, 0777, true)) { diff --git a/src/Symfony/Bundle/AsseticBundle/Tests/Command/DumpCommandTest.php b/src/Symfony/Bundle/AsseticBundle/Tests/Command/DumpCommandTest.php new file mode 100644 index 0000000000..372d5e10c8 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Tests/Command/DumpCommandTest.php @@ -0,0 +1,165 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\Tests\Command; + +use Symfony\Bundle\AsseticBundle\Command\DumpCommand; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\NullOutput; + +class DumpCommandTest extends \PHPUnit_Framework_TestCase +{ + private $writeTo; + private $application; + private $definition; + private $kernel; + private $container; + private $am; + + protected function setUp() + { + if (!class_exists('Assetic\\AssetManager')) { + $this->markTestSkipped('Assetic is not available.'); + } + + $this->writeTo = sys_get_temp_dir().'/assetic_dump'; + + $this->application = $this->getMockBuilder('Symfony\\Bundle\\FrameworkBundle\\Console\\Application') + ->disableOriginalConstructor() + ->getMock(); + $this->definition = $this->getMockBuilder('Symfony\\Component\\Console\\Input\\InputDefinition') + ->disableOriginalConstructor() + ->getMock(); + $this->kernel = $this->getMock('Symfony\\Component\\HttpKernel\\KernelInterface'); + $this->container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface'); + $this->am = $this->getMockBuilder('Assetic\\Factory\\LazyAssetManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->application->expects($this->any()) + ->method('getDefinition') + ->will($this->returnValue($this->definition)); + $this->definition->expects($this->any()) + ->method('getArguments') + ->will($this->returnValue(array())); + $this->definition->expects($this->any()) + ->method('getOptions') + ->will($this->returnValue(array())); + $this->application->expects($this->any()) + ->method('getKernel') + ->will($this->returnValue($this->kernel)); + $this->kernel->expects($this->any()) + ->method('getContainer') + ->will($this->returnValue($this->container)); + $this->container->expects($this->any()) + ->method('getParameter') + ->with('assetic.write_to') + ->will($this->returnValue($this->writeTo)); + $this->container->expects($this->once()) + ->method('get') + ->with('assetic.asset_manager') + ->will($this->returnValue($this->am)); + + $this->command = new DumpCommand(); + $this->command->setApplication($this->application); + } + + protected function tearDown() + { + if (is_dir($this->writeTo)) { + array_map('unlink', glob($this->writeTo.'/*')); + rmdir($this->writeTo); + } + } + + public function testEmptyAssetManager() + { + $this->am->expects($this->once()) + ->method('getNames') + ->will($this->returnValue(array())); + + $this->command->run(new ArrayInput(array()), new NullOutput()); + } + + public function testDumpOne() + { + $asset = $this->getMock('Assetic\\Asset\\AssetInterface'); + + $this->am->expects($this->once()) + ->method('getNames') + ->will($this->returnValue(array('test_asset'))); + $this->am->expects($this->once()) + ->method('get') + ->with('test_asset') + ->will($this->returnValue($asset)); + $this->am->expects($this->once()) + ->method('getFormula') + ->with('test_asset') + ->will($this->returnValue(array())); + $this->am->expects($this->once()) + ->method('isDebug') + ->will($this->returnValue(false)); + $asset->expects($this->once()) + ->method('getTargetUrl') + ->will($this->returnValue('test_asset.css')); + $asset->expects($this->once()) + ->method('dump') + ->will($this->returnValue('/* test_asset */')); + + $this->command->run(new ArrayInput(array()), new NullOutput()); + + $this->assertFileExists($this->writeTo.'/test_asset.css'); + $this->assertEquals('/* test_asset */', file_get_contents($this->writeTo.'/test_asset.css')); + } + + public function testDumpDebug() + { + $asset = $this->getMock('Assetic\\Asset\\AssetCollection'); + $leaf = $this->getMock('Assetic\\Asset\\AssetInterface'); + + $this->am->expects($this->once()) + ->method('getNames') + ->will($this->returnValue(array('test_asset'))); + $this->am->expects($this->once()) + ->method('get') + ->with('test_asset') + ->will($this->returnValue($asset)); + $this->am->expects($this->once()) + ->method('getFormula') + ->with('test_asset') + ->will($this->returnValue(array())); + $this->am->expects($this->once()) + ->method('isDebug') + ->will($this->returnValue(true)); + $asset->expects($this->once()) + ->method('getTargetUrl') + ->will($this->returnValue('test_asset.css')); + $asset->expects($this->once()) + ->method('dump') + ->will($this->returnValue('/* test_asset */')); + $asset->expects($this->once()) + ->method('getIterator') + ->will($this->returnValue(new \ArrayIterator(array($leaf)))); + $leaf->expects($this->once()) + ->method('getTargetUrl') + ->will($this->returnValue('test_leaf.css')); + $leaf->expects($this->once()) + ->method('dump') + ->will($this->returnValue('/* test_leaf */')); + + $this->command->run(new ArrayInput(array()), new NullOutput()); + + $this->assertFileExists($this->writeTo.'/test_asset.css'); + $this->assertFileExists($this->writeTo.'/test_leaf.css'); + $this->assertEquals('/* test_asset */', file_get_contents($this->writeTo.'/test_asset.css')); + $this->assertEquals('/* test_leaf */', file_get_contents($this->writeTo.'/test_leaf.css')); + } +}