smarty_internal_compile_block.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. <?php
  2. /**
  3. * Smarty Internal Plugin Compile Block
  4. * Compiles the {block}{/block} tags
  5. *
  6. * @package Smarty
  7. * @subpackage Compiler
  8. * @author Uwe Tews
  9. */
  10. /**
  11. * Smarty Internal Plugin Compile Block Class
  12. *
  13. * @package Smarty
  14. * @subpackage Compiler
  15. */
  16. class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
  17. {
  18. const parent = '____SMARTY_BLOCK_PARENT____';
  19. /**
  20. * Attribute definition: Overwrites base class.
  21. *
  22. * @var array
  23. * @see Smarty_Internal_CompileBase
  24. */
  25. public $required_attributes = array('name');
  26. /**
  27. * Attribute definition: Overwrites base class.
  28. *
  29. * @var array
  30. * @see Smarty_Internal_CompileBase
  31. */
  32. public $shorttag_order = array('name');
  33. /**
  34. * Attribute definition: Overwrites base class.
  35. *
  36. * @var array
  37. * @see Smarty_Internal_CompileBase
  38. */
  39. public $option_flags = array('hide', 'append', 'prepend', 'nocache');
  40. /**
  41. * Attribute definition: Overwrites base class.
  42. *
  43. * @var array
  44. * @see Smarty_Internal_CompileBase
  45. */
  46. public $optional_attributes = array('internal_file', 'internal_uid', 'internal_line');
  47. /**
  48. * nested child block names
  49. *
  50. * @var array
  51. */
  52. public static $nested_block_names = array();
  53. /**
  54. * child block source buffer
  55. *
  56. * @var array
  57. */
  58. public static $block_data = array();
  59. /**
  60. * Compiles code for the {block} tag
  61. *
  62. * @param array $args array with attributes from parser
  63. * @param object $compiler compiler object
  64. *
  65. * @return boolean true
  66. */
  67. public function compile($args, $compiler)
  68. {
  69. // check and get attributes
  70. $_attr = $this->getAttributes($compiler, $args);
  71. $_name = trim($_attr['name'], "\"'");
  72. // check if we process an inheritance child template
  73. if ($compiler->inheritance_child) {
  74. array_unshift(self::$nested_block_names, $_name);
  75. // build {block} for child block
  76. self::$block_data[$_name]['source'] =
  77. "{$compiler->smarty->left_delimiter}private_child_block name={$_attr['name']} file='{$compiler->template->source->filepath}' type='{$compiler->template->source->type}' resource='{$compiler->template->template_resource}'" .
  78. " uid='{$compiler->template->source->uid}' line={$compiler->lex->line}";
  79. if ($_attr['nocache']) {
  80. self::$block_data[$_name]['source'] .= ' nocache';
  81. }
  82. self::$block_data[$_name]['source'] .= $compiler->smarty->right_delimiter;
  83. $save = array($_attr, $compiler->inheritance);
  84. $this->openTag($compiler, 'block', $save);
  85. // set flag for {block} tag
  86. $compiler->inheritance = true;
  87. $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
  88. $compiler->has_code = false;
  89. return;
  90. }
  91. // must merge includes
  92. if ($_attr['nocache'] == true) {
  93. $compiler->tag_nocache = true;
  94. }
  95. $save = array($_attr, $compiler->inheritance, $compiler->parser->current_buffer, $compiler->nocache);
  96. $this->openTag($compiler, 'block', $save);
  97. $compiler->inheritance = true;
  98. $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
  99. $compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser);
  100. $compiler->has_code = false;
  101. return true;
  102. }
  103. /**
  104. * Compile saved child block source
  105. *
  106. * @param object $compiler compiler object
  107. * @param string $_name optional name of child block
  108. *
  109. * @return string compiled code of child block
  110. */
  111. static function compileChildBlock($compiler, $_name = null)
  112. {
  113. if ($compiler->inheritance_child) {
  114. $name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
  115. if (isset($compiler->template->block_data[$name1])) {
  116. // replace inner block name with generic
  117. Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= $compiler->template->block_data[$name1]['source'];
  118. Smarty_Internal_Compile_Block::$block_data[$name1]['child'] = true;
  119. }
  120. $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
  121. $compiler->has_code = false;
  122. return;
  123. }
  124. // if called by {$smarty.block.child} we must search the name of enclosing {block}
  125. if ($_name == null) {
  126. $stack_count = count($compiler->_tag_stack);
  127. while (--$stack_count >= 0) {
  128. if ($compiler->_tag_stack[$stack_count][0] == 'block') {
  129. $_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
  130. break;
  131. }
  132. }
  133. }
  134. if ($_name == null) {
  135. $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->lex->taglineno);
  136. }
  137. // undefined child?
  138. if (!isset($compiler->template->block_data[$_name]['source'])) {
  139. $compiler->popTrace();
  140. return '';
  141. }
  142. // flag that child is already compile by {$smarty.block.child} inclusion
  143. $compiler->template->block_data[$_name]['compiled'] = true;
  144. $_tpl = new Smarty_Internal_template('string:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id,
  145. $compiler->template->compile_id, $compiler->template->caching, $compiler->template->cache_lifetime);
  146. if ($compiler->smarty->debugging) {
  147. Smarty_Internal_Debug::ignore($_tpl);
  148. }
  149. $_tpl->tpl_vars = $compiler->template->tpl_vars;
  150. $_tpl->variable_filters = $compiler->template->variable_filters;
  151. $_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
  152. $_tpl->allow_relative_path = true;
  153. $_tpl->compiler->inheritance = true;
  154. $_tpl->compiler->suppressHeader = true;
  155. $_tpl->compiler->suppressFilter = true;
  156. $_tpl->compiler->suppressTemplatePropertyHeader = true;
  157. $_tpl->compiler->suppressMergedTemplates = true;
  158. $nocache = $compiler->nocache || $compiler->tag_nocache;
  159. if (strpos($compiler->template->block_data[$_name]['source'], self::parent) !== false) {
  160. $_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php(), $_tpl->compiler->compileTemplate($_tpl, $nocache));
  161. } elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') {
  162. $_output = $_tpl->compiler->compileTemplate($_tpl, $nocache) . $compiler->parser->current_buffer->to_smarty_php();
  163. } elseif ($compiler->template->block_data[$_name]['mode'] == 'append') {
  164. $_output = $compiler->parser->current_buffer->to_smarty_php() . $_tpl->compiler->compileTemplate($_tpl, $nocache);
  165. } elseif (!empty($compiler->template->block_data[$_name])) {
  166. $_output = $_tpl->compiler->compileTemplate($_tpl, $nocache);
  167. }
  168. $compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $_tpl->properties['file_dependency']);
  169. $compiler->template->properties['function'] = array_merge($compiler->template->properties['function'], $_tpl->properties['function']);
  170. $compiler->merged_templates = array_merge($compiler->merged_templates, $_tpl->compiler->merged_templates);
  171. $compiler->template->variable_filters = $_tpl->variable_filters;
  172. if ($_tpl->has_nocache_code) {
  173. $compiler->template->has_nocache_code = true;
  174. }
  175. foreach ($_tpl->required_plugins as $key => $tmp1) {
  176. if ($compiler->nocache && $compiler->template->caching) {
  177. $code = 'nocache';
  178. } else {
  179. $code = $key;
  180. }
  181. foreach ($tmp1 as $name => $tmp) {
  182. foreach ($tmp as $type => $data) {
  183. $compiler->template->required_plugins[$code][$name][$type] = $data;
  184. }
  185. }
  186. }
  187. unset($_tpl);
  188. $compiler->has_code = true;
  189. return $_output;
  190. }
  191. /**
  192. * Compile $smarty.block.parent
  193. *
  194. * @param object $compiler compiler object
  195. * @param string $_name optional name of child block
  196. *
  197. * @return string compiled code of child block
  198. */
  199. static function compileParentBlock($compiler, $_name = null)
  200. {
  201. // if called by {$smarty.block.parent} we must search the name of enclosing {block}
  202. if ($_name == null) {
  203. $stack_count = count($compiler->_tag_stack);
  204. while (--$stack_count >= 0) {
  205. if ($compiler->_tag_stack[$stack_count][0] == 'block') {
  206. $_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
  207. break;
  208. }
  209. }
  210. }
  211. if ($_name == null) {
  212. $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex->taglineno);
  213. }
  214. if (empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
  215. $compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', $compiler->lex->taglineno);
  216. }
  217. Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block::parent;
  218. $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
  219. $compiler->has_code = false;
  220. return;
  221. }
  222. /**
  223. * Process block source
  224. *
  225. * @param $compiler
  226. * @param string $source source text
  227. *
  228. */
  229. static function blockSource($compiler, $source)
  230. {
  231. Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= $source;
  232. }
  233. }
  234. /**
  235. * Smarty Internal Plugin Compile BlockClose Class
  236. *
  237. * @package Smarty
  238. * @subpackage Compiler
  239. */
  240. class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase
  241. {
  242. /**
  243. * Compiles code for the {/block} tag
  244. *
  245. * @param array $args array with attributes from parser
  246. * @param object $compiler compiler object
  247. *
  248. * @return string compiled code
  249. */
  250. public function compile($args, $compiler)
  251. {
  252. $compiler->has_code = true;
  253. // check and get attributes
  254. $_attr = $this->getAttributes($compiler, $args);
  255. $saved_data = $this->closeTag($compiler, array('block'));
  256. $_name = trim($saved_data[0]['name'], "\"'");
  257. // reset flag for {block} tag
  258. $compiler->inheritance = $saved_data[1];
  259. // check if we process an inheritance child template
  260. if ($compiler->inheritance_child) {
  261. $name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
  262. Smarty_Internal_Compile_Block::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}";
  263. array_shift(Smarty_Internal_Compile_Block::$nested_block_names);
  264. if (!empty(Smarty_Internal_Compile_Block::$nested_block_names)) {
  265. $name2 = Smarty_Internal_Compile_Block::$nested_block_names[0];
  266. if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
  267. if (isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child']) || !isset($compiler->template->block_data[$name1])) {
  268. Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
  269. } else {
  270. if ($compiler->template->block_data[$name1]['mode'] == 'append') {
  271. Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source'];
  272. } elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
  273. Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'] . Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
  274. } else {
  275. Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'];
  276. }
  277. }
  278. }
  279. unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
  280. $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
  281. } else {
  282. if (isset($compiler->template->block_data[$name1]) || !$saved_data[0]['hide']) {
  283. if (isset($compiler->template->block_data[$name1]) && !isset(Smarty_Internal_Compile_Block::$block_data[$name1]['child'])) {
  284. if (strpos($compiler->template->block_data[$name1]['source'], Smarty_Internal_Compile_Block::parent) !== false) {
  285. $compiler->template->block_data[$name1]['source'] =
  286. str_replace(Smarty_Internal_Compile_Block::parent, Smarty_Internal_Compile_Block::$block_data[$name1]['source'], $compiler->template->block_data[$name1]['source']);
  287. } elseif ($compiler->template->block_data[$name1]['mode'] == 'prepend') {
  288. $compiler->template->block_data[$name1]['source'] .= Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
  289. } elseif ($compiler->template->block_data[$name1]['mode'] == 'append') {
  290. $compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'] . $compiler->template->block_data[$name1]['source'];
  291. }
  292. } else {
  293. $compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
  294. }
  295. $compiler->template->block_data[$name1]['mode'] = 'replace';
  296. if ($saved_data[0]['append']) {
  297. $compiler->template->block_data[$name1]['mode'] = 'append';
  298. }
  299. if ($saved_data[0]['prepend']) {
  300. $compiler->template->block_data[$name1]['mode'] = 'prepend';
  301. }
  302. }
  303. unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
  304. $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
  305. }
  306. $compiler->has_code = false;
  307. return;
  308. }
  309. if (isset($compiler->template->block_data[$_name]) && !isset($compiler->template->block_data[$_name]['compiled'])) {
  310. $_output = Smarty_Internal_Compile_Block::compileChildBlock($compiler, $_name);
  311. } else {
  312. if ($saved_data[0]['hide'] && !isset($compiler->template->block_data[$_name]['source'])) {
  313. $_output = '';
  314. } else {
  315. $_output = $compiler->parser->current_buffer->to_smarty_php();
  316. }
  317. }
  318. unset($compiler->template->block_data[$_name]['compiled']);
  319. // reset flags
  320. $compiler->parser->current_buffer = $saved_data[2];
  321. if ($compiler->nocache) {
  322. $compiler->tag_nocache = true;
  323. }
  324. $compiler->nocache = $saved_data[3];
  325. // $_output content has already nocache code processed
  326. $compiler->suppressNocacheProcessing = true;
  327. return $_output;
  328. }
  329. }
  330. /**
  331. * Smarty Internal Plugin Compile Child Block Class
  332. *
  333. * @package Smarty
  334. * @subpackage Compiler
  335. */
  336. class Smarty_Internal_Compile_Private_Child_Block extends Smarty_Internal_CompileBase
  337. {
  338. /**
  339. * Attribute definition: Overwrites base class.
  340. *
  341. * @var array
  342. * @see Smarty_Internal_CompileBase
  343. */
  344. public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
  345. /**
  346. * Compiles code for the {private_child_block} tag
  347. *
  348. * @param array $args array with attributes from parser
  349. * @param object $compiler compiler object
  350. *
  351. * @return boolean true
  352. */
  353. public function compile($args, $compiler)
  354. {
  355. // check and get attributes
  356. $_attr = $this->getAttributes($compiler, $args);
  357. // update template with original template resource of {block}
  358. if (trim($_attr['type'], "'") == 'file') {
  359. $compiler->template->template_resource = realpath(trim($_attr['file'], "'"));
  360. } else {
  361. $compiler->template->template_resource = trim($_attr['resource'], "'");
  362. }
  363. // source object
  364. unset ($compiler->template->source);
  365. $exists = $compiler->template->source->exists;
  366. // must merge includes
  367. if ($_attr['nocache'] == true) {
  368. $compiler->tag_nocache = true;
  369. }
  370. $save = array($_attr, $compiler->nocache);
  371. // set trace back to child block
  372. $compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex->line);
  373. $this->openTag($compiler, 'private_child_block', $save);
  374. $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
  375. $compiler->has_code = false;
  376. return true;
  377. }
  378. }
  379. /**
  380. * Smarty Internal Plugin Compile Child Block Close Class
  381. *
  382. * @package Smarty
  383. * @subpackage Compiler
  384. */
  385. class Smarty_Internal_Compile_Private_Child_Blockclose extends Smarty_Internal_CompileBase
  386. {
  387. /**
  388. * Compiles code for the {/private_child_block} tag
  389. *
  390. * @param array $args array with attributes from parser
  391. * @param object $compiler compiler object
  392. *
  393. * @return boolean true
  394. */
  395. public function compile($args, $compiler)
  396. {
  397. // check and get attributes
  398. $_attr = $this->getAttributes($compiler, $args);
  399. $saved_data = $this->closeTag($compiler, array('private_child_block'));
  400. // end of child block
  401. $compiler->popTrace();
  402. $compiler->nocache = $saved_data[1];
  403. $compiler->has_code = false;
  404. return true;
  405. }
  406. }