ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
EnvironmentTest.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of Twig.
5  *
6  * (c) Fabien Potencier
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
12 require_once dirname(__FILE__).'/FilesystemHelper.php';
13 
14 class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
15 {
16  private $deprecations = array();
17 
21  public function testLegacyTokenizeSignature()
22  {
23  $env = new Twig_Environment();
24  $stream = $env->tokenize('{{ foo }}', 'foo');
25  $this->assertEquals('{{ foo }}', $stream->getSource());
26  $this->assertEquals('foo', $stream->getFilename());
27  }
28 
33  {
34  $loader = new Twig_Loader_Array(array('foo' => '{{ foo }}'));
35  $env = new Twig_Environment($loader);
36  $this->assertContains('getTemplateName', $env->compileSource('{{ foo }}', 'foo'));
37  }
38 
44  public function testRenderNoLoader()
45  {
46  $env = new Twig_Environment();
47  $env->render('test');
48  }
49 
50  public function testAutoescapeOption()
51  {
52  $loader = new Twig_Loader_Array(array(
53  'html' => '{{ foo }} {{ foo }}',
54  'js' => '{{ bar }} {{ bar }}',
55  ));
56 
57  $twig = new Twig_Environment($loader, array(
58  'debug' => true,
59  'cache' => false,
60  'autoescape' => array($this, 'escapingStrategyCallback'),
61  ));
62 
63  $this->assertEquals('foo&lt;br/ &gt; foo&lt;br/ &gt;', $twig->render('html', array('foo' => 'foo<br/ >')));
64  $this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >')));
65  }
66 
68  {
69  return $name;
70  }
71 
72  public function testGlobals()
73  {
74  // to be removed in 2.0
75  $loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
76  //$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
77  $loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Twig_Source('', '')));
78 
79  // globals can be added after calling getGlobals
80 
81  $twig = new Twig_Environment($loader);
82  $twig->addGlobal('foo', 'foo');
83  $twig->getGlobals();
84  $twig->addGlobal('foo', 'bar');
85  $globals = $twig->getGlobals();
86  $this->assertEquals('bar', $globals['foo']);
87 
88  // globals can be modified after a template has been loaded
89  $twig = new Twig_Environment($loader);
90  $twig->addGlobal('foo', 'foo');
91  $twig->getGlobals();
92  $twig->loadTemplate('index');
93  $twig->addGlobal('foo', 'bar');
94  $globals = $twig->getGlobals();
95  $this->assertEquals('bar', $globals['foo']);
96 
97  // globals can be modified after extensions init
98  $twig = new Twig_Environment($loader);
99  $twig->addGlobal('foo', 'foo');
100  $twig->getGlobals();
101  $twig->getFunctions();
102  $twig->addGlobal('foo', 'bar');
103  $globals = $twig->getGlobals();
104  $this->assertEquals('bar', $globals['foo']);
105 
106  // globals can be modified after extensions and a template has been loaded
107  $arrayLoader = new Twig_Loader_Array(array('index' => '{{foo}}'));
108  $twig = new Twig_Environment($arrayLoader);
109  $twig->addGlobal('foo', 'foo');
110  $twig->getGlobals();
111  $twig->getFunctions();
112  $twig->loadTemplate('index');
113  $twig->addGlobal('foo', 'bar');
114  $globals = $twig->getGlobals();
115  $this->assertEquals('bar', $globals['foo']);
116 
117  $twig = new Twig_Environment($arrayLoader);
118  $twig->getGlobals();
119  $twig->addGlobal('foo', 'bar');
120  $template = $twig->loadTemplate('index');
121  $this->assertEquals('bar', $template->render(array()));
122 
123  /* to be uncomment in Twig 2.0
124  // globals cannot be added after a template has been loaded
125  $twig = new Twig_Environment($loader);
126  $twig->addGlobal('foo', 'foo');
127  $twig->getGlobals();
128  $twig->loadTemplate('index');
129  try {
130  $twig->addGlobal('bar', 'bar');
131  $this->fail();
132  } catch (LogicException $e) {
133  $this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
134  }
135 
136  // globals cannot be added after extensions init
137  $twig = new Twig_Environment($loader);
138  $twig->addGlobal('foo', 'foo');
139  $twig->getGlobals();
140  $twig->getFunctions();
141  try {
142  $twig->addGlobal('bar', 'bar');
143  $this->fail();
144  } catch (LogicException $e) {
145  $this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
146  }
147 
148  // globals cannot be added after extensions and a template has been loaded
149  $twig = new Twig_Environment($loader);
150  $twig->addGlobal('foo', 'foo');
151  $twig->getGlobals();
152  $twig->getFunctions();
153  $twig->loadTemplate('index');
154  try {
155  $twig->addGlobal('bar', 'bar');
156  $this->fail();
157  } catch (LogicException $e) {
158  $this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
159  }
160 
161  // test adding globals after a template has been loaded without call to getGlobals
162  $twig = new Twig_Environment($loader);
163  $twig->loadTemplate('index');
164  try {
165  $twig->addGlobal('bar', 'bar');
166  $this->fail();
167  } catch (LogicException $e) {
168  $this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
169  }
170  */
171  }
172 
174  {
175  $cache = new Twig_Cache_Filesystem($dir = sys_get_temp_dir().'/twig');
176  $options = array('cache' => $cache, 'auto_reload' => false, 'debug' => false);
177 
178  // force compilation
179  $twig = new Twig_Environment($loader = new Twig_Loader_Array(array('index' => '{{ foo }}')), $options);
180 
181  $key = $cache->generateKey('index', $twig->getTemplateClass('index'));
182  $cache->write($key, $twig->compileSource(new Twig_Source('{{ foo }}', 'index')));
183 
184  // check that extensions won't be initialized when rendering a template that is already in the cache
185  $twig = $this
186  ->getMockBuilder('Twig_Environment')
187  ->setConstructorArgs(array($loader, $options))
188  ->setMethods(array('initExtensions'))
189  ->getMock()
190  ;
191 
192  $twig->expects($this->never())->method('initExtensions');
193 
194  // render template
195  $output = $twig->render('index', array('foo' => 'bar'));
196  $this->assertEquals('bar', $output);
197 
199  }
200 
201  public function testAutoReloadCacheMiss()
202  {
203  $templateName = __FUNCTION__;
204  $templateContent = __FUNCTION__;
205 
206  $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock();
207  $loader = $this->getMockLoader($templateName, $templateContent);
208  $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false));
209 
210  // Cache miss: getTimestamp returns 0 and as a result the load() is
211  // skipped.
212  $cache->expects($this->once())
213  ->method('generateKey')
214  ->will($this->returnValue('key'));
215  $cache->expects($this->once())
216  ->method('getTimestamp')
217  ->will($this->returnValue(0));
218  $loader->expects($this->never())
219  ->method('isFresh');
220  $cache->expects($this->once())
221  ->method('write');
222  $cache->expects($this->once())
223  ->method('load');
224 
225  $twig->loadTemplate($templateName);
226  }
227 
228  public function testAutoReloadCacheHit()
229  {
230  $templateName = __FUNCTION__;
231  $templateContent = __FUNCTION__;
232 
233  $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock();
234  $loader = $this->getMockLoader($templateName, $templateContent);
235  $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false));
236 
237  $now = time();
238 
239  // Cache hit: getTimestamp returns something > extension timestamps and
240  // the loader returns true for isFresh().
241  $cache->expects($this->once())
242  ->method('generateKey')
243  ->will($this->returnValue('key'));
244  $cache->expects($this->once())
245  ->method('getTimestamp')
246  ->will($this->returnValue($now));
247  $loader->expects($this->once())
248  ->method('isFresh')
249  ->will($this->returnValue(true));
250  $cache->expects($this->atLeastOnce())
251  ->method('load');
252 
253  $twig->loadTemplate($templateName);
254  }
255 
257  {
258  $templateName = __FUNCTION__;
259  $templateContent = __FUNCTION__;
260 
261  $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock();
262  $loader = $this->getMockLoader($templateName, $templateContent);
263  $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false));
264 
265  $now = time();
266 
267  $cache->expects($this->once())
268  ->method('generateKey')
269  ->will($this->returnValue('key'));
270  $cache->expects($this->once())
271  ->method('getTimestamp')
272  ->will($this->returnValue($now));
273  $loader->expects($this->once())
274  ->method('isFresh')
275  ->will($this->returnValue(false));
276  $cache->expects($this->once())
277  ->method('write');
278  $cache->expects($this->once())
279  ->method('load');
280 
281  $twig->loadTemplate($templateName);
282  }
283 
288  {
289  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
290 
293  $twig->addExtension($ext1);
294  $twig->addExtension($ext2);
295 
296  $this->assertTrue($twig->hasExtension('ext1'));
297  $this->assertTrue($twig->hasExtension('ext2'));
298 
299  $this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName'));
300 
301  $this->assertSame($ext1, $twig->getExtension('ext1'));
302  $this->assertSame($ext2, $twig->getExtension('ext2'));
303  }
304 
306  {
307  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
308  $twig->addExtension($ext = new Twig_Tests_EnvironmentTest_Extension());
309  $this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension'));
310  $this->assertTrue($twig->hasExtension('\Twig_Tests_EnvironmentTest_Extension'));
311 
312  $this->assertSame($ext, $twig->getExtension('Twig_Tests_EnvironmentTest_Extension'));
313  $this->assertSame($ext, $twig->getExtension('\Twig_Tests_EnvironmentTest_Extension'));
314 
315  $this->assertTrue($twig->hasExtension('Twig\Tests\EnvironmentTest\Extension'));
316  $this->assertSame($ext, $twig->getExtension('Twig\Tests\EnvironmentTest\Extension'));
317  }
318 
319  public function testAddExtension()
320  {
321  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
322  $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
323 
324  $this->assertArrayHasKey('test', $twig->getTags());
325  $this->assertArrayHasKey('foo_filter', $twig->getFilters());
326  $this->assertArrayHasKey('foo_function', $twig->getFunctions());
327  $this->assertArrayHasKey('foo_test', $twig->getTests());
328  $this->assertArrayHasKey('foo_unary', $twig->getUnaryOperators());
329  $this->assertArrayHasKey('foo_binary', $twig->getBinaryOperators());
330  $this->assertArrayHasKey('foo_global', $twig->getGlobals());
331  $visitors = $twig->getNodeVisitors();
332  $found = false;
333  foreach ($visitors as $visitor) {
334  if ($visitor instanceof Twig_Tests_EnvironmentTest_NodeVisitor) {
335  $found = true;
336  }
337  }
338  $this->assertTrue($found);
339  }
340 
345  {
346  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
347  $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithGlobals());
348 
349  $this->deprecations = array();
350  set_error_handler(array($this, 'handleError'));
351 
352  $this->assertArrayHasKey('foo_global', $twig->getGlobals());
353 
354  $this->assertCount(1, $this->deprecations);
355  $this->assertContains('Defining the getGlobals() method in the "Twig_Tests_EnvironmentTest_Extension_WithGlobals" extension ', $this->deprecations[0]);
356 
357  restore_error_handler();
358  }
359 
363  public function testRemoveExtension()
364  {
365  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
367  $twig->removeExtension('environment_test');
368 
369  $this->assertArrayNotHasKey('test', $twig->getTags());
370  $this->assertArrayNotHasKey('foo_filter', $twig->getFilters());
371  $this->assertArrayNotHasKey('foo_function', $twig->getFunctions());
372  $this->assertArrayNotHasKey('foo_test', $twig->getTests());
373  $this->assertArrayNotHasKey('foo_unary', $twig->getUnaryOperators());
374  $this->assertArrayNotHasKey('foo_binary', $twig->getBinaryOperators());
375  $this->assertArrayNotHasKey('foo_global', $twig->getGlobals());
376  $this->assertCount(2, $twig->getNodeVisitors());
377  }
378 
379  public function testAddMockExtension()
380  {
381  // should be replaced by the following in 2.0 (this current code is just to avoid a dep notice)
382  // $extension = $this->getMockBuilder('Twig_Extension')->getMock();
383  $extension = eval(<<<EOF
384 class Twig_Tests_EnvironmentTest_ExtensionInEval extends Twig_Extension
385 {
386 }
387 EOF
388  );
389  $extension = new Twig_Tests_EnvironmentTest_ExtensionInEval();
390 
391  $loader = new Twig_Loader_Array(array('page' => 'hey'));
392 
393  $twig = new Twig_Environment($loader);
394  $twig->addExtension($extension);
395 
396  $this->assertInstanceOf('Twig_ExtensionInterface', $twig->getExtension(get_class($extension)));
397  $this->assertTrue($twig->isTemplateFresh('page', time()));
398  }
399 
401  {
402  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
404  $twig->initRuntime();
405 
406  // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
407  // can be executed without throwing any deprecations
408  $this->addToAssertionCount(1);
409  }
410 
415  {
416  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
418 
419  $this->deprecations = array();
420  set_error_handler(array($this, 'handleError'));
421 
422  $twig->initRuntime();
423 
424  $this->assertCount(1, $this->deprecations);
425  $this->assertContains('Defining the initRuntime() method in the "Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime" extension is deprecated since version 1.23.', $this->deprecations[0]);
426 
427  restore_error_handler();
428  }
429 
430  public function handleError($type, $msg)
431  {
432  if (E_USER_DEPRECATED === $type) {
433  $this->deprecations[] = $msg;
434  }
435  }
436 
440  public function testOverrideExtension()
441  {
442  $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
444 
445  $this->deprecations = array();
446  set_error_handler(array($this, 'handleError'));
447 
450 
451  $this->assertCount(1, $this->deprecations);
452  $this->assertContains('The possibility to register the same extension twice', $this->deprecations[0]);
453 
454  restore_error_handler();
455  }
456 
457  public function testAddRuntimeLoader()
458  {
459  $runtimeLoader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock();
460  $runtimeLoader->expects($this->any())->method('load')->will($this->returnValue(new Twig_Tests_EnvironmentTest_Runtime()));
461 
462  $loader = new Twig_Loader_Array(array(
463  'func_array' => '{{ from_runtime_array("foo") }}',
464  'func_array_default' => '{{ from_runtime_array() }}',
465  'func_array_named_args' => '{{ from_runtime_array(name="foo") }}',
466  'func_string' => '{{ from_runtime_string("foo") }}',
467  'func_string_default' => '{{ from_runtime_string() }}',
468  'func_string_named_args' => '{{ from_runtime_string(name="foo") }}',
469  ));
470 
471  $twig = new Twig_Environment($loader);
472  $twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime());
473  $twig->addRuntimeLoader($runtimeLoader);
474 
475  $this->assertEquals('foo', $twig->render('func_array'));
476  $this->assertEquals('bar', $twig->render('func_array_default'));
477  $this->assertEquals('foo', $twig->render('func_array_named_args'));
478  $this->assertEquals('foo', $twig->render('func_string'));
479  $this->assertEquals('bar', $twig->render('func_string_default'));
480  $this->assertEquals('foo', $twig->render('func_string_named_args'));
481  }
482 
488  {
489  $twig = new Twig_Environment(new Twig_Loader_Array(array(
490  'base.html.twig' => '{% extends "base.html.twig" %}',
491  )));
492 
493  $twig->loadTemplate('base.html.twig');
494  }
495 
501  {
502  $twig = new Twig_Environment(new Twig_Loader_Array(array(
503  'base1.html.twig' => '{% extends "base2.html.twig" %}',
504  'base2.html.twig' => '{% extends "base1.html.twig" %}',
505  )));
506 
507  $twig->loadTemplate('base1.html.twig');
508  }
509 
510  protected function getMockLoader($templateName, $templateContent)
511  {
512  // to be removed in 2.0
513  $loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
514  //$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock();
515  $loader->expects($this->any())
516  ->method('getSourceContext')
517  ->with($templateName)
518  ->will($this->returnValue(new Twig_Source($templateContent, $templateName)));
519  $loader->expects($this->any())
520  ->method('getCacheKey')
521  ->with($templateName)
522  ->will($this->returnValue($templateName));
523 
524  return $loader;
525  }
526 }
527 
529 {
530  public function getGlobals()
531  {
532  return array(
533  'foo_global' => 'foo_global',
534  );
535  }
536 }
537 
539 {
540  public function getTokenParsers()
541  {
542  return array(
544  );
545  }
546 
547  public function getNodeVisitors()
548  {
549  return array(
551  );
552  }
553 
554  public function getFilters()
555  {
556  return array(
557  new Twig_SimpleFilter('foo_filter', 'foo_filter'),
558  );
559  }
560 
561  public function getTests()
562  {
563  return array(
564  new Twig_SimpleTest('foo_test', 'foo_test'),
565  );
566  }
567 
568  public function getFunctions()
569  {
570  return array(
571  new Twig_SimpleFunction('foo_function', 'foo_function'),
572  );
573  }
574 
575  public function getOperators()
576  {
577  return array(
578  array('foo_unary' => array()),
579  array('foo_binary' => array()),
580  );
581  }
582 
583  public function getGlobals()
584  {
585  return array(
586  'foo_global' => 'foo_global',
587  );
588  }
589 }
590 class_alias('Twig_Tests_EnvironmentTest_Extension', 'Twig\Tests\EnvironmentTest\Extension', false);
591 
593 {
594  public function getName()
595  {
596  return 'environment_test';
597  }
598 }
599 
601 {
602  private $name;
603 
604  public function __construct($name)
605  {
606  $this->name = $name;
607  }
608 
609  public function getName()
610  {
611  return $this->name;
612  }
613 }
614 
616 {
617  public function parse(Twig_Token $token)
618  {
619  }
620 
621  public function getTag()
622  {
623  return 'test';
624  }
625 }
626 
628 {
629  public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
630  {
631  return $node;
632  }
633 
634  public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
635  {
636  return $node;
637  }
638 
639  public function getPriority()
640  {
641  return 0;
642  }
643 }
644 
646 {
647  public function initRuntime(Twig_Environment $env)
648  {
649  }
650 }
651 
653 {
654  public function initRuntime(Twig_Environment $env)
655  {
656  }
657 }
658 
660 {
661  public function getFunctions()
662  {
663  return array(
664  new Twig_SimpleFunction('from_runtime_array', array('Twig_Tests_EnvironmentTest_Runtime', 'fromRuntime')),
665  new Twig_SimpleFunction('from_runtime_string', 'Twig_Tests_EnvironmentTest_Runtime::fromRuntime'),
666  );
667  }
668 
669  public function getName()
670  {
671  return 'from_runtime';
672  }
673 }
674 
676 {
677  public function fromRuntime($name = 'bar')
678  {
679  return $name;
680  }
681 }
682 
683 // to be removed in 2.0
685 {
686 }
Represents a node in the AST.
Represents a template function.
$template
$type
getMockLoader($templateName, $templateContent)
Enables usage of the deprecated Twig_Extension::getGlobals() method.
Enables usage of the deprecated Twig_Extension::initRuntime() method.
$stream
PHP stream implementation.
Represents a template filter.
Base class for all token parsers.
Definition: TokenParser.php:17
$env
Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
testAddExtensionWithDeprecatedGetGlobals()
PHP 5.3
testRenderNoLoader()
LogicException You must set a loader first.
testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
Adds a getSourceContext() method for loaders.
once($eventName, callable $callBack, $priority=100)
Subscribe to an event exactly once.
testInitRuntimeWithAnExtensionUsingInitRuntimeDeprecation()
PHP 5.3
parse($uri)
Parses a URI and returns its individual components.
Definition: functions.php:181
testFailLoadTemplateOnComplexCircularReference()
Twig_Error_Runtime Circular reference detected for Twig template "base1.html.twig", path: base1.html.twig -> base2.html.twig -> base1.html.twig in "base1.html.twig" at line 1
Implements a cache on the filesystem.
Definition: Filesystem.php:17
testInitRuntimeWithAnExtensionUsingInitRuntimeNoDeprecation()
testFailLoadTemplateOnCircularReference()
Twig_Error_Runtime Circular reference detected for Twig template "base.html.twig", path: base.html.twig -> base.html.twig in "base.html.twig" at line 1
Represents a template test.
Definition: SimpleTest.php:19
Holds information about a non-compiled Twig template.
Definition: Source.php:19
Stores the Twig configuration.
Definition: Environment.php:17
Interface all loaders must implement.
Loads a template from an array.
Definition: Array.php:26
$key
Definition: croninfo.php:18
const EOF
How fgetc() reports an End Of File.
Definition: JSMin_lib.php:92