From 46fdbe64a6370fe51b45a71013776045083f76dc Mon Sep 17 00:00:00 2001 From: Warnar Boekkooi Date: Wed, 16 Jul 2014 17:43:19 +0800 Subject: [PATCH] Defer added prefix + unique now only renders once --- .../BoekkooiTwigJackExtension.php | 3 ++- src/DependencyInjection/Configuration.php | 10 ++++++++- src/Resources/config/defer.yml | 1 + src/Twig/Extension/DeferExtension.php | 15 ++++++++++++- src/Twig/Node/DeferReference.php | 22 ++++++++++++++----- src/Twig/TokenParser/Defer.php | 22 +++++++++++++------ tests/Twig/Node/DeferReferenceTest.php | 12 ++++++++-- 7 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/DependencyInjection/BoekkooiTwigJackExtension.php b/src/DependencyInjection/BoekkooiTwigJackExtension.php index eec8c4e..64808de 100644 --- a/src/DependencyInjection/BoekkooiTwigJackExtension.php +++ b/src/DependencyInjection/BoekkooiTwigJackExtension.php @@ -22,7 +22,8 @@ public function load(array $config, ContainerBuilder $container) $processor = new Processor(); $config = $processor->processConfiguration(new Configuration(), $config); - if ($config['defer']) { + if ($config['defer']['enabled']) { + $container->setParameter('boekkooi.twigjack.defer.prefix', $config['defer']['prefix']); $loader->load('defer.yml'); } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 2f23d34..ce3a819 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -19,7 +19,15 @@ public function getConfigTreeBuilder() $rootNode = $treeBuilder->root('boekkooi_twig_jack'); $rootNode ->children() - ->booleanNode('defer')->defaultTrue()->end() + ->arrayNode('defer') + ->treatNullLike(array()) + ->treatFalseLike(array('enabled' => false)) + ->treatTrueLike(array('enabled' => true)) + ->children() + ->booleanNode('enabled')->defaultTrue()->end() + ->scalarNode('prefix')->defaultValue('_defer_ref_')->end() + ->end() + ->end() ->booleanNode('exclamation')->defaultTrue()->end() ->end(); diff --git a/src/Resources/config/defer.yml b/src/Resources/config/defer.yml index f0c1bc6..3115469 100644 --- a/src/Resources/config/defer.yml +++ b/src/Resources/config/defer.yml @@ -5,5 +5,6 @@ services: # defer extension boekkooi.twigjack.defer.extension: class: %boekkooi.twigjack.defer.extension.class% + arguments: [ %boekkooi.twigjack.defer.prefix% ] tags: - { name: "twig.extension" } diff --git a/src/Twig/Extension/DeferExtension.php b/src/Twig/Extension/DeferExtension.php index eaf9dd8..6ce55ff 100644 --- a/src/Twig/Extension/DeferExtension.php +++ b/src/Twig/Extension/DeferExtension.php @@ -9,13 +9,21 @@ class DeferExtension extends \Twig_Extension { protected $references = array(); + + protected $deferBlockPrefix; + + public function __construct($deferBlockPrefix = '_defer_ref_') + { + $this->deferBlockPrefix = $deferBlockPrefix; + } + /** * {@inheritdoc} */ public function getTokenParsers() { return array( - new TokenParser\Defer() + new TokenParser\Defer($this->deferBlockPrefix) ); } @@ -36,6 +44,11 @@ public function cache($type, $name, $content) $this->references[$type][$name] = $content; } + public function contains($type, $name) + { + return isset($this->references[$type]) && isset($this->references[$type][$name]); + } + public function retrieve($type, $clear = true) { if (!isset($this->references[$type])) { diff --git a/src/Twig/Node/DeferReference.php b/src/Twig/Node/DeferReference.php index e811942..75dcd9b 100644 --- a/src/Twig/Node/DeferReference.php +++ b/src/Twig/Node/DeferReference.php @@ -11,11 +11,12 @@ */ class DeferReference extends Twig_Node_BlockReference { - public function __construct($name, $reference, $lineno, $tag = null) + public function __construct($name, $unique, $reference, $lineno, $tag = null) { parent::__construct($name, $lineno, $tag); $this->setAttribute('reference', $reference); + $this->setAttribute('unique', $unique); } /** @@ -28,9 +29,20 @@ public function compile(Twig_Compiler $compiler) $name = $this->getAttribute('name'); $reference = $this->getAttribute('reference'); - $compiler - ->addDebugInfo($this) - ->write("\$this->env->getExtension('defer')->cache('{$reference}', '{$name}', \$this->renderBlock('{$name}', \$context, \$blocks));\n") - ; + if ($this->getAttribute('unique')) { + $compiler + ->addDebugInfo($this) + ->write("if (!\$this->env->getExtension('defer')->contains('{$reference}', '{$name}')) {\n") + ->indent() + ->write("\$this->env->getExtension('defer')->cache('{$reference}', '{$name}', \$this->renderBlock('{$name}', \$context, \$blocks));\n") + ->outdent() + ->write("}\n") + ; + } else { + $compiler + ->addDebugInfo($this) + ->write("\$this->env->getExtension('defer')->cache('{$reference}', '{$name}', \$this->renderBlock('{$name}', \$context, \$blocks));\n") + ; + } } } diff --git a/src/Twig/TokenParser/Defer.php b/src/Twig/TokenParser/Defer.php index fefeca3..5401584 100644 --- a/src/Twig/TokenParser/Defer.php +++ b/src/Twig/TokenParser/Defer.php @@ -25,6 +25,13 @@ class Defer extends Twig_TokenParser { private static $i = 0; + protected $blockPrefix; + + public function __construct($blockPrefix) + { + $this->blockPrefix = $blockPrefix; + } + /** * Parses a token and returns a node. * @@ -39,15 +46,16 @@ public function parse(Twig_Token $token) $reference = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); $name = $stream->nextIf(\Twig_Token::NAME_TYPE); - if ($name === null) { - do { - $name = 'defer_ref_' . $reference . (self::$i++); - } while ($this->parser->hasBlock($name)); - } else { - $name = $name->getValue(); + $unique = $name === null; + if ($unique) { + $name = $this->blockPrefix . $name->getValue(); if ($this->parser->hasBlock($name)) { return null; } + } else { + do { + $name = $this->blockPrefix . $reference . (self::$i++); + } while ($this->parser->hasBlock($name)); } $this->parser->setBlock($name, $block = new Node\Defer($name, new Twig_Node(array()), $lineno)); @@ -74,7 +82,7 @@ public function parse(Twig_Token $token) $this->parser->popBlockStack(); $this->parser->popLocalScope(); - return new Node\DeferReference($name, $reference, $lineno, $this->getTag()); + return new Node\DeferReference($name, $unique, $reference, $lineno, $this->getTag()); } public function decideBlockEnd(Twig_Token $token) diff --git a/tests/Twig/Node/DeferReferenceTest.php b/tests/Twig/Node/DeferReferenceTest.php index c57a0fd..575cd8a 100644 --- a/tests/Twig/Node/DeferReferenceTest.php +++ b/tests/Twig/Node/DeferReferenceTest.php @@ -13,10 +13,11 @@ class DeferReferenceTest extends \Twig_Test_NodeTestCase */ public function testConstructor() { - $node = new DeferReference('foo', 'bar', 1); + $node = new DeferReference('foo', false, 'bar', 1); $this->assertEquals('foo', $node->getAttribute('name')); $this->assertEquals('bar', $node->getAttribute('reference')); + $this->assertEquals(false, $node->getAttribute('unique')); } /** @@ -31,9 +32,16 @@ public function testCompile($node, $source, $environment = null) public function getTests() { return array( - array(new DeferReference('foo', 'js', 1), <<env->getExtension('defer')->cache('js', 'foo', \$this->renderBlock('foo', \$context, \$blocks)); +EOF + ), + array(new DeferReference('foo', true, 'js', 1), <<env->getExtension('defer')->contains('js', 'foo')) { + \$this->env->getExtension('defer')->cache('js', 'foo', \$this->renderBlock('foo', \$context, \$blocks)); +} EOF ), );