| 1 | <?php
 | 
  
    | 2 | 
 | 
  
    | 3 | /*
 | 
  
    | 4 |  * This file is part of Twig.
 | 
  
    | 5 |  *
 | 
  
    | 6 |  * (c) 2009 Fabien Potencier
 | 
  
    | 7 |  * (c) 2009 Armin Ronacher
 | 
  
    | 8 |  *
 | 
  
    | 9 |  * For the full copyright and license information, please view the LICENSE
 | 
  
    | 10 |  * file that was distributed with this source code.
 | 
  
    | 11 |  */
 | 
  
    | 12 | 
 | 
  
    | 13 | /**
 | 
  
    | 14 |  * Compiles a node to PHP code.
 | 
  
    | 15 |  *
 | 
  
    | 16 |  * @package    twig
 | 
  
    | 17 |  * @author     Fabien Potencier <fabien@symfony.com>
 | 
  
    | 18 |  */
 | 
  
    | 19 | class Twig_Compiler implements Twig_CompilerInterface
 | 
  
    | 20 | {
 | 
  
    | 21 |     protected $lastLine;
 | 
  
    | 22 |     protected $source;
 | 
  
    | 23 |     protected $indentation;
 | 
  
    | 24 |     protected $env;
 | 
  
    | 25 |     protected $debugInfo;
 | 
  
    | 26 |     protected $sourceOffset;
 | 
  
    | 27 |     protected $sourceLine;
 | 
  
    | 28 | 
 | 
  
    | 29 |     /**
 | 
  
    | 30 |      * Constructor.
 | 
  
    | 31 |      *
 | 
  
    | 32 |      * @param Twig_Environment $env The twig environment instance
 | 
  
    | 33 |      */
 | 
  
    | 34 |     public function __construct(Twig_Environment $env)
 | 
  
    | 35 |     {
 | 
  
    | 36 |         $this->env = $env;
 | 
  
    | 37 |         $this->debugInfo = array();
 | 
  
    | 38 |     }
 | 
  
    | 39 | 
 | 
  
    | 40 |     /**
 | 
  
    | 41 |      * Returns the environment instance related to this compiler.
 | 
  
    | 42 |      *
 | 
  
    | 43 |      * @return Twig_Environment The environment instance
 | 
  
    | 44 |      */
 | 
  
    | 45 |     public function getEnvironment()
 | 
  
    | 46 |     {
 | 
  
    | 47 |         return $this->env;
 | 
  
    | 48 |     }
 | 
  
    | 49 | 
 | 
  
    | 50 |     /**
 | 
  
    | 51 |      * Gets the current PHP code after compilation.
 | 
  
    | 52 |      *
 | 
  
    | 53 |      * @return string The PHP code
 | 
  
    | 54 |      */
 | 
  
    | 55 |     public function getSource()
 | 
  
    | 56 |     {
 | 
  
    | 57 |         return $this->source;
 | 
  
    | 58 |     }
 | 
  
    | 59 | 
 | 
  
    | 60 |     /**
 | 
  
    | 61 |      * Compiles a node.
 | 
  
    | 62 |      *
 | 
  
    | 63 |      * @param Twig_NodeInterface $node        The node to compile
 | 
  
    | 64 |      * @param integer            $indentation The current indentation
 | 
  
    | 65 |      *
 | 
  
    | 66 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 67 |      */
 | 
  
    | 68 |     public function compile(Twig_NodeInterface $node, $indentation = 0)
 | 
  
    | 69 |     {
 | 
  
    | 70 |         $this->lastLine = null;
 | 
  
    | 71 |         $this->source = '';
 | 
  
    | 72 |         $this->sourceOffset = 0;
 | 
  
    | 73 |         $this->sourceLine = 0;
 | 
  
    | 74 |         $this->indentation = $indentation;
 | 
  
    | 75 | 
 | 
  
    | 76 |         $node->compile($this);
 | 
  
    | 77 | 
 | 
  
    | 78 |         return $this;
 | 
  
    | 79 |     }
 | 
  
    | 80 | 
 | 
  
    | 81 |     public function subcompile(Twig_NodeInterface $node, $raw = true)
 | 
  
    | 82 |     {
 | 
  
    | 83 |         if (false === $raw) {
 | 
  
    | 84 |             $this->addIndentation();
 | 
  
    | 85 |         }
 | 
  
    | 86 | 
 | 
  
    | 87 |         $node->compile($this);
 | 
  
    | 88 | 
 | 
  
    | 89 |         return $this;
 | 
  
    | 90 |     }
 | 
  
    | 91 | 
 | 
  
    | 92 |     /**
 | 
  
    | 93 |      * Adds a raw string to the compiled code.
 | 
  
    | 94 |      *
 | 
  
    | 95 |      * @param  string $string The string
 | 
  
    | 96 |      *
 | 
  
    | 97 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 98 |      */
 | 
  
    | 99 |     public function raw($string)
 | 
  
    | 100 |     {
 | 
  
    | 101 |         $this->source .= $string;
 | 
  
    | 102 | 
 | 
  
    | 103 |         return $this;
 | 
  
    | 104 |     }
 | 
  
    | 105 | 
 | 
  
    | 106 |     /**
 | 
  
    | 107 |      * Writes a string to the compiled code by adding indentation.
 | 
  
    | 108 |      *
 | 
  
    | 109 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 110 |      */
 | 
  
    | 111 |     public function write()
 | 
  
    | 112 |     {
 | 
  
    | 113 |         $strings = func_get_args();
 | 
  
    | 114 |         foreach ($strings as $string) {
 | 
  
    | 115 |             $this->addIndentation();
 | 
  
    | 116 |             $this->source .= $string;
 | 
  
    | 117 |         }
 | 
  
    | 118 | 
 | 
  
    | 119 |         return $this;
 | 
  
    | 120 |     }
 | 
  
    | 121 | 
 | 
  
    | 122 |     public function addIndentation()
 | 
  
    | 123 |     {
 | 
  
    | 124 |         $this->source .= str_repeat(' ', $this->indentation * 4);
 | 
  
    | 125 | 
 | 
  
    | 126 |         return $this;
 | 
  
    | 127 |     }
 | 
  
    | 128 | 
 | 
  
    | 129 |     /**
 | 
  
    | 130 |      * Adds a quoted string to the compiled code.
 | 
  
    | 131 |      *
 | 
  
    | 132 |      * @param  string $value The string
 | 
  
    | 133 |      *
 | 
  
    | 134 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 135 |      */
 | 
  
    | 136 |     public function string($value)
 | 
  
    | 137 |     {
 | 
  
    | 138 |         $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
 | 
  
    | 139 | 
 | 
  
    | 140 |         return $this;
 | 
  
    | 141 |     }
 | 
  
    | 142 | 
 | 
  
    | 143 |     /**
 | 
  
    | 144 |      * Returns a PHP representation of a given value.
 | 
  
    | 145 |      *
 | 
  
    | 146 |      * @param  mixed $value The value to convert
 | 
  
    | 147 |      *
 | 
  
    | 148 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 149 |      */
 | 
  
    | 150 |     public function repr($value)
 | 
  
    | 151 |     {
 | 
  
    | 152 |         if (is_int($value) || is_float($value)) {
 | 
  
    | 153 |             if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
 | 
  
    | 154 |                 setlocale(LC_NUMERIC, 'C');
 | 
  
    | 155 |             }
 | 
  
    | 156 | 
 | 
  
    | 157 |             $this->raw($value);
 | 
  
    | 158 | 
 | 
  
    | 159 |             if (false !== $locale) {
 | 
  
    | 160 |                 setlocale(LC_NUMERIC, $locale);
 | 
  
    | 161 |             }
 | 
  
    | 162 |         } elseif (null === $value) {
 | 
  
    | 163 |             $this->raw('null');
 | 
  
    | 164 |         } elseif (is_bool($value)) {
 | 
  
    | 165 |             $this->raw($value ? 'true' : 'false');
 | 
  
    | 166 |         } elseif (is_array($value)) {
 | 
  
    | 167 |             $this->raw('array(');
 | 
  
    | 168 |             $i = 0;
 | 
  
    | 169 |             foreach ($value as $key => $value) {
 | 
  
    | 170 |                 if ($i++) {
 | 
  
    | 171 |                     $this->raw(', ');
 | 
  
    | 172 |                 }
 | 
  
    | 173 |                 $this->repr($key);
 | 
  
    | 174 |                 $this->raw(' => ');
 | 
  
    | 175 |                 $this->repr($value);
 | 
  
    | 176 |             }
 | 
  
    | 177 |             $this->raw(')');
 | 
  
    | 178 |         } else {
 | 
  
    | 179 |             $this->string($value);
 | 
  
    | 180 |         }
 | 
  
    | 181 | 
 | 
  
    | 182 |         return $this;
 | 
  
    | 183 |     }
 | 
  
    | 184 | 
 | 
  
    | 185 |     /**
 | 
  
    | 186 |      * Adds debugging information.
 | 
  
    | 187 |      *
 | 
  
    | 188 |      * @param Twig_NodeInterface $node The related twig node
 | 
  
    | 189 |      *
 | 
  
    | 190 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 191 |      */
 | 
  
    | 192 |     public function addDebugInfo(Twig_NodeInterface $node)
 | 
  
    | 193 |     {
 | 
  
    | 194 |         if ($node->getLine() != $this->lastLine) {
 | 
  
    | 195 |             $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
 | 
  
    | 196 |             $this->sourceOffset = strlen($this->source);
 | 
  
    | 197 |             $this->debugInfo[$this->sourceLine] = $node->getLine();
 | 
  
    | 198 | 
 | 
  
    | 199 |             $this->lastLine = $node->getLine();
 | 
  
    | 200 |             $this->write("// line {$node->getLine()}\n");
 | 
  
    | 201 |         }
 | 
  
    | 202 | 
 | 
  
    | 203 |         return $this;
 | 
  
    | 204 |     }
 | 
  
    | 205 | 
 | 
  
    | 206 |     public function getDebugInfo()
 | 
  
    | 207 |     {
 | 
  
    | 208 |         return $this->debugInfo;
 | 
  
    | 209 |     }
 | 
  
    | 210 | 
 | 
  
    | 211 |     /**
 | 
  
    | 212 |      * Indents the generated code.
 | 
  
    | 213 |      *
 | 
  
    | 214 |      * @param integer $step The number of indentation to add
 | 
  
    | 215 |      *
 | 
  
    | 216 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 217 |      */
 | 
  
    | 218 |     public function indent($step = 1)
 | 
  
    | 219 |     {
 | 
  
    | 220 |         $this->indentation += $step;
 | 
  
    | 221 | 
 | 
  
    | 222 |         return $this;
 | 
  
    | 223 |     }
 | 
  
    | 224 | 
 | 
  
    | 225 |     /**
 | 
  
    | 226 |      * Outdents the generated code.
 | 
  
    | 227 |      *
 | 
  
    | 228 |      * @param integer $step The number of indentation to remove
 | 
  
    | 229 |      *
 | 
  
    | 230 |      * @return Twig_Compiler The current compiler instance
 | 
  
    | 231 |      */
 | 
  
    | 232 |     public function outdent($step = 1)
 | 
  
    | 233 |     {
 | 
  
    | 234 |         $this->indentation -= $step;
 | 
  
    | 235 | 
 | 
  
    | 236 |         if ($this->indentation < 0) {
 | 
  
    | 237 |             throw new Twig_Error('Unable to call outdent() as the indentation would become negative');
 | 
  
    | 238 |         }
 | 
  
    | 239 | 
 | 
  
    | 240 |         return $this;
 | 
  
    | 241 |     }
 | 
  
    | 242 | }
 |