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_template_buffer($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 $_tpl->compiler
->suppressMergedTemplates
= true;
177 $nocache = $compiler->nocache ||
$compiler->tag_nocache
;
178 if (strpos($compiler->template
->block_data
[$_name]['source'], self
::parent
) !== false) {
179 $_output = str_replace(self
::parent
, $compiler->parser
->current_buffer
->to_smarty_php(), $_tpl->compiler
->compileTemplate($_tpl, $nocache));
180 } elseif ($compiler->template
->block_data
[$_name]['mode'] == 'prepend') {
181 $_output = $_tpl->compiler
->compileTemplate($_tpl, $nocache) . $compiler->parser
->current_buffer
->to_smarty_php();
182 } elseif ($compiler->template
->block_data
[$_name]['mode'] == 'append') {
183 $_output = $compiler->parser
->current_buffer
->to_smarty_php() . $_tpl->compiler
->compileTemplate($_tpl, $nocache);
184 } elseif (!empty($compiler->template
->block_data
[$_name])) {
185 $_output = $_tpl->compiler
->compileTemplate($_tpl, $nocache);
187 $compiler->template
->properties
['file_dependency'] = array_merge($compiler->template
->properties
['file_dependency'], $_tpl->properties
['file_dependency']);
188 $compiler->template
->properties
['function'] = array_merge($compiler->template
->properties
['function'], $_tpl->properties
['function']);
189 $compiler->merged_templates
= array_merge($compiler->merged_templates
, $_tpl->compiler
->merged_templates
);
190 $compiler->template
->variable_filters
= $_tpl->variable_filters
;
191 if ($_tpl->has_nocache_code
) {
192 $compiler->template
->has_nocache_code
= true;
194 foreach ($_tpl->required_plugins
as $key => $tmp1) {
195 if ($compiler->nocache
&& $compiler->template
->caching
) {
200 foreach ($tmp1 as $name => $tmp) {
201 foreach ($tmp as $type => $data) {
202 $compiler->template
->required_plugins
[$code][$name][$type] = $data;
207 $compiler->has_code
= true;
212 * Compile $smarty.block.parent
214 * @param object $compiler compiler object
215 * @param string $_name optional name of child block
217 * @return string compiled code of child block
219 static function compileParentBlock($compiler, $_name = null)
221 // if called by {$smarty.block.parent} we must search the name of enclosing {block}
222 if ($_name == null) {
223 $stack_count = count($compiler->_tag_stack
);
224 while (--$stack_count >= 0) {
225 if ($compiler->_tag_stack
[$stack_count][0] == 'block') {
226 $_name = trim($compiler->_tag_stack
[$stack_count][1][0]['name'], "\"'");
231 if ($_name == null) {
232 $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex
->taglineno
);
234 if (empty(Smarty_Internal_Compile_Block
::$nested_block_names)) {
235 $compiler->trigger_template_error(' illegal {$smarty.block.parent} in parent template ', $compiler->lex
->taglineno
);
237 Smarty_Internal_Compile_Block
::$block_data[Smarty_Internal_Compile_Block
::$nested_block_names[0]]['source'] .= Smarty_Internal_Compile_Block
::parent
;
238 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
239 $compiler->has_code
= false;
244 * Process block source
247 * @param string $source source text
250 static function blockSource($compiler, $source)
252 Smarty_Internal_Compile_Block
::$block_data[Smarty_Internal_Compile_Block
::$nested_block_names[0]]['source'] .= $source;
257 * Smarty Internal Plugin Compile BlockClose Class
260 * @subpackage Compiler
262 class Smarty_Internal_Compile_Blockclose
extends Smarty_Internal_CompileBase
265 * Compiles code for the {/block} tag
267 * @param array $args array with attributes from parser
268 * @param object $compiler compiler object
270 * @return string compiled code
272 public function compile($args, $compiler)
274 $compiler->has_code
= true;
275 // check and get attributes
276 $_attr = $this->getAttributes($compiler, $args);
277 $saved_data = $this->closeTag($compiler, array('block'));
278 $_name = trim($saved_data[0]['name'], "\"'");
279 // reset flag for {block} tag
280 $compiler->inheritance
= $saved_data[1];
281 // check if we process an inheritance child template
282 if ($compiler->inheritance_child
) {
283 $name1 = Smarty_Internal_Compile_Block
::$nested_block_names[0];
284 Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] .= "{$compiler->smarty->left_delimiter}/private_child_block{$compiler->smarty->right_delimiter}";
285 array_shift(Smarty_Internal_Compile_Block
::$nested_block_names);
286 if (!empty(Smarty_Internal_Compile_Block
::$nested_block_names)) {
287 $name2 = Smarty_Internal_Compile_Block
::$nested_block_names[0];
288 if (isset($compiler->template
->block_data
[$name1]) ||
!$saved_data[0]['hide']) {
289 if (isset(Smarty_Internal_Compile_Block
::$block_data[$name1]['child']) ||
!isset($compiler->template
->block_data
[$name1])) {
290 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
292 if ($compiler->template
->block_data
[$name1]['mode'] == 'append') {
293 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] . $compiler->template
->block_data
[$name1]['source'];
294 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'prepend') {
295 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= $compiler->template
->block_data
[$name1]['source'] . Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
297 Smarty_Internal_Compile_Block
::$block_data[$name2]['source'] .= $compiler->template
->block_data
[$name1]['source'];
301 unset(Smarty_Internal_Compile_Block
::$block_data[$name1]);
302 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBLOCK
);
304 if (isset($compiler->template
->block_data
[$name1]) ||
!$saved_data[0]['hide']) {
305 if (isset($compiler->template
->block_data
[$name1]) && !isset(Smarty_Internal_Compile_Block
::$block_data[$name1]['child'])) {
306 if (strpos($compiler->template
->block_data
[$name1]['source'], Smarty_Internal_Compile_Block
::parent
) !== false) {
307 $compiler->template
->block_data
[$name1]['source'] =
308 str_replace(Smarty_Internal_Compile_Block
::parent
, Smarty_Internal_Compile_Block
::$block_data[$name1]['source'], $compiler->template
->block_data
[$name1]['source']);
309 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'prepend') {
310 $compiler->template
->block_data
[$name1]['source'] .= Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
311 } elseif ($compiler->template
->block_data
[$name1]['mode'] == 'append') {
312 $compiler->template
->block_data
[$name1]['source'] = Smarty_Internal_Compile_Block
::$block_data[$name1]['source'] . $compiler->template
->block_data
[$name1]['source'];
315 $compiler->template
->block_data
[$name1]['source'] = Smarty_Internal_Compile_Block
::$block_data[$name1]['source'];
317 $compiler->template
->block_data
[$name1]['mode'] = 'replace';
318 if ($saved_data[0]['append']) {
319 $compiler->template
->block_data
[$name1]['mode'] = 'append';
321 if ($saved_data[0]['prepend']) {
322 $compiler->template
->block_data
[$name1]['mode'] = 'prepend';
325 unset(Smarty_Internal_Compile_Block
::$block_data[$name1]);
326 $compiler->lex
->yypushstate(Smarty_Internal_Templatelexer
::CHILDBODY
);
328 $compiler->has_code
= false;
331 if (isset($compiler->template
->block_data
[$_name]) && !isset($compiler->template
->block_data
[$_name]['compiled'])) {
332 $_output = Smarty_Internal_Compile_Block
::compileChildBlock($compiler, $_name);
334 if ($saved_data[0]['hide'] && !isset($compiler->template
->block_data
[$_name]['source'])) {
337 $_output = $compiler->parser
->current_buffer
->to_smarty_php();
340 unset($compiler->template
->block_data
[$_name]['compiled']);
342 $compiler->parser
->current_buffer
= $saved_data[2];
343 if ($compiler->nocache
) {
344 $compiler->tag_nocache
= true;
346 $compiler->nocache
= $saved_data[3];
347 // $_output content has already nocache code processed
348 $compiler->suppressNocacheProcessing
= true;
355 * Smarty Internal Plugin Compile Child Block Class
358 * @subpackage Compiler
360 class Smarty_Internal_Compile_Private_Child_Block
extends Smarty_Internal_CompileBase
364 * Attribute definition: Overwrites base class.
367 * @see Smarty_Internal_CompileBase
369 public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
372 * Compiles code for the {private_child_block} tag
374 * @param array $args array with attributes from parser
375 * @param object $compiler compiler object
377 * @return boolean true
379 public function compile($args, $compiler)
381 // check and get attributes
382 $_attr = $this->getAttributes($compiler, $args);
384 // update template with original template resource of {block}
385 if (trim($_attr['type'], "'") == 'file') {
386 $compiler->template
->template_resource
= 'file:' . realpath(trim($_attr['file'], "'"));
388 $compiler->template
->template_resource
= trim($_attr['resource'], "'");
391 unset ($compiler->template
->source
);
392 $exists = $compiler->template
->source
->exists
;
394 // must merge includes
395 if ($_attr['nocache'] == true) {
396 $compiler->tag_nocache
= true;
398 $save = array($_attr, $compiler->nocache
);
400 // set trace back to child block
401 $compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex
->line
);
403 $this->openTag($compiler, 'private_child_block', $save);
405 $compiler->nocache
= $compiler->nocache |
$compiler->tag_nocache
;
406 $compiler->has_code
= false;
413 * Smarty Internal Plugin Compile Child Block Close Class
416 * @subpackage Compiler
418 class Smarty_Internal_Compile_Private_Child_Blockclose
extends Smarty_Internal_CompileBase
422 * Compiles code for the {/private_child_block} tag
424 * @param array $args array with attributes from parser
425 * @param object $compiler compiler object
427 * @return boolean true
429 public function compile($args, $compiler)
431 // check and get attributes
432 $_attr = $this->getAttributes($compiler, $args);
434 $saved_data = $this->closeTag($compiler, array('private_child_block'));
436 // end of child block
437 $compiler->popTrace();
439 $compiler->nocache
= $saved_data[1];
440 $compiler->has_code
= false;