1 <?php
3 /**
4 * Smarty Internal Plugin Compile extend
5 *
6 * Compiles the {extends} tag
7 *
8 * @package Smarty
9 * @subpackage Compiler
10 * @author Uwe Tews
11 */
12 /**
13 * Smarty Internal Plugin Compile extend Class
14 */
15 class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase {
16 /**
17 * Compiles code for the {extends} tag
18 *
19 * @param array $args array with attributes from parser
20 * @param object $compiler compiler object
21 * @return string compiled code
22 */
23 public function compile($args, $compiler)
24 {
25 $this->compiler = $compiler;
26 $this->smarty = $compiler->smarty;
27 $this->_rdl = preg_quote($this->smarty->right_delimiter);
28 $this->_ldl = preg_quote($this->smarty->left_delimiter);
29 $this->required_attributes = array('file');
30 // check and get attributes
31 $_attr = $this->_get_attributes($args);
32 $_smarty_tpl = $compiler->template;
33 // $include_file = '';
34 eval('$include_file = ' . $_attr['file'] . ';');
35 // create template object
36 $_template = new $compiler->smarty->template_class($include_file, $this->smarty, $compiler->template);
37 // save file dependency
38 $compiler->template->properties['file_dependency'][sha1($_template->getTemplateFilepath())] = array($_template->getTemplateFilepath(), $_template->getTemplateTimestamp());
39 $_content = $compiler->template->template_source;
40 if (preg_match_all("!({$this->_ldl}block(.+?){$this->_rdl})!", $_content, $s) !=
41 preg_match_all("!({$this->_ldl}/block(.*?){$this->_rdl})!", $_content, $c)) {
42 $this->compiler->trigger_template_error('unmatched {block} {/block} pairs');
43 }
44 preg_match_all("!{$this->_ldl}block(.+?){$this->_rdl}|{$this->_ldl}/block(.*?){$this->_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE);
45 $_result_count = count($_result[0]);
46 $_start = 0;
47 while ($_start < $_result_count) {
48 $_end = 0;
49 $_level = 1;
50 while ($_level != 0) {
51 $_end++;
52 if (!strpos($_result[0][$_start + $_end][0], '/')) {
53 $_level++;
54 } else {
55 $_level--;
56 }
57 }
58 $_block_content = str_replace($this->smarty->left_delimiter . '$smarty.block.parent' . $this->smarty->right_delimiter, '%%%%SMARTY_PARENT%%%%',
59 substr($_content, $_result[0][$_start][1] + strlen($_result[0][$_start][0]), $_result[0][$_start + $_end][1] - $_result[0][$_start][1] - + strlen($_result[0][$_start][0])));
60 $this->saveBlockData($_block_content, $_result[0][$_start][0], $compiler->template);
61 $_start = $_start + $_end + 1;
62 }
63 $compiler->template->template_source = $_template->getTemplateSource();
64 $compiler->template->template_filepath = $_template->getTemplateFilepath();
65 $compiler->abort_and_recompile = true;
66 return ' ';
67 }
69 protected function saveBlockData($block_content, $block_tag, $template)
70 {
71 if (0 == preg_match("!(.?)(name=)(.*?)(?=(\s|{$this->_rdl}))!", $block_tag, $_match)) {
72 $this->compiler->trigger_template_error("\"" . $block_tag . "\" missing name attribute");
73 } else {
74 $_name = trim($_match[3], '\'"');
75 // replace {$smarty.block.child}
76 if (strpos($block_content, $this->smarty->left_delimiter . '$smarty.block.child' . $this->smarty->right_delimiter) !== false) {
77 if (isset($this->smarty->block_data[$_name])) {
78 $block_content = str_replace($this->smarty->left_delimiter . '$smarty.block.child' . $this->smarty->right_delimiter,
79 $this->smarty->block_data[$_name]['source'], $block_content);
80 unset($this->smarty->block_data[$_name]);
81 } else {
82 $block_content = str_replace($this->smarty->left_delimiter . '$smarty.block.child' . $this->smarty->right_delimiter,
83 '', $block_content);
84 }
85 }
86 if (isset($this->smarty->block_data[$_name])) {
87 if (strpos($this->smarty->block_data[$_name]['source'], '%%%%SMARTY_PARENT%%%%') !== false) {
88 $this->smarty->block_data[$_name]['source'] =
89 str_replace('%%%%SMARTY_PARENT%%%%', $block_content, $this->smarty->block_data[$_name]['source']);
90 } elseif ($this->smarty->block_data[$_name]['mode'] == 'prepend') {
91 $this->smarty->block_data[$_name]['source'] .= $block_content;
92 } elseif ($this->smarty->block_data[$_name]['mode'] == 'append') {
93 $this->smarty->block_data[$_name]['source'] = $block_content . $this->smarty->block_data[$_name]['source'];
94 }
95 } else {
96 $this->smarty->block_data[$_name]['source'] = $block_content;
97 }
98 if (preg_match('/(.?)(append)(.*)/', $block_tag, $_match) != 0) {
99 $this->smarty->block_data[$_name]['mode'] = 'append';
100 } elseif (preg_match('/(.?)(prepend)(.*)/', $block_tag, $_match) != 0) {
101 $this->smarty->block_data[$_name]['mode'] = 'prepend';
102 } else {
103 $this->smarty->block_data[$_name]['mode'] = 'replace';
104 }
105 $this->smarty->block_data[$_name]['file'] = $template->getTemplateFilepath();
106 }
107 }
108 }
110 ?>