PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/twig/twig/lib/Twig/Template.php

https://gitlab.com/arthur_quiroga/dystawork
PHP | 413 lines | 205 code | 51 blank | 157 comment | 29 complexity | 892b2607d39024b9ba5a594383b11792 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) Fabien Potencier
  6. * (c) Armin Ronacher
  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. * Default base class for compiled templates.
  13. *
  14. * This class is an implementation detail of how template compilation currently
  15. * works, which might change. It should never be used directly. Use $twig->load()
  16. * instead, which returns an instance of Twig_TemplateWrapper.
  17. *
  18. * @author Fabien Potencier <fabien@symfony.com>
  19. *
  20. * @internal
  21. */
  22. abstract class Twig_Template
  23. {
  24. const ANY_CALL = 'any';
  25. const ARRAY_CALL = 'array';
  26. const METHOD_CALL = 'method';
  27. /**
  28. * @internal
  29. */
  30. protected static $cache = array();
  31. protected $parent;
  32. protected $parents = array();
  33. protected $env;
  34. protected $blocks = array();
  35. protected $traits = array();
  36. public function __construct(Twig_Environment $env)
  37. {
  38. $this->env = $env;
  39. }
  40. /**
  41. * @internal this method will be removed in 2.0 and is only used internally to provide an upgrade path from 1.x to 2.0
  42. */
  43. public function __toString()
  44. {
  45. return $this->getTemplateName();
  46. }
  47. /**
  48. * Returns the template name.
  49. *
  50. * @return string The template name
  51. */
  52. abstract public function getTemplateName();
  53. /**
  54. * Returns debug information about the template.
  55. *
  56. * @return array Debug information
  57. *
  58. * @internal
  59. */
  60. abstract public function getDebugInfo();
  61. /**
  62. * Returns information about the original template source code.
  63. *
  64. * @return Twig_Source
  65. */
  66. public function getSourceContext()
  67. {
  68. return new Twig_Source('', $this->getTemplateName());
  69. }
  70. /**
  71. * Returns the parent template.
  72. *
  73. * This method is for internal use only and should never be called
  74. * directly.
  75. *
  76. * @param array $context
  77. *
  78. * @return Twig_Template|false The parent template or false if there is no parent
  79. *
  80. * @internal
  81. */
  82. public function getParent(array $context)
  83. {
  84. if (null !== $this->parent) {
  85. return $this->parent;
  86. }
  87. try {
  88. $parent = $this->doGetParent($context);
  89. if (false === $parent) {
  90. return false;
  91. }
  92. if ($parent instanceof self) {
  93. return $this->parents[$parent->getTemplateName()] = $parent;
  94. }
  95. if (!isset($this->parents[$parent])) {
  96. $this->parents[$parent] = $this->loadTemplate($parent);
  97. }
  98. } catch (Twig_Error_Loader $e) {
  99. $e->setSourceContext(null);
  100. $e->guess();
  101. throw $e;
  102. }
  103. return $this->parents[$parent];
  104. }
  105. protected function doGetParent(array $context)
  106. {
  107. return false;
  108. }
  109. public function isTraitable()
  110. {
  111. return true;
  112. }
  113. /**
  114. * Displays a parent block.
  115. *
  116. * This method is for internal use only and should never be called
  117. * directly.
  118. *
  119. * @param string $name The block name to display from the parent
  120. * @param array $context The context
  121. * @param array $blocks The current set of blocks
  122. *
  123. * @internal
  124. */
  125. public function displayParentBlock($name, array $context, array $blocks = array())
  126. {
  127. if (isset($this->traits[$name])) {
  128. $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
  129. } elseif (false !== $parent = $this->getParent($context)) {
  130. $parent->displayBlock($name, $context, $blocks, false);
  131. } else {
  132. throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext());
  133. }
  134. }
  135. /**
  136. * Displays a block.
  137. *
  138. * This method is for internal use only and should never be called
  139. * directly.
  140. *
  141. * @param string $name The block name to display
  142. * @param array $context The context
  143. * @param array $blocks The current set of blocks
  144. * @param bool $useBlocks Whether to use the current set of blocks
  145. *
  146. * @internal
  147. */
  148. public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true)
  149. {
  150. if ($useBlocks && isset($blocks[$name])) {
  151. $template = $blocks[$name][0];
  152. $block = $blocks[$name][1];
  153. } elseif (isset($this->blocks[$name])) {
  154. $template = $this->blocks[$name][0];
  155. $block = $this->blocks[$name][1];
  156. } else {
  157. $template = null;
  158. $block = null;
  159. }
  160. // avoid RCEs when sandbox is enabled
  161. if (null !== $template && !$template instanceof self) {
  162. throw new LogicException('A block must be a method on a Twig_Template instance.');
  163. }
  164. if (null !== $template) {
  165. try {
  166. $template->$block($context, $blocks);
  167. } catch (Twig_Error $e) {
  168. if (!$e->getSourceContext()) {
  169. $e->setSourceContext($template->getSourceContext());
  170. }
  171. // this is mostly useful for Twig_Error_Loader exceptions
  172. // see Twig_Error_Loader
  173. if (false === $e->getTemplateLine()) {
  174. $e->setTemplateLine(-1);
  175. $e->guess();
  176. }
  177. throw $e;
  178. } catch (Exception $e) {
  179. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e);
  180. }
  181. } elseif (false !== $parent = $this->getParent($context)) {
  182. $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
  183. } else {
  184. throw new Twig_Error_Runtime(sprintf('Block "%s" on template "%s" does not exist.', $name, $this->getTemplateName()), -1, $this->getTemplateName());
  185. }
  186. }
  187. /**
  188. * Renders a parent block.
  189. *
  190. * This method is for internal use only and should never be called
  191. * directly.
  192. *
  193. * @param string $name The block name to render from the parent
  194. * @param array $context The context
  195. * @param array $blocks The current set of blocks
  196. *
  197. * @return string The rendered block
  198. *
  199. * @internal
  200. */
  201. public function renderParentBlock($name, array $context, array $blocks = array())
  202. {
  203. ob_start();
  204. $this->displayParentBlock($name, $context, $blocks);
  205. return ob_get_clean();
  206. }
  207. /**
  208. * Renders a block.
  209. *
  210. * This method is for internal use only and should never be called
  211. * directly.
  212. *
  213. * @param string $name The block name to render
  214. * @param array $context The context
  215. * @param array $blocks The current set of blocks
  216. * @param bool $useBlocks Whether to use the current set of blocks
  217. *
  218. * @return string The rendered block
  219. *
  220. * @internal
  221. */
  222. public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true)
  223. {
  224. ob_start();
  225. $this->displayBlock($name, $context, $blocks, $useBlocks);
  226. return ob_get_clean();
  227. }
  228. /**
  229. * Returns whether a block exists or not in the current context of the template.
  230. *
  231. * This method checks blocks defined in the current template
  232. * or defined in "used" traits or defined in parent templates.
  233. *
  234. * @param string $name The block name
  235. * @param array $context The context
  236. * @param array $blocks The current set of blocks
  237. *
  238. * @return bool true if the block exists, false otherwise
  239. *
  240. * @internal
  241. */
  242. public function hasBlock($name, array $context, array $blocks = array())
  243. {
  244. if (isset($blocks[$name])) {
  245. return $blocks[$name][0] instanceof self;
  246. }
  247. if (isset($this->blocks[$name])) {
  248. return true;
  249. }
  250. if (false !== $parent = $this->getParent($context)) {
  251. return $parent->hasBlock($name, $context);
  252. }
  253. return false;
  254. }
  255. /**
  256. * Returns all block names in the current context of the template.
  257. *
  258. * This method checks blocks defined in the current template
  259. * or defined in "used" traits or defined in parent templates.
  260. *
  261. * @param array $context The context
  262. * @param array $blocks The current set of blocks
  263. *
  264. * @return array An array of block names
  265. *
  266. * @internal
  267. */
  268. public function getBlockNames(array $context, array $blocks = array())
  269. {
  270. $names = array_merge(array_keys($blocks), array_keys($this->blocks));
  271. if (false !== $parent = $this->getParent($context)) {
  272. $names = array_merge($names, $parent->getBlockNames($context));
  273. }
  274. return array_unique($names);
  275. }
  276. protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
  277. {
  278. try {
  279. if (is_array($template)) {
  280. return $this->env->resolveTemplate($template);
  281. }
  282. if ($template instanceof self) {
  283. return $template;
  284. }
  285. if ($template instanceof Twig_TemplateWrapper) {
  286. return $template;
  287. }
  288. return $this->env->loadTemplate($template, $index);
  289. } catch (Twig_Error $e) {
  290. if (!$e->getSourceContext()) {
  291. $e->setSourceContext($templateName ? new Twig_Source('', $templateName) : $this->getSourceContext());
  292. }
  293. if ($e->getTemplateLine()) {
  294. throw $e;
  295. }
  296. if (!$line) {
  297. $e->guess();
  298. } else {
  299. $e->setTemplateLine($line);
  300. }
  301. throw $e;
  302. }
  303. }
  304. /**
  305. * Returns all blocks.
  306. *
  307. * This method is for internal use only and should never be called
  308. * directly.
  309. *
  310. * @return array An array of blocks
  311. *
  312. * @internal
  313. */
  314. public function getBlocks()
  315. {
  316. return $this->blocks;
  317. }
  318. public function display(array $context, array $blocks = array())
  319. {
  320. $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
  321. }
  322. public function render(array $context)
  323. {
  324. $level = ob_get_level();
  325. ob_start();
  326. try {
  327. $this->display($context);
  328. } catch (Throwable $e) {
  329. while (ob_get_level() > $level) {
  330. ob_end_clean();
  331. }
  332. throw $e;
  333. }
  334. return ob_get_clean();
  335. }
  336. protected function displayWithErrorHandling(array $context, array $blocks = array())
  337. {
  338. try {
  339. $this->doDisplay($context, $blocks);
  340. } catch (Twig_Error $e) {
  341. if (!$e->getSourceContext()) {
  342. $e->setSourceContext($this->getSourceContext());
  343. }
  344. // this is mostly useful for Twig_Error_Loader exceptions
  345. // see Twig_Error_Loader
  346. if (false === $e->getTemplateLine()) {
  347. $e->setTemplateLine(-1);
  348. $e->guess();
  349. }
  350. throw $e;
  351. } catch (Exception $e) {
  352. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e);
  353. }
  354. }
  355. /**
  356. * Auto-generated method to display the template with the given context.
  357. *
  358. * @param array $context An array of parameters to pass to the template
  359. * @param array $blocks An array of blocks to pass to the template
  360. */
  361. abstract protected function doDisplay(array $context, array $blocks = array());
  362. }