]> git.mxchange.org Git - friendica.git/blob - vendor/smarty/smarty/libs/sysplugins/smarty_internal_compile_include.php
Add Smarty to Composer
[friendica.git] / vendor / smarty / smarty / libs / sysplugins / smarty_internal_compile_include.php
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('parent' => Smarty::SCOPE_PARENT, 'root' => Smarty::SCOPE_ROOT,
62                                  'global' => Smarty::SCOPE_GLOBAL, 'tpl_root' => Smarty::SCOPE_TPL_ROOT,
63                                  'smarty' => Smarty::SCOPE_SMARTY);
64
65     /**
66      * Compiles code for the {include} tag
67      *
68      * @param  array                                  $args      array with attributes from parser
69      * @param  Smarty_Internal_SmartyTemplateCompiler $compiler  compiler object
70      * @param  array                                  $parameter array with compilation parameter
71      *
72      * @throws SmartyCompilerException
73      * @return string compiled code
74      */
75     public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter)
76     {
77         $uid = $t_hash = null;
78         // check and get attributes
79         $_attr = $this->getAttributes($compiler, $args);
80
81         $fullResourceName = $source_resource = $_attr[ 'file' ];
82         $variable_template = false;
83         $cache_tpl = false;
84         // parse resource_name
85         if (preg_match('/^([\'"])(([A-Za-z0-9_\-]{2,})[:])?(([^$()]+)|(.+))\1$/', $source_resource, $match)) {
86             $type = !empty($match[ 3 ]) ? $match[ 3 ] : $compiler->template->smarty->default_resource_type;
87             $name = !empty($match[ 5 ]) ? $match[ 5 ] : $match[ 6 ];
88             $handler = Smarty_Resource::load($compiler->smarty, $type);
89             if ($handler->recompiled || $handler->uncompiled) {
90                 $variable_template = true;
91             }
92             if (!$variable_template) {
93                 if ($type != 'string') {
94                     $fullResourceName = "{$type}:{$name}";
95                     $compiled = $compiler->parent_compiler->template->compiled;
96                     if (isset($compiled->includes[ $fullResourceName ])) {
97                         $compiled->includes[ $fullResourceName ] ++;
98                         $cache_tpl = true;
99                     } else {
100                         if ("{$compiler->template->source->type}:{$compiler->template->source->name}" ==
101                             $fullResourceName
102                         ) {
103                             // recursive call of current template
104                             $compiled->includes[ $fullResourceName ] = 2;
105                             $cache_tpl = true;
106                         } else {
107                             $compiled->includes[ $fullResourceName ] = 1;
108                         }
109                     }
110                     $fullResourceName = $match[ 1 ] . $fullResourceName . $match[ 1 ];
111                 }
112             }
113             if (empty($match[ 5 ])) {
114                 $variable_template = true;
115             }
116         } else {
117             $variable_template = true;
118         }
119
120         // scope setup
121         $_scope = $compiler->convertScope($_attr, $this->valid_scopes);
122
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
132         $call_nocache = $compiler->tag_nocache || $compiler->nocache;
133
134         // caching was on and {include} is not in nocache mode
135         if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) {
136             $_caching = self::CACHING_NOCACHE_CODE;
137         }
138
139         // flag if included template code should be merged into caller
140         $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr[ 'inline' ] === true) &&
141                                    !$compiler->template->source->handler->recompiled;
142
143         if ($merge_compiled_includes) {
144             // variable template name ?
145             if ($variable_template) {
146                 $merge_compiled_includes = false;
147             }
148             // variable compile_id?
149             if (isset($_attr[ 'compile_id' ]) && $compiler->isVariable($_attr[ 'compile_id' ])) {
150                 $merge_compiled_includes = false;
151             }
152         }
153
154         /*
155         * if the {include} tag provides individual parameter for caching or compile_id
156         * the subtemplate must not be included into the common cache file and is treated like
157         * a call in nocache mode.
158         *
159         */
160         if ($_attr[ 'nocache' ] !== true && $_attr[ 'caching' ]) {
161             $_caching = $_new_caching = (int) $_attr[ 'caching' ];
162             $call_nocache = true;
163         } else {
164             $_new_caching = Smarty::CACHING_LIFETIME_CURRENT;
165         }
166         if (isset($_attr[ 'cache_lifetime' ])) {
167             $_cache_lifetime = $_attr[ 'cache_lifetime' ];
168             $call_nocache = true;
169             $_caching = $_new_caching;
170         } else {
171             $_cache_lifetime = '$_smarty_tpl->cache_lifetime';
172         }
173         if (isset($_attr[ 'cache_id' ])) {
174             $_cache_id = $_attr[ 'cache_id' ];
175             $call_nocache = true;
176             $_caching = $_new_caching;
177         } else {
178             $_cache_id = '$_smarty_tpl->cache_id';
179         }
180         if (isset($_attr[ 'compile_id' ])) {
181             $_compile_id = $_attr[ 'compile_id' ];
182         } else {
183             $_compile_id = '$_smarty_tpl->compile_id';
184         }
185
186         // if subtemplate will be called in nocache mode do not merge
187         if ($compiler->template->caching && $call_nocache) {
188             $merge_compiled_includes = false;
189         }
190         // assign attribute
191         if (isset($_attr[ 'assign' ])) {
192             // output will be stored in a smarty variable instead of being displayed
193             if ($_assign = $compiler->getId($_attr[ 'assign' ])) {
194                 $_assign = "'{$_assign}'";
195                 if ($compiler->tag_nocache || $compiler->nocache || $call_nocache) {
196                     // create nocache var to make it know for further compiling
197                     $compiler->setNocacheInVariable($_attr[ 'assign' ]);
198                 }
199             } else {
200                 $_assign = $_attr[ 'assign' ];
201             }
202         }
203
204         $has_compiled_template = false;
205         if ($merge_compiled_includes) {
206             $c_id = isset($_attr[ 'compile_id' ]) ? $_attr[ 'compile_id' ] : $compiler->template->compile_id;
207             // we must observe different compile_id and caching
208             $t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
209             $compiler->smarty->allow_ambiguous_resources = true;
210             /* @var Smarty_Internal_Template $tpl */
211             $tpl = new $compiler->smarty->template_class (trim($fullResourceName, '"\''), $compiler->smarty,
212                                                           $compiler->template, $compiler->template->cache_id, $c_id,
213                                                           $_caching);
214             $uid = $tpl->source->type . $tpl->source->uid;
215             if (!isset($compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ])) {
216                 $has_compiled_template = $this->compileInlineTemplate($compiler, $tpl, $t_hash);
217             } else {
218                 $has_compiled_template = true;
219             }
220             unset($tpl);
221         }
222         // delete {include} standard attributes
223         unset($_attr[ 'file' ], $_attr[ 'assign' ], $_attr[ 'cache_id' ], $_attr[ 'compile_id' ], $_attr[ 'cache_lifetime' ], $_attr[ 'nocache' ], $_attr[ 'caching' ], $_attr[ 'scope' ], $_attr[ 'inline' ]);
224         // remaining attributes must be assigned as smarty variable
225         $_vars = 'array()';
226         if (!empty($_attr)) {
227             $_pairs = array();
228             // create variables
229             foreach ($_attr as $key => $value) {
230                 $_pairs[] = "'$key'=>$value";
231             }
232             $_vars = 'array(' . join(',', $_pairs) . ')';
233         }
234         $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
235                              $_compile_id != '$_smarty_tpl->compile_id';
236         if ($has_compiled_template && !$call_nocache) {
237             $_output = "<?php\n";
238             if ($update_compile_id) {
239                 $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
240             }
241             if (!empty($_attr) && $_caching == 9999 && $compiler->template->caching) {
242                 $_vars_nc = "foreach ($_vars as \$ik => \$iv) {\n";
243                 $_vars_nc .= "\$_smarty_tpl->tpl_vars[\$ik] =  new Smarty_Variable(\$iv);\n";
244                 $_vars_nc .= "}\n";
245                 $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, - 3);
246             }
247             if (isset($_assign)) {
248                 $_output .= "ob_start();\n";
249             }
250             $_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";
251             if (isset($_assign)) {
252                 $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
253             }
254             if ($update_compile_id) {
255                 $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
256             }
257             $_output .= "?>\n";
258
259             return $_output;
260         }
261
262         if ($call_nocache) {
263             $compiler->tag_nocache = true;
264         }
265         $_output = "<?php ";
266         if ($update_compile_id) {
267             $_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n";
268         }
269         // was there an assign attribute
270         if (isset($_assign)) {
271             $_output .= "ob_start();\n";
272         }
273         $_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
274         if (isset($_assign)) {
275             $_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
276         }
277         if ($update_compile_id) {
278             $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
279         }
280         $_output .= "?>\n";
281         return $_output;
282     }
283
284     /**
285      * Compile inline sub template
286      *
287      * @param \Smarty_Internal_SmartyTemplateCompiler $compiler
288      * @param \Smarty_Internal_Template               $tpl
289      * @param  string                                 $t_hash
290      *
291      * @return bool
292      */
293     public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $compiler,
294                                           Smarty_Internal_Template $tpl, $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 ($compiler->template->source->type == 'file') {
313                 $sourceInfo = $compiler->template->source->filepath;
314             } else {
315                 $basename = $compiler->template->source->handler->getBasename($compiler->template->source);
316                 $sourceInfo = $compiler->template->source->type . ':' .
317                               ($basename ? $basename : $compiler->template->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_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("{$tpl->compiled->nocache_hash}", $compiler->template->compiled->nocache_hash,
335                                 $compiled_code);
336                 $compiler->template->compiled->has_nocache_code = true;
337             }
338             $compiler->parent_compiler->mergedSubTemplatesCode[ $tpl->compiled->unifunc ] = $compiled_code;
339             return true;
340         } else {
341             return false;
342         }
343     }
344 }