root/include/functions_template.php

Revision 211, 21.1 kB (checked in by Nafania, 3 years ago)

--

Line 
1 <?php
2 /**</span>
3 <span class="code-comment">*
4 * @package phpBB3
5 * @version $Id: functions_template.php,v 1.41 2007/04/20 09:09:20 acydburn Exp $
6 * @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
8 *
9 */
10
11 /**
12 */
13
14 /**
15 * Extension of template class - Functions needed for compiling templates only.
16 *
17 * psoTFX, phpBB Development Team - Completion of file caching, decompilation
18 * routines and implementation of conditionals/keywords and associated changes
19 *
20 * The interface was inspired by PHPLib templates,  and the template file (formats are
21 * quite similar)
22 *
23 * The keyword/conditional implementation is currently based on sections of code from
24 * the Smarty templating engine (c) 2001 ispi of Lincoln, Inc. which is released
25 * (on its own and in whole) under the LGPL. Section 3 of the LGPL states that any code
26 * derived from an LGPL application may be relicenced under the GPL, this applies
27 * to this source
28 *
29 * DEFINE directive inspired by a request by Cyberalien
30 *
31 * @package phpBB3
32 */
33 class template_compile
34 {</span>
35 <span class="code-keyword">    var $template;
36
37     // Various storage arrays
38     var $block_names = array();
39     var $block_else_level = array();
40
41     /**
42     * constuctor
43     */
44     function template_compile(&$template)
45     {
46         $this->template = &$template;
47     }
48    
49     /**
50     * Load template source from file
51     * @access private
52     */
53     function _tpl_load_file($handle, $store_in_db = false)
54     {
55         // Try and open template for read
56         if (!file_exists($this->template->files[$handle]))
57         {
58             trigger_error("template->_tpl_load_file(): File {$this->template->files[$handle]} does not exist or is empty", E_USER_ERROR);
59         }
60
61         $this->template->compiled_code[$handle] = $this->compile(trim(@file_get_contents($this->template->files[$handle])));
62
63         // Actually compile the code now.
64         $this->compile_write($handle, $this->template->compiled_code[$handle]);
65     }
66
67     /**
68     * Remove any PHP tags that do not belong, these regular expressions are derived from
69     * the ones that exist in zend_language_scanner.l
70     * @access private
71     */
72     function remove_php_tags(&$code)
73     {
74         // This matches the information gathered from the internal PHP lexer
75         $match = array(
76             '#<([\?%])=?.*?\1>#s',
77             '#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s',
78             '#<\?php(?:\r\n?|[ \n\t]).*?\?>#s'
79         );
80
81         $code = preg_replace($match, '', $code);
82     }
83
84     /**
85     * The all seeing all doing compile method. Parts are inspired by or directly from Smarty
86     * @access private
87     */
88     function compile($code, $no_echo = false, $echo_var = '')
89     {
90         global $config;
91
92         if ($echo_var)
93         {
94             global $$echo_var;
95         }
96
97         // Remove any "loose" php ... we want to give admins the ability
98         // to switch on/off PHP for a given template. Allowing unchecked
99         // php is a no-no. There is a potential issue here in that non-php
100         // content may be removed ... however designers should use entities
101         // if they wish to display < and >
102         $this->remove_php_tags($code);
103
104         // Pull out all block/statement level elements and separate plain text
105         preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches);
106         $php_blocks = $matches[1];
107         $code = preg_replace('#<!-- PHP -->.*?<!-- ENDPHP -->#s', '<!-- PHP -->', $code);
108
109         preg_match_all('#<!-- INCLUDE ([a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches);
110         $include_blocks = $matches[1];
111         $code = preg_replace('#<!-- INCLUDE [a-zA-Z0-9\_\-\+\./]+ -->#', '<!-- INCLUDE -->', $code);
112
113         preg_match_all('#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches);
114         $includephp_blocks = $matches[1];
115         $code = preg_replace('#<!-- INCLUDEPHP [a-zA-Z0-9\_\-\+\./]+ -->#', '<!-- INCLUDEPHP -->', $code);
116
117         preg_match_all('#<!-- ([^<].*?) (.*?)? ?-->#', $code, $blocks, PREG_SET_ORDER);
118
119         $text_blocks = preg_split('#<!-- [^<].*? (?:.*?)? ?-->#', $code);
120
121         for ($i = 0, $j = sizeof($text_blocks); $i < $j; $i++)
122         {
123             $this->compile_var_tags($text_blocks[$i]);
124         }
125         $compile_blocks = array();
126
127         for ($curr_tb = 0, $tb_size = sizeof($blocks); $curr_tb < $tb_size; $curr_tb++)
128         {
129             $block_val = &$blocks[$curr_tb];
130
131             switch ($block_val[1])
132             {
133                 case 'BEGIN':
134                     $this->block_else_level[] = false;
135                     $compile_blocks[] = '<?php ' . $this->compile_tag_block($block_val[2]) . ' ?>';
136                 break;
137
138                 case 'BEGINELSE':
139                     $this->block_else_level[sizeof($this->block_else_level) - 1] = true;
140                     $compile_blocks[] = '<?php }} else { ?>';
141                 break;
142
143                 case 'END':
144                     array_pop($this->block_names);
145                     $compile_blocks[] = '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>';
146                 break;
147
148                 case 'IF':
149                     $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], false) . ' ?>';
150                 break;
151
152                 case 'ELSE':
153                     $compile_blocks[] = '<?php } else { ?>';
154                 break;
155
156                 case 'ELSEIF':
157                     $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], true) . ' ?>';
158                 break;
159
160                 case 'ENDIF':
161                     $compile_blocks[] = '<?php } ?>';
162                 break;
163
164                 case 'DEFINE':
165                     $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], true) . ' ?>';
166                 break;
167
168                 case 'UNDEFINE':
169                     $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], false) . ' ?>';
170                 break;
171
172                 case 'INCLUDE':
173                     $temp = array_shift($include_blocks);
174                     $compile_blocks[] = '<?php ' . $this->compile_tag_include($temp) . ' ?>';
175                     $this->template->_tpl_include($temp, false);
176                 break;
177
178                 case 'INCLUDEPHP':
179                     $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . $this->compile_tag_include_php(array_shift($includephp_blocks)) . ' ?>' : '';
180                 break;
181
182                 case 'PHP':
183                     $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . array_shift($php_blocks) . ' ?>' : '';
184                 break;
185
186                 default:
187                     $this->compile_var_tags($block_val[0]);
188                     $trim_check = trim($block_val[0]);
189                     $compile_blocks[] = (!$no_echo) ? ((!empty($trim_check)) ? $block_val[0] : '') : ((!empty($trim_check)) ? $block_val[0] : '');
190                 break;
191             }
192         }
193
194         $template_php = '';
195         for ($i = 0, $size = sizeof($text_blocks); $i < $size; $i++)
196         {
197             $trim_check_text = trim($text_blocks[$i]);
198             $template_php .= (!$no_echo) ? (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '') : (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '');
199         }
200
201         // There will be a number of occasions where we switch into and out of
202         // PHP mode instantaneously. Rather than "burden" the parser with this
203         // we'll strip out such occurences, minimising such switching
204         $template_php = str_replace(' ?><?php ', ' ', $template_php);
205
206         return (!$no_echo) ? $template_php : "\$$echo_var .= '" . $template_php . "'";
207     }
208
209     /**
210     * Compile variables
211     * @access private
212     */
213     function compile_var_tags(&$text_blocks)
214     {
215         // change template varrefs into PHP varrefs
216         $varrefs = array();
217
218         // This one will handle varrefs WITH namespaces
219         preg_match_all('#\{((?:[a-z0-9\-_]+\.)+)(\$)?([A-Z0-9\-_]+)\}#', $text_blocks, $varrefs, PREG_SET_ORDER);
220
221         foreach ($varrefs as $var_val)
222         {
223             $namespace = $var_val[1];
224             $varname = $var_val[3];
225             $new = $this->generate_block_varref($namespace, $varname, true, $var_val[2]);
226
227             $text_blocks = str_replace($var_val[0], $new, $text_blocks);
228         }
229
230         // This will handle the remaining root-level varrefs
231         // transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array
232         if (strpos($text_blocks, '{L_') !== false)
233         {
234             $text_blocks = preg_replace('#\{L_([a-z0-9\-_]*)\}#is', "<?php echo ((isset(\$this->_rootref['L_\\1'])) ? \$this->_rootref['L_\\1'] : (isset(\$lang[strtolower('\\1')]) ? \$lang[strtolower('\\1')] : '{ ' . ucfirst(strtolower(str_replace('_', ' ', '\\1'))) . ' }')); ?>", $text_blocks);
235         }
236
237         // Handle addslashed language variables prefixed with LA_
238         // If a template variable already exist, it will be used in favor of it...
239         if (strpos($text_blocks, '{LA_') !== false)
240         {
241             $text_blocks = preg_replace('#\{LA_([a-z0-9\-_]*)\}#is', "<?php echo ((isset(\$this->_rootref['LA_\\1'])) ? \$this->_rootref['LA_\\1'] : ((isset(\$this->_rootref['L_\\1'])) ? addslashes(\$this->_rootref['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks);
242         }
243
244         // Handle remaining varrefs
245         $text_blocks = preg_replace('#\{([a-z0-9\-_]*)\}#is', "<?php echo (isset(\$this->_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks);
246         $text_blocks = preg_replace('#\{\$([a-z0-9\-_]*)\}#is', "<?php echo (isset(\$this->_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks);
247
248         return;
249     }
250
251     /**
252     * Compile blocks
253     * @access private
254     */
255     function compile_tag_block($tag_args)
256     {
257         $no_nesting = false;
258
259         // Is the designer wanting to call another loop in a loop?
260         if (strpos($tag_args, '!') === 0)
261         {
262             // Count the number if ! occurrences (not allowed in vars)
263             $no_nesting = substr_count($tag_args, '!');
264             $tag_args = substr($tag_args, $no_nesting);
265         }
266
267         // Allow for control of looping (indexes start from zero):
268         // foo(2)    : Will start the loop on the 3rd entry
269         // foo(-2)   : Will start the loop two entries from the end
270         // foo(3,4)  : Will start the loop on the fourth entry and end it on the fifth
271         // foo(3,-4) : Will start the loop on the fourth entry and end it four from last
272         if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#', $tag_args, $match))
273         {
274             $tag_args = $match[1];
275
276             if ($match[2] < 0)
277             {
278                 $loop_start = '($_' . $tag_args . '_count ' . $match[2] . ' < 0 ? 0 : $_' . $tag_args . '_count ' . $match[2] . ')';
279             }
280             else
281             {
282                 $loop_start = '($_' . $tag_args . '_count < ' . $match[2] . ' ? $_' . $tag_args . '_count : ' . $match[2] . ')';
283             }
284
285             if (strlen($match[3]) < 1 || $match[3] == -1)
286             {
287                 $loop_end = '$_' . $tag_args . '_count';
288             }
289             else if ($match[3] >= 0)
290             {
291                 $loop_end = '(' . ($match[3] + 1) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ($match[3] + 1) . ')';
292             }
293             else //if ($match[3] < -1)
294             {
295                 $loop_end = '$_' . $tag_args . '_count' . ($match[3] + 1);
296             }
297         }
298         else
299         {
300             $loop_start = 0;
301             $loop_end = '$_' . $tag_args . '_count';
302         }
303
304         $tag_template_php = '';
305         array_push($this->block_names, $tag_args);
306
307         if ($no_nesting !== false)
308         {
309             // We need to implode $no_nesting times from the end...
310             $block = array_slice($this->block_names, -$no_nesting);
311         }
312         else
313         {
314             $block = $this->block_names;
315         }
316
317         if (sizeof($block) < 2)
318         {
319             // Block is not nested.
320             $tag_template_php = '$_' . $tag_args . "_count = (isset(\$this->_tpldata['$tag_args'])) ? sizeof(\$this->_tpldata['$tag_args']) : 0;";
321             $varref = "\$this->_tpldata['$tag_args']";
322         }
323         else
324         {
325             // This block is nested.
326             // Generate a namespace string for this block.
327             $namespace = implode('.', $block);
328
329             // Get a reference to the data array for this block that depends on the
330             // current indices of all parent blocks.
331             $varref = $this->generate_block_data_ref($namespace, false);
332
333             // Create the for loop code to iterate over this block.
334             $tag_template_php = '$_' . $tag_args . '_count = (isset(' . $varref . ')) ? sizeof(' . $varref . ') : 0;';
335         }
336
337         $tag_template_php .= 'if ($_' . $tag_args . '_count) {';
338
339         /**
340         * The following uses foreach for iteration instead of a for loop, foreach is faster but requires PHP to make a copy of the contents of the array which uses more memory
341         * <code>
342         *    if (!$offset)
343         *    {
344         *        $tag_template_php .= 'foreach (' . $varref . ' as $_' . $tag_args . '_i => $_' . $tag_args . '_val){';
345         *    }
346         * </code>
347         */
348
349         $tag_template_php .= 'for ($_' . $tag_args . '_i = ' . $loop_start . '; $_' . $tag_args . '_i < ' . $loop_end . '; ++$_' . $tag_args . '_i){';
350         $tag_template_php .= '$_'. $tag_args . '_val = &' . $varref . '[$_'. $tag_args. '_i];';
351
352         return $tag_template_php;
353     }
354
355     /**
356     * Compile IF tags - much of this is from Smarty with
357     * some adaptions for our block level methods
358     * @access private
359     */
360     function compile_tag_if($tag_args, $elseif)
361     {
362         // Tokenize args for 'if' tag.
363         preg_match_all('/(?:
364             "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
365             \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
366             [(),]                                  |
367             [^\s(),]+)/x', $tag_args, $match);
368
369         $tokens = $match[0];
370         $is_arg_stack = array();
371
372         for ($i = 0, $size = sizeof($tokens); $i < $size; $i++)
373         {
374             $token = &$tokens[$i];
375
376             switch ($token)
377             {
378                 case '!==':
379                 case '===':
380                 case '<<':
381                 case '>>':
382                 case '|':
383                 case '^':
384                 case '&':
385                 case '~':
386                 case ')':
387                 case ',':
388                 case '+':
389                 case '-':
390                 case '*':
391                 case '/':
392                 case '@':
393                 break;
394
395                 case '==':
396                 case 'eq':
397                     $token = '==';
398                 break;
399
400                 case '!=':
401                 case '<>':
402                 case 'ne':
403                 case 'neq':
404                     $token = '!=';
405                 break;
406
407                 case '<':
408                 case 'lt':
409                     $token = '<';
410                 break;
411
412                 case '<=':
413                 case 'le':
414                 case 'lte':
415                     $token = '<=';
416                 break;
417
418                 case '>':
419                 case 'gt':
420                     $token = '>';
421                 break;
422
423                 case '>=':
424                 case 'ge':
425                 case 'gte':
426                     $token = '>=';
427                 break;
428
429                 case '&&':
430                 case 'and':
431                     $token = '&&';
432                 break;
433
434                 case '||':
435                 case 'or':
436                     $token = '||';
437                 break;
438
439                 case '!':
440                 case 'not':
441                     $token = '!';
442                 break;
443
444                 case '%':
445                 case 'mod':
446                     $token = '%';
447                 break;
448
449                 case '(':
450                     array_push($is_arg_stack, $i);
451                 break;
452
453                 case 'is':
454                     $is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1;
455                     $is_arg    = implode('    ', array_slice($tokens,    $is_arg_start, $i -    $is_arg_start));
456
457                     $new_tokens    = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
458
459                     array_splice($tokens, $is_arg_start, sizeof($tokens), $new_tokens);
460
461                     $i = $is_arg_start;
462
463                 // no break
464
465                 default:
466                     if (preg_match('#^((?:[a-z0-9\-_]+\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s', $token, $varrefs))
467                     {
468                         $token = (!empty($varrefs[1])) ? $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[2]) . '[\'' . $varrefs[3] . '\']' : (($varrefs[2]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$this->_rootref[\'' . $varrefs[3] . '\']');
469                     }
470                     else if (preg_match('#^\.((?:[a-z0-9\-_]+\.?)+)$#s', $token, $varrefs))
471                     {
472                         // Allow checking if loops are set with .loopname
473                         // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example
474                         $blocks = explode('.', $varrefs[1]);
475
476                         // If the block is nested, we have a reference that we can grab.
477                         // If the block is not nested, we just go and grab the block from _tpldata
478                         if (sizeof($blocks) > 1)
479                         {
480                             $block = array_pop($blocks);
481                             $namespace = implode('.', $blocks);
482                             $varref = $this->generate_block_data_ref($namespace, true);
483
484                             // Add the block reference for the last child.
485                             $varref .= "['" . $block . "']";
486                         }
487                         else
488                         {
489                             $varref = '$this->_tpldata';
490
491                             // Add the block reference for the last child.
492                             $varref .= "['" . $blocks[0] . "']";
493                         }
494                         $token = "sizeof($varref)";
495                     }
496
497                 break;
498             }
499         }
500
501         return (($elseif) ? '} else if (' : 'if (') . (implode(' ', $tokens) . ') { ');
502     }
503
504     /**
505     * Compile DEFINE tags
506     * @access private
507     */
508     function compile_tag_define($tag_args, $op)
509     {
510         preg_match('#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#', $tag_args, $match);
511
512         if (empty($match[2]) || (!isset($match[4]) && $op))
513         {
514             return '';
515         }
516
517         if (!$op)
518         {
519             return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');';
520         }
521
522         // Are we a string?
523         if ($match[3] && $match[5])
524         {
525             $match[4] = str_replace(array('\\\'', '\\\\', '\''), array('\'', '\\', '\\\''), $match[4]);
526
527             // Compile reference, we allow template variables in defines...
528             $match[4] = $this->compile($match[4]);
529
530             // Now replace the php code
531             $match[4] = "'" . str_replace(array('<?php echo ', '; ?>'), array("' . ", " . '"), $match[4]) . "'";
532         }
533         else
534         {
535             preg_match('#true|false|\.#i', $match[4], $type);
536
537             switch (strtolower($type[0]))
538             {
539                 case 'true':
540                 case 'false':
541                     $match[4] = strtoupper($match[4]);
542                 break;
543
544                 case '.':
545                     $match[4] = doubleval($match[4]);
546                 break;
547
548                 default:
549                     $match[4] = intval($match[4]);
550                 break;
551             }
552         }
553
554         return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $match[4] . ';';
555     }
556
557     /**
558     * Compile INCLUDE tag
559     * @access private
560     */
561     function compile_tag_include($tag_args)
562     {
563         return "\$this->_tpl_include('$tag_args');";
564     }
565
566     /**
567     * Compile INCLUDE_PHP tag
568     * @access private
569     */
570     function compile_tag_include_php($tag_args)
571     {
572         return "include('" . $tag_args . "');";
573     }
574
575     /**
576     * parse expression
577     * This is from Smarty
578     * @access private
579     */
580     function _parse_is_expr($is_arg, $tokens)
581     {
582         $expr_end = 0;
583         $negate_expr = false;
584
585         if (($first_token = array_shift($tokens)) == 'not')
586         {
587             $negate_expr = true;
588             $expr_type = array_shift($tokens);
589         }
590         else
591         {
592             $expr_type = $first_token;
593         }
594
595         switch ($expr_type)
596         {
597             case 'even':
598                 if (@$tokens[$expr_end] == 'by')
599                 {
600                     $expr_end++;
601                     $expr_arg = $tokens[$expr_end++];
602                     $expr = "!(($is_arg / $expr_arg) % $expr_arg)";
603                 }
604                 else
605                 {
606                     $expr = "!($is_arg & 1)";
607                 }
608             break;
609
610             case 'odd':
611                 if (@$tokens[$expr_end] == 'by')
612                 {
613                     $expr_end++;
614                     $expr_arg = $tokens[$expr_end++];
615                     $expr = "(($is_arg / $expr_arg) % $expr_arg)";
616                 }
617                 else
618                 {
619                     $expr = "($is_arg & 1)";
620                 }
621             break;
622
623             case 'div':
624                 if (@$tokens[$expr_end] == 'by')
625                 {
626                     $expr_end++;
627                     $expr_arg = $tokens[$expr_end++];
628                     $expr = "!($is_arg % $expr_arg)";
629                 }
630             break;
631         }
632
633         if ($negate_expr)
634         {
635             $expr = "!($expr)";
636         }
637
638         array_splice($tokens, 0, $expr_end, $expr);
639
640         return $tokens;
641     }
642
643     /**
644     * Generates a reference to the given variable inside the given (possibly nested)
645     * block namespace. This is a string of the form:
646     * ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
647     * It's ready to be inserted into an "echo" line in one of the templates.
648     * NOTE: expects a trailing "." on the namespace.
649     * @access private
650     */
651     function generate_block_varref($namespace, $varname, $echo = true, $defop = false)
652     {
653         // Strip the trailing period.
654         $namespace = substr($namespace, 0, -1);
655
656         // Get a reference to the data block for this namespace.
657         $varref = $this->generate_block_data_ref($namespace, true, $defop);
658         // Prepend the necessary code to stick this in an echo line.
659
660         // Append the variable reference.
661         $varref .= "['$varname']";
662         $varref = ($echo) ? "<?php echo $varref; ?>" : ((isset($varref)) ? $varref : '');
663
664         return $varref;
665     }
666
667     /**
668     * Generates a reference to the array of data values for the given
669     * (possibly nested) block namespace. This is a string of the form:
670     * $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN']
671     *
672     * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
673     * NOTE: does not expect a trailing "." on the blockname.
674     * @access private
675     */
676     function generate_block_data_ref($blockname, $include_last_iterator, $defop = false)
677     {
678         // Get an array of the blocks involved.
679         $blocks = explode('.', $blockname);
680         $blockcount = sizeof($blocks) - 1;
681
682         // DEFINE is not an element of any referenced variable, we must use _tpldata to access it
683         if ($defop)
684         {
685             $varref = '$this->_tpldata[\'DEFINE\']';
686             // Build up the string with everything but the last child.
687             for ($i = 0; $i < $blockcount; $i++)
688             {
689                 $varref .= "['" . $blocks[$i] . "'][\$_" . $blocks[$i] . '_i]';
690             }
691             // Add the block reference for the last child.
692             $varref .= "['" . $blocks[$blockcount] . "']";
693             // Add the iterator for the last child if requried.
694             if ($include_last_iterator)
695             {
696                 $varref .= '[$_' . $blocks[$blockcount] . '_i]';
697             }
698             return $varref;
699         }
700         else if ($include_last_iterator)
701         {
702             return '$_'. $blocks[$blockcount] . '_val';
703         }
704         else
705         {
706             return '$_'. $blocks[$blockcount - 1] . '_val[\''. $blocks[$blockcount]. '\']';
707         }
708     }
709
710     /**
711     * Write compiled file to cache directory
712     * @access private
713     */
714     function compile_write($handle, $data)
715     {
716
717         $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.php';
718
719         if ($fp = @fopen($filename, 'wb'))
720         {
721             @flock($fp, LOCK_EX);
722             @fwrite ($fp, $data);
723             @flock($fp, LOCK_UN);
724             @fclose($fp);
725
726             @chmod($filename, 0666);
727         }
728
729         return;
730     }
731 }
732
733 ?>
Note: See TracBrowser for help on using the browser.