smarty_internal_compile_block.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. /*
  3. * This file is part of Smarty.
  4. *
  5. * (c) 2015 Uwe Tews
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * Smarty Internal Plugin Compile Block Class
  12. *
  13. * @author Uwe Tews <uwe.tews@googlemail.com>
  14. */
  15. class Smarty_Internal_Compile_Block extends Smarty_Internal_Compile_Shared_Inheritance
  16. {
  17. /**
  18. * Attribute definition: Overwrites base class.
  19. *
  20. * @var array
  21. * @see Smarty_Internal_CompileBase
  22. */
  23. public $required_attributes = array('name');
  24. /**
  25. * Attribute definition: Overwrites base class.
  26. *
  27. * @var array
  28. * @see Smarty_Internal_CompileBase
  29. */
  30. public $shorttag_order = array('name');
  31. /**
  32. * Attribute definition: Overwrites base class.
  33. *
  34. * @var array
  35. * @see Smarty_Internal_CompileBase
  36. */
  37. public $option_flags = array('hide', 'nocache');
  38. /**
  39. * Attribute definition: Overwrites base class.
  40. *
  41. * @var array
  42. * @see Smarty_Internal_CompileBase
  43. */
  44. public $optional_attributes = array('assign');
  45. /**
  46. * nesting level of block tags
  47. *
  48. * @var int
  49. */
  50. public static $blockTagNestingLevel = 0;
  51. /**
  52. * Saved compiler object
  53. *
  54. * @var Smarty_Internal_TemplateCompilerBase
  55. */
  56. public $compiler = null;
  57. /**
  58. * Compiles code for the {block} tag
  59. *
  60. * @param array $args array with attributes from parser
  61. * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
  62. * @param array $parameter array with compilation parameter
  63. *
  64. * @return bool true
  65. */
  66. public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
  67. {
  68. if (!isset($compiler->_cache[ 'blockNesting' ])) {
  69. $compiler->_cache[ 'blockNesting' ] = 0;
  70. }
  71. if ($compiler->_cache[ 'blockNesting' ] == 0) {
  72. // make sure that inheritance gets initialized in template code
  73. $this->registerInit($compiler);
  74. $this->option_flags = array('hide', 'nocache', 'append', 'prepend');
  75. } else {
  76. $this->option_flags = array('hide', 'nocache');
  77. }
  78. // check and get attributes
  79. $_attr = $this->getAttributes($compiler, $args);
  80. $compiler->_cache[ 'blockNesting' ] ++;
  81. $compiler->_cache[ 'blockName' ][ $compiler->_cache[ 'blockNesting' ] ] = $_attr[ 'name' ];
  82. $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ] = array();
  83. $this->openTag($compiler, 'block', array($_attr, $compiler->nocache, $compiler->parser->current_buffer,
  84. $compiler->template->compiled->has_nocache_code,
  85. $compiler->template->caching));
  86. // must whole block be nocache ?
  87. if ($compiler->tag_nocache) {
  88. $i = 0;
  89. }
  90. $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
  91. // $compiler->suppressNocacheProcessing = true;
  92. if ($_attr[ 'nocache' ] === true) {
  93. //$compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->taglineno);
  94. }
  95. $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
  96. $compiler->template->compiled->has_nocache_code = false;
  97. $compiler->suppressNocacheProcessing = true;
  98. }
  99. /**
  100. * Compile saved child block source
  101. *
  102. * @param \Smarty_Internal_TemplateCompilerBase compiler object
  103. * @param string $_name optional name of child block
  104. *
  105. * @return string compiled code of child block
  106. */
  107. static function compileChildBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
  108. {
  109. if (!isset($compiler->_cache[ 'blockNesting' ])) {
  110. $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ',
  111. $compiler->parser->lex->taglineno);
  112. }
  113. $compiler->has_code = true;
  114. $compiler->suppressNocacheProcessing = true;
  115. $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ][ 'callsChild' ] = 'true';
  116. $output = "<?php \n\$_smarty_tpl->inheritance->callChild(\$_smarty_tpl, \$this);\n?>\n";
  117. return $output;
  118. }
  119. /**
  120. * Compile $smarty.block.parent
  121. *
  122. * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
  123. * @param string $_name optional name of child block
  124. *
  125. * @return string compiled code of child block
  126. */
  127. static function compileParentBlock(Smarty_Internal_TemplateCompilerBase $compiler, $_name = null)
  128. {
  129. if (!isset($compiler->_cache[ 'blockNesting' ])) {
  130. $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ',
  131. $compiler->parser->lex->taglineno);
  132. }
  133. $compiler->suppressNocacheProcessing = true;
  134. $compiler->has_code = true;
  135. $output = "<?php \n\$_smarty_tpl->inheritance->callParent(\$_smarty_tpl, \$this);\n?>\n";
  136. return $output;
  137. }
  138. }
  139. /**
  140. * Smarty Internal Plugin Compile BlockClose Class
  141. *
  142. */
  143. class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_Inheritance
  144. {
  145. /**
  146. * Compiles code for the {/block} tag
  147. *
  148. * @param array $args array with attributes from parser
  149. * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
  150. * @param array $parameter array with compilation parameter
  151. *
  152. * @return bool true
  153. */
  154. public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
  155. {
  156. list($_attr, $_nocache, $_buffer, $_has_nocache_code, $_caching) = $this->closeTag($compiler, array('block'));
  157. // init block parameter
  158. $_block = $compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ];
  159. unset($compiler->_cache[ 'blockParams' ][ $compiler->_cache[ 'blockNesting' ] ]);
  160. $_name = $_attr[ 'name' ];
  161. $_assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : null;
  162. unset($_attr[ 'assign' ], $_attr[ 'name' ]);
  163. foreach ($_attr as $name => $stat) {
  164. if ((is_bool($stat) && $stat !== false) || (!is_bool($stat) && $stat != 'false')) {
  165. $_block[ $name ] = 'true';
  166. }
  167. }
  168. $_className = 'Block_' . preg_replace('![^\w]+!', '_', uniqid(rand(), true));
  169. // get compiled block code
  170. $_functionCode = $compiler->parser->current_buffer;
  171. // setup buffer for template function code
  172. $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
  173. $output = "<?php\n";
  174. $output .= "/* {block {$_name}} */\n";
  175. $output .= "class {$_className} extends Smarty_Internal_Block\n";
  176. $output .= "{\n";
  177. foreach ($_block as $property => $value) {
  178. $output .= "public \${$property} = {$value};\n";
  179. }
  180. $output .= "public function callBlock(Smarty_Internal_Template \$_smarty_tpl) {\n";
  181. //$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\n";
  182. if ($compiler->template->compiled->has_nocache_code) {
  183. $output .= "\$_smarty_tpl->cached->hashes['{$compiler->template->compiled->nocache_hash}'] = true;\n";
  184. }
  185. if (isset($_assign)) {
  186. $output .= "ob_start();\n";
  187. }
  188. $output .= "?>\n";
  189. $compiler->parser->current_buffer->append_subtree($compiler->parser,
  190. new Smarty_Internal_ParseTree_Tag($compiler->parser,
  191. $output));
  192. $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
  193. $output = "<?php\n";
  194. if (isset($_assign)) {
  195. $output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
  196. }
  197. $output .= "}\n";
  198. $output .= "}\n";
  199. $output .= "/* {/block {$_name}} */\n\n";
  200. $output .= "?>\n";
  201. $compiler->parser->current_buffer->append_subtree($compiler->parser,
  202. new Smarty_Internal_ParseTree_Tag($compiler->parser,
  203. $output));
  204. $compiler->blockOrFunctionCode .= $f = $compiler->parser->current_buffer->to_smarty_php($compiler->parser);
  205. $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
  206. // nocache plugins must be copied
  207. if (!empty($compiler->template->compiled->required_plugins[ 'nocache' ])) {
  208. foreach ($compiler->template->compiled->required_plugins[ 'nocache' ] as $plugin => $tmp) {
  209. foreach ($tmp as $type => $data) {
  210. $compiler->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin ][ $type ] =
  211. $data;
  212. }
  213. }
  214. }
  215. // restore old status
  216. $compiler->template->compiled->has_nocache_code = $_has_nocache_code;
  217. $compiler->tag_nocache = $compiler->nocache;
  218. $compiler->nocache = $_nocache;
  219. $compiler->parser->current_buffer = $_buffer;
  220. $output = "<?php \n";
  221. if ($compiler->_cache[ 'blockNesting' ] == 1) {
  222. $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name);\n";
  223. } else {
  224. $output .= "\$_smarty_tpl->inheritance->instanceBlock(\$_smarty_tpl, '$_className', $_name, \$this->tplIndex);\n";
  225. }
  226. $output .= "?>\n";
  227. $compiler->_cache[ 'blockNesting' ] --;
  228. if ($compiler->_cache[ 'blockNesting' ] == 0) {
  229. unset($compiler->_cache[ 'blockNesting' ]);
  230. }
  231. $compiler->has_code = true;
  232. $compiler->suppressNocacheProcessing = true;
  233. return $output;
  234. }
  235. }