~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to www/php/phpBB3/includes/functions_template.php

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

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