KXStudio Website https://kx.studio/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

755 lines
17KB

  1. <?php
  2. /**
  3. * Twig::AST
  4. * ~~~~~~~~~
  5. *
  6. * This module implements the abstract syntax tree and compiler.
  7. *
  8. * :copyright: 2008 by Armin Ronacher.
  9. * :license: BSD.
  10. */
  11. class Twig_Node
  12. {
  13. public $lineno;
  14. public function __construct($lineno)
  15. {
  16. $this->lineno = $lineno;
  17. }
  18. public function compile($compiler)
  19. {
  20. }
  21. }
  22. class Twig_NodeList extends Twig_Node
  23. {
  24. public $nodes;
  25. public function __construct($nodes, $lineno)
  26. {
  27. parent::__construct($lineno);
  28. $this->nodes = $nodes;
  29. }
  30. public function compile($compiler)
  31. {
  32. foreach ($this->nodes as $node)
  33. $node->compile($compiler);
  34. }
  35. public static function fromArray($array, $lineno)
  36. {
  37. if (count($array) == 1)
  38. return $array[0];
  39. return new Twig_NodeList($array, $lineno);
  40. }
  41. }
  42. class Twig_Module extends Twig_Node
  43. {
  44. public $body;
  45. public $extends;
  46. public $blocks;
  47. public $filename;
  48. public $id;
  49. public function __construct($body, $extends, $blocks, $filename)
  50. {
  51. parent::__construct(1);
  52. $this->body = $body;
  53. $this->extends = $extends;
  54. $this->blocks = $blocks;
  55. $this->filename = $filename;
  56. }
  57. public function compile($compiler)
  58. {
  59. $compiler->raw("<?php\n");
  60. if (!is_null($this->extends)) {
  61. $compiler->raw('$this->requireTemplate(');
  62. $compiler->repr($this->extends);
  63. $compiler->raw(");\n");
  64. }
  65. $compiler->raw('class __TwigTemplate_' . md5($this->filename));
  66. if (!is_null($this->extends)) {
  67. $parent = md5($this->extends);
  68. $compiler->raw(" extends __TwigTemplate_$parent {\n");
  69. }
  70. else {
  71. $compiler->raw(" {\npublic function render(\$context) {\n");
  72. $this->body->compile($compiler);
  73. $compiler->raw("}\n");
  74. }
  75. foreach ($this->blocks as $node)
  76. $node->compile($compiler);
  77. $compiler->raw("}\n");
  78. }
  79. }
  80. class Twig_Print extends Twig_Node
  81. {
  82. public $expr;
  83. public function __construct($expr, $lineno)
  84. {
  85. parent::__construct($lineno);
  86. $this->expr = $expr;
  87. }
  88. public function compile($compiler)
  89. {
  90. $compiler->addDebugInfo($this);
  91. $compiler->raw('echo ');
  92. $this->expr->compile($compiler);
  93. $compiler->raw(";\n");
  94. }
  95. }
  96. class Twig_Text extends Twig_Node
  97. {
  98. public $data;
  99. public function __construct($data, $lineno)
  100. {
  101. parent::__construct($lineno);
  102. $this->data = $data;
  103. }
  104. public function compile($compiler)
  105. {
  106. $compiler->addDebugInfo($this);
  107. $compiler->raw('echo ');
  108. $compiler->string($this->data);
  109. $compiler->raw(";\n");
  110. }
  111. }
  112. class Twig_ForLoop extends Twig_Node
  113. {
  114. public $is_multitarget;
  115. public $item;
  116. public $seq;
  117. public $body;
  118. public $else;
  119. public function __construct($is_multitarget, $item, $seq, $body, $else,
  120. $lineno)
  121. {
  122. parent::__construct($lineno);
  123. $this->is_multitarget = $is_multitarget;
  124. $this->item = $item;
  125. $this->seq = $seq;
  126. $this->body = $body;
  127. $this->else = $else;
  128. $this->lineno = $lineno;
  129. }
  130. public function compile($compiler)
  131. {
  132. $compiler->addDebugInfo($this);
  133. $compiler->pushContext();
  134. $compiler->raw('foreach (twig_iterate($context, ');
  135. $this->seq->compile($compiler);
  136. $compiler->raw(") as \$iterator) {\n");
  137. if ($this->is_multitarget) {
  138. $compiler->raw('twig_set_loop_context_multitarget($context, ' .
  139. '$iterator, array(');
  140. $idx = 0;
  141. foreach ($this->item as $node) {
  142. if ($idx++)
  143. $compiler->raw(', ');
  144. $compiler->repr($node->name);
  145. }
  146. $compiler->raw("));\n");
  147. }
  148. else {
  149. $compiler->raw('twig_set_loop_context($context, $iterator, ');
  150. $compiler->repr($this->item->name);
  151. $compiler->raw(");\n");
  152. }
  153. $this->body->compile($compiler);
  154. $compiler->raw("}\n");
  155. if (!is_null($this->else)) {
  156. $compiler->raw("if (!\$context['loop']['iterated']) {\n");
  157. $this->else->compile($compiler);
  158. $compiler->raw('}');
  159. }
  160. $compiler->popContext();
  161. }
  162. }
  163. class Twig_PaginateLoop extends Twig_Node
  164. {
  165. public $item;
  166. public $seq;
  167. public $body;
  168. public $else;
  169. public function __construct($item, $per_page, $target,
  170. $as, $body, $else, $lineno)
  171. {
  172. parent::__construct($lineno);
  173. $this->item = $item;
  174. $this->per_page = $per_page;
  175. $this->seq = $target;
  176. $this->as = $as;
  177. $this->body = $body;
  178. $this->else = $else;
  179. $this->lineno = $lineno;
  180. }
  181. public function compile($compiler)
  182. {
  183. $compiler->addDebugInfo($this);
  184. $compiler->pushContext();
  185. $compiler->raw('twig_paginate($context,');
  186. $compiler->raw('"'.$this->as->name.'", ');
  187. if (isset($this->seq->node) and isset($this->seq->attr)) {
  188. $compiler->raw('array($context["::parent"]["');
  189. $compiler->raw($this->seq->node->name.'"],');
  190. $compiler->raw('"'.$this->seq->attr->value.'")');
  191. } else
  192. $this->seq->compile($compiler);
  193. $compiler->raw(', ');
  194. $this->per_page->compile($compiler);
  195. $compiler->raw(");\n");
  196. $compiler->raw('foreach (twig_iterate($context,');
  197. $compiler->raw(' $context["::parent"]["'.$this->as->name);
  198. $compiler->raw("\"]->paginated) as \$iterator) {\n");
  199. $compiler->raw('twig_set_loop_context($context, $iterator, ');
  200. $compiler->repr($this->item->name);
  201. $compiler->raw(");\n");
  202. $this->body->compile($compiler);
  203. $compiler->raw("}\n");
  204. if (!is_null($this->else)) {
  205. $compiler->raw("if (!\$context['loop']['iterated']) {\n");
  206. $this->else->compile($compiler);
  207. $compiler->raw('}');
  208. }
  209. $compiler->popContext();
  210. }
  211. }
  212. class Twig_IfCondition extends Twig_Node
  213. {
  214. public $tests;
  215. public $else;
  216. public function __construct($tests, $else, $lineno)
  217. {
  218. parent::__construct($lineno);
  219. $this->tests = $tests;
  220. $this->else = $else;
  221. }
  222. public function compile($compiler)
  223. {
  224. $compiler->addDebugInfo($this);
  225. $idx = 0;
  226. foreach ($this->tests as $test) {
  227. $compiler->raw(($idx++ ? "}\nelse" : '') . 'if (');
  228. $test[0]->compile($compiler);
  229. $compiler->raw(") {\n");
  230. $test[1]->compile($compiler);
  231. }
  232. if (!is_null($this->else)) {
  233. $compiler->raw("} else {\n");
  234. $this->else->compile($compiler);
  235. }
  236. $compiler->raw("}\n");
  237. }
  238. }
  239. class Twig_Block extends Twig_Node
  240. {
  241. public $name;
  242. public $body;
  243. public $parent;
  244. public function __construct($name, $body, $lineno, $parent=NULL)
  245. {
  246. parent::__construct($lineno);
  247. $this->name = $name;
  248. $this->body = $body;
  249. $this->parent = $parent;
  250. }
  251. public function replace($other)
  252. {
  253. $this->body = $other->body;
  254. }
  255. public function compile($compiler)
  256. {
  257. $compiler->addDebugInfo($this);
  258. $compiler->format('public function block_%s($context) {' . "\n",
  259. $this->name);
  260. if (!is_null($this->parent))
  261. $compiler->raw('$context[\'::superblock\'] = array($this, ' .
  262. "'parent::block_$this->name');\n");
  263. $this->body->compile($compiler);
  264. $compiler->format("}\n\n");
  265. }
  266. }
  267. class Twig_BlockReference extends Twig_Node
  268. {
  269. public $name;
  270. public function __construct($name, $lineno)
  271. {
  272. parent::__construct($lineno);
  273. $this->name = $name;
  274. }
  275. public function compile($compiler)
  276. {
  277. $compiler->addDebugInfo($this);
  278. $compiler->format('$this->block_%s($context);' . "\n", $this->name);
  279. }
  280. }
  281. class Twig_Super extends Twig_Node
  282. {
  283. public $block_name;
  284. public function __construct($block_name, $lineno)
  285. {
  286. parent::__construct($lineno);
  287. $this->block_name = $block_name;
  288. }
  289. public function compile($compiler)
  290. {
  291. $compiler->addDebugInfo($this);
  292. $compiler->raw('parent::block_' . $this->block_name . '($context);' . "\n");
  293. }
  294. }
  295. class Twig_Include extends Twig_Node
  296. {
  297. public $expr;
  298. public function __construct($expr, $lineno)
  299. {
  300. parent::__construct($lineno);
  301. $this->expr = $expr;
  302. }
  303. public function compile($compiler)
  304. {
  305. $compiler->addDebugInfo($this);
  306. $compiler->raw('twig_get_current_template()->loader->getTemplate(');
  307. $this->expr->compile($compiler);
  308. $compiler->raw(')->display($context);' . "\n");
  309. }
  310. }
  311. class Twig_URL extends Twig_Node
  312. {
  313. public $expr;
  314. public function __construct($expr, $cont, $lineno)
  315. {
  316. parent::__construct($lineno);
  317. $this->expr = $expr;
  318. $this->cont = $cont;
  319. }
  320. public function compile($compiler)
  321. {
  322. $compiler->addDebugInfo($this);
  323. $compiler->raw('echo url(');
  324. $this->expr->compile($compiler);
  325. if (!empty($this->cont) and class_exists($this->cont->name."Controller") and is_callable(array($this->cont->name."Controller", "current")))
  326. $compiler->raw(", ".$this->cont->name."Controller::current()");
  327. $compiler->raw(');'."\n");
  328. }
  329. }
  330. class Twig_AdminURL extends Twig_Node
  331. {
  332. public $expr;
  333. public function __construct($expr, $lineno)
  334. {
  335. parent::__construct($lineno);
  336. $this->expr = $expr;
  337. }
  338. public function compile($compiler)
  339. {
  340. $compiler->addDebugInfo($this);
  341. $compiler->raw('echo fix(Config::current()->chyrp_url."/admin/?action=".(');
  342. $this->expr->compile($compiler);
  343. $compiler->raw('));'."\n");
  344. }
  345. }
  346. class Twig_Expression extends Twig_Node
  347. {
  348. }
  349. class Twig_ConditionalExpression extends Twig_Expression
  350. {
  351. public $expr1;
  352. public $expr2;
  353. public $expr3;
  354. public function __construct($expr1, $expr2, $expr3, $lineno)
  355. {
  356. parent::__construct($lineno);
  357. $this->expr1 = $expr1;
  358. $this->expr2 = $expr2;
  359. $this->expr3 = $expr3;
  360. }
  361. public function compile($compiler)
  362. {
  363. $compiler->raw('(');
  364. $this->expr1->compile($compiler);
  365. $compiler->raw(') ? (');
  366. $this->expr2->compile($compiler);
  367. $compiler->raw(') ; (');
  368. $this->expr3->compile($compiler);
  369. $compiler->raw(')');
  370. }
  371. }
  372. class Twig_BinaryExpression extends Twig_Expression
  373. {
  374. public $left;
  375. public $right;
  376. public function __construct($left, $right, $lineno)
  377. {
  378. parent::__construct($lineno);
  379. $this->left = $left;
  380. $this->right = $right;
  381. }
  382. public function compile($compiler)
  383. {
  384. $compiler->raw('(');
  385. $this->left->compile($compiler);
  386. $compiler->raw(') ');
  387. $this->operator($compiler);
  388. $compiler->raw(' (');
  389. $this->right->compile($compiler);
  390. $compiler->raw(')');
  391. }
  392. }
  393. class Twig_OrExpression extends Twig_BinaryExpression
  394. {
  395. public function operator($compiler)
  396. {
  397. return $compiler->raw('||');
  398. }
  399. }
  400. class Twig_AndExpression extends Twig_BinaryExpression
  401. {
  402. public function operator($compiler)
  403. {
  404. return $compiler->raw('&&');
  405. }
  406. }
  407. class Twig_AddExpression extends Twig_BinaryExpression
  408. {
  409. public function operator($compiler)
  410. {
  411. return $compiler->raw('+');
  412. }
  413. }
  414. class Twig_SubExpression extends Twig_BinaryExpression
  415. {
  416. public function operator($compiler)
  417. {
  418. return $compiler->raw('-');
  419. }
  420. }
  421. class Twig_ConcatExpression extends Twig_BinaryExpression
  422. {
  423. public function operator($compiler)
  424. {
  425. return $compiler->raw('.');
  426. }
  427. }
  428. class Twig_MulExpression extends Twig_BinaryExpression
  429. {
  430. public function operator($compiler)
  431. {
  432. return $compiler->raw('*');
  433. }
  434. }
  435. class Twig_DivExpression extends Twig_BinaryExpression
  436. {
  437. public function operator($compiler)
  438. {
  439. return $compiler->raw('/');
  440. }
  441. }
  442. class Twig_ModExpression extends Twig_BinaryExpression
  443. {
  444. public function operator($compiler)
  445. {
  446. return $compiler->raw('%');
  447. }
  448. }
  449. class Twig_CompareExpression extends Twig_Expression
  450. {
  451. public $expr;
  452. public $ops;
  453. public function __construct($expr, $ops, $lineno)
  454. {
  455. parent::__construct($lineno);
  456. $this->expr = $expr;
  457. $this->ops = $ops;
  458. }
  459. public function compile($compiler)
  460. {
  461. $this->expr->compile($compiler);
  462. $i = 0;
  463. foreach ($this->ops as $op) {
  464. if ($i)
  465. $compiler->raw(' && ($tmp' . $i);
  466. list($op, $node) = $op;
  467. $compiler->raw(' ' . $op . ' ');
  468. $compiler->raw('($tmp' . ++$i . ' = ');
  469. $node->compile($compiler);
  470. $compiler->raw(')');
  471. }
  472. if ($i > 1)
  473. $compiler->raw(')');
  474. }
  475. }
  476. class Twig_UnaryExpression extends Twig_Expression
  477. {
  478. public $node;
  479. public function __construct($node, $lineno)
  480. {
  481. parent::__construct($lineno);
  482. $this->node = $node;
  483. }
  484. public function compile($compiler)
  485. {
  486. $compiler->raw('(');
  487. $this->operator($compiler);
  488. $this->node->compile($compiler);
  489. $compiler->raw(')');
  490. }
  491. }
  492. class Twig_NotExpression extends Twig_UnaryExpression
  493. {
  494. public function operator($compiler)
  495. {
  496. $compiler->raw('!');
  497. }
  498. }
  499. class Twig_NegExpression extends Twig_UnaryExpression
  500. {
  501. public function operator($compiler)
  502. {
  503. $compiler->raw('-');
  504. }
  505. }
  506. class Twig_PosExpression extends Twig_UnaryExpression
  507. {
  508. public function operator($compiler)
  509. {
  510. $compiler->raw('+');
  511. }
  512. }
  513. class Twig_Constant extends Twig_Expression
  514. {
  515. public $value;
  516. public function __construct($value, $lineno)
  517. {
  518. parent::__construct($lineno);
  519. $this->value = $value;
  520. }
  521. public function compile($compiler)
  522. {
  523. $compiler->repr($this->value);
  524. }
  525. }
  526. class Twig_NameExpression extends Twig_Expression
  527. {
  528. public $name;
  529. public function __construct($name, $lineno)
  530. {
  531. parent::__construct($lineno);
  532. $this->name = $name;
  533. }
  534. public function compile($compiler)
  535. {
  536. $compiler->format('(isset($context[\'%s\']) ? $context[\'%s\'] ' .
  537. ': NULL)', $this->name, $this->name);
  538. }
  539. }
  540. class Twig_AssignNameExpression extends Twig_NameExpression
  541. {
  542. public function compile($compiler)
  543. {
  544. $compiler->format('$context[\'%s\']', $this->name);
  545. }
  546. }
  547. class Twig_GetAttrExpression extends Twig_Expression
  548. {
  549. public $node;
  550. public $attr;
  551. public function __construct($node, $attr, $lineno, $token_value)
  552. {
  553. parent::__construct($lineno);
  554. $this->node = $node;
  555. $this->attr = $attr;
  556. $this->token_value = $token_value;
  557. }
  558. public function compile($compiler)
  559. {
  560. $compiler->raw('twig_get_attribute(');
  561. $this->node->compile($compiler);
  562. $compiler->raw(', ');
  563. $this->attr->compile($compiler);
  564. if ($this->token_value == "[") # Don't look for functions if they're using foo[bar]
  565. $compiler->raw(', false');
  566. $compiler->raw(')');
  567. }
  568. }
  569. class Twig_MethodCallExpression extends Twig_Expression
  570. {
  571. public $node;
  572. public $method;
  573. public $arguments;
  574. public function __construct($node, $method, $arguments, $lineno)
  575. {
  576. parent::__construct($lineno);
  577. $this->node = $node;
  578. $this->method = $method;
  579. $this->arguments = $arguments;
  580. }
  581. public function compile($compiler)
  582. {
  583. $compiler->raw('call_user_func(array(');
  584. $this->node->compile($compiler);
  585. $compiler->raw(', ');
  586. $this->method->compile($compiler);
  587. $compiler->raw(')');
  588. foreach ($this->arguments as $argument) {
  589. $compiler->raw(', ');
  590. $argument->compile($compiler);
  591. }
  592. $compiler->raw(')');
  593. }
  594. }
  595. class Twig_FilterExpression extends Twig_Expression
  596. {
  597. public $node;
  598. public $filters;
  599. public function __construct($node, $filters, $lineno)
  600. {
  601. parent::__construct($lineno);
  602. $this->node = $node;
  603. $this->filters = $filters;
  604. }
  605. public function compile($compiler)
  606. {
  607. global $twig_filters;
  608. $postponed = array();
  609. for ($i = count($this->filters) - 1; $i >= 0; --$i) {
  610. list($name, $attrs) = $this->filters[$i];
  611. if (!isset($twig_filters[$name])) {
  612. $compiler->raw('twig_missing_filter(');
  613. $compiler->repr($name);
  614. $compiler->raw(', ');
  615. }
  616. else
  617. $compiler->raw($twig_filters[$name] . '(');
  618. $postponed[] = $attrs;
  619. }
  620. $this->node->compile($compiler);
  621. foreach (array_reverse($postponed) as $attributes) {
  622. foreach ($attributes as $node) {
  623. $compiler->raw(', ');
  624. $node->compile($compiler);
  625. }
  626. $compiler->raw(')');
  627. }
  628. }
  629. }