Subversion Repositories ALCASAR

Rev

Details | Last modification | View Log

Rev Author Line No. Line
2809 rexy 1
<?php
2
/**
3
 * Smarty Internal Plugin Compile Include
4
 * Compiles the {include} tag
5
 *
6
 * @package    Smarty
7
 * @subpackage Compiler
8
 * @author     Uwe Tews
9
 */
10
 
11
/**
12
 * Smarty Internal Plugin Compile Include Class
13
 *
14
 * @package    Smarty
15
 * @subpackage Compiler
16
 */
17
class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
18
{
19
    /**
20
     * caching mode to create nocache code but no cache file
21
     */
22
    const CACHING_NOCACHE_CODE = 9999;
23
 
24
    /**
25
     * Attribute definition: Overwrites base class.
26
     *
27
     * @var array
28
     * @see Smarty_Internal_CompileBase
29
     */
30
    public $required_attributes = array('file');
31
 
32
    /**
33
     * Attribute definition: Overwrites base class.
34
     *
35
     * @var array
36
     * @see Smarty_Internal_CompileBase
37
     */
38
    public $shorttag_order = array('file');
39
 
40
    /**
41
     * Attribute definition: Overwrites base class.
42
     *
43
     * @var array
44
     * @see Smarty_Internal_CompileBase
45
     */
46
    public $option_flags = array('nocache', 'inline', 'caching');
47
 
48
    /**
49
     * Attribute definition: Overwrites base class.
50
     *
51
     * @var array
52
     * @see Smarty_Internal_CompileBase
53
     */
54
    public $optional_attributes = array('_any');
55
 
56
    /**
57
     * Valid scope names
58
     *
59
     * @var array
60
     */
61
    public $valid_scopes = array(
62
        'parent' => Smarty::SCOPE_PARENT, 'root' => Smarty::SCOPE_ROOT,
63
        'global' => Smarty::SCOPE_GLOBAL, 'tpl_root' => Smarty::SCOPE_TPL_ROOT,
64
        'smarty' => Smarty::SCOPE_SMARTY
65
    );
66
 
67
    /**
68
     * Compiles code for the {include} tag
69
     *
70
     * @param array                                  $args     array with attributes from parser
71
     * @param Smarty_Internal_SmartyTemplateCompiler $compiler compiler object
72
     *
73
     * @return string
74
     * @throws \Exception
75
     * @throws \SmartyCompilerException
76
     * @throws \SmartyException
77
     */
78
    public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler)
79
    {
80
        $uid = $t_hash = null;
81
        // check and get attributes
82
        $_attr = $this->getAttributes($compiler, $args);
83
        $fullResourceName = $source_resource = $_attr[ 'file' ];
84
        $variable_template = false;
85
        $cache_tpl = false;
86
        // parse resource_name
87
        if (preg_match('/^([\'"])(([A-Za-z0-9_\-]{2,})[:])?(([^$()]+)|(.+))\1$/', $source_resource, $match)) {
88
            $type = !empty($match[ 3 ]) ? $match[ 3 ] : $compiler->template->smarty->default_resource_type;
89
            $name = !empty($match[ 5 ]) ? $match[ 5 ] : $match[ 6 ];
90
            $handler = Smarty_Resource::load($compiler->smarty, $type);
91
            if ($handler->recompiled || $handler->uncompiled) {
92
                $variable_template = true;
93
            }
94
            if (!$variable_template) {
95
                if ($type !== 'string') {
96
                    $fullResourceName = "{$type}:{$name}";
97
                    $compiled = $compiler->parent_compiler->template->compiled;
98
                    if (isset($compiled->includes[ $fullResourceName ])) {
99
                        $compiled->includes[ $fullResourceName ]++;
100
                        $cache_tpl = true;
101
                    } else {
102
                        if ("{$compiler->template->source->type}:{$compiler->template->source->name}" ==
103
                            $fullResourceName
104
                        ) {
105
                            // recursive call of current template
106
                            $compiled->includes[ $fullResourceName ] = 2;
107
                            $cache_tpl = true;
108
                        } else {
109
                            $compiled->includes[ $fullResourceName ] = 1;
110
                        }
111
                    }
112
                    $fullResourceName = $match[ 1 ] . $fullResourceName . $match[ 1 ];
113
                }
114
            }
115
            if (empty($match[ 5 ])) {
116
                $variable_template = true;
117
            }
118
        } else {
119
            $variable_template = true;
120
        }
121
        // scope setup
122
        $_scope = $compiler->convertScope($_attr, $this->valid_scopes);
123
        // set flag to cache subtemplate object when called within loop or template name is variable.
124
        if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) {
125
            $_cache_tpl = 'true';
126
        } else {
127
            $_cache_tpl = 'false';
128
        }
129
        // assume caching is off
130
        $_caching = Smarty::CACHING_OFF;
131
        $call_nocache = $compiler->tag_nocache || $compiler->nocache;
132
        // caching was on and {include} is not in nocache mode
133
        if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) {
134
            $_caching = self::CACHING_NOCACHE_CODE;
135
        }
136
        // flag if included template code should be merged into caller
137
        $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr[ 'inline' ] === true) &&
138
                                   !$compiler->template->source->handler->recompiled;
139
        if ($merge_compiled_includes) {
140
            // variable template name ?
141
            if ($variable_template) {
142
                $merge_compiled_includes = false;
143
            }
144
            // variable compile_id?
145
            if (isset($_attr[ 'compile_id' ]) && $compiler->isVariable($_attr[ 'compile_id' ])) {
146
                $merge_compiled_includes = false;
147
            }
148
        }
149
        /*
150
        * if the {include} tag provides individual parameter for caching or compile_id
151
        * the subtemplate must not be included into the common cache file and is treated like
152
        * a call in nocache mode.
153
        *
154
        */
155
        if ($_attr[ 'nocache' ] !== true && $_attr[ 'caching' ]) {
156
            $_caching = $_new_caching = (int)$_attr[ 'caching' ];
157
            $call_nocache = true;
158
        } else {
159
            $_new_caching = Smarty::CACHING_LIFETIME_CURRENT;
160
        }
161
        if (isset($_attr[ 'cache_lifetime' ])) {
162
            $_cache_lifetime = $_attr[ 'cache_lifetime' ];
163
            $call_nocache = true;
164
            $_caching = $_new_caching;
165
        } else {
166
            $_cache_lifetime = '$_smarty_tpl->cache_lifetime';
167
        }
168
        if (isset($_attr[ 'cache_id' ])) {
169
            $_cache_id = $_attr[ 'cache_id' ];
170
            $call_nocache = true;
171
            $_caching = $_new_caching;
172
        } else {
173
            $_cache_id = '$_smarty_tpl->cache_id';
174
        }
175
        if (isset($_attr[ 'compile_id' ])) {
176
            $_compile_id = $_attr[ 'compile_id' ];
177
        } else {
178
            $_compile_id = '$_smarty_tpl->compile_id';
179
        }
180
        // if subtemplate will be called in nocache mode do not merge
181
        if ($compiler->template->caching && $call_nocache) {
182
            $merge_compiled_includes = false;
183
        }
184
        // assign attribute
185
        if (isset($_attr[ 'assign' ])) {
186
            // output will be stored in a smarty variable instead of being displayed
187
            if ($_assign = $compiler->getId($_attr[ 'assign' ])) {
188
                $_assign = "'{$_assign}'";
189
                if ($compiler->tag_nocache || $compiler->nocache || $call_nocache) {
190
                    // create nocache var to make it know for further compiling
191
                    $compiler->setNocacheInVariable($_attr[ 'assign' ]);
192
                }
193
            } else {
194
                $_assign = $_attr[ 'assign' ];
195
            }
196
        }
197
        $has_compiled_template = false;
198
        if ($merge_compiled_includes) {
199
            $c_id = isset($_attr[ 'compile_id' ]) ? $_attr[ 'compile_id' ] : $compiler->template->compile_id;
200
            // we must observe different compile_id and caching
201
            $t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
202
            $compiler->smarty->allow_ambiguous_resources = true;
203
            /* @var Smarty_Internal_Template $tpl */
204
            $tpl = new $compiler->smarty->template_class(
205
                trim($fullResourceName, '"\''),
206
                $compiler->smarty,
207
                $compiler->template,
208
                $compiler->template->cache_id,
209
                $c_id,
210
                $_caching
211
            );
212
            $uid = $tpl->source->type . $tpl->source->uid;
213
            if (!isset($compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ])) {
214
                $has_compiled_template = $this->compileInlineTemplate($compiler, $tpl, $t_hash);
215
            } else {
216
                $has_compiled_template = true;
217
            }
218
            unset($tpl);
219
        }
220
        // delete {include} standard attributes
221
        unset($_attr[ 'file' ], $_attr[ 'assign' ], $_attr[ 'cache_id' ], $_attr[ 'compile_id' ], $_attr[ 'cache_lifetime' ], $_attr[ 'nocache' ], $_attr[ 'caching' ], $_attr[ 'scope' ], $_attr[ 'inline' ]);
222
        // remaining attributes must be assigned as smarty variable
223
        $_vars = 'array()';
