PageRenderTime 29ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/vendors/Twig/Node/Module.php

https://bitbucket.org/mrblackus/micro-muffin
PHP | 383 lines | 337 code | 25 blank | 21 comment | 9 complexity | 5d515b77a03456edfd1b4ad896a61227 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) 2009 Fabien Potencier
  6. * (c) 2009 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. * Represents a module node.
  13. *
  14. * @author Fabien Potencier <fabien@symfony.com>
  15. */
  16. class Twig_Node_Module extends Twig_Node
  17. {
  18. public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
  19. {
  20. // embedded templates are set as attributes so that they are only visited once by the visitors
  21. parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
  22. }
  23. public function setIndex($index)
  24. {
  25. $this->setAttribute('index', $index);
  26. }
  27. /**
  28. * Compiles the node to PHP.
  29. *
  30. * @param Twig_Compiler A Twig_Compiler instance
  31. */
  32. public function compile(Twig_Compiler $compiler)
  33. {
  34. $this->compileTemplate($compiler);
  35. foreach ($this->getAttribute('embedded_templates') as $template)
  36. {
  37. $compiler->subcompile($template);
  38. }
  39. }
  40. protected function compileTemplate(Twig_Compiler $compiler)
  41. {
  42. if (!$this->getAttribute('index'))
  43. {
  44. $compiler->write('<?php');
  45. }
  46. $this->compileClassHeader($compiler);
  47. if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant)
  48. {
  49. $this->compileConstructor($compiler);
  50. }
  51. $this->compileGetParent($compiler);
  52. $this->compileDisplayHeader($compiler);
  53. $this->compileDisplayBody($compiler);
  54. $this->compileDisplayFooter($compiler);
  55. $compiler->subcompile($this->getNode('blocks'));
  56. $this->compileMacros($compiler);
  57. $this->compileGetTemplateName($compiler);
  58. $this->compileIsTraitable($compiler);
  59. $this->compileDebugInfo($compiler);
  60. $this->compileClassFooter($compiler);
  61. }
  62. protected function compileGetParent(Twig_Compiler $compiler)
  63. {
  64. if (null === $this->getNode('parent'))
  65. {
  66. return;
  67. }
  68. $compiler
  69. ->write("protected function doGetParent(array \$context)\n", "{\n")
  70. ->indent()
  71. ->write("return ");
  72. if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant)
  73. {
  74. $compiler->subcompile($this->getNode('parent'));
  75. }
  76. else
  77. {
  78. $compiler
  79. ->raw("\$this->env->resolveTemplate(")
  80. ->subcompile($this->getNode('parent'))
  81. ->raw(")");
  82. }
  83. $compiler
  84. ->raw(";\n")
  85. ->outdent()
  86. ->write("}\n\n");
  87. }
  88. protected function compileDisplayBody(Twig_Compiler $compiler)
  89. {
  90. $compiler->subcompile($this->getNode('body'));
  91. if (null !== $this->getNode('parent'))
  92. {
  93. if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant)
  94. {
  95. $compiler->write("\$this->parent");
  96. }
  97. else
  98. {
  99. $compiler->write("\$this->getParent(\$context)");
  100. }
  101. $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
  102. }
  103. }
  104. protected function compileClassHeader(Twig_Compiler $compiler)
  105. {
  106. $compiler
  107. ->write("\n\n")
  108. // if the filename contains */, add a blank to avoid a PHP parse error
  109. ->write("/* " . str_replace('*/', '* /', $this->getAttribute('filename')) . " */\n")
  110. ->write('class ' . $compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
  111. ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
  112. ->write("{\n")
  113. ->indent();
  114. }
  115. protected function compileConstructor(Twig_Compiler $compiler)
  116. {
  117. $compiler
  118. ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
  119. ->indent()
  120. ->write("parent::__construct(\$env);\n\n");
  121. // parent
  122. if (null === $this->getNode('parent'))
  123. {
  124. $compiler->write("\$this->parent = false;\n\n");
  125. }
  126. elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant)
  127. {
  128. $compiler
  129. ->write("\$this->parent = \$this->env->loadTemplate(")
  130. ->subcompile($this->getNode('parent'))
  131. ->raw(");\n\n");
  132. }
  133. $countTraits = count($this->getNode('traits'));
  134. if ($countTraits)
  135. {
  136. // traits
  137. foreach ($this->getNode('traits') as $i => $trait)
  138. {
  139. $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
  140. $compiler
  141. ->addDebugInfo($trait->getNode('template'))
  142. ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
  143. ->indent()
  144. ->write("throw new Twig_Error_Runtime('Template \"'.")
  145. ->subcompile($trait->getNode('template'))
  146. ->raw(".'\" cannot be used as a trait.');\n")
  147. ->outdent()
  148. ->write("}\n")
  149. ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i));
  150. foreach ($trait->getNode('targets') as $key => $value)
  151. {
  152. $compiler
  153. ->write(sprintf("\$_trait_%s_blocks[", $i))
  154. ->subcompile($value)
  155. ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
  156. ->string($key)
  157. ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
  158. ->string($key)
  159. ->raw("]);\n\n");
  160. }
  161. }
  162. if ($countTraits > 1)
  163. {
  164. $compiler
  165. ->write("\$this->traits = array_merge(\n")
  166. ->indent();
  167. for ($i = 0; $i < $countTraits; $i++)
  168. {
  169. $compiler
  170. ->write(sprintf("\$_trait_%s_blocks" . ($i == $countTraits - 1 ? '' : ',') . "\n", $i));
  171. }
  172. $compiler
  173. ->outdent()
  174. ->write(");\n\n");
  175. }
  176. else
  177. {
  178. $compiler
  179. ->write("\$this->traits = \$_trait_0_blocks;\n\n");
  180. }
  181. $compiler
  182. ->write("\$this->blocks = array_merge(\n")
  183. ->indent()
  184. ->write("\$this->traits,\n")
  185. ->write("array(\n");
  186. }
  187. else
  188. {
  189. $compiler
  190. ->write("\$this->blocks = array(\n");
  191. }
  192. // blocks
  193. $compiler
  194. ->indent();
  195. foreach ($this->getNode('blocks') as $name => $node)
  196. {
  197. $compiler
  198. ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name));
  199. }
  200. if ($countTraits)
  201. {
  202. $compiler
  203. ->outdent()
  204. ->write(")\n");
  205. }
  206. $compiler
  207. ->outdent()
  208. ->write(");\n")
  209. ->outdent()
  210. ->write("}\n\n");;
  211. }
  212. protected function compileDisplayHeader(Twig_Compiler $compiler)
  213. {
  214. $compiler
  215. ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
  216. ->indent();
  217. }
  218. protected function compileDisplayFooter(Twig_Compiler $compiler)
  219. {
  220. $compiler
  221. ->outdent()
  222. ->write("}\n\n");
  223. }
  224. protected function compileClassFooter(Twig_Compiler $compiler)
  225. {
  226. $compiler
  227. ->outdent()
  228. ->write("}\n");
  229. }
  230. protected function compileMacros(Twig_Compiler $compiler)
  231. {
  232. $compiler->subcompile($this->getNode('macros'));
  233. }
  234. protected function compileGetTemplateName(Twig_Compiler $compiler)
  235. {
  236. $compiler
  237. ->write("public function getTemplateName()\n", "{\n")
  238. ->indent()
  239. ->write('return ')
  240. ->repr($this->getAttribute('filename'))
  241. ->raw(";\n")
  242. ->outdent()
  243. ->write("}\n\n");
  244. }
  245. protected function compileIsTraitable(Twig_Compiler $compiler)
  246. {
  247. // A template can be used as a trait if:
  248. // * it has no parent
  249. // * it has no macros
  250. // * it has no body
  251. //
  252. // Put another way, a template can be used as a trait if it
  253. // only contains blocks and use statements.
  254. $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
  255. if ($traitable)
  256. {
  257. if ($this->getNode('body') instanceof Twig_Node_Body)
  258. {
  259. $nodes = $this->getNode('body')->getNode(0);
  260. }
  261. else
  262. {
  263. $nodes = $this->getNode('body');
  264. }
  265. if (!count($nodes))
  266. {
  267. $nodes = new Twig_Node(array($nodes));
  268. }
  269. foreach ($nodes as $node)
  270. {
  271. if (!count($node))
  272. {
  273. continue;
  274. }
  275. if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data')))
  276. {
  277. continue;
  278. }
  279. if ($node instanceof Twig_Node_BlockReference)
  280. {
  281. continue;
  282. }
  283. $traitable = false;
  284. break;
  285. }
  286. }
  287. if ($traitable)
  288. {
  289. return;
  290. }
  291. $compiler
  292. ->write("public function isTraitable()\n", "{\n")
  293. ->indent()
  294. ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
  295. ->outdent()
  296. ->write("}\n\n");
  297. }
  298. protected function compileDebugInfo(Twig_Compiler $compiler)
  299. {
  300. $compiler
  301. ->write("public function getDebugInfo()\n", "{\n")
  302. ->indent()
  303. ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
  304. ->outdent()
  305. ->write("}\n");
  306. }
  307. protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
  308. {
  309. if ($node instanceof Twig_Node_Expression_Constant)
  310. {
  311. $compiler
  312. ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
  313. ->subcompile($node)
  314. ->raw(");\n");
  315. }
  316. else
  317. {
  318. $compiler
  319. ->write(sprintf("%s = ", $var))
  320. ->subcompile($node)
  321. ->raw(";\n")
  322. ->write(sprintf("if (!%s", $var))
  323. ->raw(" instanceof Twig_Template) {\n")
  324. ->indent()
  325. ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
  326. ->outdent()
  327. ->write("}\n");
  328. }
  329. }
  330. }