PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Web/Portal/App/Lib/Twig/Node/Module.php

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