vendor/twig/twig/src/Node/MacroNode.php line 26

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Twig.
  4.  *
  5.  * (c) 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. namespace Twig\Node;
  11. use Twig\Compiler;
  12. use Twig\Error\SyntaxError;
  13. /**
  14.  * Represents a macro node.
  15.  *
  16.  * @author Fabien Potencier <fabien@symfony.com>
  17.  */
  18. class MacroNode extends Node
  19. {
  20.     public const VARARGS_NAME 'varargs';
  21.     public function __construct(string $nameNode $bodyNode $argumentsint $linenostring $tag null)
  22.     {
  23.         foreach ($arguments as $argumentName => $argument) {
  24.             if (self::VARARGS_NAME === $argumentName) {
  25.                 throw new SyntaxError(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.'self::VARARGS_NAME$nameself::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext());
  26.             }
  27.         }
  28.         parent::__construct(['body' => $body'arguments' => $arguments], ['name' => $name], $lineno$tag);
  29.     }
  30.     public function compile(Compiler $compiler): void
  31.     {
  32.         $compiler
  33.             ->addDebugInfo($this)
  34.             ->write(sprintf('public function macro_%s('$this->getAttribute('name')))
  35.         ;
  36.         $count = \count($this->getNode('arguments'));
  37.         $pos 0;
  38.         foreach ($this->getNode('arguments') as $name => $default) {
  39.             $compiler
  40.                 ->raw('$__'.$name.'__ = ')
  41.                 ->subcompile($default)
  42.             ;
  43.             if (++$pos $count) {
  44.                 $compiler->raw(', ');
  45.             }
  46.         }
  47.         if ($count) {
  48.             $compiler->raw(', ');
  49.         }
  50.         $compiler
  51.             ->raw('...$__varargs__')
  52.             ->raw(")\n")
  53.             ->write("{\n")
  54.             ->indent()
  55.             ->write("\$macros = \$this->macros;\n")
  56.             ->write("\$context = \$this->env->mergeGlobals([\n")
  57.             ->indent()
  58.         ;
  59.         foreach ($this->getNode('arguments') as $name => $default) {
  60.             $compiler
  61.                 ->write('')
  62.                 ->string($name)
  63.                 ->raw(' => $__'.$name.'__')
  64.                 ->raw(",\n")
  65.             ;
  66.         }
  67.         $compiler
  68.             ->write('')
  69.             ->string(self::VARARGS_NAME)
  70.             ->raw(' => ')
  71.         ;
  72.         $compiler
  73.             ->raw("\$__varargs__,\n")
  74.             ->outdent()
  75.             ->write("]);\n\n")
  76.             ->write("\$blocks = [];\n\n")
  77.         ;
  78.         if ($compiler->getEnvironment()->isDebug()) {
  79.             $compiler->write("ob_start();\n");
  80.         } else {
  81.             $compiler->write("ob_start(function () { return ''; });\n");
  82.         }
  83.         $compiler
  84.             ->write("try {\n")
  85.             ->indent()
  86.             ->subcompile($this->getNode('body'))
  87.             ->raw("\n")
  88.             ->write("return ('' === \$tmp = ob_get_contents()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n")
  89.             ->outdent()
  90.             ->write("} finally {\n")
  91.             ->indent()
  92.             ->write("ob_end_clean();\n")
  93.             ->outdent()
  94.             ->write("}\n")
  95.             ->outdent()
  96.             ->write("}\n\n")
  97.         ;
  98.     }
  99. }