1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10: 
 11: 
 12:  13:  14:  15:  16:  17: 
 18: class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
 19: {
 20: 
 21:     const parent = '____SMARTY_BLOCK_PARENT____';
 22:      23:  24:  25:  26:  27: 
 28:     public $required_attributes = array('name');
 29: 
 30:      31:  32:  33:  34:  35: 
 36:     public $shorttag_order = array('name');
 37: 
 38:      39:  40:  41:  42:  43: 
 44:     public $option_flags = array('hide', 'append', 'prepend', 'nocache');
 45: 
 46:      47:  48:  49:  50:  51: 
 52:     public $optional_attributes = array('internal_file', 'internal_uid', 'internal_line');
 53:      54:  55:  56:  57: 
 58:     public static $nested_block_names = array();
 59: 
 60:      61:  62:  63:  64: 
 65:     public static $block_data = array();
 66: 
 67:      68:  69:  70:  71:  72:  73:  74: 
 75:     public function compile($args, $compiler)
 76:     {
 77:         
 78:         $_attr = $this->getAttributes($compiler, $args);
 79:         $_name = trim($_attr['name'], "\"'");
 80: 
 81:         
 82:         if (isset($compiler->template->block_data[$_name]) && $compiler->template->block_data[$_name]['mode'] == 'replace') {
 83:             $_attr['append'] = false;
 84:             $_attr['prepend'] = false;
 85:         }
 86: 
 87:         
 88:         if ($compiler->inheritance_child) {
 89:             array_unshift(self::$nested_block_names, $_name);
 90:             
 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';
 96:             }
 97:             self::$block_data[$_name]['source'] .= $compiler->smarty->right_delimiter;
 98: 
 99:             $save = array($_attr, $compiler->inheritance);
100:             $this->openTag($compiler, 'block', $save);
101:             
102:             $compiler->inheritance = true;
103:             $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
104:             $compiler->has_code = false;
105:             return;
106:         }
107:         
108:         if ($_attr['nocache'] == true) {
109:             $compiler->tag_nocache = true;
110:         }
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;
115: 
116:         $compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser);
117:         $compiler->has_code = false;
118: 
119:         return true;
120:     }
121: 
122:     123: 124: 125: 126: 127: 128: 129: 
130:     static function compileChildBlock($compiler, $_name = null)
131:     {
132:         if ($compiler->inheritance_child) {
133:             $name1 = Smarty_Internal_Compile_Block::$nested_block_names[0];
134:             if (isset($compiler->template->block_data[$name1])) {
135:                 
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;
138:             }
139:             $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
140:             $compiler->has_code = false;
141:             return;
142:         }
143:         
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'], "\"'");
149:                     break;
150:                 }
151:             }
152:         }
153:         if ($_name == null) {
154:             $compiler->trigger_template_error(' tag {$smarty.block.child} used outside {block} tags ', $compiler->lex->taglineno);
155:         }
156:         
157:         if (!isset($compiler->template->block_data[$_name]['source'])) {
158:             $compiler->popTrace();
159:             return '';
160:         }
161:         
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);
167:         }
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);
186:         }
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;
193:         }
194:         foreach ($_tpl->required_plugins as $key => $tmp1) {
195:             if ($compiler->nocache && $compiler->template->caching) {
196:                 $code = 'nocache';
197:             } else {
198:                 $code = $key;
199:             }
200:             foreach ($tmp1 as $name => $tmp) {
201:                 foreach ($tmp as $type => $data) {
202:                     $compiler->template->required_plugins[$code][$name][$type] = $data;
203:                 }
204:             }
205:         }
206:         unset($_tpl);
207:         $compiler->has_code = true;
208:         return $_output;
209:     }
210: 
211:     212: 213: 214: 215: 216: 217: 218: 
219:     static function compileParentBlock($compiler, $_name = null)
220:     {
221:         
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'], "\"'");
227:                     break;
228:                 }
229:             }
230:         }
231:         if ($_name == null) {
232:             $compiler->trigger_template_error(' tag {$smarty.block.parent} used outside {block} tags ', $compiler->lex->taglineno);
233:         }
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);
236:         }
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;
240:         return;
241:     }
242: 
243:     244: 245: 246: 247: 248: 249: 
250:     static function blockSource($compiler, $source)
251:     {
252:         Smarty_Internal_Compile_Block::$block_data[Smarty_Internal_Compile_Block::$nested_block_names[0]]['source'] .= $source;
253:     }
254: }
255: 
256: 257: 258: 259: 260: 261: 
262: class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase
263: {
264:     265: 266: 267: 268: 269: 270: 271: 
272:     public function compile($args, $compiler)
273:     {
274:         $compiler->has_code = true;
275:         
276:         $_attr = $this->getAttributes($compiler, $args);
277:         $saved_data = $this->closeTag($compiler, array('block'));
278:         $_name = trim($saved_data[0]['name'], "\"'");
279:         
280:         $compiler->inheritance = $saved_data[1];
281:         
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'];
291:                     } else {
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'];
296:                         } else {
297:                             Smarty_Internal_Compile_Block::$block_data[$name2]['source'] .= $compiler->template->block_data[$name1]['source'];
298:                         }
299:                     }
300:                 }
301:                 unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
302:                 $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBLOCK);
303:             } else {
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'];
313:                         }
314:                     } else {
315:                         $compiler->template->block_data[$name1]['source'] = Smarty_Internal_Compile_Block::$block_data[$name1]['source'];
316:                     }
317:                     $compiler->template->block_data[$name1]['mode'] = 'replace';
318:                     if ($saved_data[0]['append']) {
319:                         $compiler->template->block_data[$name1]['mode'] = 'append';
320:                     }
321:                     if ($saved_data[0]['prepend']) {
322:                         $compiler->template->block_data[$name1]['mode'] = 'prepend';
323:                     }
324:                 }
325:                 unset(Smarty_Internal_Compile_Block::$block_data[$name1]);
326:                 $compiler->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);
327:             }
328:             $compiler->has_code = false;
329:             return;
330:         }
331:         if (isset($compiler->template->block_data[$_name]) && !isset($compiler->template->block_data[$_name]['compiled'])) {
332:             $_output = Smarty_Internal_Compile_Block::compileChildBlock($compiler, $_name);
333:         } else {
334:             if ($saved_data[0]['hide'] && !isset($compiler->template->block_data[$_name]['source'])) {
335:                 $_output = '';
336:             } else {
337:                 $_output = $compiler->parser->current_buffer->to_smarty_php();
338:             }
339:         }
340:         unset($compiler->template->block_data[$_name]['compiled']);
341:         
342:         $compiler->parser->current_buffer = $saved_data[2];
343:         if ($compiler->nocache) {
344:             $compiler->tag_nocache = true;
345:         }
346:         $compiler->nocache = $saved_data[3];
347:         
348:         $compiler->suppressNocacheProcessing = true;
349: 
350:         return $_output;
351:     }
352: }
353: 
354: 355: 356: 357: 358: 359: 
360: class Smarty_Internal_Compile_Private_Child_Block extends Smarty_Internal_CompileBase
361: {
362: 
363:     364: 365: 366: 367: 368: 
369:     public $required_attributes = array('name', 'file', 'uid', 'line', 'type', 'resource');
370: 
371:     372: 373: 374: 375: 376: 377: 378: 
379:     public function compile($args, $compiler)
380:     {
381:         
382:         $_attr = $this->getAttributes($compiler, $args);
383: 
384:         
385:         if (trim($_attr['type'], "'") == 'file') {
386:             $compiler->template->template_resource = 'file:' . realpath(trim($_attr['file'], "'"));
387:         } else {
388:             $compiler->template->template_resource = trim($_attr['resource'], "'");
389:         }
390:         
391:         unset ($compiler->template->source);
392:         $exists = $compiler->template->source->exists;
393: 
394:         
395:         if ($_attr['nocache'] == true) {
396:             $compiler->tag_nocache = true;
397:         }
398:         $save = array($_attr, $compiler->nocache);
399: 
400:         
401:         $compiler->pushTrace(trim($_attr['file'], "\"'"), trim($_attr['uid'], "\"'"), $_attr['line'] - $compiler->lex->line);
402: 
403:         $this->openTag($compiler, 'private_child_block', $save);
404: 
405:         $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
406:         $compiler->has_code = false;
407: 
408:         return true;
409:     }
410: }
411: 
412: 413: 414: 415: 416: 417: 
418: class Smarty_Internal_Compile_Private_Child_Blockclose extends Smarty_Internal_CompileBase
419: {
420: 
421:     422: 423: 424: 425: 426: 427: 428: 
429:     public function compile($args, $compiler)
430:     {
431:         
432:         $_attr = $this->getAttributes($compiler, $args);
433: 
434:         $saved_data = $this->closeTag($compiler, array('private_child_block'));
435: 
436:         
437:         $compiler->popTrace();
438: 
439:         $compiler->nocache = $saved_data[1];
440:         $compiler->has_code = false;
441: 
442:         return true;
443:     }
444: }
445: