1: <?php
2: /**
3: * Smarty Internal Plugin Compile extend
4: * Compiles the {extends} tag
5: *
6: * @package Smarty
7: * @subpackage Compiler
8: * @author Uwe Tews
9: */
10:
11: /**
12: * Smarty Internal Plugin Compile extend Class
13: *
14: * @package Smarty
15: * @subpackage Compiler
16: */
17: class Smarty_Internal_Compile_Extends extends Smarty_Internal_Compile_Shared_Inheritance
18: {
19: /**
20: * Attribute definition: Overwrites base class.
21: *
22: * @var array
23: * @see Smarty_Internal_CompileBase
24: */
25: public $required_attributes = array('file');
26:
27: /**
28: * Array of names of optional attribute required by tag
29: * use array('_any') if there is no restriction of attributes names
30: *
31: * @var array
32: */
33: public $optional_attributes = array('extends_resource');
34:
35: /**
36: * Attribute definition: Overwrites base class.
37: *
38: * @var array
39: * @see Smarty_Internal_CompileBase
40: */
41: public $shorttag_order = array('file');
42:
43: /**
44: * Compiles code for the {extends} tag extends: resource
45: *
46: * @param array $args array with attributes from parser
47: * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
48: *
49: * @return string compiled code
50: * @throws \SmartyCompilerException
51: * @throws \SmartyException
52: */
53: public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
54: {
55: // check and get attributes
56: $_attr = $this->getAttributes($compiler, $args);
57: if ($_attr[ 'nocache' ] === true) {
58: $compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1);
59: }
60: if (strpos($_attr[ 'file' ], '$_tmp') !== false) {
61: $compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1);
62: }
63: // add code to initialize inheritance
64: $this->registerInit($compiler, true);
65: $file = trim($_attr[ 'file' ], '\'"');
66: if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') {
67: // generate code for each template
68: $files = array_reverse(explode('|', substr($file, 8)));
69: $i = 0;
70: foreach ($files as $file) {
71: if ($file[ 0 ] === '"') {
72: $file = trim($file, '".');
73: } else {
74: $file = "'{$file}'";
75: }
76: $i++;
77: if ($i === count($files) && isset($_attr[ 'extends_resource' ])) {
78: $this->compileEndChild($compiler);
79: }
80: $this->compileInclude($compiler, $file);
81: }
82: if (!isset($_attr[ 'extends_resource' ])) {
83: $this->compileEndChild($compiler);
84: }
85: } else {
86: $this->compileEndChild($compiler, $_attr[ 'file' ]);
87: }
88: $compiler->has_code = false;
89: return '';
90: }
91:
92: /**
93: * Add code for inheritance endChild() method to end of template
94: *
95: * @param \Smarty_Internal_TemplateCompilerBase $compiler
96: * @param null|string $template optional inheritance parent template
97: *
98: * @throws \SmartyCompilerException
99: * @throws \SmartyException
100: */
101: private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler, $template = null)
102: {
103: $inlineUids = '';
104: if (isset($template) && $compiler->smarty->merge_compiled_includes) {
105: $code = $compiler->compileTag('include', array($template, array('scope' => 'parent')));
106: if (preg_match('/([,][\s]*[\'][a-z0-9]+[\'][,][\s]*[\']content.*[\'])[)]/', $code, $match)) {
107: $inlineUids = $match[ 1 ];
108: }
109: }
110: $compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag(
111: $compiler->parser,
112: '<?php $_smarty_tpl->inheritance->endChild($_smarty_tpl' .
113: (isset($template) ?
114: ", {$template}{$inlineUids}" :
115: '') . ");\n?>"
116: );
117: }
118:
119: /**
120: * Add code for including subtemplate to end of template
121: *
122: * @param \Smarty_Internal_TemplateCompilerBase $compiler
123: * @param string $template subtemplate name
124: *
125: * @throws \SmartyCompilerException
126: * @throws \SmartyException
127: */
128: private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $template)
129: {
130: $compiler->parser->template_postfix[] = new Smarty_Internal_ParseTree_Tag(
131: $compiler->parser,
132: $compiler->compileTag(
133: 'include',
134: array(
135: $template,
136: array('scope' => 'parent')
137: )
138: )
139: );
140: }
141:
142: /**
143: * Create source code for {extends} from source components array
144: *
145: * @param \Smarty_Internal_Template $template
146: *
147: * @return string
148: */
149: public static function extendsSourceArrayCode(Smarty_Internal_Template $template)
150: {
151: $resources = array();
152: foreach ($template->source->components as $source) {
153: $resources[] = $source->resource;
154: }
155: return $template->smarty->left_delimiter . 'extends file=\'extends:' . join('|', $resources) .
156: '\' extends_resource=true' . $template->smarty->right_delimiter;
157: }
158: }
159: