Project

General

Profile

1
<?php
2

    
3
// $Id$
4

    
5
/*
6
 * Session Management for PHP3
7
 *
8
 * (C) Copyright 1999-2000 NetUSE GmbH
9
 *                    Kristian Koehntopp
10
 *
11
 * $Id: template.inc,v 1.15 2004/07/23 20:36:29 layne_weathers Exp $
12
 *
13
 */
14

    
15
/*
16
 * Change log since version 7.2c
17
 *
18
 * Bug fixes to version 7.2c compiled by Richard Archer <rha@juggernaut.com.au>:
19
 * (credits given to first person to post a diff to phplib mailing list)
20
 *
21
 * Normalised all comments and whitespace (rha)
22
 * replaced "$handle" with "$varname" and "$h" with "$v" throughout (from phplib-devel)
23
 * added braces around all one-line if statements in: get_undefined, loadfile and halt (rha)
24
 * set_var was missing two sets of braces (rha)
25
 * added a couple of "return true" statements (rha)
26
 * set_unknowns had "keep" as default instead of "remove" (from phplib-devel)
27
 * set_file failed to check for empty strings if passed an array of filenames (phplib-devel)
28
 * remove @ from call to preg_replace in subst -- report errors if there are any (NickM)
29
 * set_block unnecessarily required a newline in the template file (Marc Tardif)
30
 * pparse now calls this->finish to replace undefined vars (Layne Weathers)
31
 * get_var now checks for unset varnames (NickM & rha)
32
 * get_var when passed an array used the array key instead of the value (rha)
33
 * get_vars now uses a call to get_var rather than this->varvals to prevent undefined var warning (rha)
34
 * in finish, the replacement string referenced an unset variable (rha)
35
 * loadfile would try to load a file if the varval had been set to "" (rha)
36
 * in get_undefined, only match non-whitespace in variable tags as in finish (Layne Weathers & rha)
37
 * more elegant fix to the problem of subst stripping '$n', '\n' and '\\' strings (rha)
38
 * parse uses get_var to obtain return value (Jordi via SF)
39
 * set_block reports an error if the block could not be extracted (rha)
40
 * filename is now windows-pathname aware (krabu @ SF)
41
 *
42
 *
43
 * Changes in functionality which go beyond bug fixes:
44
 *
45
 * added ability for filename comments to be output (from phplib-users layne)
46
 * changed debug handling so set, get and internals can be tracked separately (rha)
47
 * added debug statements throughout to track most function calls (rha)
48
 * debug output contained raw HTML -- is now escaped with htmlentities (rha)
49
 * Alter regex in set_block to remove more whitespace around BEGIN/END tags to improve HTML layout (rha)
50
 * Add "append" option to set_var, works just like append in parse (dale at linuxwebpro.com, rha)
51
 * Altered parse so that append is honored if passed an array (Brian)
52
 * Converted comments and documentation to phpdoc style (rha)
53
 * Added clear_var to set the value of variables to "" (rha)
54
 * Added unset_var to usset variables (rha)
55
 *
56
 */
57

    
58
/**
59
 * The template class allows you to keep your HTML code in some external files
60
 * which are completely free of PHP code, but contain replacement fields.
61
 * The class provides you with functions which can fill in the replacement fields
62
 * with arbitrary strings. These strings can become very large, e.g. entire tables.
63
 *
64
 * Note: If you think that this is like FastTemplates, read carefully. It isn't.
65
 *
66
 */
