Просмотр файла engine/classes/lib/Twig/Compiler.php

Размер файла: 6.73Kb
  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. * @author Fabien Potencier <fabien@symfony.com>
  17. */
  18. class Twig_Compiler implements Twig_CompilerInterface
  19. {
  20. protected $lastLine;
  21. protected $source;
  22. protected $indentation;
  23. protected $env;
  24. protected $debugInfo;
  25. protected $sourceOffset;
  26. protected $sourceLine;
  27. protected $filename;
  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. public function getFilename()
  41. {
  42. return $this->filename;
  43. }
  44.  
  45. /**
  46. * Returns the environment instance related to this compiler.
  47. *
  48. * @return Twig_Environment The environment instance
  49. */
  50. public function getEnvironment()
  51. {
  52. return $this->env;
  53. }
  54.  
  55. /**
  56. * Gets the current PHP code after compilation.
  57. *
  58. * @return string The PHP code
  59. */
  60. public function getSource()
  61. {
  62. return $this->source;
  63. }
  64.  
  65. /**
  66. * Compiles a node.
  67. *
  68. * @param Twig_NodeInterface $node The node to compile
  69. * @param integer $indentation The current indentation
  70. *
  71. * @return Twig_Compiler The current compiler instance
  72. */
  73. public function compile(Twig_NodeInterface $node, $indentation = 0)
  74. {
  75. $this->lastLine = null;
  76. $this->source = '';
  77. $this->sourceOffset = 0;
  78. // source code starts at 1 (as we then increment it when we encounter new lines)
  79. $this->sourceLine = 1;
  80. $this->indentation = $indentation;
  81.  
  82. if ($node instanceof Twig_Node_Module) {
  83. $this->filename = $node->getAttribute('filename');
  84. }
  85.  
  86. $node->compile($this);
  87.  
  88. return $this;
  89. }
  90.  
  91. public function subcompile(Twig_NodeInterface $node, $raw = true)
  92. {
  93. if (false === $raw) {
  94. $this->addIndentation();
  95. }
  96.  
  97. $node->compile($this);
  98.  
  99. return $this;
  100. }
  101.  
  102. /**
  103. * Adds a raw string to the compiled code.
  104. *
  105. * @param string $string The string
  106. *
  107. * @return Twig_Compiler The current compiler instance
  108. */
  109. public function raw($string)
  110. {
  111. $this->source .= $string;
  112.  
  113. return $this;
  114. }
  115.  
  116. /**
  117. * Writes a string to the compiled code by adding indentation.
  118. *
  119. * @return Twig_Compiler The current compiler instance
  120. */
  121. public function write()
  122. {
  123. $strings = func_get_args();
  124. foreach ($strings as $string) {
  125. $this->addIndentation();
  126. $this->source .= $string;
  127. }
  128.  
  129. return $this;
  130. }
  131.  
  132. /**
  133. * Appends an indentation to the current PHP code after compilation.
  134. *
  135. * @return Twig_Compiler The current compiler instance
  136. */
  137. public function addIndentation()
  138. {
  139. $this->source .= str_repeat(' ', $this->indentation * 4);
  140.  
  141. return $this;
  142. }
  143.  
  144. /**
  145. * Adds a quoted string to the compiled code.
  146. *
  147. * @param string $value The string
  148. *
  149. * @return Twig_Compiler The current compiler instance
  150. */
  151. public function string($value)
  152. {
  153. $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
  154.  
  155. return $this;
  156. }
  157.  
  158. /**
  159. * Returns a PHP representation of a given value.
  160. *
  161. * @param mixed $value The value to convert
  162. *
  163. * @return Twig_Compiler The current compiler instance
  164. */
  165. public function repr($value)
  166. {
  167. if (is_int($value) || is_float($value)) {
  168. if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
  169. setlocale(LC_NUMERIC, 'C');
  170. }
  171.  
  172. $this->raw($value);
  173.  
  174. if (false !== $locale) {
  175. setlocale(LC_NUMERIC, $locale);
  176. }
  177. } elseif (null === $value) {
  178. $this->raw('null');
  179. } elseif (is_bool($value)) {
  180. $this->raw($value ? 'true' : 'false');
  181. } elseif (is_array($value)) {
  182. $this->raw('array(');
  183. $first = true;
  184. foreach ($value as $key => $value) {
  185. if (!$first) {
  186. $this->raw(', ');
  187. }
  188. $first = false;
  189. $this->repr($key);
  190. $this->raw(' => ');
  191. $this->repr($value);
  192. }
  193. $this->raw(')');
  194. } else {
  195. $this->string($value);
  196. }
  197.  
  198. return $this;
  199. }
  200.  
  201. /**
  202. * Adds debugging information.
  203. *
  204. * @param Twig_NodeInterface $node The related twig node
  205. *
  206. * @return Twig_Compiler The current compiler instance
  207. */
  208. public function addDebugInfo(Twig_NodeInterface $node)
  209. {
  210. if ($node->getLine() != $this->lastLine) {
  211. $this->write("// line {$node->getLine()}\n");
  212.  
  213. // when mbstring.func_overload is set to 2
  214. // mb_substr_count() replaces substr_count()
  215. // but they have different signatures!
  216. if (((int) ini_get('mbstring.func_overload')) & 2) {
  217. // this is much slower than the "right" version
  218. $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
  219. } else {
  220. $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
  221. }
  222. $this->sourceOffset = strlen($this->source);
  223. $this->debugInfo[$this->sourceLine] = $node->getLine();
  224.  
  225. $this->lastLine = $node->getLine();
  226. }
  227.  
  228. return $this;
  229. }
  230.  
  231. public function getDebugInfo()
  232. {
  233. return $this->debugInfo;
  234. }
  235.  
  236. /**
  237. * Indents the generated code.
  238. *
  239. * @param integer $step The number of indentation to add
  240. *
  241. * @return Twig_Compiler The current compiler instance
  242. */
  243. public function indent($step = 1)
  244. {
  245. $this->indentation += $step;
  246.  
  247. return $this;
  248. }
  249.  
  250. /**
  251. * Outdents the generated code.
  252. *
  253. * @param integer $step The number of indentation to remove
  254. *
  255. * @return Twig_Compiler The current compiler instance
  256. *
  257. * @throws LogicException When trying to outdent too much so the indentation would become negative
  258. */
  259. public function outdent($step = 1)
  260. {
  261. // can't outdent by more steps than the current indentation level
  262. if ($this->indentation < $step) {
  263. throw new LogicException('Unable to call outdent() as the indentation would become negative');
  264. }
  265.  
  266. $this->indentation -= $step;
  267.  
  268. return $this;
  269. }
  270. }