Переглянути джерело

Merge remote branch 'kriswallsmith/assetic/dump-fix'

* kriswallsmith/assetic/dump-fix:
  [AsseticBundle] made some methods private
  [AsseticBundle] added a test of dumping in debug mode
  [AsseticBundle] added test of dumping one asset
  [AsseticBundle] added the beginnings of a test class for the assetic:dump command
  [AsseticBundle] updated dump command to dump leaf assets per debug mode
  [AsseticBundle] rearranged execute() method
  [AsseticBundle] moved debug flag to object property
  [AsseticBundle] moved asset manager to object property
  [AsseticBundle] moved base path to object property
Fabien Potencier 14 роки тому
батько
коміт
b99b1e1e59

+ 62 - 35
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 execute(InputInterface $input, OutputInterface $output)
+    protected function initialize(InputInterface $input, OutputInterface $output)
     {
-        if (!$basePath = $input->getArgument('write_to')) {
-            $basePath = $this->container->getParameter('assetic.write_to');
-        }
+        parent::initialize($input, $output);
 
-        $am = $this->container->get('assetic.asset_manager');
+        $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 (!$input->getOption('watch')) {
+            foreach ($this->am->getNames() as $name) {
+                $this->dumpAsset($name, $output);
+            }
 
-        if ($input->getOption('watch')) {
-            return $this->watch($am, $basePath, $output, $this->container->getParameter('kernel.debug'));
+            return;
         }
 
-        foreach ($am->getNames() as $name) {
-            $this->dumpAsset($am->get($name), $basePath, $output);
+        if (!$this->am->isDebug()) {
+            throw new \RuntimeException('The --watch option is only available in debug mode.');
         }
+
+        $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('<info>[dir+]</info> '.$dir);
             if (false === @mkdir($dir, 0777, true)) {

+ 165 - 0
src/Symfony/Bundle/AsseticBundle/Tests/Command/DumpCommandTest.php

@@ -0,0 +1,165 @@
+<?php
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * 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'));
+    }
+}