diff --git a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php index 6c4df58208ed..264694cf4617 100644 --- a/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php +++ b/src/Symfony/Bundle/AsseticBundle/AsseticBundle.php @@ -13,7 +13,9 @@ use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\AssetFactoryPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\AssetManagerPass; +use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckYuiFilterPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\FilterManagerPass; +use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckClosureFilterPass; use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; @@ -29,6 +31,8 @@ public function build(ContainerBuilder $container) { parent::build($container); + $container->addCompilerPass(new CheckClosureFilterPass()); + $container->addCompilerPass(new CheckYuiFilterPass()); $container->addCompilerPass(new TemplatingPass()); $container->addCompilerPass(new AssetFactoryPass()); $container->addCompilerPass(new AssetManagerPass()); diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php index 2658c9498b27..67ba1acf2784 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php @@ -34,6 +34,8 @@ class AsseticExtension extends Extension */ public function load(array $configs, ContainerBuilder $container) { + $parameterBag = $container->getParameterBag(); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('assetic.xml'); $loader->load('templating_twig.xml'); @@ -46,17 +48,28 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('assetic.read_from', $config['read_from']); $container->setParameter('assetic.write_to', $config['write_to']); - if (isset($config['closure'])) { - $container->setParameter('assetic.google_closure_compiler_jar', $config['closure']); - $loader->load('google_closure_compiler.xml'); - } + $container->setParameter('assetic.closure.jar', $config['closure']); + $container->setParameter('assetic.java.bin', $config['java']); + $container->setParameter('assetic.node.bin', $config['node']); + $container->setParameter('assetic.sass.bin', $config['sass']); + $container->setParameter('assetic.yui.jar', $config['yui']); + + // register filters + foreach ($config['filters'] as $name => $filter) { + if (isset($filter['resource'])) { + $loader->load($parameterBag->resolveValue($filter['resource'])); + unset($filter['resource']); + } else { + $loader->load('filters/'.$name.'.xml'); + } - if (isset($config['yui'])) { - $container->setParameter('assetic.yui_jar', $config['yui']); - $loader->load('yui_compressor.xml'); + foreach ($filter as $key => $value) { + $container->setParameter('assetic.filter.'.$name.'.'.$key, $value); + } } - if ($container->getParameterBag()->resolveValue($container->getParameterBag()->get('assetic.use_controller'))) { + // choose dynamic or static + if ($parameterBag->resolveValue($parameterBag->get('assetic.use_controller'))) { $loader->load('controller.xml'); $container->setParameter('assetic.twig_extension.class', '%assetic.twig_extension.dynamic.class%'); } else { @@ -64,11 +77,8 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('assetic.twig_extension.class', '%assetic.twig_extension.static.class%'); } - if ($container->hasParameter('assetic.less.compress')) { - $container->getDefinition('assetic.filter.less')->addMethodCall('setCompress', array('%assetic.less.compress%')); - } - - $this->registerFormulaResources($container, $container->getParameterBag()->resolveValue($config['bundles'])); + // register config resources + self::registerFormulaResources($container, $parameterBag->resolveValue($config['bundles'])); } static protected function processConfigs(array $configs, $debug, array $bundles) diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php new file mode 100644 index 000000000000..fd14b0b400e3 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckClosureFilterPass.php @@ -0,0 +1,33 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Tags either the closure JAR or API filter for the filter manager. + * + * @author Kris Wallsmith + */ +class CheckClosureFilterPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if ($container->hasDefinition('assetic.filter.closure.jar') && + $container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.closure.jar'))) { + $container->remove('assetic.filter.closure.api'); + } elseif ($container->hasDefinition('assetic.filter.closure.api')) { + $container->remove('assetic.filter.closure.jar'); + } + } +} diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckYuiFilterPass.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckYuiFilterPass.php new file mode 100644 index 000000000000..9e4588bde107 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Compiler/CheckYuiFilterPass.php @@ -0,0 +1,36 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Checks that the location of the YUI JAR has been configured. + * + * @author Kris Wallsmith + */ +class CheckYuiFilterPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if ($container->hasDefinition('assetic.filter.yui_css') && + !$container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.yui_css.jar'))) { + throw new \RuntimeException('The Assetic "yui_css" configuration requires a "jar" value.'); + } + + if ($container->hasDefinition('assetic.filter.yui_js') && + !$container->getParameterBag()->resolveValue($container->getParameter('assetic.filter.yui_js.jar'))) { + throw new \RuntimeException('The Assetic "yui_js" configuration requires a "jar" value.'); + } + } +} diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php index 0be37a93bbe2..940082054cc8 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php @@ -20,6 +20,7 @@ * sections are normalized, and merged. * * @author Christophe Coevoet + * @author Kris Wallsmith */ class Configuration { @@ -41,8 +42,11 @@ public function getConfigTree($debug, array $bundles) ->booleanNode('use_controller')->defaultValue($debug)->end() ->scalarNode('read_from')->defaultValue('%kernel.root_dir%/../web')->end() ->scalarNode('write_to')->defaultValue('%assetic.read_from%')->end() - ->scalarNode('closure')->end() - ->scalarNode('yui')->end() + ->scalarNode('closure')->defaultNull()->end() + ->scalarNode('java')->defaultNull()->end() + ->scalarNode('node')->defaultNull()->end() + ->scalarNode('sass')->defaultNull()->end() + ->scalarNode('yui')->defaultNull()->end() ->end() ->fixXmlConfig('bundle') ->children() @@ -50,17 +54,26 @@ public function getConfigTree($debug, array $bundles) ->defaultValue($bundles) ->requiresAtLeastOneElement() ->beforeNormalization() - ->ifTrue(function($v){ return !is_array($v); }) - ->then(function($v){ return array($v); }) + ->ifTrue(function($v) { return !is_array($v); }) + ->then(function($v) { return array($v); }) ->end() ->prototype('scalar') ->beforeNormalization() ->ifTrue(function($v) { return is_array($v) && isset($v['name']); }) - ->then(function($v){ return $v['name']; }) + ->then(function($v) { return $v['name']; }) ->end() ->end() ->end() ->end() + ->fixXmlConfig('filter') + ->children() + ->arrayNode('filters') + ->addDefaultsIfNotSet() + ->requiresAtLeastOneElement() + ->useAttributeAsKey('name') + ->prototype('array')->end() + ->end() + ->end() ; return $tree->buildTree(); diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml index 9ff9f23cb45f..d2819989dacd 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/assetic.xml @@ -7,28 +7,18 @@ Symfony\Bundle\AsseticBundle\Factory\AssetFactory Assetic\Factory\LazyAssetManager - Symfony\Bundle\AsseticBundle\FilterManager + Symfony\Bundle\AsseticBundle\CacheWarmer\AssetManagerCacheWarmer Assetic\Factory\Loader\CachedFormulaLoader Assetic\Cache\ConfigCache - Symfony\Bundle\AsseticBundle\CacheWarmer\AssetManagerCacheWarmer Symfony\Bundle\AsseticBundle\Factory\Resource\DirectoryResource + Symfony\Bundle\AsseticBundle\FilterManager - Assetic\Filter\CoffeeScriptFilter - Assetic\Filter\CssRewriteFilter - Assetic\Filter\GoogleClosure\CompilerApiFilter - Assetic\Filter\GoogleClosure\CompilerJarFilter - Assetic\Filter\LessFilter - Assetic\Filter\Sass\SassFilter - Assetic\Filter\Sass\ScssFilter - Assetic\Filter\SprocketsFilter - Assetic\Filter\StylusFilter - - /usr/bin/java - /usr/bin/sass - /usr/bin/node - - /usr/bin/sprocketize - /usr/bin/coffee + + /usr/bin/java + /usr/bin/node + + /usr/bin/sass + %kernel.cache_dir%/assetic @@ -43,52 +33,13 @@ + %assetic.read_from% %assetic.debug% - - - - - - - - %assetic.read_from% - %assetic.node_bin% - %assetic.node_paths% - - - - %assetic.sass_bin% - - - - %assetic.sass_bin% - - - - - - - %assetic.read_from% - %assetic.sprocketize_bin% - - - - %assetic.coffee_bin% - %assetic.node_bin% - - - - %assetic.read_from% - %assetic.node_bin% - %assetic.node_paths% - - - %assetic.cache_dir%/config diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/closure.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/closure.xml new file mode 100644 index 000000000000..5012fb121560 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/closure.xml @@ -0,0 +1,25 @@ + + + + + + Assetic\Filter\GoogleClosure\CompilerApiFilter + Assetic\Filter\GoogleClosure\CompilerJarFilter + %assetic.java.bin% + %assetic.closure.jar% + + + + + + %assetic.filter.closure.jar% + %assetic.filter.closure.java% + + + + + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/coffee.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/coffee.xml new file mode 100644 index 000000000000..d6b5a936fbb8 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/coffee.xml @@ -0,0 +1,20 @@ + + + + + + Assetic\Filter\CoffeeScriptFilter + /usr/bin/coffee + %assetic.node.bin% + + + + + + %assetic.filter.coffee.bin% + %assetic.filter.coffee.node% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/google_closure_compiler.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssrewrite.xml similarity index 51% rename from src/Symfony/Bundle/AsseticBundle/Resources/config/google_closure_compiler.xml rename to src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssrewrite.xml index f475b6ca7802..383d8cdbf86f 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/google_closure_compiler.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/cssrewrite.xml @@ -4,11 +4,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + Assetic\Filter\CssRewriteFilter + + - - - %assetic.google_closure_compiler_jar% - %assetic.java_bin% + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/less.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/less.xml new file mode 100644 index 000000000000..4f149dad36ef --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/less.xml @@ -0,0 +1,21 @@ + + + + + + Assetic\Filter\LessFilter + %assetic.node.bin% + %assetic.node.paths% + + + + + + %assetic.read_from% + %assetic.filter.less.node% + %assetic.filter.less.node_paths% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sass.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sass.xml new file mode 100644 index 000000000000..a3d930397450 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sass.xml @@ -0,0 +1,18 @@ + + + + + + Assetic\Filter\Sass\SassFilter + %assetic.sass.bin% + + + + + + %assetic.filter.sass.bin% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/scss.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/scss.xml new file mode 100644 index 000000000000..89e2ea23b364 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/scss.xml @@ -0,0 +1,18 @@ + + + + + + Assetic\Filter\Sass\ScssFilter + %assetic.sass.bin% + + + + + + %assetic.filter.scss.sass% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sprockets.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sprockets.xml new file mode 100644 index 000000000000..c67576aba03c --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/sprockets.xml @@ -0,0 +1,19 @@ + + + + + + Assetic\Filter\SprocketsFilter + /usr/bin/sprocketize + + + + + + %assetic.read_from% + %assetic.filter.sprockets.bin% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/stylus.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/stylus.xml new file mode 100644 index 000000000000..4e60f7ee1fa0 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/stylus.xml @@ -0,0 +1,21 @@ + + + + + + Assetic\Filter\StylusFilter + %assetic.node.bin% + %assetic.node.paths% + + + + + + %assetic.read_from% + %assetic.filter.stylus.node% + %assetic.filter.stylus.node_paths% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/yui_compressor.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_css.xml similarity index 56% rename from src/Symfony/Bundle/AsseticBundle/Resources/config/yui_compressor.xml rename to src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_css.xml index 38c55b03b487..c857b2a2634c 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/yui_compressor.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_css.xml @@ -6,19 +6,15 @@ Assetic\Filter\Yui\CssCompressorFilter - Assetic\Filter\Yui\JsCompressorFilter + %assetic.java.bin% + %assetic.yui.jar% - %assetic.yui_jar% - %assetic.java_bin% - - - - %assetic.yui_jar% - %assetic.java_bin% + %assetic.filter.yui_css.jar% + %assetic.filter.yui_css.java% diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_js.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_js.xml new file mode 100644 index 000000000000..3d8fcdadcdd8 --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/filters/yui_js.xml @@ -0,0 +1,20 @@ + + + + + + Assetic\Filter\Yui\JsCompressorFilter + %assetic.java.bin% + %assetic.yui.jar% + + + + + + %assetic.filter.yui_js.jar% + %assetic.filter.yui_js.java% + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/schema/assetic-1.0.xsd b/src/Symfony/Bundle/AsseticBundle/Resources/config/schema/assetic-1.0.xsd index 85e13fc31d22..1d63ea187fe2 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/schema/assetic-1.0.xsd +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/schema/assetic-1.0.xsd @@ -10,16 +10,26 @@ + + + + - + + + + + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Tests/DependencyInjection/AsseticExtensionTest.php b/src/Symfony/Bundle/AsseticBundle/Tests/DependencyInjection/AsseticExtensionTest.php index 68dfe66f86f5..6ee53069c19e 100644 --- a/src/Symfony/Bundle/AsseticBundle/Tests/DependencyInjection/AsseticExtensionTest.php +++ b/src/Symfony/Bundle/AsseticBundle/Tests/DependencyInjection/AsseticExtensionTest.php @@ -12,10 +12,13 @@ namespace Symfony\Bundle\AsseticBundle\Tests\DependencyInjection; use Symfony\Bundle\AsseticBundle\DependencyInjection\AsseticExtension; +use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckYuiFilterPass; +use Symfony\Bundle\AsseticBundle\DependencyInjection\Compiler\CheckClosureFilterPass; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; use Symfony\Component\DependencyInjection\Scope; +use Symfony\Component\Finder\Finder; use Symfony\Component\HttpFoundation\Request; class AsseticExtensionTest extends \PHPUnit_Framework_TestCase @@ -81,17 +84,33 @@ public function getDebugModes() ); } - public function testYuiConfig() + /** + * @dataProvider getFilterNames + */ + public function testFilterConfigs($filter) { - $extension = new AsseticExtension(); - $extension->load(array(array('yui' => '/path/to/yuicompressor.jar')), $this->container); + $config = array('filters' => array($filter => array())); - $this->assertTrue($this->container->has('assetic.filter.yui_css'), '->load() loads the yui_css filter when a yui value is provided'); - $this->assertTrue($this->container->has('assetic.filter.yui_js'), '->load() loads the yui_js filter when a yui value is provided'); + $extension = new AsseticExtension(); + $extension->load(array($config), $this->container); $this->assertSaneContainer($this->getDumpedContainer()); } + public function getFilterNames() + { + $data = array(); + + $finder = new Finder(); + $finder->files()->name('*.xml')->in(__DIR__.'/../../Resources/config/filters'); + + foreach ($finder as $file) { + $data[] = array($file->getBasename('.xml')); + } + + return $data; + } + /** * @dataProvider getUseControllerKeys */ @@ -119,12 +138,52 @@ public function getUseControllerKeys() ); } - public function testClosure() + /** + * @dataProvider getClosureJarAndExpected + */ + public function testClosureCompilerPass($jar, $expected) { + $this->container->addCompilerPass(new CheckClosureFilterPass()); + + $config = array( + 'closure' => $jar, + 'filters' => array( + 'closure' => array(), + ), + ); + $extension = new AsseticExtension(); - $extension->load(array(array('closure' => '/path/to/closure.jar')), $this->container); + $extension->load(array($config), $this->container); $this->assertSaneContainer($this->getDumpedContainer()); + + $this->assertTrue($this->container->getDefinition($expected)->hasTag('assetic.filter')); + } + + public function getClosureJarAndExpected() + { + return array( + array(null, 'assetic.filter.closure.api'), + array('/path/to/closure.jar', 'assetic.filter.closure.jar'), + ); + } + + public function testInvalidYuiConfig() + { + $this->setExpectedException('RuntimeException'); + + $this->container->addCompilerPass(new CheckYuiFilterPass()); + + $config = array( + 'filters' => array( + 'yui_js' => array(), + ), + ); + + $extension = new AsseticExtension(); + $extension->load(array($config), $this->container); + + $this->getDumpedContainer(); } private function getDumpedContainer()