diff --git a/src/Symfony/Bundle/AsseticBundle/Controller/AsseticController.php b/src/Symfony/Bundle/AsseticBundle/Controller/AsseticController.php
index b34a845241..136ef133d6 100644
--- a/src/Symfony/Bundle/AsseticBundle/Controller/AsseticController.php
+++ b/src/Symfony/Bundle/AsseticBundle/Controller/AsseticController.php
@@ -36,13 +36,21 @@ class AsseticController
$this->cache = $cache;
}
- public function render($name)
+ public function render($name, $pos = null)
{
if (!$this->am->has($name)) {
- throw new NotFoundHttpException('Asset Not Found');
+ throw new NotFoundHttpException(sprintf('The "%s" asset could not be found.', $name));
}
$asset = $this->getAsset($name);
+ if (null !== $pos) {
+ $leaves = array_values(iterator_to_array($asset));
+ if (!isset($leaves[$pos])) {
+ throw new NotFoundHttpException(sprintf('The "%s" asset does not include a leaf at position %d.', $name, $pos));
+ }
+ $asset = $leaves[$pos];
+ }
+
$response = $this->createResponse();
// last-modified
diff --git a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php
index 19213c6aee..1284628dde 100644
--- a/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php
+++ b/src/Symfony/Bundle/AsseticBundle/DependencyInjection/AsseticExtension.php
@@ -74,12 +74,10 @@ class AsseticExtension extends Extension
// 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%');
$container->getDefinition('assetic.helper.dynamic')->addTag('templating.helper', array('alias' => 'assetic'));
$container->removeDefinition('assetic.helper.static');
} else {
$loader->load('asset_writer.xml');
- $container->setParameter('assetic.twig_extension.class', '%assetic.twig_extension.static.class%');
$container->getDefinition('assetic.helper.static')->addTag('templating.helper', array('alias' => 'assetic'));
$container->removeDefinition('assetic.helper.dynamic');
}
diff --git a/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml b/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml
index 5e3d070eb4..a2340dc316 100644
--- a/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml
+++ b/src/Symfony/Bundle/AsseticBundle/Resources/config/templating_twig.xml
@@ -5,8 +5,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
- Symfony\Bundle\AsseticBundle\Twig\DynamicExtension
- Symfony\Bundle\AsseticBundle\Twig\StaticExtension
+ Symfony\Bundle\AsseticBundle\Twig\AsseticExtension
Assetic\Extension\Twig\TwigFormulaLoader
@@ -16,6 +15,7 @@
%assetic.debug%
+ %assetic.use_controller%
diff --git a/src/Symfony/Bundle/AsseticBundle/Routing/AsseticLoader.php b/src/Symfony/Bundle/AsseticBundle/Routing/AsseticLoader.php
index 763ef31be4..214c9bc8fe 100644
--- a/src/Symfony/Bundle/AsseticBundle/Routing/AsseticLoader.php
+++ b/src/Symfony/Bundle/AsseticBundle/Routing/AsseticLoader.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\AsseticBundle\Routing;
+use Assetic\Asset\AssetInterface;
use Assetic\Factory\LazyAssetManager;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Config\Resource\FileResource;
@@ -62,22 +63,40 @@ class AsseticLoader extends Loader
// routes
foreach ($this->am->getNames() as $name) {
$asset = $this->am->get($name);
+ $formula = $this->am->getFormula($name);
- $defaults = array(
- '_controller' => 'assetic.controller:render',
- 'name' => $name,
- );
+ $this->loadRouteForAsset($routes, $asset, $name);
- if ($extension = pathinfo($asset->getTargetUrl(), PATHINFO_EXTENSION)) {
- $defaults['_format'] = $extension;
+ // add a route for each "leaf" in debug mode
+ if (isset($formula[2]['debug']) ? $formula[2]['debug'] : $this->am->isDebug()) {
+ $i = 0;
+ foreach ($asset as $leaf) {
+ $pos = $i++;
+ $this->loadRouteForAsset($routes, $leaf, $name.'_'.$pos, $pos);
+ }
}
-
- $routes->add('assetic_'.$name, new Route($asset->getTargetUrl(), $defaults));
}
return $routes;
}
+ private function loadRouteForAsset(RouteCollection $routes, AssetInterface $asset, $name, $pos = null)
+ {
+ $defaults = array(
+ '_controller' => 'assetic.controller:render',
+ 'name' => $name,
+ 'pos' => $pos,
+ );
+
+ $pattern = $asset->getTargetUrl();
+
+ if ($format = pathinfo($pattern, PATHINFO_EXTENSION)) {
+ $defaults['_format'] = $format;
+ }
+
+ $routes->add('_assetic_'.$name, new Route($pattern, $defaults));
+ }
+
public function supports($resource, $type = null)
{
return 'assetic' == $type;
diff --git a/src/Symfony/Bundle/AsseticBundle/Templating/DynamicAsseticHelper.php b/src/Symfony/Bundle/AsseticBundle/Templating/DynamicAsseticHelper.php
index e1ad188abe..a3dad04501 100644
--- a/src/Symfony/Bundle/AsseticBundle/Templating/DynamicAsseticHelper.php
+++ b/src/Symfony/Bundle/AsseticBundle/Templating/DynamicAsseticHelper.php
@@ -40,6 +40,6 @@ class DynamicAsseticHelper extends AsseticHelper
protected function getAssetUrl(AssetInterface $asset, $options = array())
{
- return $this->routerHelper->generate('assetic_'.$options['name']);
+ return $this->routerHelper->generate('_assetic_'.$options['name']);
}
}
diff --git a/src/Symfony/Bundle/AsseticBundle/Tests/FunctionalTest.php b/src/Symfony/Bundle/AsseticBundle/Tests/FunctionalTest.php
index 76a6c600a0..3c9ba424ff 100644
--- a/src/Symfony/Bundle/AsseticBundle/Tests/FunctionalTest.php
+++ b/src/Symfony/Bundle/AsseticBundle/Tests/FunctionalTest.php
@@ -44,7 +44,7 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
}
/**
- * @dataProvider provideDebugAndAssetCount
+ * @dataProvider provideAmDebugAndAssetCount
*/
public function testKernel($debug, $count)
{
@@ -55,7 +55,7 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
}
/**
- * @dataProvider provideDebugAndAssetCount
+ * @dataProvider provideRouterDebugAndAssetCount
*/
public function testRoutes($debug, $count)
{
@@ -64,7 +64,7 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
$matches = 0;
foreach (array_keys($kernel->getContainer()->get('router')->getRouteCollection()->all()) as $name) {
- if (0 === strpos($name, 'assetic_')) {
+ if (0 === strpos($name, '_assetic_')) {
++$matches;
}
}
@@ -102,11 +102,18 @@ class FunctionalTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(2, count($crawler->filter('script[src$=".js"]')));
}
- public function provideDebugAndAssetCount()
+ public function provideAmDebugAndAssetCount()
{
- // totals include assets defined in both php and twig templates
return array(
- array(true, 6),
+ array(true, 3),
+ array(false, 3),
+ );
+ }
+
+ public function provideRouterDebugAndAssetCount()
+ {
+ return array(
+ array(true, 9),
array(false, 3),
);
}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php
new file mode 100644
index 0000000000..e5302ed71c
--- /dev/null
+++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticExtension.php
@@ -0,0 +1,49 @@
+
+ *
+ * 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\AsseticExtension as BaseAsseticExtension;
+use Assetic\Factory\AssetFactory;
+
+/**
+ * Assetic extension.
+ *
+ * @author Kris Wallsmith
+ */
+class AsseticExtension extends BaseAsseticExtension
+{
+ private $useController;
+
+ public function __construct(AssetFactory $factory, $debug = false, $useController = false)
+ {
+ parent::__construct($factory, $debug);
+
+ $this->useController = $useController;
+ }
+
+ public function getTokenParsers()
+ {
+ return array(
+ new AsseticTokenParser($this->factory, 'javascripts', 'js/*.js', false, array('package')),
+ new AsseticTokenParser($this->factory, 'stylesheets', 'css/*.css', false, array('package')),
+ new AsseticTokenParser($this->factory, 'image', 'images/*', true, array('package')),
+ );
+ }
+
+ public function getGlobals()
+ {
+ $globals = parent::getGlobals();
+ $globals['assetic']['use_controller'] = $this->useController;
+
+ return $globals;
+ }
+}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNode.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNode.php
new file mode 100644
index 0000000000..1202b4abe0
--- /dev/null
+++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticNode.php
@@ -0,0 +1,57 @@
+
+ *
+ * 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\Asset\AssetInterface;
+use Assetic\Extension\Twig\AsseticNode as BaseAsseticNode;
+
+/**
+ * Assetic node.
+ *
+ * @author Kris Wallsmith
+ */
+class AsseticNode extends BaseAsseticNode
+{
+ protected function compileAssetUrl(\Twig_Compiler $compiler, AssetInterface $asset, $name)
+ {
+ $compiler
+ ->raw('isset($context[\'assetic\'][\'use_controller\']) && $context[\'assetic\'][\'use_controller\'] ? ')
+ ->subcompile($this->getPathFunction($name))
+ ->raw(' : ')
+ ->subcompile($this->getAssetFunction($asset->getTargetUrl()))
+ ;
+ }
+
+ private function getPathFunction($name)
+ {
+ return new \Twig_Node_Expression_Function(
+ new \Twig_Node_Expression_Name('path', $this->getLine()),
+ new \Twig_Node(array(new \Twig_Node_Expression_Constant('_assetic_'.$name, $this->getLine()))),
+ $this->getLine()
+ );
+ }
+
+ private function getAssetFunction($path)
+ {
+ $arguments = array(new \Twig_Node_Expression_Constant($path, $this->getLine()));
+
+ if ($this->hasAttribute('package')) {
+ $arguments[] = new \Twig_Node_Expression_Constant($this->getAttribute('package'), $this->getLine());
+ }
+
+ return new \Twig_Node_Expression_Function(
+ new \Twig_Node_Expression_Name('asset', $this->getLine()),
+ new \Twig_Node($arguments),
+ $this->getLine()
+ );
+ }
+}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/AsseticTokenParser.php b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticTokenParser.php
new file mode 100644
index 0000000000..fc0673ea24
--- /dev/null
+++ b/src/Symfony/Bundle/AsseticBundle/Twig/AsseticTokenParser.php
@@ -0,0 +1,28 @@
+
+ *
+ * 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\Asset\AssetInterface;
+use Assetic\Extension\Twig\AsseticTokenParser as BaseAsseticTokenParser;
+
+/**
+ * Assetic token parser.
+ *
+ * @author Kris Wallsmith
+ */
+class AsseticTokenParser extends BaseAsseticTokenParser
+{
+ protected function createNode(AssetInterface $asset, \Twig_NodeInterface $body, array $inputs, array $filters, $name, array $attributes = array(), $lineno = 0, $tag = null)
+ {
+ return new AsseticNode($asset, $body, $inputs, $filters, $name, $attributes, $lineno, $tag);
+ }
+}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicExtension.php b/src/Symfony/Bundle/AsseticBundle/Twig/DynamicExtension.php
deleted file mode 100644
index fc95aec740..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicExtension.php
+++ /dev/null
@@ -1,32 +0,0 @@
-
- *
- * 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\AsseticExtension;
-use Assetic\Factory\AssetFactory;
-
-/**
- * The dynamic extension is used when use_controllers is enabled.
- *
- * @author Kris Wallsmith
- */
-class DynamicExtension extends AsseticExtension
-{
- public function getTokenParsers()
- {
- return array(
- new DynamicTokenParser($this->factory, 'javascripts', 'js/*.js', $this->debug, false, array('package')),
- new DynamicTokenParser($this->factory, 'stylesheets', 'css/*.css', $this->debug, false, array('package')),
- new DynamicTokenParser($this->factory, 'image', 'images/*', $this->debug, true, array('package')),
- );
- }
-}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicNode.php b/src/Symfony/Bundle/AsseticBundle/Twig/DynamicNode.php
deleted file mode 100644
index b17c0d0541..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicNode.php
+++ /dev/null
@@ -1,36 +0,0 @@
-
- *
- * 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\AsseticNode;
-
-/**
- * The "dynamic" node uses a controller to render assets.
- *
- * @author Kris Wallsmith
- */
-class DynamicNode extends AsseticNode
-{
- /**
- * Renders the asset URL using Symfony's path() function.
- */
- protected function getAssetUrlNode(\Twig_NodeInterface $body)
- {
- return new \Twig_Node_Expression_Function(
- new \Twig_Node_Expression_Name('path', $body->getLine()),
- new \Twig_Node(array(
- new \Twig_Node_Expression_Constant('assetic_'.$this->getAttribute('name'), $body->getLine()),
- )),
- $body->getLine()
- );
- }
-}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicTokenParser.php b/src/Symfony/Bundle/AsseticBundle/Twig/DynamicTokenParser.php
deleted file mode 100644
index 418b48d50e..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/DynamicTokenParser.php
+++ /dev/null
@@ -1,27 +0,0 @@
-
- *
- * 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\AsseticTokenParser;
-
-/**
- * Parses an Assetic tag.
- *
- * @author Kris Wallsmith
- */
-class DynamicTokenParser extends AsseticTokenParser
-{
- static protected function createNode(\Twig_NodeInterface $body, array $inputs, array $filters, array $attributes, $lineno = 0, $tag = null)
- {
- return new DynamicNode($body, $inputs, $filters, $attributes, $lineno, $tag);
- }
-}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/StaticExtension.php b/src/Symfony/Bundle/AsseticBundle/Twig/StaticExtension.php
deleted file mode 100644
index 884e6c7f24..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/StaticExtension.php
+++ /dev/null
@@ -1,32 +0,0 @@
-
- *
- * 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\AsseticExtension;
-use Assetic\Factory\AssetFactory;
-
-/**
- * The static extension is used when use_controllers is disabled.
- *
- * @author Kris Wallsmith
- */
-class StaticExtension extends AsseticExtension
-{
- public function getTokenParsers()
- {
- return array(
- new StaticTokenParser($this->factory, 'javascripts', 'js/*.js', $this->debug, false, array('package')),
- new StaticTokenParser($this->factory, 'stylesheets', 'css/*.css', $this->debug, false, array('package')),
- new StaticTokenParser($this->factory, 'image', 'images/*', $this->debug, true, array('package')),
- );
- }
-}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/StaticNode.php b/src/Symfony/Bundle/AsseticBundle/Twig/StaticNode.php
deleted file mode 100644
index 73f0fe383f..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/StaticNode.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- *
- * 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\AsseticNode;
-
-/**
- * The "static" node references a file in the web directory.
- *
- * @author Kris Wallsmith
- */
-class StaticNode extends AsseticNode
-{
- /**
- * Renders the asset URL using Symfony's asset() function.
- */
- protected function getAssetUrlNode(\Twig_NodeInterface $body)
- {
- return new \Twig_Node_Expression_Function(
- new \Twig_Node_Expression_Name('asset', $body->getLine()),
- new \Twig_Node(array(
- new \Twig_Node_Expression_Constant($this->getAttribute('output'), $body->getLine()),
- new \Twig_Node_Expression_Constant($this->hasAttribute('package') ? $this->getAttribute('package') : null, $body->getLine()),
- )),
- $body->getLine()
- );
- }
-}
diff --git a/src/Symfony/Bundle/AsseticBundle/Twig/StaticTokenParser.php b/src/Symfony/Bundle/AsseticBundle/Twig/StaticTokenParser.php
deleted file mode 100644
index 5ee21b8ec7..0000000000
--- a/src/Symfony/Bundle/AsseticBundle/Twig/StaticTokenParser.php
+++ /dev/null
@@ -1,27 +0,0 @@
-
- *
- * 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\AsseticTokenParser;
-
-/**
- * Parses an Assetic tag.
- *
- * @author Kris Wallsmith
- */
-class StaticTokenParser extends AsseticTokenParser
-{
- static protected function createNode(\Twig_NodeInterface $body, array $inputs, array $filters, array $attributes, $lineno = 0, $tag = null)
- {
- return new StaticNode($body, $inputs, $filters, $attributes, $lineno, $tag);
- }
-}