changed the way globals behave to be more BC with 1.11 and to avoid speed problems at runtime introduced in 4487387 (closes #932)

* Globals are now managed by themselves, independently of other elements
  contained in extensions

* A global variable value can now be changed after the runtime has been
  initialized (to be more BC with the way Twig 1.11 works)

* Extensions are not initialized anymore when rendering a template that
  is already in the cache (like in Twig 1.11)
This commit is contained in:
Fabien Potencier
2012-12-27 09:44:14 +01:00
parent a65e7e4e2e
commit 2450f79a0e
2 changed files with 127 additions and 9 deletions
+22 -9
View File
@@ -964,16 +964,24 @@ class Twig_Environment
/**
* Registers a Global.
*
* New globals can be added before compiling or rendering a template;
* but after, you can only update existing globals.
*
* @param string $name The global name
* @param mixed $value The global value
*/
public function addGlobal($name, $value)
{
if ($this->extensionInitialized) {
throw new LogicException(sprintf('Unable to add global "%s" as extensions have already been initialized.', $name));
if (($this->extensionInitialized || $this->runtimeInitialized) && !array_key_exists($name, $this->globals)) {
throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
}
$this->staging->addGlobal($name, $value);
if ($this->extensionInitialized || $this->runtimeInitialized) {
// update the value
$this->globals[$name] = $value;
} else {
$this->staging->addGlobal($name, $value);
}
}
/**
@@ -983,8 +991,8 @@ class Twig_Environment
*/
public function getGlobals()
{
if (!$this->extensionInitialized) {
$this->initExtensions();
if (null === $this->globals || !($this->runtimeInitialized || $this->extensionInitialized)) {
$this->initGlobals();
}
return $this->globals;
@@ -1052,6 +1060,15 @@ class Twig_Environment
return array_keys($alternatives);
}
protected function initGlobals()
{
$this->globals = array();
foreach ($this->extensions as $extension) {
$this->globals = array_merge($this->globals, $extension->getGlobals());
}
$this->globals = array_merge($this->globals, $this->staging->getGlobals());
}
protected function initExtensions()
{
if ($this->extensionInitialized) {
@@ -1063,7 +1080,6 @@ class Twig_Environment
$this->filters = array();
$this->functions = array();
$this->tests = array();
$this->globals = array();
$this->visitors = array();
$this->unaryOperators = array();
$this->binaryOperators = array();
@@ -1112,9 +1128,6 @@ class Twig_Environment
$this->tests[$name] = $test;
}
// globals
$this->globals = array_merge($this->globals, $extension->getGlobals());
// token parsers
foreach ($extension->getTokenParsers() as $parser) {
if ($parser instanceof Twig_TokenParserInterface) {
+105
View File
@@ -33,6 +33,111 @@ class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
return $filename;
}
public function testGlobals()
{
// globals can be added after calling getGlobals
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after runtime init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->initRuntime();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after extensions init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->getFunctions();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
// globals can be modified after extensions and runtime init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->getFunctions();
$twig->initRuntime();
$twig->addGlobal('foo', 'bar');
$globals = $twig->getGlobals();
$this->assertEquals('bar', $globals['foo']);
// globals cannot be added after runtime init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->initRuntime();
try {
$twig->addGlobal('bar', 'bar');
$this->fail();
} catch (LogicException $e) {
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
}
// globals cannot be added after extensions init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->getFunctions();
try {
$twig->addGlobal('bar', 'bar');
$this->fail();
} catch (LogicException $e) {
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
}
// globals cannot be added after extensions and runtime init
$twig = new Twig_Environment(new Twig_Loader_String());
$twig->addGlobal('foo', 'foo');
$globals = $twig->getGlobals();
$twig->getFunctions();
$twig->initRuntime();
try {
$twig->addGlobal('bar', 'bar');
$this->fail();
} catch (LogicException $e) {
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
}
}
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
{
$options = array('cache' => sys_get_temp_dir().'/twig', 'auto_reload' => false, 'debug' => false);
// force compilation
$twig = new Twig_Environment(new Twig_Loader_String(), $options);
$cache = $twig->getCacheFilename('{{ foo }}');
if (!is_dir(dirname($cache))) {
mkdir(dirname($cache), 0777, true);
}
file_put_contents($cache, $twig->compileSource('{{ foo }}', '{{ foo }}'));
// check that extensions won't be initialized when rendering a template that is already in the cache
$twig = $this
->getMockBuilder('Twig_Environment')
->setConstructorArgs(array(new Twig_Loader_String(), $options))
->setMethods(array('initExtensions'))
->getMock()
;
$twig->expects($this->never())->method('initExtensions');
// render template
$output = $twig->render('{{ foo }}', array('foo' => 'bar'));
$this->assertEquals('bar', $output);
unlink($cache);
}
public function testAddExtension()
{
$twig = new Twig_Environment(new Twig_Loader_String());