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
),
);