Macro.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <?php
  2. /*
  3. * This file is part of Twig.
  4. *
  5. * (c) 2009 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. /**
  11. * Represents a macro node.
  12. *
  13. * @author Fabien Potencier <fabien@symfony.com>
  14. */
  15. class Twig_Node_Macro extends Twig_Node
  16. {
  17. const VARARGS_NAME = 'varargs';
  18. public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
  19. {
  20. foreach ($arguments as $argumentName => $argument) {
  21. if (self::VARARGS_NAME === $argumentName) {
  22. throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getLine());
  23. }
  24. }
  25. parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
  26. }
  27. public function compile(Twig_Compiler $compiler)
  28. {
  29. $compiler
  30. ->addDebugInfo($this)
  31. ->write(sprintf('public function get%s(', $this->getAttribute('name')))
  32. ;
  33. $count = count($this->getNode('arguments'));
  34. $pos = 0;
  35. foreach ($this->getNode('arguments') as $name => $default) {
  36. $compiler
  37. ->raw('$__'.$name.'__ = ')
  38. ->subcompile($default)
  39. ;
  40. if (++$pos < $count) {
  41. $compiler->raw(', ');
  42. }
  43. }
  44. if (PHP_VERSION_ID >= 50600) {
  45. if ($count) {
  46. $compiler->raw(', ');
  47. }
  48. $compiler->raw('...$__varargs__');
  49. }
  50. $compiler
  51. ->raw(")\n")
  52. ->write("{\n")
  53. ->indent()
  54. ;
  55. $compiler
  56. ->write("\$context = \$this->env->mergeGlobals(array(\n")
  57. ->indent()
  58. ;
  59. foreach ($this->getNode('arguments') as $name => $default) {
  60. $compiler
  61. ->addIndentation()
  62. ->string($name)
  63. ->raw(' => $__'.$name.'__')
  64. ->raw(",\n")
  65. ;
  66. }
  67. $compiler
  68. ->addIndentation()
  69. ->string(self::VARARGS_NAME)
  70. ->raw(' => ')
  71. ;
  72. if (PHP_VERSION_ID >= 50600) {
  73. $compiler->raw("\$__varargs__,\n");
  74. } else {
  75. $compiler
  76. ->raw('func_num_args() > ')
  77. ->repr($count)
  78. ->raw(' ? array_slice(func_get_args(), ')
  79. ->repr($count)
  80. ->raw(") : array(),\n")
  81. ;
  82. }
  83. $compiler
  84. ->outdent()
  85. ->write("));\n\n")
  86. ->write("\$blocks = array();\n\n")
  87. ->write("ob_start();\n")
  88. ->write("try {\n")
  89. ->indent()
  90. ->subcompile($this->getNode('body'))
  91. ->outdent()
  92. ->write("} catch (Exception \$e) {\n")
  93. ->indent()
  94. ->write("ob_end_clean();\n\n")
  95. ->write("throw \$e;\n")
  96. ->outdent()
  97. ->write("}\n\n")
  98. ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
  99. ->outdent()
  100. ->write("}\n\n")
  101. ;
  102. }
  103. }