mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-21 15:48:42 +00:00
optimized variable access when using PHP 5.4
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
* 1.4.0
|
* 1.4.0
|
||||||
|
|
||||||
|
* optimized variable access when using PHP 5.4
|
||||||
* changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby
|
* changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby
|
||||||
* added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders
|
* added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders
|
||||||
* added Twig_Function_Node to allow more complex functions to have their own Node class
|
* added Twig_Function_Node to allow more complex functions to have their own Node class
|
||||||
|
|||||||
@@ -35,18 +35,29 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|||||||
} elseif ($this->isSpecial()) {
|
} elseif ($this->isSpecial()) {
|
||||||
$compiler->raw($this->specialVars[$name]);
|
$compiler->raw($this->specialVars[$name]);
|
||||||
} else {
|
} else {
|
||||||
$compiler
|
if (version_compare(phpversion(), '5.4.0RC1', '>=') && ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables())) {
|
||||||
->raw('$this->getContext($context, ')
|
// PHP 5.4 ternary operator performance was optimized
|
||||||
->string($name)
|
$compiler
|
||||||
;
|
->raw('(isset($context[')
|
||||||
|
->string($name)
|
||||||
|
->raw(']) ? $context[')
|
||||||
|
->string($name)
|
||||||
|
->raw('] : null)')
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
$compiler
|
||||||
|
->raw('$this->getContext($context, ')
|
||||||
|
->string($name)
|
||||||
|
;
|
||||||
|
|
||||||
if ($this->getAttribute('ignore_strict_check')) {
|
if ($this->getAttribute('ignore_strict_check')) {
|
||||||
$compiler->raw(', true');
|
$compiler->raw(', true');
|
||||||
|
}
|
||||||
|
|
||||||
|
$compiler
|
||||||
|
->raw(')')
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
$compiler
|
|
||||||
->raw(')')
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||||||
$this->enterOptimizeFor($node, $env);
|
$this->enterOptimizeFor($node, $env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
|
if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
|
||||||
if ($this->inABody) {
|
if ($this->inABody) {
|
||||||
if (!$node instanceof Twig_Node_Expression) {
|
if (!$node instanceof Twig_Node_Expression) {
|
||||||
if (get_class($node) !== 'Twig_Node') {
|
if (get_class($node) !== 'Twig_Node') {
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase
|
|||||||
$attr = new Twig_Node_Expression_Constant('bar', 0);
|
$attr = new Twig_Node_Expression_Constant('bar', 0);
|
||||||
$args = new Twig_Node();
|
$args = new Twig_Node();
|
||||||
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ANY_CALL, 0);
|
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ANY_CALL, 0);
|
||||||
$tests[] = array($node, '$this->getAttribute($this->getContext($context, "foo"), "bar")');
|
$tests[] = array($node, sprintf('$this->getAttribute(%s, "bar")', $this->getVariableGetter('foo')));
|
||||||
|
|
||||||
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 0);
|
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 0);
|
||||||
$tests[] = array($node, '$this->getAttribute($this->getContext($context, "foo"), "bar", array(), "array")');
|
$tests[] = array($node, sprintf('$this->getAttribute(%s, "bar", array(), "array")', $this->getVariableGetter('foo')));
|
||||||
|
|
||||||
|
|
||||||
$args = new Twig_Node(array(
|
$args = new Twig_Node(array(
|
||||||
@@ -60,7 +60,7 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase
|
|||||||
new Twig_Node_Expression_Constant('bar', 0),
|
new Twig_Node_Expression_Constant('bar', 0),
|
||||||
));
|
));
|
||||||
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::METHOD_CALL, 0);
|
$node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::METHOD_CALL, 0);
|
||||||
$tests[] = array($node, '$this->getAttribute($this->getContext($context, "foo"), "bar", array($this->getContext($context, "foo"), "bar", ), "method")');
|
$tests[] = array($node, sprintf('$this->getAttribute(%s, "bar", array(%s, "bar", ), "method")', $this->getVariableGetter('foo'), $this->getVariableGetter('foo')));
|
||||||
|
|
||||||
return $tests;
|
return $tests;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,11 @@ class Twig_Tests_Node_Expression_NameTest extends Twig_Tests_Node_TestCase
|
|||||||
$context = new Twig_Node_Expression_Name('_context', 0);
|
$context = new Twig_Node_Expression_Name('_context', 0);
|
||||||
|
|
||||||
$env = new Twig_Environment(null, array('strict_variables' => true));
|
$env = new Twig_Environment(null, array('strict_variables' => true));
|
||||||
|
$env1 = new Twig_Environment(null, array('strict_variables' => false));
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array($node, '$this->getContext($context, "foo")', $env),
|
array($node, '$this->getContext($context, "foo")', $env),
|
||||||
array($node, '$this->getContext($context, "foo")'),
|
array($node, $this->getVariableGetter('foo'), $env1),
|
||||||
array($self, '$this'),
|
array($self, '$this'),
|
||||||
array($context, '$context'),
|
array($context, '$context'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
\$context['_parent'] = (array) \$context;
|
\$context['_parent'] = (array) \$context;
|
||||||
\$context['_seq'] = twig_ensure_traversable(\$this->getContext(\$context, "items"));
|
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('items')});
|
||||||
foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) {
|
foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
}
|
}
|
||||||
\$_parent = \$context['_parent'];
|
\$_parent = \$context['_parent'];
|
||||||
unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
|
unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
|
||||||
@@ -86,7 +86,7 @@ EOF
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
\$context['_parent'] = (array) \$context;
|
\$context['_parent'] = (array) \$context;
|
||||||
\$context['_seq'] = twig_ensure_traversable(\$this->getContext(\$context, "values"));
|
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
||||||
\$context['loop'] = array(
|
\$context['loop'] = array(
|
||||||
'parent' => \$context['_parent'],
|
'parent' => \$context['_parent'],
|
||||||
'index0' => 0,
|
'index0' => 0,
|
||||||
@@ -101,7 +101,7 @@ if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_
|
|||||||
\$context['loop']['last'] = 1 === \$length;
|
\$context['loop']['last'] = 1 === \$length;
|
||||||
}
|
}
|
||||||
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
++\$context['loop']['index0'];
|
++\$context['loop']['index0'];
|
||||||
++\$context['loop']['index'];
|
++\$context['loop']['index'];
|
||||||
\$context['loop']['first'] = false;
|
\$context['loop']['first'] = false;
|
||||||
@@ -128,7 +128,7 @@ EOF
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
\$context['_parent'] = (array) \$context;
|
\$context['_parent'] = (array) \$context;
|
||||||
\$context['_seq'] = twig_ensure_traversable(\$this->getContext(\$context, "values"));
|
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
||||||
\$context['loop'] = array(
|
\$context['loop'] = array(
|
||||||
'parent' => \$context['_parent'],
|
'parent' => \$context['_parent'],
|
||||||
'index0' => 0,
|
'index0' => 0,
|
||||||
@@ -137,7 +137,7 @@ EOF
|
|||||||
);
|
);
|
||||||
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
||||||
if (true) {
|
if (true) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
++\$context['loop']['index0'];
|
++\$context['loop']['index0'];
|
||||||
++\$context['loop']['index'];
|
++\$context['loop']['index'];
|
||||||
\$context['loop']['first'] = false;
|
\$context['loop']['first'] = false;
|
||||||
@@ -160,7 +160,7 @@ EOF
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
\$context['_parent'] = (array) \$context;
|
\$context['_parent'] = (array) \$context;
|
||||||
\$context['_seq'] = twig_ensure_traversable(\$this->getContext(\$context, "values"));
|
\$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')});
|
||||||
\$context['_iterated'] = false;
|
\$context['_iterated'] = false;
|
||||||
\$context['loop'] = array(
|
\$context['loop'] = array(
|
||||||
'parent' => \$context['_parent'],
|
'parent' => \$context['_parent'],
|
||||||
@@ -176,7 +176,7 @@ if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_
|
|||||||
\$context['loop']['last'] = 1 === \$length;
|
\$context['loop']['last'] = 1 === \$length;
|
||||||
}
|
}
|
||||||
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
\$context['_iterated'] = true;
|
\$context['_iterated'] = true;
|
||||||
++\$context['loop']['index0'];
|
++\$context['loop']['index0'];
|
||||||
++\$context['loop']['index'];
|
++\$context['loop']['index'];
|
||||||
@@ -188,7 +188,7 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!\$context['_iterated']) {
|
if (!\$context['_iterated']) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
}
|
}
|
||||||
\$_parent = \$context['_parent'];
|
\$_parent = \$context['_parent'];
|
||||||
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
|
unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class Twig_Tests_Node_IfTest extends Twig_Tests_Node_TestCase
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
if (true) {
|
if (true) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -71,9 +71,9 @@ EOF
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
if (true) {
|
if (true) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
} elseif (false) {
|
} elseif (false) {
|
||||||
echo \$this->getContext(\$context, "bar");
|
echo {$this->getVariableGetter('bar')};
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -87,9 +87,9 @@ EOF
|
|||||||
|
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
if (true) {
|
if (true) {
|
||||||
echo \$this->getContext(\$context, "foo");
|
echo {$this->getVariableGetter('foo')};
|
||||||
} else {
|
} else {
|
||||||
echo \$this->getContext(\$context, "bar");
|
echo {$this->getVariableGetter('bar')};
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ EOF
|
|||||||
$values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 0), new Twig_Node_Expression_Name('bar', 0)), array(), 0);
|
$values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 0), new Twig_Node_Expression_Name('bar', 0)), array(), 0);
|
||||||
$node = new Twig_Node_Set(false, $names, $values, 0);
|
$node = new Twig_Node_Set(false, $names, $values, 0);
|
||||||
$tests[] = array($node, <<<EOF
|
$tests[] = array($node, <<<EOF
|
||||||
list(\$context["foo"], \$context["bar"]) = array("foo", \$this->getContext(\$context, "bar"));
|
list(\$context["foo"], \$context["bar"]) = array("foo", {$this->getVariableGetter('bar')});
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -37,4 +37,13 @@ abstract class Twig_Tests_Node_TestCase extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
return new Twig_Environment();
|
return new Twig_Environment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getVariableGetter($name)
|
||||||
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
||||||
|
return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('$this->getContext($context, "%s")', $name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testRenderVariableBlockOptimizer()
|
public function testRenderVariableBlockOptimizer()
|
||||||
{
|
{
|
||||||
|
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
$env = new Twig_Environment(new Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||||
$env->addExtension(new Twig_Extension_Optimizer());
|
$env->addExtension(new Twig_Extension_Optimizer());
|
||||||
$stream = $env->parse($env->tokenize('{{ block(name|lower) }}', 'index'));
|
$stream = $env->parse($env->tokenize('{{ block(name|lower) }}', 'index'));
|
||||||
|
|||||||
Reference in New Issue
Block a user