4 * Smarty Internal Plugin Compile Block
5 * Compiles the {block}{/block} tags
13 * Smarty Internal Plugin Compile Block Class
16 * @subpackage Compiler
18 class Smarty_Internal_Compile_Block
extends Smarty_Internal_CompileBase
21 const parent
= '____SMARTY_BLOCK_PARENT____';
23 * Attribute definition: Overwrites base class.
26 * @see Smarty_Internal_CompileBase
28 public $required_attributes = array('name');
31 * Attribute definition: Overwrites base class.
34 * @see Smarty_Internal_CompileBase
36 public $shorttag_order = array('name');
39 * Attribute definition: Overwrites base class.
42 * @see Smarty_Internal_CompileBase
44 public $option_flags = array('hide', 'append', 'prepend', 'nocache');
47 * Attribute definition: Overwrites base class.
50 * @see Smarty_Internal_CompileBase
52 public $optional_attributes = array('internal_file', 'internal_uid', 'internal_line');
54 * nested child block names
58 public static $nested_block_names = array();
61 * child block source buffer
65 public static $block_data = array();
68 * Compiles code for the {block} tag
70 * @param array $args array with attributes from parser
71 * @param object $compiler compiler object
73 * @return boolean true
75 public function compile($args, $compiler)
77 // check and get attributes
78 $_attr = $this->getAttributes($compiler, $args);
79 $_name = trim($_attr['name'], "\"'");
81 // existing child must override parent settings
82 if (isset($compiler->template
->block_data
[$_name]) && $compiler->template
->block_data
[$_name]['mode'] == 'replace') {
83 $_attr['append'] = false;
84 $_attr['prepend'] = false;
87 // check if we process an inheritance child template
88 if ($compiler->inheritance_child
) {
89 array_unshift(self
::$nested_block_names, $_name);
90 // build {block} for child block
91 self
::$block_data[$_name]['source'] =
92 "{$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}'" .
93 " uid='{$compiler->template->source->uid}' line={$compiler->lex->line}";
94 if ($_attr['nocache']) {
95 self
::$block_data[$_name]['source'] .= ' nocache';
97 self
::$block_data[$_name]['source'] .= $compiler->smarty
->right_delimiter
;
99 $save = array($_attr, $compiler->inheritance
);
100 $this->openTag($compiler, 'block', $save);
101 // set flag for {block} tag
102 $compiler->inheritance
= true;
103 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
104 $compiler->has_code
= false;
107 // must merge includes
108 if ($_attr['nocache'] == true) {
109 $compiler->tag_nocache
= true;
111 $save = array($_attr, $compiler->inheritance
, $compiler->parser
->current_buffer
, $compiler->nocache
);
112 $this->openTag($compiler, 'block', $save);
113 $compiler->inheritance
= true;
114 $compiler->nocache
= $compiler->nocache |
$compiler->tag_nocache
;
116 $compiler->parser
->current_buffer
= new Smarty_Internal_ParseTree_Template($compiler->parser
);
117 $compiler->has_code
= false;
123 * Compile saved child block source
125 * @param object $compiler compiler object
126 * @param string $_name optional name of child block
128 * @return string compiled code of child block
130 static function compileChildBlock($compiler, $_name = null)
132 if ($compiler->inheritance_child
) {
133 $name1 = Smarty_Internal_Compile_Block
::$nested_block_names[0];
134 if (isset($compiler->template
->block_data
[$name1])) {
135 // replace inner block name with generic
136 Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] .= $compiler->template
->block_data
[$name1]['source'];
137 Smarty_Internal_Compile_Block
::$block_data[$name1]['child'] = true;
139 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
140 $compiler->has_code
= false;
143 // if called by {$smarty.block.child} we must search the name of enclosing {block}
144 if ($_name == null) {
145 $stack_count = count($compiler->_tag_stack
);
146 while (-- $stack_count >= 0) {
147 if ($compiler->_tag_stack
[$stack_count][0] == 'block') {
148 $_name = trim($compiler->_tag_stack
[$stack_count][1][0]['name'], "\"'");
153 if ($_name == null) {
154 $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->lex
->taglineno
);
157 if (!isset($compiler->template
->block_data
[$_name]['source'])) {
158 $compiler->popTrace();
161 // flag that child is already compile by {$smarty.block.child} inclusion
162 $compiler->template
->block_data
[$_name]['compiled'] = true;
163 $_tpl = new Smarty_Internal_template('string:' . $compiler->template
->block_data
[$_name]['source'], $compiler->smarty
, $compiler->template
, $compiler->template
->cache_id
,
164 $compiler->template
->compile_id
, $compiler->template
->caching
, $compiler->template
->cache_lifetime
);
165 if ($compiler->smarty
->debugging
) {
166 Smarty_Internal_Debug
::ignore($_tpl);
168 $_tpl->tpl_vars
= $compiler->template
->tpl_vars
;
169 $_tpl->variable_filters
= $compiler->template
->variable_filters
;
170 $_tpl->properties
['nocache_hash'] = $compiler->template
->properties
['nocache_hash'];
171 $_tpl->allow_relative_path
= true;
172 $_tpl->compiler
->inheritance
= true;
173 $_tpl->compiler
->suppressHeader
= true;
174 $_tpl->compiler
->suppressFilter
= true;
175 $_tpl->compiler
->suppressTemplatePropertyHeader
= true;
176 $nocache = $compiler->nocache ||
$compiler->tag_nocache
;
177 if (strpos($compiler->template
->block_data
[$_name]['source'], self
::parent
) !== false) {
178 $_output = str_replace(self
::parent
, $compiler->parser
->current_buffer
->to_smarty_php(), $_tpl->compiler
->compileTemplate($_tpl, $nocache, $compiler->parent_compiler
));
179 } elseif ($compiler->template
->block_data
[$_name]['mode'] == 'prepend') {
180 $_output = $_tpl->compiler
->compileTemplate($_tpl, $nocache, $compiler->parent_compiler
) . $compiler->parser
->current_buffer
->to_smarty_php();
181 } elseif ($compiler->template
->block_data
[$_name]['mode'] == 'append') {
182 $_output = $compiler->parser
->current_buffer
->to_smarty_php() . $_tpl->compiler
->compileTemplate($_tpl, $nocache, $compiler->parent_compiler
);
183 } elseif (!empty($compiler->template
->block_data
[$_name])) {
184 $_output = $_tpl->compiler
->compileTemplate($_tpl, $nocache, $compiler->parent_compiler
);
186 $compiler->template
->properties
['file_dependency'] = array_merge($compiler->template
->properties
['file_dependency'], $_tpl->properties
['file_dependency']);
187 $compiler->template
->properties
['tpl_function'] = array_merge($compiler->template
->properties
['tpl_function'], $_tpl->properties
['tpl_function']);
188 $compiler->template
->variable_filters
= $_tpl->variable_filters
;
189 if ($_tpl->has_nocache_code
) {
190 $compiler->template
->has_nocache_code
= true;
192 foreach ($_tpl->required_plugins
as $key => $tmp1) {
193 if ($compiler->nocache
&& $compiler->template
->caching
) {
198 foreach ($tmp1 as $name => $tmp) {
199 foreach ($tmp as $type => $data) {
200 $compiler->template
->required_plugins
[$code][$name][$type] = $data;
205 $compiler->has_code
= true;
210 * Compile $smarty.block.parent
212 * @param object $compiler compiler object
213 * @param string $_name optional name of child block
215 * @return string compiled code of child block
217 static function compileParentBlock($compiler, $_name = null)
219 // if called by {$smarty.block.parent} we must search the name of enclosing {block}
220 if ($_name == null) {
221 $stack_count = count($compiler->_tag_stack
);
222 while (-- $stack_count >= 0) {
223 if ($compiler->_tag_stack
[$stack_count][0] == 'block') {
224 $_name = trim($compiler->_tag_stack
[$stack_count][1][0]['name'], "\"'");
229 if ($_name == null) {
230 $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex
->taglineno
);
232 if (empty(Smarty_Internal_Compile_Block
::$nested_block_names)) {
233 $compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', $compiler->lex
->taglineno
);
235 Smarty_Internal_Compile_Block
::$block_data[Smarty_Internal_Compile_Block
::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block
::parent
;
236 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
237 $compiler->has_code
= false;
242 * Process block source
245 * @param string $source source text
247 static function blockSource($compiler, $source)
249 Smarty_Internal_Compile_Block
::$block_data[Smarty_Internal_Compile_Block
::$nested_block_names[0]]['source'] .= $source;
254 * Smarty Internal Plugin Compile BlockClose Class
257 * @subpackage Compiler
259 class Smarty_Internal_Compile_Blockclose
extends Smarty_Internal_CompileBase
262 * Compiles code for the {/block} tag
264 * @param array $args array with attributes from parser
265 * @param object $compiler compiler object
267 * @return string compiled code
269 public function compile($args, $compiler)
271 $compiler->has_code
= true;
272 // check and get attributes
273 $_attr = $this->getAttributes($compiler, $args);
274 $saved_data = $this->closeTag($compiler, array('block'));
275 $_name = trim($saved_data[0]['name'], "\"'");
276 // reset flag for {block} tag
277 $compiler->inheritance
= $saved_data[1];
278 // check if we process an inheritance child template
279 if ($compiler->inheritance_child
) {
280 $name1 = Smarty_Internal_Compile_Block
::$nested_block_names[0];
281 Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}";
282 array_shift(Smarty_Internal_Compile_Block
::$nested_block_names);
283 if (!empty(Smarty_Internal_Compile_Block
::$nested_block_names)) {
284 $name2 = Smarty_Internal_Compile_Block
::$nested_block_names[0];
285 if (isset($compiler->template
->block_data
[$name1]) ||
!$saved_data[0]['hide']) {
286 if (isset(Smarty_Internal_Compile_Block
::$block_data[$name1]['child']) ||
!isset($compiler->template
->block_data
[$name1])) {
287 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
289 if ($compiler->template
->block_data
[$name1]['mode'] == 'append') {
290 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] . $compiler->template
->block_data
[$name1]['source'];
291 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'prepend') {
292 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= $compiler->template
->block_data
[$name1]['source'] . Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
294 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= $compiler->template
->block_data
[$name1]['source'];
298 unset(Smarty_Internal_Compile_Block
::$block_data[$name1]);
299 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
301 if (isset($compiler->template
->block_data
[$name1]) ||
!$saved_data[0]['hide']) {
302 if (isset($compiler->template
->block_data
[$name1]) && !isset(Smarty_Internal_Compile_Block
::$block_data[$name1]['child'])) {
303 if (strpos($compiler->template
->block_data
[$name1]['source'], Smarty_Internal_Compile_Block
::parent
) !== false) {
304 $compiler->template
->block_data
[$name1]['source'] =
305 str_replace(Smarty_Internal_Compile_Block
::parent
, Smarty_Internal_Compile_Block
::$block_data[$name1]['source'], $compiler->template
->block_data
[$name1]['source']);
306 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'prepend') {
307 $compiler->template
->block_data
[$name1]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
308 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'append') {
309 $compiler->template
->block_data
[$name1]['source'] = Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] . $compiler->template
->block_data
[$name1]['source'];
312 $compiler->template
->block_data
[$name1]['source'] = Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
314 $compiler->template
->block_data
[$name1]['mode'] = 'replace';
315 if ($saved_data[0]['append']) {
316 $compiler->template
->block_data
[$name1]['mode'] = 'append';
318 if ($saved_data[0]['prepend']) {
319 $compiler->template
->block_data
[$name1]['mode'] = 'prepend';
322 unset(Smarty_Internal_Compile_Block
::$block_data[$name1]);
323 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBODY
);
325 $compiler->has_code
= false;
328 if (isset($compiler->template
->block_data
[$_name]) && !isset($compiler->template
->block_data
[$_name]['compiled'])) {
329 $_output = Smarty_Internal_Compile_Block
::compileChildBlock($compiler, $_name);
331 if ($saved_data[0]['hide'] && !isset($compiler->template
->block_data
[$_name]['source'])) {
334 $_output = $compiler->parser
->current_buffer
->to_smarty_php();
337 unset($compiler->template
->block_data
[$_name]['compiled']);
339 $compiler->parser
->current_buffer
= $saved_data[2];
340 if ($compiler->nocache
) {
341 $compiler->tag_nocache
= true;
343 $compiler->nocache
= $saved_data[3];
344 // $_output content has already nocache code processed
345 $compiler->suppressNocacheProcessing
= true;
352 * Smarty Internal Plugin Compile Child Block Class
355 * @subpackage Compiler
357 class Smarty_Internal_Compile_Private_Child_Block
extends Smarty_Internal_CompileBase
361 * Attribute definition: Overwrites base class.
364 * @see Smarty_Internal_CompileBase
366 public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
369 * Compiles code for the {private_child_block} tag
371 * @param array $args array with attributes from parser
372 * @param object $compiler compiler object
374 * @return boolean true
376 public function compile($args, $compiler)
378 // check and get attributes
379 $_attr = $this->getAttributes($compiler, $args);
381 // update template with original template resource of {block}
382 if (trim($_attr['type'], "'") == 'file') {
383 $compiler->template
->template_resource
= 'file:' . realpath(trim($_attr['file'], "'"));
385 $compiler->template
->template_resource
= trim($_attr['resource'], "'");
388 unset ($compiler->template
->source
);
389 $exists = $compiler->template
->source
->exists
;
391 // must merge includes
392 if ($_attr['nocache'] == true) {
393 $compiler->tag_nocache
= true;
395 $save = array($_attr, $compiler->nocache
);
397 // set trace back to child block
398 $compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex
->line
);
400 $this->openTag($compiler, 'private_child_block', $save);
402 $compiler->nocache
= $compiler->nocache |
$compiler->tag_nocache
;
403 $compiler->has_code
= false;
410 * Smarty Internal Plugin Compile Child Block Close Class
413 * @subpackage Compiler
415 class Smarty_Internal_Compile_Private_Child_Blockclose
extends Smarty_Internal_CompileBase
419 * Compiles code for the {/private_child_block} tag
421 * @param array $args array with attributes from parser
422 * @param object $compiler compiler object
424 * @return boolean true
426 public function compile($args, $compiler)
428 // check and get attributes
429 $_attr = $this->getAttributes($compiler, $args);
431 $saved_data = $this->closeTag($compiler, array('private_child_block'));
433 // end of child block
434 $compiler->popTrace();
436 $compiler->nocache
= $saved_data[1];
437 $compiler->has_code
= false;