67

    
68
class Template
69
{
70
 /**
71
  * Serialization helper, the name of this class.
72
  *
73
  * @var       string
74
  * @access    public
75
  */
76
  var $classname = "Template";
77

    
78
 /**
79
  * Determines how much debugging output Template will produce.
80
  * This is a bitwise mask of available debug levels:
81
  * 0 = no debugging
82
  * 1 = debug variable assignments
83
  * 2 = debug calls to get variable
84
  * 4 = debug internals (outputs all function calls with parameters).
85
  *
86
  * Note: setting $this->debug = true will enable debugging of variable
87
  * assignments only which is the same behaviour as versions up to release 7.2d.
88
  *
89
  * @var       int
90
  * @access    public
91
  */
92
  var $debug    = false;
93

    
94
 /**
95
  * Determines whether Template outputs filename comments.
96
  * false = no filename outputs
97
  * true = HTML comments (e.g. <!-- START FILE $filename -->) placed in output
98
  *
99
  * @var       int
100
  * @access    public
101
  */
102
  var $filename_comments = false;
103

    
104
 /**
105
  * Determines the regular expression used to find unknown variable tags.
106
  * "loose"  = traditional match all curly braces with no whitespace between
107
  * "strict" = adopts PHP's variable naming rules
108
  *              ("loose" has a nasty habit of deleting JavaScript RegEx components)
109
  *              (should future major version releases of PHPLib default this "strict"?)
110
  *
111
  * @var       string
112
  * @access    public
113
  */
114
  var $unknown_regexp = "loose";
115

    
116
 /**
117
  * The base directory from which template files are loaded.
118
  *
119
  * @var       string
120
  * @access    private
121
  * @see       set_root
122
  */
123
  var $root     = ".";
124

    
125
 /**
126
  * A hash of strings forming a translation table which translates variable names
127
  * into names of files containing the variable content.
128
  * $file[varname] = "filename";
129
  *
130
  * @var       array
131
  * @access    private
132
  * @see       set_file
133
  */
134
  var $file     = array();
135

    
136
 /**
137
  * A hash of strings forming a translation table which translates variable names
138
  * into regular expressions for themselves.
139
  * $varkeys[varname] = "/varname/"
140
  *
141
  * @var       array
142
  * @access    private
143
  * @see       set_var
144
  */
145
  var $varkeys  = array();
146

    
147
 /**
148
  * A hash of strings forming a translation table which translates variable names
149
  * into values for their respective varkeys.
150
  * $varvals[varname] = "value"
151
  *
152
  * @var       array
153
  * @access    private
154
  * @see       set_var
155
  */
156
  var $varvals  = array();
157

    
158
 /**
159
  * Determines how to output variable tags with no assigned value in templates.
160
  *
161
  * @var       string
162
  * @access    private
163
  * @see       set_unknowns
164
  */
165
  var $unknowns = "remove";
166

    
167
 /**
168
  * Determines how Template handles error conditions.
169
  * "yes"      = the error is reported, then execution is halted
170
  * "report"   = the error is reported, then execution continues by returning "false"
171
  * "no"       = errors are silently ignored, and execution resumes reporting "false"
172
  *
173
  * @var       string
174
  * @access    public
175
  * @see       halt
176
  */
177
  var $halt_on_error  = "yes";
178

    
179
 /**
180
  * The last error message is retained in this variable.
181
  *
182
  * @var       string
183
  * @access    public
184
  * @see       halt
185
  */
186
  var $last_error     = "";
187

    
188
 /******************************************************************************
189
  * Class constructor. May be called with two optional parameters.
190
  * The first parameter sets the template directory the second parameter
191
  * sets the policy regarding handling of unknown variables.
192
  *
193
  * usage: Template([string $root = "."], [string $unknowns = "remove"])
194
  *
195
  * @param     $root        path to template directory
196
  * @param     $string      what to do with undefined variables
197
  * @see       set_root
198
  * @see       set_unknowns
199
  * @access    public
200
  * @return    void
201
  */
202
  function Template($root = ".", $unknowns = "remove") {
203
    if ($this->debug & 4) {
204
      echo "<p><b>Template:</b> root = $root, unknowns = $unknowns</p>\n";
205
    }
206
    $this->set_root($root);
207
    $this->set_unknowns($unknowns);
208
  }
209

    
210

    
211
 /******************************************************************************
212
  * Checks that $root is a valid directory and if so sets this directory as the
213
  * base directory from which templates are loaded by storing the value in
214
  * $this->root. Relative filenames are prepended with the path in $this->root.
215
  *
216
  * Returns true on success, false on error.
217
  *
218
  * usage: set_root(string $root)
219
  *
220
  * @param     $root         string containing new template directory
221
  * @see       root
222
  * @access    public
223
  * @return    boolean
224
  */
225
  function set_root($root) {
226
    if(ereg('/$', $root)) {
227
      $root = substr($root, 0, -1);
228
    }
229
    if ($this->debug & 4) {
230
      echo "<p><b>set_root:</b> root = $root</p>\n";
231
    }
232
    if (!is_dir($root)) {
233
      $this->halt("set_root: $root is not a directory.");
234
      return false;
235
    }
236

    
237
    $this->root = $root;
238
    return true;
239
  }
240

    
241

    
242
 /******************************************************************************
243
  * Sets the policy for dealing with unresolved variable names.
244
  *
245
  * unknowns defines what to do with undefined template variables
246
  * "remove"   = remove undefined variables
247
  * "comment"  = replace undefined variables with comments
248
  * "keep"     = keep undefined variables
249
  *
250
  * Note: "comment" can cause unexpected results when the variable tag is embedded
251
  * inside an HTML tag, for example a tag which is expected to be replaced with a URL.
252
  *
253
  * usage: set_unknowns(string $unknowns)
254
  *
255
  * @param     $unknowns         new value for unknowns
256
  * @see       unknowns
257
  * @access    public
258
  * @return    void
259
  */
260
  function set_unknowns($unknowns = "remove") {
261
    if ($this->debug & 4) {
262
      echo "<p><b>unknowns:</b> unknowns = $unknowns</p>\n";
263
    }
264
    $this->unknowns = $unknowns;
265
  }
266

    
267

    
268
 /******************************************************************************
269
  * Defines a filename for the initial value of a variable.
270
  *
271
  * It may be passed either a varname and a file name as two strings or
272
  * a hash of strings with the key being the varname and the value
273
  * being the file name.
274
  *
275
  * The new mappings are stored in the array $this->file.
276
  * The files are not loaded yet, but only when needed.
277
  *
278
  * Returns true on success, false on error.
279
  *
280
  * usage: set_file(array $filelist = (string $varname => string $filename))
281
  * or
282
  * usage: set_file(string $varname, string $filename)
283
  *
284
  * @param     $varname      either a string containing a varname or a hash of varname/file name pairs.
285
  * @param     $filename     if varname is a string this is the filename otherwise filename is not required
286
  * @access    public
287
  * @return    boolean
288
  */
289
  function set_file($varname, $filename = "") {
290
    if (!is_array($varname)) {
291
      if ($this->debug & 4) {
292
        echo "<p><b>set_file:</b> (with scalar) varname = $varname, filename = $filename</p>\n";
293
      }
294
      if ($filename == "") {
295
        $this->halt("set_file: For varname $varname filename is empty.");
296
        return false;
297
      }
298
      $this->file[$varname] = $this->filename($filename);
299
    } else {
300
      reset($varname);
301
      while (list($v, $f) = each($varname)) {
302
        if ($this->debug & 4) {
303
          echo "<p><b>set_file:</b> (with array) varname = $v, filename = $f</p>\n";
304
        }
305
        if ($f == "") {
306
          $this->halt("set_file: For varname $v filename is empty.");
307
          return false;
308
        }
309
        $this->file[$v] = $this->filename($f);
310
      }
311
    }
312
    return true;
313
  }
314

    
315

    
316
 /******************************************************************************
317
  * A variable $parent may contain a variable block defined by:
318
  * &lt;!-- BEGIN $varname --&gt; content &lt;!-- END $varname --&gt;. This function removes
319
  * that block from $parent and replaces it with a variable reference named $name.
320
  * The block is inserted into the varkeys and varvals hashes. If $name is
321
  * omitted, it is assumed to be the same as $varname.
322
  *
323
  * Blocks may be nested but care must be taken to extract the blocks in order
324
  * from the innermost block to the outermost block.
325
  *
326
  * Returns true on success, false on error.
327
  *
328
  * usage: set_block(string $parent, string $varname, [string $name = ""])
329
  *
330
  * @param     $parent       a string containing the name of the parent variable
331
  * @param     $varname      a string containing the name of the block to be extracted
332
  * @param     $name         the name of the variable in which to store the block
333
  * @access    public
334
  * @return    boolean
335
  */
336
  function set_block($parent, $varname, $name = "") {
337
    if ($this->debug & 4) {
338
      echo "<p><b>set_block:</b> parent = $parent, varname = $varname, name = $name</p>\n";
339
    }
340
    if (!$this->loadfile($parent)) {
341
      $this->halt("set_block: unable to load $parent.");
342
      return false;
343
    }
344
    if ($name == "") {
345
      $name = $varname;
346
    }
347

    
348
    $str = $this->get_var($parent);
349
    $reg = "/[ \t]*<!--\s+BEGIN $varname\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $varname\s+-->\s*?\n?/sm";
350
    preg_match_all($reg, $str, $m);
351
/* workaround to avoid problems with some WB files/modules (e.g. massmail)
352
    if (!isset($m[1][0])) {
353
      $this->halt("set_block: unable to set block $varname.");
354
      return false;
355
    }
356
*/
357
    $str = preg_replace($reg, "{" . $name . "}", $str);
358
    @$this->set_var($varname, $m[1][0]);
359
    $this->set_var($parent, $str);
360
    return true;
361
  }
362

    
363

    
364
 /******************************************************************************
365
  * This functions sets the value of a variable.
366
  *
367
  * It may be called with either a varname and a value as two strings or an
368
  * an associative array with the key being the varname and the value being
369
  * the new variable value.
370
  *
371
  * The function inserts the new value of the variable into the $varkeys and
372
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
373
  * before calling this function.
374
  *
375
  * An optional third parameter allows the value for each varname to be appended
376
  * to the existing variable instead of replacing it. The default is to replace.
377
  * This feature was introduced after the 7.2d release.
378
  *
379
  *
380
  * usage: set_var(string $varname, [string $value = ""], [boolean $append = false])
381
  * or
382
  * usage: set_var(array $varname = (string $varname => string $value), [mixed $dummy_var], [boolean $append = false])
383
  *
384
  * @param     $varname      either a string containing a varname or a hash of varname/value pairs.
385
  * @param     $value        if $varname is a string this contains the new value for the variable otherwise this parameter is ignored
386
  * @param     $append       if true, the value is appended to the variable's existing value
387
  * @access    public
388
  * @return    void
389
  */
390
  function set_var($varname, $value = "", $append = false) {
391
    if (!is_array($varname)) {
392
      if (!empty($varname)) {
393
        if ($this->debug & 1) {
394
          printf("<b>set_var:</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($value));
395
        }
396
        $this->varkeys[$varname] = "/".$this->varname($varname)."/";
397
        if ($append && isset($this->varvals[$varname])) {
398
          $this->varvals[$varname] .= $value;
399
        } else {
400
          $this->varvals[$varname] = $value;
401
        }
402
      }
403
    } else {
404
      reset($varname);
405
      while (list($k, $v) = each($varname)) {
406
        if (!empty($k)) {
407
          if ($this->debug & 1) {
408
            printf("<b>set_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $k, htmlentities($v));
409
          }
410
          $this->varkeys[$k] = "/".$this->varname($k)."/";
411
          if ($append && isset($this->varvals[$k])) {
412
            $this->varvals[$k] .= $v;
413
          } else {
414
            $this->varvals[$k] = $v;
415
          }
416
        }
417
      }
418
    }
419
  }
420

    
421

    
422
 /******************************************************************************
423
  * This functions clears the value of a variable.
424
  *
425
  * It may be called with either a varname as a string or an array with the 
426
  * values being the varnames to be cleared.
427
  *
428
  * The function sets the value of the variable in the $varkeys and $varvals 
429
  * hashes to "". It is not necessary for a variable to exist in these hashes
430
  * before calling this function.
431
  *
432
  *
433
  * usage: clear_var(string $varname)
434
  * or
435
  * usage: clear_var(array $varname = (string $varname))
436
  *
437
  * @param     $varname      either a string containing a varname or an array of varnames.
438
  * @access    public
439
  * @return    void
440
  */
441
  function clear_var($varname) {
442
    if (!is_array($varname)) {
443
      if (!empty($varname)) {
444
        if ($this->debug & 1) {
445
          printf("<b>clear_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
446
        }
447
        $this->set_var($varname, "");
448
      }
449
    } else {
450
      reset($varname);
451
      while (list($k, $v) = each($varname)) {
452
        if (!empty($v)) {
453
          if ($this->debug & 1) {
454
            printf("<b>clear_var:</b> (with array) <b>%s</b><br>\n", $v);
455
          }
456
          $this->set_var($v, "");
457
        }
458
      }
459
    }
460
  }
461

    
462

    
463
 /******************************************************************************
464
  * This functions unsets a variable completely.
465
  *
466
  * It may be called with either a varname as a string or an array with the 
467
  * values being the varnames to be cleared.
468
  *
469
  * The function removes the variable from the $varkeys and $varvals hashes.
470
  * It is not necessary for a variable to exist in these hashes before calling
471
  * this function.
472
  *
473
  *
474
  * usage: unset_var(string $varname)
475
  * or
476
  * usage: unset_var(array $varname = (string $varname))
477
  *
478
  * @param     $varname      either a string containing a varname or an array of varnames.
479
  * @access    public
480
  * @return    void
481
  */
482
  function unset_var($varname) {
483
    if (!is_array($varname)) {
484
      if (!empty($varname)) {
485
        if ($this->debug & 1) {
486
          printf("<b>unset_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
487
        }
488
        unset($this->varkeys[$varname]);
489
        unset($this->varvals[$varname]);
490
      }
491
    } else {
492
      reset($varname);
493
      while (list($k, $v) = each($varname)) {
494
        if (!empty($v)) {
495
          if ($this->debug & 1) {
496
            printf("<b>unset_var:</b> (with array) <b>%s</b><br>\n", $v);
497
          }
498
          unset($this->varkeys[$v]);
499
          unset($this->varvals[$v]);
500
        }
501
      }
502
    }
503
  }
504

    
505

    
506
 /******************************************************************************
507
  * This function fills in all the variables contained within the variable named
508
  * $varname. The resulting value is returned as the function result and the
509
  * original value of the variable varname is not changed. The resulting string
510
  * is not "finished", that is, the unresolved variable name policy has not been
511
  * applied yet.
512
  *
513
  * Returns: the value of the variable $varname with all variables substituted.
514
  *
515
  * usage: subst(string $varname)
516
  *
517
  * @param     $varname      the name of the variable within which variables are to be substituted
518
  * @access    public
519
  * @return    string
520
  */
521
  function subst($varname) {
522
    $varvals_quoted = array();
523
    if ($this->debug & 4) {
524
      echo "<p><b>subst:</b> varname = $varname</p>\n";
525
    }
526
    if (!$this->loadfile($varname)) {
527
      $this->halt("subst: unable to load $varname.");
528
      return false;
529
    }
530

    
531
    // quote the replacement strings to prevent bogus stripping of special chars
532
    reset($this->varvals);
533
    while (list($k, $v) = each($this->varvals)) {
534
      $varvals_quoted[$k] = preg_replace(array('/\\\\/', '/\$/'), array('\\\\\\\\', '\\\\$'), $v);
535
    }
536

    
537
    $str = $this->get_var($varname);
538
    $str = preg_replace($this->varkeys, $varvals_quoted, $str);
539
    return $str;
540
  }
541

    
542

    
543
 /******************************************************************************
544
  * This is shorthand for print $this->subst($varname). See subst for further
545
  * details.
546
  *
547
  * Returns: always returns false.
548
  *
549
  * usage: psubst(string $varname)
550
  *
551
  * @param     $varname      the name of the variable within which variables are to be substituted
552
  * @access    public
553
  * @return    false
554
  * @see       subst
555
  */
556
  function psubst($varname) {
557
    if ($this->debug & 4) {
558
      echo "<p><b>psubst:</b> varname = $varname</p>\n";
559
    }
560
    print $this->subst($varname);
561

    
562
    return false;
563
  }
564

    
565

    
566
 /******************************************************************************
567
  * The function substitutes the values of all defined variables in the variable
568
  * named $varname and stores or appends the result in the variable named $target.
569
  *
570
  * It may be called with either a target and a varname as two strings or a
571
  * target as a string and an array of variable names in varname.
572
  *
573
  * The function inserts the new value of the variable into the $varkeys and
574
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
575
  * before calling this function.
576
  *
577
  * An optional third parameter allows the value for each varname to be appended
578
  * to the existing target variable instead of replacing it. The default is to
579
  * replace.
580
  *
581
  * If $target and $varname are both strings, the substituted value of the
582
  * variable $varname is inserted into or appended to $target.
583
  *
584
  * If $handle is an array of variable names the variables named by $handle are
585
  * sequentially substituted and the result of each substitution step is
586
  * inserted into or appended to in $target. The resulting substitution is
587
  * available in the variable named by $target, as is each intermediate step
588
  * for the next $varname in sequence. Note that while it is possible, it
589
  * is only rarely desirable to call this function with an array of varnames
590
  * and with $append = true. This append feature was introduced after the 7.2d
591
  * release.
592
  *
593
  * Returns: the last value assigned to $target.
594
  *
595
  * usage: parse(string $target, string $varname, [boolean $append])
596
  * or
597
  * usage: parse(string $target, array $varname = (string $varname), [boolean $append])
598
  *
599
  * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
600
  * @param     $varname     if a string, the name the name of the variable to substitute or if an array a list of variables to be substituted
601
  * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
602
  * @access    public
603
  * @return    string
604
  * @see       subst
605
  */
606
  function parse($target, $varname, $append = false) {
607
    if (!is_array($varname)) {
608
      if ($this->debug & 4) {
609
        echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";
610
      }
611
      $str = $this->subst($varname);
612
      if ($append) {
613
        $this->set_var($target, $this->get_var($target) . $str);
614
      } else {
615
        $this->set_var($target, $str);
616
      }
617
    } else {
618
      reset($varname);
619
      while (list($i, $v) = each($varname)) {
620
        if ($this->debug & 4) {
621
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";
622
        }
623
        $str = $this->subst($v);
624
        if ($append) {
625
          $this->set_var($target, $this->get_var($target) . $str);
626
        } else {
627
          $this->set_var($target, $str);
628
        }
629
      }
630
    }
631

    
632
    if ($this->debug & 4) {
633
      echo "<p><b>parse:</b> completed</p>\n";
634
    }
635
    return $this->get_var($target);
636
  }
637

    
638

    
639
 /******************************************************************************
640
  * This is shorthand for print $this->parse(...) and is functionally identical.
641
  * See parse for further details.
642
  *
643
  * Returns: always returns false.
644
  *
645
  * usage: pparse(string $target, string $varname, [boolean $append])
646
  * or
647
  * usage: pparse(string $target, array $varname = (string $varname), [boolean $append])
648
  *
649
  * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
650
  * @param     $varname     if a string, the name the name of the variable to substitute or if an array a list of variables to be substituted
651
  * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
652
  * @access    public
653
  * @return    false
654
  * @see       parse
655
  */
656
  function pparse($target, $varname, $append = false) {
657
    if ($this->debug & 4) {
658
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
659
    }
660
    print $this->finish($this->parse($target, $varname, $append));
661
    return false;
662
  }
663

    
664

    
665
 /******************************************************************************
666
  * This function returns an associative array of all defined variables with the
667
  * name as the key and the value of the variable as the value.
668
  *
669
  * This is mostly useful for debugging. Also note that $this->debug can be used
670
  * to echo all variable assignments as they occur and to trace execution.
671
  *
672
  * Returns: a hash of all defined variable values keyed by their names.
673
  *
674
  * usage: get_vars()
675
  *
676
  * @access    public
677
  * @return    array
678
  * @see       $debug
679
  */
680
  function get_vars() {
681
    if ($this->debug & 4) {
682
      echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";
683
    }
684
    reset($this->varkeys);
685
    while (list($k, $v) = each($this->varkeys)) {
686
      $result[$k] = $this->get_var($k);
687
    }
688
    return $result;
689
  }
690

    
691

    
692
 /******************************************************************************
693
  * This function returns the value of the variable named by $varname.
694
  * If $varname references a file and that file has not been loaded yet, the
695
  * variable will be reported as empty.
696
  *
697
  * When called with an array of variable names this function will return a a
698
  * hash of variable values keyed by their names.
699
  *
700
  * Returns: a string or an array containing the value of $varname.
701
  *
702
  * usage: get_var(string $varname)
703
  * or
704
  * usage: get_var(array $varname)
705
  *
706
  * @param     $varname     if a string, the name the name of the variable to get the value of, or if an array a list of variables to return the value of
707
  * @access    public
708
  * @return    string or array
709
  */
710
  function get_var($varname) {
711
    if (!is_array($varname)) {
712
      if (isset($this->varvals[$varname])) {
713
        $str = $this->varvals[$varname];
714
      } else {
715
        $str = "";
716
      }
717
      if ($this->debug & 2) {
718
        printf ("<b>get_var</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($str));
719
      }
720
      return $str;
721
    } else {
722
      reset($varname);
723
      while (list($k, $v) = each($varname)) {
724
        if (isset($this->varvals[$v])) {
725
          $str = $this->varvals[$v];
726
        } else {
727
          $str = "";
728
        }
729
        if ($this->debug & 2) {
730
          printf ("<b>get_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $v, htmlentities($str));
731
        }
732
        $result[$v] = $str;
733
      }
734
      return $result;
735
    }
736
  }
737

    
738

    
739
 /******************************************************************************
740
  * This function returns a hash of unresolved variable names in $varname, keyed
741
  * by their names (that is, the hash has the form $a[$name] = $name).
742
  *
743
  * Returns: a hash of varname/varname pairs or false on error.
744
  *
745
  * usage: get_undefined(string $varname)
746
  *
747
  * @param     $varname     a string containing the name the name of the variable to scan for unresolved variables
748
  * @access    public
749
  * @return    array
750
  */
751
  function get_undefined($varname) {
752
    if ($this->debug & 4) {
753
      echo "<p><b>get_undefined:</b> varname = $varname</p>\n";
754
    }
755
    if (!$this->loadfile($varname)) {
756
      $this->halt("get_undefined: unable to load $varname.");
757
      return false;
758
    }
759

    
760
    preg_match_all(
761
        (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
762
        $this->get_var($varname),
763
        $m);
764
    $m = $m[1];
765
    if (!is_array($m)) {
766
      return false;
767
    }
768

    
769
    reset($m);
770
    while (list($k, $v) = each($m)) {
771
      if (!isset($this->varkeys[$v])) {
772
        if ($this->debug & 4) {
773
         echo "<p><b>get_undefined:</b> undefined: $v</p>\n";
774
        }
775
        $result[$v] = $v;
776
      }
777
    }
778

    
779
    if (count($result)) {
780
      return $result;
781
    } else {
782
      return false;
783
    }
784
  }
785

    
786

    
787
 /******************************************************************************
788
  * This function returns the finished version of $str. That is, the policy
789
  * regarding unresolved variable names will be applied to $str.
790
  *
791
  * Returns: a finished string derived from $str and $this->unknowns.
792
  *
793
  * usage: finish(string $str)
794
  *
795
  * @param     $str         a string to which to apply the unresolved variable policy
796
  * @access    public
797
  * @return    string
798
  * @see       set_unknowns
799
  */
800
  function finish($str) {
801
    switch ($this->unknowns) {
802
      case "keep":
803
      break;
804

    
805
      case "remove":
806
        $str = preg_replace(
807
            (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
808
            "",
809
            $str);
810
      break;
811

    
812
      case "comment":
813
        $str = preg_replace(
814
             (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
815
            "<!-- Template variable \\1 undefined -->",
816
            $str);
817
      break;
818
    }
819

    
820
    return $str;
821
  }
822

    
823

    
824
 /******************************************************************************
825
  * This function prints the finished version of the value of the variable named
826
  * by $varname. That is, the policy regarding unresolved variable names will be
827
  * applied to the variable $varname then it will be printed.
828
  *
829
  * usage: p(string $varname)
830
  *
831
  * @param     $varname     a string containing the name of the variable to finish and print
832
  * @access    public
833
  * @return    void
834
  * @see       set_unknowns
835
  * @see       finish
836
  */
837
  function p($varname) {
838
    print $this->finish($this->get_var($varname));
839
  }
840

    
841

    
842
 /******************************************************************************
843
  * This function returns the finished version of the value of the variable named
844
  * by $varname. That is, the policy regarding unresolved variable names will be
845
  * applied to the variable $varname and the result returned.
846
  *
847
  * Returns: a finished string derived from the variable $varname.
848
  *
849
  * usage: get(string $varname)
850
  *
851
  * @param     $varname     a string containing the name of the variable to finish
852
  * @access    public
853
  * @return    void
854
  * @see       set_unknowns
855
  * @see       finish
856
  */
857
  function get($varname) {
858
    return $this->finish($this->get_var($varname));
859
  }
860

    
861

    
862
 /******************************************************************************
863
  * When called with a relative pathname, this function will return the pathname
864
  * with $this->root prepended. Absolute pathnames are returned unchanged.
865
  *
866
  * Returns: a string containing an absolute pathname.
867
  *
868
  * usage: filename(string $filename)
869
  *
870
  * @param     $filename    a string containing a filename
871
  * @access    private
872
  * @return    string
873
  * @see       set_root
874
  */
875
  function filename($filename) {
876
    if ($this->debug & 4) {
877
      echo "<p><b>filename:</b> filename = $filename</p>\n";
878
    }
879
    if (substr($filename, 0, 1) != "/" 
880
       && substr($filename, 0, 1) != "\\"
881
       && substr($filename, 1, 2) != ":\\"
882
       && substr($filename, 1, 2) != ":/"
883
    ) {
884
      $filename = $this->root."/".$filename;
885
    }
886

    
887
    if (!file_exists($filename)) {
888
      $this->halt("filename: file $filename does not exist.");
889
    }
890
    return $filename;
891
  }
892

    
893

    
894
 /******************************************************************************
895
  * This function will construct a regexp for a given variable name with any
896
  * special chars quoted.
897
  *
898
  * Returns: a string containing an escaped variable name.
899
  *
900
  * usage: varname(string $varname)
901
  *
902
  * @param     $varname    a string containing a variable name
903
  * @access    private
904
  * @return    string
905
  */
906
  function varname($varname) {
907
    return preg_quote("{" . $varname . "}");
908
  }
909

    
910

    
911
 /******************************************************************************
912
  * If a variable's value is undefined and the variable has a filename stored in
913
  * $this->file[$varname] then the backing file will be loaded and the file's
914
  * contents will be assigned as the variable's value.
915
  *
916
  * Note that the behaviour of this function changed slightly after the 7.2d
917
  * release. Where previously a variable was reloaded from file if the value
918
  * was empty, now this is not done. This allows a variable to be loaded then
919
  * set to "", and also prevents attempts to load empty variables. Files are
920
  * now only loaded if $this->varvals[$varname] is unset.
921
  *
922
  * Returns: true on success, false on error.
923
  *
924
  * usage: loadfile(string $varname)
925
  *
926
  * @param     $varname    a string containing the name of a variable to load
927
  * @access    private
928
  * @return    boolean
929
  * @see       set_file
930
  */
931
  function loadfile($varname) {
932
    if ($this->debug & 4) {
933
      echo "<p><b>loadfile:</b> varname = $varname</p>\n";
934
    }
935

    
936
    if (!isset($this->file[$varname])) {
937
      // $varname does not reference a file so return
938
      if ($this->debug & 4) {
939
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
940
      }
941
      return true;
942
    }
943

    
944
    if (isset($this->varvals[$varname])) {
945
      // will only be unset if varname was created with set_file and has never been loaded
946
      // $varname has already been loaded so return
947
      if ($this->debug & 4) {
948
        echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";
949
      }
950
      return true;
951
    }
952
    $filename = $this->file[$varname];
953

    
954
    /* use @file here to avoid leaking filesystem information if there is an error */
955
    $str = implode("", @file($filename));
956
    if (empty($str)) {
957
      $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");
958
      return false;
959
    }
960

    
961
    if ($this->filename_comments) {
962
      $str = "<!-- START FILE $filename -->\n$str<!-- END FILE $filename -->\n";
963
    }
964
    if ($this->debug & 4) {
965
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
966
    }
967
    $this->set_var($varname, $str);
968

    
969
    return true;
970
  }
971

    
972

    
973
 /******************************************************************************
974
  * This function is called whenever an error occurs and will handle the error
975
  * according to the policy defined in $this->halt_on_error. Additionally the
976
  * error message will be saved in $this->last_error.
977
  *
978
  * Returns: always returns false.
979
  *
980
  * usage: halt(string $msg)
981
  *
982
  * @param     $msg         a string containing an error message
983
  * @access    private
984
  * @return    void
985
  * @see       $halt_on_error
986
  */
987
  function halt($msg) {
988
    $this->last_error = $msg;
989

    
990
    if ($this->halt_on_error != "no") {
991
      $this->haltmsg($msg);
992
    }
993

    
994
    if ($this->halt_on_error == "yes") {
995
      die("<b>Halted.</b>");
996
    }
997

    
998
    return false;
999
  }
1000

    
1001

    
1002
 /******************************************************************************
1003
  * This function prints an error message.
1004
  * It can be overridden by your subclass of Template. It will be called with an
1005
  * error message to display.
1006
  *
1007
  * usage: haltmsg(string $msg)
1008
  *
1009
  * @param     $msg         a string containing the error message to display
1010
  * @access    public
1011
  * @return    void
1012
  * @see       halt
1013
  */
1014
  function haltmsg($msg) {
1015
    printf("<b>Template Error:</b> %s<br>\n", $msg);
1016
  }
1017

    
1018
}
1019
?>
(2-2/2)