From f3728744b497a60552aca686d58b5453a63fe031 Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Mon, 25 Apr 2011 08:34:59 -0700 Subject: [PATCH 1/3] [AsseticBundle] added support for Twig functions --- .../DependencyInjection/AsseticExtension.php | 3 +++ .../DependencyInjection/Configuration.php | 23 +++++++++++++++++++ .../Resources/config/schema/assetic-1.0.xsd | 12 ++++++++++ .../Resources/config/templating_twig.xml | 2 +- .../Tests/Resources/config/config.yml | 6 +++++ .../AsseticBundle/Twig/AsseticExtension.php | 4 ++-- 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php index 1284628dde..19ee3dcfc3 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php @@ -71,6 +71,9 @@ class AsseticExtension extends Extension } } + // twig functions + $container->getDefinition('assetic.twig_extension')->replaceArgument(2, $config['twig']['functions']); + // choose dynamic or static if ($parameterBag->resolveValue($parameterBag->get('assetic.use_controller'))) { $loader->load('controller.xml'); diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php index 76d20263c1..16c45c0228 100644 --- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/Configuration.php @@ -91,6 +91,29 @@ class Configuration implements ConfigurationInterface ->end() ->end() ->end() + + // twig + ->children() + ->arrayNode('twig') + ->addDefaultsIfNotSet() + ->defaultValue(array()) + ->fixXmlConfig('function') + ->children() + ->arrayNode('functions') + ->addDefaultsIfNotSet() + ->defaultValue(array()) + ->useAttributeAsKey('name') + ->prototype('variable') + ->treatNullLike(array()) + ->validate() + ->ifTrue(function($v) { return !is_array($v); }) + ->thenInvalid('The assetic.twig.functions config %s must be either null or an array.') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() ; return $builder; 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 1d63ea187f..e2928fd13a 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 @@ -11,6 +11,7 @@ + @@ -32,4 +33,15 @@ + + + + + + + + + + + diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml index a2340dc316..1a32250152 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml @@ -14,8 +14,8 @@ - %assetic.debug% %assetic.use_controller% + diff --git a/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml b/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml index 1049c0e4a7..bbc87b4daa 100644 --- a/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml +++ b/src/Symfony/Bundle/AsseticBundle/Tests/Resources/config/config.yml @@ -20,3 +20,9 @@ assetic: use_controller: true read_from: "%kernel.root_dir%/web" bundles: [TestBundle] + filters: + yui_css: + jar: %kernel.root_dir/java/yui-compressor-2.4.6.jar + twig: + functions: + yui_css: { output: css/*.css } diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php index e5302ed71c..ba76a9e18f 100644 --- a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php +++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php @@ -23,9 +23,9 @@ class AsseticExtension extends BaseAsseticExtension { private $useController; - public function __construct(AssetFactory $factory, $debug = false, $useController = false) + public function __construct(AssetFactory $factory, $useController = false, $functions = array()) { - parent::__construct($factory, $debug); + parent::__construct($factory, $functions); $this->useController = $useController; } From a005796d3b55b05a59cd86d49180a9283f4093c5 Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Mon, 25 Apr 2011 23:28:41 -0700 Subject: [PATCH 2/3] [AsseticBundle] added a node visitor to wrap runtime filter functions with runtime use_controller check --- .../AsseticBundle/Twig/AsseticExtension.php | 5 + .../AsseticBundle/Twig/AsseticNodeVisitor.php | 97 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 src/Symfony/Bundle/AsseticBundle/Twig/AsseticNodeVisitor.php diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php index ba76a9e18f..3fcffefacb 100644 --- a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php +++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php @@ -39,6 +39,11 @@ class AsseticExtension extends BaseAsseticExtension ); } + public function getNodeVisitors() + { + return array(new AsseticNodeVisitor()); + } + public function getGlobals() { $globals = parent::getGlobals(); diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNodeVisitor.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNodeVisitor.php new file mode 100644 index 0000000000..2e92f22c7d --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNodeVisitor.php @@ -0,0 +1,97 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\Twig; + +use Assetic\Extension\Twig\AsseticFilterFunction; + +/** + * Assetic node visitor. + * + * @author Kris Wallsmith + */ +class AsseticNodeVisitor implements \Twig_NodeVisitorInterface +{ + public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + return $node; + } + + public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + if (!$formula = $this->checkNode($node, $env)) { + return $node; + } + + list($input, $filters, $options) = $formula; + $line = $node->getLine(); + + // check context and call either asset() or path() + return new \Twig_Node_Expression_Conditional( + new \Twig_Node_Expression_GetAttr( + new \Twig_Node_Expression_Name('assetic', $line), + new \Twig_Node_Expression_Constant('use_controller', $line), + new \Twig_Node(), + \Twig_TemplateInterface::ARRAY_CALL, + $line + ), + new \Twig_Node_Expression_Function( + new \Twig_Node_Expression_Name('path', $line), + new \Twig_Node(array( + new \Twig_Node_Expression_Constant('_assetic_'.$options['name'], $line), + )), + $line + ), + new \Twig_Node_Expression_Function( + new \Twig_Node_Expression_Name('asset', $line), + new \Twig_Node(array($node, new \Twig_Node_Expression_Constant(isset($options['package']) ? $options['package'] : null, $line))), + $line + ), + $line + ); + } + + /** + * Extracts formulae from filter function nodes. + * + * @return array|null The formula + */ + private function checkNode(\Twig_NodeInterface $node, \Twig_Environment $env) + { + if ($node instanceof \Twig_Node_Expression_Function) { + $name = $node->getNode('name')->getAttribute('name'); + if ($env->getFunction($name) instanceof AsseticFilterFunction) { + $arguments = array(); + foreach ($node->getNode('arguments') as $argument) { + $arguments[] = eval('return '.$env->compile($argument).';'); + } + + $invoker = $env->getExtension('assetic')->getFilterInvoker($name); + $factory = $invoker->getFactory(); + + $inputs = isset($arguments[0]) ? (array) $arguments[0] : array(); + $filters = $invoker->getFilters(); + $options = array_replace($invoker->getOptions(), isset($arguments[1]) ? $arguments[1] : array()); + + if (!isset($options['name'])) { + $options['name'] = $factory->generateAssetName($inputs, $filters); + } + + return array($inputs, $filters, $options); + } + } + } + + public function getPriority() + { + return 0; + } +} From f9c300e8db3d2edf65481884243133f1e34b5f6c Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Tue, 26 Apr 2011 00:05:35 -0700 Subject: [PATCH 3/3] [AsseticBundle] added a listener to add common image request formats when use_controller is on --- .../Listener/RequestListener.php | 31 +++++++++++++++++++ .../Resources/config/controller.xml | 4 +++ 2 files changed, 35 insertions(+) create mode 100644 src/Symfony/Bundle/AsseticBundle/Listener/RequestListener.php diff --git a/src/Symfony/Bundle/AsseticBundle/Listener/RequestListener.php b/src/Symfony/Bundle/AsseticBundle/Listener/RequestListener.php new file mode 100644 index 0000000000..97289e6ccc --- /dev/null +++ b/src/Symfony/Bundle/AsseticBundle/Listener/RequestListener.php @@ -0,0 +1,31 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Symfony\Bundle\AsseticBundle\Listener; + +use Symfony\Component\HttpKernel\Event\GetResponseEvent; + +/** + * Adds a few formats to each request. + * + * @author Kris Wallsmith + */ +class RequestListener +{ + public function onCoreRequest(GetResponseEvent $event) + { + $request = $event->getRequest(); + + $request->setFormat('png', 'image/png'); + $request->setFormat('jpg', 'image/jpeg'); + $request->setFormat('gif', 'image/gif'); + } +} diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/controller.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/controller.xml index 1da0a603e5..222628c89f 100644 --- a/src/Symfony/Bundle/AsseticBundle/Resources/config/controller.xml +++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/controller.xml @@ -9,6 +9,7 @@ Symfony\Bundle\AsseticBundle\Routing\AsseticLoader Assetic\Cache\FilesystemCache Symfony\Bundle\AsseticBundle\Factory\Worker\UseControllerWorker + Symfony\Bundle\AsseticBundle\Listener\RequestListener @@ -27,5 +28,8 @@ + + +