224
        if (!empty($_attr)) {
225
            $_pairs = array();
226
            // create variables
227
            foreach ($_attr as $key => $value) {
228
                $_pairs[] = "'$key'=>$value";
229
            }
230
            $_vars = 'array(' . join(',', $_pairs) . ')';
231
        }
232
        $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
233
                             $_compile_id !== '$_smarty_tpl->compile_id';
234
        if ($has_compiled_template && !$call_nocache) {
235
            $_output = "<?php\n";
236
            if ($update_compile_id) {
237
                $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
238
            }
239
            if (!empty($_attr) && $_caching === 9999 && $compiler->template->caching) {
240
                $_vars_nc = "foreach ($_vars as \$ik => \$iv) {\n";
241
                $_vars_nc .= "\$_smarty_tpl->tpl_vars[\$ik] =  new Smarty_Variable(\$iv);\n";
242
                $_vars_nc .= "}\n";
243
                $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, -3);
244
            }
245
            if (isset($_assign)) {
246
                $_output .= "ob_start();\n";
247
            }
248
            $_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$uid][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$uid][$t_hash]['func']}');\n";
249
            if (isset($_assign)) {
250
                $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
251
            }
252
            if ($update_compile_id) {
253
                $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
254
            }
255
            $_output .= "?>";
256
            return $_output;
257
        }
258
        if ($call_nocache) {
259
            $compiler->tag_nocache = true;
260
        }
261
        $_output = "<?php ";
262
        if ($update_compile_id) {
263
            $_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n";
264
        }
265
        // was there an assign attribute
266
        if (isset($_assign)) {
267
            $_output .= "ob_start();\n";
268
        }
269
        $_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
270
        if (isset($_assign)) {
271
            $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
272
        }
273
        if ($update_compile_id) {
274
            $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
275
        }
276
        $_output .= "?>";
277
        return $_output;
278
    }
279
 
280
    /**
281
     * Compile inline sub template
282
     *
283
     * @param \Smarty_Internal_SmartyTemplateCompiler $compiler
284
     * @param \Smarty_Internal_Template               $tpl
285
     * @param string                                  $t_hash
286
     *
287
     * @return bool
288
     * @throws \Exception
289
     * @throws \SmartyException
290
     */
291
    public function compileInlineTemplate(
292
        Smarty_Internal_SmartyTemplateCompiler $compiler,
293
        Smarty_Internal_Template $tpl,
294
        $t_hash
295
    ) {
296
        $uid = $tpl->source->type . $tpl->source->uid;
297
        if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) {
298
            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'uid' ] = $tpl->source->uid;
299
            if (isset($compiler->template->inheritance)) {
300
                $tpl->inheritance = clone $compiler->template->inheritance;
301
            }
302
            $tpl->compiled = new Smarty_Template_Compiled();
303
            $tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash;
304
            $tpl->loadCompiler();
305
            // save unique function name
306
            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'func' ] =
307
            $tpl->compiled->unifunc = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
308
            // make sure whole chain gets compiled
309
            $tpl->mustCompile = true;
310
            $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'nocache_hash' ] =
311
                $tpl->compiled->nocache_hash;
312
            if ($tpl->source->type === 'file') {
313
                $sourceInfo = $tpl->source->filepath;
314
            } else {
315
                $basename = $tpl->source->handler->getBasename($tpl->source);
316
                $sourceInfo = $tpl->source->type . ':' .
317
                              ($basename ? $basename : $tpl->source->name);
318
            }
319
            // get compiled code
320
            $compiled_code = "<?php\n\n";
321
            $compiled_code .= "/* Start inline template \"{$sourceInfo}\" =============================*/\n";
322
            $compiled_code .= "function {$tpl->compiled->unifunc} (Smarty_Internal_Template \$_smarty_tpl) {\n";
323
            $compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
324
            $compiled_code .= "<?php\n";
325
            $compiled_code .= "}\n?>\n";
326
            $compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
327
            $compiled_code .= "<?php\n\n";
328
            $compiled_code .= "/* End inline template \"{$sourceInfo}\" =============================*/\n";
329
            $compiled_code .= '?>';
330
            unset($tpl->compiler);
331
            if ($tpl->compiled->has_nocache_code) {
332
                // replace nocache_hash
333
                $compiled_code =
334
                    str_replace(
335
                        "{$tpl->compiled->nocache_hash}",
336
                        $compiler->template->compiled->nocache_hash,
337
                        $compiled_code
338
                    );
339
                $compiler->template->compiled->has_nocache_code = true;
340
            }
341
            $compiler->parent_compiler->mergedSubTemplatesCode[ $tpl->compiled->unifunc ] = $compiled_code;
342
            return true;
343
        } else {
344
            return false;
345
        }
346
    }
347
}