From afa47bd9a42c40aa87e4d87452e78e95c1c70bee Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 19 Dec 2010 14:01:21 +0100 Subject: [PATCH] added global variables --- CHANGELOG | 1 + lib/Twig/Environment.php | 22 ++++++++++++++++++++++ lib/Twig/Extension.php | 10 ++++++++++ lib/Twig/ExtensionInterface.php | 7 +++++++ lib/Twig/Node/Macro.php | 4 ++-- lib/Twig/Node/Module.php | 2 ++ test/Twig/Tests/Fixtures/globals.test | 25 +++++++++++++++++++++++++ test/Twig/Tests/Node/MacroTest.php | 4 ++-- test/Twig/Tests/Node/ModuleTest.php | 6 ++++++ test/Twig/Tests/Node/SandboxedModuleTest.php | 4 ++++ 10 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 test/Twig/Tests/Fixtures/globals.test diff --git a/CHANGELOG b/CHANGELOG index efa3759..53c7bb2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ Backward incompatibilities: Changes: + * added global variables support * made macros return their value instead of echoing directly (fixes calling a macro in sandbox mode) * added the "from" tag to import macros as functions * added support for functions (a function is just syntactic sugar for a getAttribute() call) diff --git a/lib/Twig/Environment.php b/lib/Twig/Environment.php index 5d683c1..d561ee5 100644 --- a/lib/Twig/Environment.php +++ b/lib/Twig/Environment.php @@ -27,6 +27,7 @@ class Twig_Environment protected $visitors; protected $filters; protected $tests; + protected $globals; protected $runtimeInitialized; protected $loadedTemplates; protected $strictVariables; @@ -454,6 +455,27 @@ class Twig_Environment return $this->tests; } + public function addGlobal($name, $value) + { + if (null === $this->globals) { + $this->getGlobals(); + } + + $this->globals[$name] = $value; + } + + public function getGlobals() + { + if (null === $this->globals) { + $this->globals = array(); + foreach ($this->getExtensions() as $extension) { + $this->globals = array_merge($this->globals, $extension->getGlobals()); + } + } + + return $this->globals; + } + public function getUnaryOperators() { if (null === $this->unaryOperators) { diff --git a/lib/Twig/Extension.php b/lib/Twig/Extension.php index 9294fc5..41832e2 100644 --- a/lib/Twig/Extension.php +++ b/lib/Twig/Extension.php @@ -70,4 +70,14 @@ abstract class Twig_Extension implements Twig_ExtensionInterface { return array(); } + + /** + * Returns a list of global functions to add to the existing list. + * + * @return array An array of global functions + */ + public function getGlobals() + { + return array(); + } } diff --git a/lib/Twig/ExtensionInterface.php b/lib/Twig/ExtensionInterface.php index f3684f9..d430b95 100644 --- a/lib/Twig/ExtensionInterface.php +++ b/lib/Twig/ExtensionInterface.php @@ -62,6 +62,13 @@ interface Twig_ExtensionInterface public function getOperators(); /** + * Returns a list of global functions to add to the existing list. + * + * @return array An array of global functions + */ + public function getGlobals(); + + /** * Returns the name of the extension. * * @return string The extension name diff --git a/lib/Twig/Node/Macro.php b/lib/Twig/Node/Macro.php index 7b9d31d..62f2da1 100644 --- a/lib/Twig/Node/Macro.php +++ b/lib/Twig/Node/Macro.php @@ -38,7 +38,7 @@ class Twig_Node_Macro extends Twig_Node ->addDebugInfo($this) ->write(sprintf("public function get%s(%s)\n", $this->getAttribute('name'), implode(', ', $arguments)), "{\n") ->indent() - ->write("\$context = array(\n") + ->write("\$context = array_merge(\$this->env->getGlobals(), array(\n") ->indent() ; @@ -53,7 +53,7 @@ class Twig_Node_Macro extends Twig_Node $compiler ->outdent() - ->write(");\n\n") + ->write("));\n\n") ->write("ob_start();\n") ->subcompile($this->getNode('body')) ->raw("\n") diff --git a/lib/Twig/Node/Module.php b/lib/Twig/Node/Module.php index aef28fb..d8c3641 100644 --- a/lib/Twig/Node/Module.php +++ b/lib/Twig/Node/Module.php @@ -102,6 +102,8 @@ class Twig_Node_Module extends Twig_Node protected function compileDisplayBody($compiler) { + $compiler->write("\$context = array_merge(\$this->env->getGlobals(), \$context);\n\n"); + if (null !== $this->getNode('parent')) { // remove all but import nodes foreach ($this->getNode('body') as $node) { diff --git a/test/Twig/Tests/Fixtures/globals.test b/test/Twig/Tests/Fixtures/globals.test new file mode 100644 index 0000000..02d577c --- /dev/null +++ b/test/Twig/Tests/Fixtures/globals.test @@ -0,0 +1,25 @@ +--TEST-- +global variables +--TEMPLATE-- +{{ foo() }} +{{ bar() }} +{% include "included.twig" %} +{% from "included.twig" import foobar %} +{{ foobar() }} +--TEMPLATE(included.twig)-- +{% macro foobar() %} +{{ foo() }} + +{% endmacro %} +{{ foo() }} + +--DATA-- +$twig->addGlobal('foo', new Twig_Function(new Foo(), 'getFoo')); +$twig->addGlobal('bar', new Twig_Function('barObj', 'getFoo')); +return array('barObj' => new Foo()); +--EXPECT-- +foo +foo + +foo +foo diff --git a/test/Twig/Tests/Node/MacroTest.php b/test/Twig/Tests/Node/MacroTest.php index c0dbda9..904cfb4 100644 --- a/test/Twig/Tests/Node/MacroTest.php +++ b/test/Twig/Tests/Node/MacroTest.php @@ -46,9 +46,9 @@ class Twig_Tests_Node_MacroTest extends Twig_Tests_Node_TestCase array($node, <<env->getGlobals(), array( "foo" => \$foo, - ); + )); ob_start(); echo "foo"; diff --git a/test/Twig/Tests/Node/ModuleTest.php b/test/Twig/Tests/Node/ModuleTest.php index edf9d2c..b0f94de 100644 --- a/test/Twig/Tests/Node/ModuleTest.php +++ b/test/Twig/Tests/Node/ModuleTest.php @@ -69,6 +69,8 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template { public function display(array \$context, array \$blocks = array()) { + \$context = array_merge(\$this->env->getGlobals(), \$context); + echo "foo"; } @@ -105,6 +107,8 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template public function display(array \$context, array \$blocks = array()) { + \$context = array_merge(\$this->env->getGlobals(), \$context); + \$context['macro'] = \$this->env->loadTemplate("foo.twig", true); \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks)); } @@ -148,6 +152,8 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template public function display(array \$context, array \$blocks = array()) { + \$context = array_merge(\$this->env->getGlobals(), \$context); + \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks)); } diff --git a/test/Twig/Tests/Node/SandboxedModuleTest.php b/test/Twig/Tests/Node/SandboxedModuleTest.php index b8a8196..5b41117 100644 --- a/test/Twig/Tests/Node/SandboxedModuleTest.php +++ b/test/Twig/Tests/Node/SandboxedModuleTest.php @@ -68,6 +68,8 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template public function display(array \$context, array \$blocks = array()) { \$this->checkSecurity(); + \$context = array_merge(\$this->env->getGlobals(), \$context); + echo "foo"; } @@ -114,6 +116,8 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template public function display(array \$context, array \$blocks = array()) { + \$context = array_merge(\$this->env->getGlobals(), \$context); + \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks)); } -- 1.7.2.5