4da2d57500eb5b49398aada87f1252d1a1c5abb4
[yaffs-website] / vendor / twig / twig / test / Twig / Tests / TemplateTest.php
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 class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
12 {
13     /**
14      * @expectedException LogicException
15      */
16     public function testDisplayBlocksAcceptTemplateOnlyAsBlocks()
17     {
18         $template = $this->getMockForAbstractClass('Twig_Template', array(), '', false);
19         $template->displayBlock('foo', array(), array('foo' => array(new stdClass(), 'foo')));
20     }
21
22     /**
23      * @dataProvider getAttributeExceptions
24      */
25     public function testGetAttributeExceptions($template, $message)
26     {
27         $templates = array('index' => $template);
28         $env = new Twig_Environment(new Twig_Loader_Array($templates), array('strict_variables' => true));
29         $template = $env->loadTemplate('index');
30
31         $context = array(
32             'string' => 'foo',
33             'null' => null,
34             'empty_array' => array(),
35             'array' => array('foo' => 'foo'),
36             'array_access' => new Twig_TemplateArrayAccessObject(),
37             'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(),
38             'object' => new stdClass(),
39         );
40
41         try {
42             $template->render($context);
43             $this->fail('Accessing an invalid attribute should throw an exception.');
44         } catch (Twig_Error_Runtime $e) {
45             $this->assertSame(sprintf($message, 'index'), $e->getMessage());
46         }
47     }
48
49     public function getAttributeExceptions()
50     {
51         return array(
52             array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1.'),
53             array('{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1.'),
54             array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'),
55             array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'),
56             array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1.'),
57             array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1.'),
58             array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1.'),
59             array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.'),
60             array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.'),
61             array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'),
62             array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'),
63             array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.'),
64             array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
65             array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
66             array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'),
67             array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'),
68         );
69     }
70
71     /**
72      * @dataProvider getGetAttributeWithSandbox
73      */
74     public function testGetAttributeWithSandbox($object, $item, $allowed)
75     {
76         $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
77         $policy = new Twig_Sandbox_SecurityPolicy(array(), array(), array(/*method*/), array(/*prop*/), array());
78         $twig->addExtension(new Twig_Extension_Sandbox($policy, !$allowed));
79         $template = new Twig_TemplateTest($twig);
80
81         try {
82             $template->getAttribute($object, $item, array(), 'any');
83
84             if (!$allowed) {
85                 $this->fail();
86             } else {
87                 $this->addToAssertionCount(1);
88             }
89         } catch (Twig_Sandbox_SecurityError $e) {
90             if ($allowed) {
91                 $this->fail();
92             } else {
93                 $this->addToAssertionCount(1);
94             }
95
96             $this->assertContains('is not allowed', $e->getMessage());
97         }
98     }
99
100     public function getGetAttributeWithSandbox()
101     {
102         return array(
103             array(new Twig_TemplatePropertyObject(), 'defined', false),
104             array(new Twig_TemplatePropertyObject(), 'defined', true),
105             array(new Twig_TemplateMethodObject(), 'defined', false),
106             array(new Twig_TemplateMethodObject(), 'defined', true),
107         );
108     }
109
110     /**
111      * @group legacy
112      */
113     public function testGetAttributeWithTemplateAsObject()
114     {
115         // to be removed in 2.0
116         $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock());
117         //$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock());
118
119         $template = new Twig_TemplateTest($twig, 'index.twig');
120         $template1 = new Twig_TemplateTest($twig, 'index1.twig');
121
122         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
123         $this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
124
125         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true'));
126         $this->assertEquals('1', $template->getAttribute($template1, 'true'));
127
128         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero'));
129         $this->assertEquals('0', $template->getAttribute($template1, 'zero'));
130
131         $this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
132         $this->assertSame('', $template->getAttribute($template1, 'empty'));
133
134         $this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true));
135         $this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true));
136         $this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true));
137         $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true));
138     }
139
140     /**
141      * @group legacy
142      * @expectedDeprecation Calling "string" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
143      * @expectedDeprecation Calling "string" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
144      * @expectedDeprecation Calling "true" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
145      * @expectedDeprecation Calling "true" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
146      * @expectedDeprecation Calling "zero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
147      * @expectedDeprecation Calling "zero" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
148      * @expectedDeprecation Calling "empty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
149      * @expectedDeprecation Calling "empty" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0.
150      * @expectedDeprecation Calling "renderBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead).
151      * @expectedDeprecation Calling "displayBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name") instead).
152      * @expectedDeprecation Calling "hasBlock" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name") is defined" instead).
153      * @expectedDeprecation Calling "render" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead).
154      * @expectedDeprecation Calling "display" on template "index.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index.twig") instead).
155      * @expectedDeprecation Calling "renderBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead).
156      * @expectedDeprecation Calling "displayBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use block("name", template) instead).
157      * @expectedDeprecation Calling "hasBlock" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use "block("name", template) is defined" instead).
158      * @expectedDeprecation Calling "render" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead).
159      * @expectedDeprecation Calling "display" on template "index1.twig" from template "index.twig" is deprecated since version 1.28 and won't be supported anymore in 2.0. Use include("index1.twig") instead).
160      */
161     public function testGetAttributeWithTemplateAsObjectForDeprecations()
162     {
163         // to be removed in 2.0
164         $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock());
165         //$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock());
166
167         $template = new Twig_TemplateTest($twig, 'index.twig');
168         $template1 = new Twig_TemplateTest($twig, 'index1.twig');
169
170         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string'));
171         $this->assertEquals('some_string', $template->getAttribute($template1, 'string'));
172
173         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true'));
174         $this->assertEquals('1', $template->getAttribute($template1, 'true'));
175
176         $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero'));
177         $this->assertEquals('0', $template->getAttribute($template1, 'zero'));
178
179         $this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty'));
180         $this->assertSame('', $template->getAttribute($template1, 'empty'));
181
182         $blocks = array('name' => array($template1, 'block_name'));
183
184         // trigger some deprecation notice messages to check them with @expectedDeprecation
185         $template->getAttribute($template, 'renderBlock', array('name', array(), $blocks));
186         $template->getAttribute($template, 'displayBlock', array('name', array(), $blocks));
187         $template->getAttribute($template, 'hasBlock', array('name', array()));
188         $template->getAttribute($template, 'render', array(array()));
189         $template->getAttribute($template, 'display', array(array()));
190
191         $template->getAttribute($template1, 'renderBlock', array('name', array(), $blocks));
192         $template->getAttribute($template1, 'displayBlock', array('name', array(), $blocks));
193         $template->getAttribute($template1, 'hasBlock', array('name', array()));
194         $template->getAttribute($template1, 'render', array(array()));
195         $template->getAttribute($template1, 'display', array(array()));
196
197         $this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true));
198         $this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true));
199         $this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true));
200         $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true));
201     }
202
203     /**
204      * @group legacy
205      * @expectedDeprecation Silent display of undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block('unknown') is defined" expression to test for block existence.
206      * @expectedDeprecation Silent display of undefined block "unknown" in template "index.twig" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block('unknown') is defined" expression to test for block existence.
207      */
208     public function testRenderBlockWithUndefinedBlock()
209     {
210         $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock());
211
212         $template = new Twig_TemplateTest($twig, 'index.twig');
213         $template->renderBlock('unknown', array());
214         $template->displayBlock('unknown', array());
215     }
216
217     public function testGetAttributeOnArrayWithConfusableKey()
218     {
219         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
220
221         $array = array('Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros');
222
223         $this->assertSame('Zero', $array[false]);
224         $this->assertSame('One', $array[true]);
225         $this->assertSame('One', $array[1.5]);
226         $this->assertSame('One', $array['1']);
227         $this->assertSame('MinusOne', $array[-1.5]);
228         $this->assertSame('FloatButString', $array['1.5']);
229         $this->assertSame('IntegerButStringWithLeadingZeros', $array['01']);
230         $this->assertSame('EmptyString', $array[null]);
231
232         $this->assertSame('Zero', $template->getAttribute($array, false), 'false is treated as 0 when accessing an array (equals PHP behavior)');
233         $this->assertSame('One', $template->getAttribute($array, true), 'true is treated as 1 when accessing an array (equals PHP behavior)');
234         $this->assertSame('One', $template->getAttribute($array, 1.5), 'float is casted to int when accessing an array (equals PHP behavior)');
235         $this->assertSame('One', $template->getAttribute($array, '1'), '"1" is treated as integer 1 when accessing an array (equals PHP behavior)');
236         $this->assertSame('MinusOne', $template->getAttribute($array, -1.5), 'negative float is casted to int when accessing an array (equals PHP behavior)');
237         $this->assertSame('FloatButString', $template->getAttribute($array, '1.5'), '"1.5" is treated as-is when accessing an array (equals PHP behavior)');
238         $this->assertSame('IntegerButStringWithLeadingZeros', $template->getAttribute($array, '01'), '"01" is treated as-is when accessing an array (equals PHP behavior)');
239         $this->assertSame('EmptyString', $template->getAttribute($array, null), 'null is treated as "" when accessing an array (equals PHP behavior)');
240     }
241
242     /**
243      * @dataProvider getGetAttributeTests
244      */
245     public function testGetAttribute($defined, $value, $object, $item, $arguments, $type)
246     {
247         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
248
249         $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
250     }
251
252     /**
253      * @dataProvider getGetAttributeTests
254      */
255     public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $exceptionMessage = null)
256     {
257         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)));
258
259         if ($defined) {
260             $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
261         } else {
262             if (method_exists($this, 'expectException')) {
263                 $this->expectException('Twig_Error_Runtime');
264                 if (null !== $exceptionMessage) {
265                     $this->expectExceptionMessage($exceptionMessage);
266                 }
267             } else {
268                 $this->setExpectedException('Twig_Error_Runtime', $exceptionMessage);
269             }
270             $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
271         }
272     }
273
274     /**
275      * @dataProvider getGetAttributeTests
276      */
277     public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type)
278     {
279         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
280
281         $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
282     }
283
284     /**
285      * @dataProvider getGetAttributeTests
286      */
287     public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type)
288     {
289         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)));
290
291         $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
292     }
293
294     public function testGetAttributeCallExceptions()
295     {
296         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
297
298         $object = new Twig_TemplateMagicMethodExceptionObject();
299
300         $this->assertNull($template->getAttribute($object, 'foo'));
301     }
302
303     public function getGetAttributeTests()
304     {
305         $array = array(
306             'defined' => 'defined',
307             'zero' => 0,
308             'null' => null,
309             '1' => 1,
310             'bar' => true,
311             'baz' => 'baz',
312             '09' => '09',
313             '+4' => '+4',
314         );
315
316         $objectArray = new Twig_TemplateArrayAccessObject();
317         $stdObject = (object) $array;
318         $magicPropertyObject = new Twig_TemplateMagicPropertyObject();
319         $propertyObject = new Twig_TemplatePropertyObject();
320         $propertyObject1 = new Twig_TemplatePropertyObjectAndIterator();
321         $propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess();
322         $propertyObject3 = new Twig_TemplatePropertyObjectDefinedWithUndefinedValue();
323         $methodObject = new Twig_TemplateMethodObject();
324         $magicMethodObject = new Twig_TemplateMagicMethodObject();
325
326         $anyType = Twig_Template::ANY_CALL;
327         $methodType = Twig_Template::METHOD_CALL;
328         $arrayType = Twig_Template::ARRAY_CALL;
329
330         $basicTests = array(
331             // array(defined, value, property to fetch)
332             array(true,  'defined', 'defined'),
333             array(false, null,      'undefined'),
334             array(false, null,      'protected'),
335             array(true,  0,         'zero'),
336             array(true,  1,         1),
337             array(true,  1,         1.0),
338             array(true,  null,      'null'),
339             array(true,  true,      'bar'),
340             array(true,  'baz',     'baz'),
341             array(true,  '09',      '09'),
342             array(true,  '+4',      '+4'),
343         );
344         $testObjects = array(
345             // array(object, type of fetch)
346             array($array,               $arrayType),
347             array($objectArray,         $arrayType),
348             array($stdObject,           $anyType),
349             array($magicPropertyObject, $anyType),
350             array($methodObject,        $methodType),
351             array($methodObject,        $anyType),
352             array($propertyObject,      $anyType),
353             array($propertyObject1,     $anyType),
354             array($propertyObject2,     $anyType),
355         );
356
357         $tests = array();
358         foreach ($testObjects as $testObject) {
359             foreach ($basicTests as $test) {
360                 // properties cannot be numbers
361                 if (($testObject[0] instanceof stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) {
362                     continue;
363                 }
364
365                 if ('+4' === $test[2] && $methodObject === $testObject[0]) {
366                     continue;
367                 }
368
369                 $tests[] = array($test[0], $test[1], $testObject[0], $test[2], array(), $testObject[1]);
370             }
371         }
372
373         // additional properties tests
374         $tests = array_merge($tests, array(
375             array(true, null, $propertyObject3, 'foo', array(), $anyType),
376         ));
377
378         // additional method tests
379         $tests = array_merge($tests, array(
380             array(true, 'defined', $methodObject, 'defined',    array(), $methodType),
381             array(true, 'defined', $methodObject, 'DEFINED',    array(), $methodType),
382             array(true, 'defined', $methodObject, 'getDefined', array(), $methodType),
383             array(true, 'defined', $methodObject, 'GETDEFINED', array(), $methodType),
384             array(true, 'static',  $methodObject, 'static',     array(), $methodType),
385             array(true, 'static',  $methodObject, 'getStatic',  array(), $methodType),
386
387             array(true, '__call_undefined', $magicMethodObject, 'undefined', array(), $methodType),
388             array(true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', array(), $methodType),
389         ));
390
391         // add the same tests for the any type
392         foreach ($tests as $test) {
393             if ($anyType !== $test[5]) {
394                 $test[5] = $anyType;
395                 $tests[] = $test;
396             }
397         }
398
399         $methodAndPropObject = new Twig_TemplateMethodAndPropObject();
400
401         // additional method tests
402         $tests = array_merge($tests, array(
403             array(true, 'a', $methodAndPropObject, 'a', array(), $anyType),
404             array(true, 'a', $methodAndPropObject, 'a', array(), $methodType),
405             array(false, null, $methodAndPropObject, 'a', array(), $arrayType),
406
407             array(true, 'b_prop', $methodAndPropObject, 'b', array(), $anyType),
408             array(true, 'b', $methodAndPropObject, 'B', array(), $anyType),
409             array(true, 'b', $methodAndPropObject, 'b', array(), $methodType),
410             array(true, 'b', $methodAndPropObject, 'B', array(), $methodType),
411             array(false, null, $methodAndPropObject, 'b', array(), $arrayType),
412
413             array(false, null, $methodAndPropObject, 'c', array(), $anyType),
414             array(false, null, $methodAndPropObject, 'c', array(), $methodType),
415             array(false, null, $methodAndPropObject, 'c', array(), $arrayType),
416         ));
417
418         // tests when input is not an array or object
419         $tests = array_merge($tests, array(
420             array(false, null, 42, 'a', array(), $anyType, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'),
421             array(false, null, 'string', 'a', array(), $anyType, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'),
422             array(false, null, array(), 'a', array(), $anyType, 'Key "a" does not exist as the array is empty in "index.twig".'),
423         ));
424
425         return $tests;
426     }
427
428     /**
429      * @expectedException Twig_Error_Runtime
430      */
431     public function testGetIsMethods()
432     {
433         $getIsObject = new Twig_TemplateGetIsMethods();
434         $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)));
435         // first time should not create a cache for "get"
436         $this->assertNull($template->getAttribute($getIsObject, 'get'));
437         // 0 should be in the method cache now, so this should fail
438         $this->assertNull($template->getAttribute($getIsObject, 0));
439     }
440 }
441
442 class Twig_TemplateTest extends Twig_Template
443 {
444     private $name;
445
446     public function __construct(Twig_Environment $env, $name = 'index.twig')
447     {
448         parent::__construct($env);
449         self::$cache = array();
450         $this->name = $name;
451     }
452
453     public function getZero()
454     {
455         return 0;
456     }
457
458     public function getEmpty()
459     {
460         return '';
461     }
462
463     public function getString()
464     {
465         return 'some_string';
466     }
467
468     public function getTrue()
469     {
470         return true;
471     }
472
473     public function getTemplateName()
474     {
475         return $this->name;
476     }
477
478     public function getDebugInfo()
479     {
480         return array();
481     }
482
483     protected function doGetParent(array $context)
484     {
485         return false;
486     }
487
488     protected function doDisplay(array $context, array $blocks = array())
489     {
490     }
491
492     public function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
493     {
494         if (function_exists('twig_template_get_attributes')) {
495             return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
496         } else {
497             return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
498         }
499     }
500
501     public function block_name($context, array $blocks = array())
502     {
503     }
504 }
505
506 class Twig_TemplateArrayAccessObject implements ArrayAccess
507 {
508     protected $protected = 'protected';
509
510     public $attributes = array(
511         'defined' => 'defined',
512         'zero' => 0,
513         'null' => null,
514         '1' => 1,
515         'bar' => true,
516         'baz' => 'baz',
517         '09' => '09',
518         '+4' => '+4',
519     );
520
521     public function offsetExists($name)
522     {
523         return array_key_exists($name, $this->attributes);
524     }
525
526     public function offsetGet($name)
527     {
528         return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
529     }
530
531     public function offsetSet($name, $value)
532     {
533     }
534
535     public function offsetUnset($name)
536     {
537     }
538 }
539
540 class Twig_TemplateMagicPropertyObject
541 {
542     public $defined = 'defined';
543
544     public $attributes = array(
545         'zero' => 0,
546         'null' => null,
547         '1' => 1,
548         'bar' => true,
549         'baz' => 'baz',
550         '09' => '09',
551         '+4' => '+4',
552     );
553
554     protected $protected = 'protected';
555
556     public function __isset($name)
557     {
558         return array_key_exists($name, $this->attributes);
559     }
560
561     public function __get($name)
562     {
563         return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
564     }
565 }
566
567 class Twig_TemplateMagicPropertyObjectWithException
568 {
569     public function __isset($key)
570     {
571         throw new Exception('Hey! Don\'t try to isset me!');
572     }
573 }
574
575 class Twig_TemplatePropertyObject
576 {
577     public $defined = 'defined';
578     public $zero = 0;
579     public $null = null;
580     public $bar = true;
581     public $baz = 'baz';
582
583     protected $protected = 'protected';
584 }
585
586 class Twig_TemplatePropertyObjectAndIterator extends Twig_TemplatePropertyObject implements IteratorAggregate
587 {
588     public function getIterator()
589     {
590         return new ArrayIterator(array('foo', 'bar'));
591     }
592 }
593
594 class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObject implements ArrayAccess
595 {
596     private $data = array(
597         'defined' => 'defined',
598         'zero' => 0,
599         'null' => null,
600         'bar' => true,
601         'baz' => 'baz',
602     );
603
604     public function offsetExists($offset)
605     {
606         return array_key_exists($offset, $this->data);
607     }
608
609     public function offsetGet($offset)
610     {
611         return $this->offsetExists($offset) ? $this->data[$offset] : 'n/a';
612     }
613
614     public function offsetSet($offset, $value)
615     {
616     }
617
618     public function offsetUnset($offset)
619     {
620     }
621 }
622
623 class Twig_TemplatePropertyObjectDefinedWithUndefinedValue
624 {
625     public $foo;
626
627     public function __construct()
628     {
629         $this->foo = @$notExist;
630     }
631 }
632
633 class Twig_TemplateMethodObject
634 {
635     public function getDefined()
636     {
637         return 'defined';
638     }
639
640     public function get1()
641     {
642         return 1;
643     }
644
645     public function get09()
646     {
647         return '09';
648     }
649
650     public function getZero()
651     {
652         return 0;
653     }
654
655     public function getNull()
656     {
657     }
658
659     public function isBar()
660     {
661         return true;
662     }
663
664     public function isBaz()
665     {
666         return 'should never be returned';
667     }
668
669     public function getBaz()
670     {
671         return 'baz';
672     }
673
674     protected function getProtected()
675     {
676         return 'protected';
677     }
678
679     public static function getStatic()
680     {
681         return 'static';
682     }
683 }
684
685 class Twig_TemplateGetIsMethods
686 {
687     public function get()
688     {
689     }
690
691     public function is()
692     {
693     }
694 }
695
696 class Twig_TemplateMethodAndPropObject
697 {
698     private $a = 'a_prop';
699
700     public function getA()
701     {
702         return 'a';
703     }
704
705     public $b = 'b_prop';
706
707     public function getB()
708     {
709         return 'b';
710     }
711
712     private $c = 'c_prop';
713
714     private function getC()
715     {
716         return 'c';
717     }
718 }
719
720 class Twig_TemplateMagicMethodObject
721 {
722     public function __call($method, $arguments)
723     {
724         return '__call_'.$method;
725     }
726 }
727
728 class Twig_TemplateMagicMethodExceptionObject
729 {
730     public function __call($method, $arguments)
731     {
732         throw new BadMethodCallException(sprintf('Unknown method "%s".', $method));
733     }
734 }
735
736 class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface
737 {
738     public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
739     {
740         if ($node instanceof Twig_Node_Expression_GetAttr) {
741             $node->setAttribute('disable_c_ext', true);
742         }
743
744         return $node;
745     }
746
747     public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
748     {
749         return $node;
750     }
751
752     public function getPriority()
753     {
754         return 0;
755     }
756 }
757
758 // to be removed in 2.0
759 interface Twig_TemplateTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface
760 {
761 }