smarty_internal_parsetree.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <?php
  2. /**
  3. * Smarty Internal Plugin Templateparser Parsetrees
  4. * These are classes to build parsetrees in the template parser
  5. *
  6. * @package Smarty
  7. * @subpackage Compiler
  8. * @author Thue Kristensen
  9. * @author Uwe Tews
  10. */
  11. /**
  12. * @package Smarty
  13. * @subpackage Compiler
  14. * @ignore
  15. */
  16. abstract class _smarty_parsetree
  17. {
  18. /**
  19. * Parser object
  20. *
  21. * @var object
  22. */
  23. public $parser;
  24. /**
  25. * Buffer content
  26. *
  27. * @var mixed
  28. */
  29. public $data;
  30. /**
  31. * Subtree array
  32. *
  33. * @var array
  34. */
  35. public $subtrees = array();
  36. /**
  37. * Return buffer
  38. *
  39. * @return string buffer content
  40. */
  41. abstract public function to_smarty_php();
  42. }
  43. /**
  44. * A complete smarty tag.
  45. *
  46. * @package Smarty
  47. * @subpackage Compiler
  48. * @ignore
  49. */
  50. class _smarty_tag extends _smarty_parsetree
  51. {
  52. /**
  53. * Saved block nesting level
  54. *
  55. * @var int
  56. */
  57. public $saved_block_nesting;
  58. /**
  59. * Create parse tree buffer for Smarty tag
  60. *
  61. * @param object $parser parser object
  62. * @param string $data content
  63. */
  64. public function __construct($parser, $data)
  65. {
  66. $this->parser = $parser;
  67. $this->data = $data;
  68. $this->saved_block_nesting = $parser->block_nesting_level;
  69. }
  70. /**
  71. * Return buffer content
  72. *
  73. * @return string content
  74. */
  75. public function to_smarty_php()
  76. {
  77. return $this->data;
  78. }
  79. /**
  80. * Return complied code that loads the evaluated output of buffer content into a temporary variable
  81. *
  82. * @return string template code
  83. */
  84. public function assign_to_var()
  85. {
  86. $var = sprintf('$_tmp%d', ++Smarty_Internal_Templateparser::$prefix_number);
  87. $this->parser->compiler->prefix_code[] = sprintf("<?php ob_start();\n%s\n%s=ob_get_clean();?>", preg_replace(array('/^\s*<\?php\s+/','/\s*\?>\s*$/'), '', $this->data), $var);
  88. return $var;
  89. }
  90. }
  91. /**
  92. * Code fragment inside a tag.
  93. *
  94. * @package Smarty
  95. * @subpackage Compiler
  96. * @ignore
  97. */
  98. class _smarty_code extends _smarty_parsetree
  99. {
  100. /**
  101. * Create parse tree buffer for code fragment
  102. *
  103. * @param object $parser parser object
  104. * @param string $data content
  105. */
  106. public function __construct($parser, $data)
  107. {
  108. $this->parser = $parser;
  109. $this->data = $data;
  110. }
  111. /**
  112. * Return buffer content in parentheses
  113. *
  114. * @return string content
  115. */
  116. public function to_smarty_php()
  117. {
  118. return sprintf("(%s)", $this->data);
  119. }
  120. }
  121. /**
  122. * Double quoted string inside a tag.
  123. *
  124. * @package Smarty
  125. * @subpackage Compiler
  126. * @ignore
  127. */
  128. class _smarty_doublequoted extends _smarty_parsetree
  129. {
  130. /**
  131. * Create parse tree buffer for double quoted string subtrees
  132. *
  133. * @param object $parser parser object
  134. * @param _smarty_parsetree $subtree parsetree buffer
  135. */
  136. public function __construct($parser, _smarty_parsetree $subtree)
  137. {
  138. $this->parser = $parser;
  139. $this->subtrees[] = $subtree;
  140. if ($subtree instanceof _smarty_tag) {
  141. $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
  142. }
  143. }
  144. /**
  145. * Append buffer to subtree
  146. *
  147. * @param _smarty_parsetree $subtree parsetree buffer
  148. */
  149. public function append_subtree(_smarty_parsetree $subtree)
  150. {
  151. $last_subtree = count($this->subtrees) - 1;
  152. if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof _smarty_tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) {
  153. if ($subtree instanceof _smarty_code) {
  154. $this->subtrees[$last_subtree]->data .= '<?php echo ' . $subtree->data . ';?>';
  155. } elseif ($subtree instanceof _smarty_dq_content) {
  156. $this->subtrees[$last_subtree]->data .= '<?php echo "' . $subtree->data . '";?>';
  157. } else {
  158. $this->subtrees[$last_subtree]->data .= $subtree->data;
  159. }
  160. } else {
  161. $this->subtrees[] = $subtree;
  162. }
  163. if ($subtree instanceof _smarty_tag) {
  164. $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
  165. }
  166. }
  167. /**
  168. * Merge subtree buffer content together
  169. *
  170. * @return string compiled template code
  171. */
  172. public function to_smarty_php()
  173. {
  174. $code = '';
  175. foreach ($this->subtrees as $subtree) {
  176. if ($code !== "") {
  177. $code .= ".";
  178. }
  179. if ($subtree instanceof _smarty_tag) {
  180. $more_php = $subtree->assign_to_var();
  181. } else {
  182. $more_php = $subtree->to_smarty_php();
  183. }
  184. $code .= $more_php;
  185. if (!$subtree instanceof _smarty_dq_content) {
  186. $this->parser->compiler->has_variable_string = true;
  187. }
  188. }
  189. return $code;
  190. }
  191. }
  192. /**
  193. * Raw chars as part of a double quoted string.
  194. *
  195. * @package Smarty
  196. * @subpackage Compiler
  197. * @ignore
  198. */
  199. class _smarty_dq_content extends _smarty_parsetree
  200. {
  201. /**
  202. * Create parse tree buffer with string content
  203. *
  204. * @param object $parser parser object
  205. * @param string $data string section
  206. */
  207. public function __construct($parser, $data)
  208. {
  209. $this->parser = $parser;
  210. $this->data = $data;
  211. }
  212. /**
  213. * Return content as double quoted string
  214. *
  215. * @return string doubled quoted string
  216. */
  217. public function to_smarty_php()
  218. {
  219. return '"' . $this->data . '"';
  220. }
  221. }
  222. /**
  223. * Template element
  224. *
  225. * @package Smarty
  226. * @subpackage Compiler
  227. * @ignore
  228. */
  229. class _smarty_template_buffer extends _smarty_parsetree
  230. {
  231. /**
  232. * Array of template elements
  233. *
  234. * @var array
  235. */
  236. public $subtrees = Array();
  237. /**
  238. * Create root of parse tree for template elements
  239. *
  240. * @param object $parser parse object
  241. */
  242. public function __construct($parser)
  243. {
  244. $this->parser = $parser;
  245. }
  246. /**
  247. * Append buffer to subtree
  248. *
  249. * @param _smarty_parsetree $subtree
  250. */
  251. public function append_subtree(_smarty_parsetree $subtree)
  252. {
  253. if ($subtree->data !== '') {
  254. $this->subtrees[] = $subtree;
  255. }
  256. }
  257. /**
  258. * Sanitize and merge subtree buffers together
  259. *
  260. * @return string template code content
  261. */
  262. public function to_smarty_php()
  263. {
  264. $code = '';
  265. for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key ++) {
  266. if ($this->subtrees[$key] instanceof _smarty_text) {
  267. $subtree = $this->subtrees[$key]->to_smarty_php();
  268. while ($key + 1 < $cnt && ($this->subtrees[$key+1] instanceof _smarty_text || $this->subtrees[$key +1]->data == '')) {
  269. $key++;
  270. if ($this->subtrees[$key]->data == '') {
  271. continue;
  272. }
  273. $subtree .= $this->subtrees[$key]->to_smarty_php();
  274. }
  275. if ($subtree == '') {
  276. continue;
  277. }
  278. $code .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<\/?script)/', "<?php echo '\$1'; ?>\n", $subtree);
  279. continue;
  280. }
  281. if ($this->subtrees[$key] instanceof _smarty_tag) {
  282. $subtree = $this->subtrees[$key]->to_smarty_php();
  283. while ($key + 1 < $cnt && ($this->subtrees[$key+1] instanceof _smarty_tag || $this->subtrees[$key +1]->data == '')) {
  284. $key++;
  285. if ($this->subtrees[$key]->data == '') {
  286. continue;
  287. }
  288. $newCode = $this->subtrees[$key]->to_smarty_php();
  289. if ((preg_match('/^\s*<\?php\s+/', $newCode) && preg_match('/\s*\?>\s*$/', $subtree))) {
  290. $subtree = preg_replace('/\s*\?>\s*$/', "\n", $subtree);
  291. $subtree .= preg_replace('/^\s*<\?php\s+/', '', $newCode);
  292. } else {
  293. $subtree .= $newCode;
  294. }
  295. }
  296. if ($subtree == '') {
  297. continue;
  298. }
  299. $code .= $subtree;
  300. continue;
  301. }
  302. $code .= $this->subtrees[$key]->to_smarty_php();
  303. }
  304. return $code;
  305. }
  306. }
  307. /**
  308. * template text
  309. *
  310. * @package Smarty
  311. * @subpackage Compiler
  312. * @ignore
  313. */
  314. class _smarty_text extends _smarty_parsetree
  315. {
  316. /**
  317. * Create template text buffer
  318. *
  319. * @param object $parser parser object
  320. * @param string $data text
  321. */
  322. public function __construct($parser, $data)
  323. {
  324. $this->parser = $parser;
  325. $this->data = $data;
  326. }
  327. /**
  328. * Return buffer content
  329. *
  330. * @return strint text
  331. */
  332. public function to_smarty_php()
  333. {
  334. return $this->data;
  335. }
  336. }