vendor/twig/twig/src/Compiler.php line 100

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Twig.
  4.  *
  5.  * (c) Fabien Potencier
  6.  * (c) 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. namespace Twig;
  12. use Twig\Node\Node;
  13. /**
  14.  * @author Fabien Potencier <fabien@symfony.com>
  15.  */
  16. class Compiler
  17. {
  18.     private $lastLine;
  19.     private $source;
  20.     private $indentation;
  21.     private $env;
  22.     private $debugInfo = [];
  23.     private $sourceOffset;
  24.     private $sourceLine;
  25.     private $varNameSalt 0;
  26.     private $didUseEcho false;
  27.     private $didUseEchoStack = [];
  28.     public function __construct(Environment $env)
  29.     {
  30.         $this->env $env;
  31.     }
  32.     public function getEnvironment(): Environment
  33.     {
  34.         return $this->env;
  35.     }
  36.     public function getSource(): string
  37.     {
  38.         return $this->source;
  39.     }
  40.     /**
  41.      * @return $this
  42.      */
  43.     public function reset(int $indentation 0)
  44.     {
  45.         $this->lastLine null;
  46.         $this->source '';
  47.         $this->debugInfo = [];
  48.         $this->sourceOffset 0;
  49.         // source code starts at 1 (as we then increment it when we encounter new lines)
  50.         $this->sourceLine 1;
  51.         $this->indentation $indentation;
  52.         $this->varNameSalt 0;
  53.         return $this;
  54.     }
  55.     /**
  56.      * @return $this
  57.      */
  58.     public function compile(Node $nodeint $indentation 0)
  59.     {
  60.         $this->reset($indentation);
  61.         $this->didUseEchoStack[] = $this->didUseEcho;
  62.         try {
  63.             $this->didUseEcho false;
  64.             $node->compile($this);
  65.             if ($this->didUseEcho) {
  66.                 trigger_deprecation('twig/twig''3.9''Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[YieldReady].'$this->didUseEcho\get_class($node));
  67.             }
  68.             return $this;
  69.         } finally {
  70.             $this->didUseEcho array_pop($this->didUseEchoStack);
  71.         }
  72.     }
  73.     /**
  74.      * @return $this
  75.      */
  76.     public function subcompile(Node $nodebool $raw true)
  77.     {
  78.         if (!$raw) {
  79.             $this->source .= str_repeat(' '$this->indentation 4);
  80.         }
  81.         $this->didUseEchoStack[] = $this->didUseEcho;
  82.         try {
  83.             $this->didUseEcho false;
  84.             $node->compile($this);
  85.             if ($this->didUseEcho) {
  86.                 trigger_deprecation('twig/twig''3.9''Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[YieldReady].'$this->didUseEcho\get_class($node));
  87.             }
  88.             return $this;
  89.         } finally {
  90.             $this->didUseEcho array_pop($this->didUseEchoStack);
  91.         }
  92.     }
  93.     /**
  94.      * Adds a raw string to the compiled code.
  95.      *
  96.      * @return $this
  97.      */
  98.     public function raw(string $string)
  99.     {
  100.         $this->checkForEcho($string);
  101.         $this->source .= $string;
  102.         return $this;
  103.     }
  104.     /**
  105.      * Writes a string to the compiled code by adding indentation.
  106.      *
  107.      * @return $this
  108.      */
  109.     public function write(...$strings)
  110.     {
  111.         foreach ($strings as $string) {
  112.             $this->checkForEcho($string);
  113.             $this->source .= str_repeat(' '$this->indentation 4).$string;
  114.         }
  115.         return $this;
  116.     }
  117.     /**
  118.      * Adds a quoted string to the compiled code.
  119.      *
  120.      * @return $this
  121.      */
  122.     public function string(string $value)
  123.     {
  124.         $this->source .= sprintf('"%s"'addcslashes($value"\0\t\"\$\\"));
  125.         return $this;
  126.     }
  127.     /**
  128.      * Returns a PHP representation of a given value.
  129.      *
  130.      * @return $this
  131.      */
  132.     public function repr($value)
  133.     {
  134.         if (\is_int($value) || \is_float($value)) {
  135.             if (false !== $locale setlocale(\LC_NUMERIC'0')) {
  136.                 setlocale(\LC_NUMERIC'C');
  137.             }
  138.             $this->raw(var_export($valuetrue));
  139.             if (false !== $locale) {
  140.                 setlocale(\LC_NUMERIC$locale);
  141.             }
  142.         } elseif (null === $value) {
  143.             $this->raw('null');
  144.         } elseif (\is_bool($value)) {
  145.             $this->raw($value 'true' 'false');
  146.         } elseif (\is_array($value)) {
  147.             $this->raw('array(');
  148.             $first true;
  149.             foreach ($value as $key => $v) {
  150.                 if (!$first) {
  151.                     $this->raw(', ');
  152.                 }
  153.                 $first false;
  154.                 $this->repr($key);
  155.                 $this->raw(' => ');
  156.                 $this->repr($v);
  157.             }
  158.             $this->raw(')');
  159.         } else {
  160.             $this->string($value);
  161.         }
  162.         return $this;
  163.     }
  164.     /**
  165.      * @return $this
  166.      */
  167.     public function addDebugInfo(Node $node)
  168.     {
  169.         if ($node->getTemplateLine() != $this->lastLine) {
  170.             $this->write(sprintf("// line %d\n"$node->getTemplateLine()));
  171.             $this->sourceLine += substr_count($this->source"\n"$this->sourceOffset);
  172.             $this->sourceOffset \strlen($this->source);
  173.             $this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
  174.             $this->lastLine $node->getTemplateLine();
  175.         }
  176.         return $this;
  177.     }
  178.     public function getDebugInfo(): array
  179.     {
  180.         ksort($this->debugInfo);
  181.         return $this->debugInfo;
  182.     }
  183.     /**
  184.      * @return $this
  185.      */
  186.     public function indent(int $step 1)
  187.     {
  188.         $this->indentation += $step;
  189.         return $this;
  190.     }
  191.     /**
  192.      * @return $this
  193.      *
  194.      * @throws \LogicException When trying to outdent too much so the indentation would become negative
  195.      */
  196.     public function outdent(int $step 1)
  197.     {
  198.         // can't outdent by more steps than the current indentation level
  199.         if ($this->indentation $step) {
  200.             throw new \LogicException('Unable to call outdent() as the indentation would become negative.');
  201.         }
  202.         $this->indentation -= $step;
  203.         return $this;
  204.     }
  205.     public function getVarName(): string
  206.     {
  207.         return sprintf('__internal_compile_%d'$this->varNameSalt++);
  208.     }
  209.     private function checkForEcho(string $string): void
  210.     {
  211.         if ($this->didUseEcho) {
  212.             return;
  213.         }
  214.         $this->didUseEcho preg_match('/^\s*+(echo|print)\b/'$string$m) ? $m[1] : false;
  215.     }
  216. }