TemplateTest.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) Fabien Potencier
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
  11. {
  12. /**
  13. * @expectedException Twig_Error_Runtime
  14. * @expectedExceptionMessage Impossible to access a key ("a") on a "string" variable
  15. */
  16. public function testAttributeOnAString()
  17. {
  18. $template = new Twig_TemplateTest(
  19. new Twig_Environment(null, array('strict_variables' => true)),
  20. false
  21. );
  22. $template->getAttribute('string', 'a', array(), Twig_TemplateInterface::ARRAY_CALL, false);
  23. }
  24. /**
  25. * @dataProvider getGetAttributeTests
  26. */
  27. public function testGetAttribute($defined, $value, $object, $item, $arguments, $type, $useExt = false)
  28. {
  29. $template = new Twig_TemplateTest(
  30. new Twig_Environment(),
  31. $useExt
  32. );
  33. $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
  34. }
  35. /**
  36. * @dataProvider getGetAttributeTests
  37. */
  38. public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $useExt = false, $exceptionMessage = null)
  39. {
  40. $template = new Twig_TemplateTest(
  41. new Twig_Environment(null, array('strict_variables' => true)),
  42. $useExt
  43. );
  44. if ($defined) {
  45. $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
  46. } else {
  47. try {
  48. $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
  49. throw new Exception('Expected Twig_Error_Runtime exception.');
  50. } catch (Twig_Error_Runtime $e) {
  51. if (null !== $exceptionMessage) {
  52. $this->assertSame($exceptionMessage, $e->getMessage());
  53. }
  54. }
  55. }
  56. }
  57. /**
  58. * @dataProvider getGetAttributeTests
  59. */
  60. public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type, $useExt = false)
  61. {
  62. $template = new Twig_TemplateTest(
  63. new Twig_Environment(),
  64. $useExt
  65. );
  66. $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
  67. }
  68. /**
  69. * @dataProvider getGetAttributeTests
  70. */
  71. public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type, $useExt = false)
  72. {
  73. $template = new Twig_TemplateTest(
  74. new Twig_Environment(null, array('strict_variables' => true)),
  75. $useExt
  76. );
  77. $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
  78. }
  79. public function getGetAttributeTests()
  80. {
  81. $array = array(
  82. 'defined' => 'defined',
  83. 'zero' => 0,
  84. 'null' => null,
  85. '1' => 1,
  86. );
  87. $objectArray = new Twig_TemplateArrayAccessObject();
  88. $stdObject = (object) $array;
  89. $magicPropertyObject = new Twig_TemplateMagicPropertyObject();
  90. $propertyObject = new Twig_TemplatePropertyObject();
  91. $propertyObject1 = new Twig_TemplatePropertyObjectAndIterator();
  92. $propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess();
  93. $methodObject = new Twig_TemplateMethodObject();
  94. $magicMethodObject = new Twig_TemplateMagicMethodObject();
  95. $anyType = Twig_TemplateInterface::ANY_CALL;
  96. $methodType = Twig_TemplateInterface::METHOD_CALL;
  97. $arrayType = Twig_TemplateInterface::ARRAY_CALL;
  98. $basicTests = array(
  99. // array(defined, value, property to fetch)
  100. array(true, 'defined', 'defined'),
  101. array(false, null, 'undefined'),
  102. array(false, null, 'protected'),
  103. array(true, 0, 'zero'),
  104. array(true, 1, 1),
  105. array(true, 1, 1.0),
  106. array(true, null, 'null'),
  107. );
  108. $testObjects = array(
  109. // array(object, type of fetch)
  110. array($array, $arrayType),
  111. array($objectArray, $arrayType),
  112. array($stdObject, $anyType),
  113. array($magicPropertyObject, $anyType),
  114. array($methodObject, $methodType),
  115. array($methodObject, $anyType),
  116. array($propertyObject, $anyType),
  117. array($propertyObject1, $anyType),
  118. array($propertyObject2, $anyType),
  119. );
  120. $tests = array();
  121. foreach ($testObjects as $testObject) {
  122. foreach ($basicTests as $test) {
  123. // properties cannot be numbers
  124. if (($testObject[0] instanceof stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) {
  125. continue;
  126. }
  127. $tests[] = array($test[0], $test[1], $testObject[0], $test[2], array(), $testObject[1]);
  128. }
  129. }
  130. // additional method tests
  131. $tests = array_merge($tests, array(
  132. array(true, 'defined', $methodObject, 'defined', array(), $methodType),
  133. array(true, 'defined', $methodObject, 'DEFINED', array(), $methodType),
  134. array(true, 'defined', $methodObject, 'getDefined', array(), $methodType),
  135. array(true, 'defined', $methodObject, 'GETDEFINED', array(), $methodType),
  136. array(true, 'static', $methodObject, 'static', array(), $methodType),
  137. array(true, 'static', $methodObject, 'getStatic', array(), $methodType),
  138. array(true, '__call_undefined', $magicMethodObject, 'undefined', array(), $methodType),
  139. array(true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', array(), $methodType),
  140. ));
  141. // add the same tests for the any type
  142. foreach ($tests as $test) {
  143. if ($anyType !== $test[5]) {
  144. $test[5] = $anyType;
  145. $tests[] = $test;
  146. }
  147. }
  148. $methodAndPropObject = new Twig_TemplateMethodAndPropObject;
  149. // additional method tests
  150. $tests = array_merge($tests, array(
  151. array(true, 'a', $methodAndPropObject, 'a', array(), $anyType),
  152. array(true, 'a', $methodAndPropObject, 'a', array(), $methodType),
  153. array(false, null, $methodAndPropObject, 'a', array(), $arrayType),
  154. array(true, 'b_prop', $methodAndPropObject, 'b', array(), $anyType),
  155. array(true, 'b', $methodAndPropObject, 'B', array(), $anyType),
  156. array(true, 'b', $methodAndPropObject, 'b', array(), $methodType),
  157. array(true, 'b', $methodAndPropObject, 'B', array(), $methodType),
  158. array(false, null, $methodAndPropObject, 'b', array(), $arrayType),
  159. array(false, null, $methodAndPropObject, 'c', array(), $anyType),
  160. array(false, null, $methodAndPropObject, 'c', array(), $methodType),
  161. array(false, null, $methodAndPropObject, 'c', array(), $arrayType),
  162. ));
  163. // tests when input is not an array or object
  164. $tests = array_merge($tests, array(
  165. array(false, null, 42, 'a', array(), $anyType, false, 'Item "a" for "42" does not exist'),
  166. array(false, null, "string", 'a', array(), $anyType, false, 'Item "a" for "string" does not exist'),
  167. array(false, null, array(), 'a', array(), $anyType, false, 'Item "a" for "Array" does not exist'),
  168. ));
  169. // add twig_template_get_attributes tests
  170. if (function_exists('twig_template_get_attributes')) {
  171. foreach(array_slice($tests, 0) as $test) {
  172. $test = array_pad($test, 7, null);
  173. $test[6] = true;
  174. $tests[] = $test;
  175. }
  176. }
  177. return $tests;
  178. }
  179. public function useExtGetAttribute()
  180. {
  181. return false;
  182. }
  183. }
  184. class Twig_TemplateTest extends Twig_Template
  185. {
  186. protected $useExtGetAttribute = false;
  187. public function __construct(Twig_Environment $env, $useExtGetAttribute = false)
  188. {
  189. parent::__construct($env);
  190. $this->useExtGetAttribute = $useExtGetAttribute;
  191. Twig_Template::clearCache();
  192. }
  193. public function getTemplateName()
  194. {
  195. }
  196. public function getDebugInfo()
  197. {
  198. return array();
  199. }
  200. protected function doGetParent(array $context)
  201. {
  202. }
  203. protected function doDisplay(array $context, array $blocks = array())
  204. {
  205. }
  206. public function getAttribute($object, $item, array $arguments = array(), $type = Twig_TemplateInterface::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
  207. {
  208. if ($this->useExtGetAttribute) {
  209. return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
  210. } else {
  211. return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
  212. }
  213. }
  214. }
  215. class Twig_TemplateArrayAccessObject implements ArrayAccess
  216. {
  217. protected $protected = 'protected';
  218. public $attributes = array(
  219. 'defined' => 'defined',
  220. 'zero' => 0,
  221. 'null' => null,
  222. '1' => 1,
  223. );
  224. public function offsetExists($name)
  225. {
  226. return array_key_exists($name, $this->attributes);
  227. }
  228. public function offsetGet($name)
  229. {
  230. return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
  231. }
  232. public function offsetSet($name, $value)
  233. {
  234. }
  235. public function offsetUnset($name)
  236. {
  237. }
  238. }
  239. class Twig_TemplateMagicPropertyObject
  240. {
  241. public $defined = 'defined';
  242. public $attributes = array(
  243. 'zero' => 0,
  244. 'null' => null,
  245. '1' => 1,
  246. );
  247. protected $protected = 'protected';
  248. public function __isset($name)
  249. {
  250. return array_key_exists($name, $this->attributes);
  251. }
  252. public function __get($name)
  253. {
  254. return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null;
  255. }
  256. }
  257. class Twig_TemplatePropertyObject
  258. {
  259. public $defined = 'defined';
  260. public $zero = 0;
  261. public $null = null;
  262. protected $protected = 'protected';
  263. }
  264. class Twig_TemplatePropertyObjectAndIterator extends Twig_TemplatePropertyObject implements IteratorAggregate
  265. {
  266. public function getIterator()
  267. {
  268. return new ArrayIterator(array('foo', 'bar'));
  269. }
  270. }
  271. class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObject implements ArrayAccess
  272. {
  273. private $data = array();
  274. public function offsetExists($offset)
  275. {
  276. return array_key_exists($offset, $this->data);
  277. }
  278. public function offsetGet($offset)
  279. {
  280. return $this->offsetExists($offset) ? $this->data[$offset] : 'n/a';
  281. }
  282. public function offsetSet($offset, $value)
  283. {
  284. }
  285. public function offsetUnset($offset)
  286. {
  287. }
  288. }
  289. class Twig_TemplateMethodObject
  290. {
  291. public function getDefined()
  292. {
  293. return 'defined';
  294. }
  295. public function get1()
  296. {
  297. return 1;
  298. }
  299. public function getZero()
  300. {
  301. return 0;
  302. }
  303. public function getNull()
  304. {
  305. return null;
  306. }
  307. protected function getProtected()
  308. {
  309. return 'protected';
  310. }
  311. static public function getStatic()
  312. {
  313. return 'static';
  314. }
  315. }
  316. class Twig_TemplateMethodAndPropObject
  317. {
  318. private $a = 'a_prop';
  319. public function getA() {
  320. return 'a';
  321. }
  322. public $b = 'b_prop';
  323. public function getB() {
  324. return 'b';
  325. }
  326. private $c = 'c_prop';
  327. private function getC() {
  328. return 'c';
  329. }
  330. }
  331. class Twig_TemplateMagicMethodObject
  332. {
  333. public function __call($method, $arguments) {
  334. return '__call_'.$method;
  335. }
  336. }