Project

General

Profile

1 2 Manuela
<?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$
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
 * Fixes
67
 * Ticket #812 depricated Fix 2009/11/25
68
 */
69
70
class Template
71
{
72 29 Manuela
    use \Phplib_FtanTrait;
73 2 Manuela
 /**
74
  * Serialization helper, the name of this class.
75
  *
76
 * @var       string
77
 * @access    public
78
  */
79
  public $classname = "Template";
80
81
 /**
82
  * Determines how much debugging output Template will produce.
83
  * This is a bitwise mask of available debug levels:
84
  * 0 = no debugging
85
  * 1 = debug variable assignments
86
  * 2 = debug calls to get variable
87
  * 4 = debug internals (outputs all function calls with parameters).
88
  *
89
  * Note: setting $this->debug = true will enable debugging of variable
90
  * assignments only which is the same behaviour as versions up to release 7.2d.
91
  *
92
 * @var       int
93
 * @access    public
94
  */
95
  public $debug    = false;
96
97
 /**
98
  * Determines whether Template outputs filename comments.
99
  * false = no filename outputs
100
  * true = HTML comments (e.g. <!-- START FILE $filename -->) placed in output
101
  *
102
 * @var       int
103
 * @access    public
104
  */
105
  public $filename_comments = false;
106
107
 /**
108
  * Determines the regular expression used to find unknown variable tags.
109
  * "loose"  = traditional match all curly braces with no whitespace between
110
  * "strict" = adopts PHP's variable naming rules
111
  *              ("loose" has a nasty habit of deleting JavaScript RegEx components)
112
  *              (should future major version releases of PHPLib default this "strict"?)
113
  *
114
 * @var       string
115
 * @access    public
116
  */
117
  public $unknown_regexp = "loose";
118
119
 /**
120
  * The base directory from which template files are loaded.
121
  *
122
 * @var       string
123
 * @access    private
124
 * @see       set_root
125
  */
126
  public $root     = ".";
127
128
 /**
129
  * A hash of strings forming a translation table which translates variable names
130
  * into names of files containing the variable content.
131
  * $file[varname] = "filename";
132
  *
133
 * @var       array
134
 * @access    private
135
 * @see       set_file
136
  */
137
  public $file     = array();
138
139
 /**
140
  * A hash of strings forming a translation table which translates variable names
141
  * into regular expressions for themselves.
142
  * $varkeys[varname] = "/varname/"
143
  *
144
 * @var       array
145
 * @access    private
146
 * @see       set_var
147
  */
148
  public $varkeys  = array();
149
150
 /**
151
  * A hash of strings forming a translation table which translates variable names
152
  * into values for their respective varkeys.
153
  * $varvals[varname] = "value"
154
  *
155
 * @var       array
156
 * @access    private
157
 * @see       set_var
158
  */
159
  public $varvals  = array();
160
161
 /**
162
  * Determines how to output variable tags with no assigned value in templates.
163
  *
164
 * @var       string
165
 * @access    private
166
 * @see       set_unknowns
167
  */
168
  public $unknowns = "remove";
169
170
 /**
171
  * Determines how Template handles error conditions.
172
  * "yes"      = the error is reported, then execution is halted
173
  * "report"   = the error is reported, then execution continues by returning "false"
174
  * "no"       = errors are silently ignored, and execution resumes reporting "false"
175
  *
176
 * @var       string
177
 * @access    public
178
 * @see       halt
179
  */
180
  public $halt_on_error  = "yes";
181
182
 /**
183
  * The last error message is retained in this variable.
184
  *
185
 * @var       string
186
 * @access    public
187
 * @see       halt
188
  */
189
  public $last_error     = "";
190
191
 /******************************************************************************
192
  * Class constructor. May be called with two optional parameters.
193
  * The first parameter sets the template directory the second parameter
194
  * sets the policy regarding handling of unknown variables.
195
  *
196
  * usage: Template([string $root = "."], [string $unknowns = "remove"])
197
  *
198
 * @param     $root        path to template directory
199
 * @param     $string      what to do with undefined variables
200
 * @see       set_root
201
 * @see       set_unknowns
202
 * @access    public
203
 * @return    void
204
  */
205
  public function __construct($root = ".", $unknowns = "remove") {
206
    if ($this->debug & 4) {
207
      echo "<p><b>Template:</b> root = $root, unknowns = $unknowns</p>\n";
208
    }
209
    $this->set_root($root);
210
    $this->set_unknowns($unknowns);
211
  }
212
213
214
 /******************************************************************************
215
  * Checks that $root is a valid directory and if so sets this directory as the
216
  * base directory from which templates are loaded by storing the value in
217
  * $this->root. Relative filenames are prepended with the path in $this->root.
218
  *
219
  * Returns true on success, false on error.
220
  *
221
  * usage: set_root(string $root)
222
  *
223
 * @param     $root         string containing new template directory
224
 * @see       root
225
 * @access    public
226
 * @return    boolean
227
  */
228
  public function set_root($root) {
229
    if(preg_match ('/\/$/', $root)) {
230
      $root = substr($root, 0, -1);
231
    }
232
    if ($this->debug & 4) {
233
      echo "<p><b>set_root:</b> root = $root</p>\n";
234
    }
235
    if (!is_dir($root)) {
236
      $this->halt("set_root: $root is not a directory.");
237
      return false;
238
    }
239
240
    $this->root = $root;
241
    return true;
242
  }
243
244
245
 /******************************************************************************
246
  * Sets the policy for dealing with unresolved variable names.
247
  *
248
  * unknowns defines what to do with undefined template variables
249
  * "remove"   = remove undefined variables
250
  * "comment"  = replace undefined variables with comments
251
  * "keep"     = keep undefined variables
252
  *
253
  * Note: "comment" can cause unexpected results when the variable tag is embedded
254
  * inside an HTML tag, for example a tag which is expected to be replaced with a URL.
255
  *
256
  * usage: set_unknowns(string $unknowns)
257
  *
258
 * @param     $unknowns         new value for unknowns
259
 * @see       unknowns
260
 * @access    public
261
 * @return    void
262
  */
263
  public function set_unknowns($unknowns = "remove") {
264
    if ($this->debug & 4) {
265
      echo "<p><b>unknowns:</b> unknowns = $unknowns</p>\n";
266
    }
267
    $this->unknowns = $unknowns;
268
  }
269
270
271
 /******************************************************************************
272
  * Defines a filename for the initial value of a variable.
273
  *
274
  * It may be passed either a varname and a file name as two strings or
275
  * a hash of strings with the key being the varname and the value
276
  * being the file name.
277
  *
278
  * The new mappings are stored in the array $this->file.
279
  * The files are not loaded yet, but only when needed.
280
  *
281
  * Returns true on success, false on error.
282
  *
283
  * usage: set_file(array $filelist = (string $varname => string $filename))
284
  * or
285
  * usage: set_file(string $varname, string $filename)
286
  *
287
 * @param     $varname      either a string containing a varname or a hash of varname/file name pairs.
288
 * @param     $filename     if varname is a string this is the filename otherwise filename is not required
289
 * @access    public
290
 * @return    boolean
291
  */
292
  public function set_file($varname, $filename = "") {
293
    if (!is_array($varname)) {
294
      if ($this->debug & 4) {
295
        echo "<p><b>set_file:</b> (with scalar) varname = $varname, filename = $filename</p>\n";
296
      }
297
      if ($filename == "") {
298
        $this->halt("set_file: For varname $varname filename is empty.");
299
        return false;
300
      }
301
      $this->file[$varname] = $this->filename($filename);
302
    } else {
303
      reset($varname);
304
      while (list($v, $f) = each($varname)) {
305
        if ($this->debug & 4) {
306
          echo "<p><b>set_file:</b> (with array) varname = $v, filename = $f</p>\n";
307
        }
308
        if ($f == "") {
309
          $this->halt("set_file: For varname $v filename is empty.");
310
          return false;
311
        }
312
        $this->file[$v] = $this->filename($f);
313
      }
314
    }
315
    return true;
316
  }
317
318
319
 /******************************************************************************
320
  * A variable $parent may contain a variable block defined by:
321
  * &lt;!-- BEGIN $varname --&gt; content &lt;!-- END $varname --&gt;. This function removes
322
  * that block from $parent and replaces it with a variable reference named $name.
323
  * The block is inserted into the varkeys and varvals hashes. If $name is
324
  * omitted, it is assumed to be the same as $varname.
325
  *
326
  * Blocks may be nested but care must be taken to extract the blocks in order
327
  * from the innermost block to the outermost block.
328
  *
329
  * Returns true on success, false on error.
330
  *
331
  * usage: set_block(string $parent, string $varname, [string $name = ""])
332
  *
333
 * @param     $parent       a string containing the name of the parent variable
334
 * @param     $varname      a string containing the name of the block to be extracted
335
 * @param     $name         the name of the variable in which to store the block
336
 * @access    public
337
 * @return    boolean
338
  */
339
  public function set_block($parent, $varname, $name = "") {
340
    if ($this->debug & 4) {
341
      echo "<p><b>set_block:</b> parent = $parent, varname = $varname, name = $name</p>\n";
342
    }
343
    if (!$this->loadfile($parent)) {
344
      $this->halt("set_block: unable to load $parent.");
345
      return false;
346
    }
347
    if ($name == "") {
348
      $name = $varname;
349
    }
350
351
    $str = $this->get_var($parent);
352
    $reg = '/[ \t]*<!--\s+BEGIN '.$varname.'\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END '.$varname.'\s+-->\s*?\n?/sm';
353
    preg_match_all($reg, $str, $m);
354
/* workaround to avoid problems with some WB files/modules (e.g. massmail)
355
    if (!isset($m[1][0])) {
356
      $this->halt("set_block: unable to set block $varname.");
357
      return false;
358
    }
359
*/
360
    $str = preg_replace($reg, "{" . $name . "}", $str);
361
    @$this->set_var($varname, (isset($m[1][0])?$m[1][0]:''));
362
    $this->set_var($parent, $str);
363
    return true;
364
  }
365
366
367
 /******************************************************************************
368
  * This functions sets the value of a variable.
369
  *
370
  * It may be called with either a varname and a value as two strings or an
371
  * an associative array with the key being the varname and the value being
372
  * the new variable value.
373
  *
374
  * The function inserts the new value of the variable into the $varkeys and
375
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
376
  * before calling this function.
377
  *
378
  * An optional third parameter allows the value for each varname to be appended
379
  * to the existing variable instead of replacing it. The default is to replace.
380
  * This feature was introduced after the 7.2d release.
381
  *
382
  *
383
  * usage: set_var(string $varname, [string $value = ""], [boolean $append = false])
384
  * or
385
  * usage: set_var(array $varname = (string $varname => string $value), [mixed $dummy_var], [boolean $append = false])
386
  *
387
 * @param     $varname      either a string containing a varname or a hash of varname/value pairs.
388
 * @param     $value        if $varname is a string this contains the new value for the variable otherwise this parameter is ignored
389
 * @param     $append       if true, the value is appended to the variable's existing value
390
 * @access    public
391
 * @return    void
392
  */
393
  public function set_var($varname, $value = "", $append = false) {
394
    if (!is_array($varname)) {
395
      if (!empty($varname)) {
396
        if ($this->debug & 1) {
397
          printf("<b>set_var:</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($value));
398
        }
399
        $this->varkeys[$varname] = "/".$this->varname($varname)."/";
400
        if ($append && isset($this->varvals[$varname])) {
401
          $this->varvals[$varname] .= $value;
402
        } else {
403
          $this->varvals[$varname] = $value;
404
        }
405
      }
406
    } else {
407
      reset($varname);
408
      while (list($k, $v) = each($varname)) {
409
        if (!empty($k)) {
410
          if ($this->debug & 1) {
411
            printf("<b>set_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $k, htmlentities($v));
412
          }
413
          $this->varkeys[$k] = "/".$this->varname($k)."/";
414
          if ($append && isset($this->varvals[$k])) {
415
            $this->varvals[$k] .= $v;
416
          } else {
417
            $this->varvals[$k] = $v;
418
          }
419
        }
420
      }
421
    }
422
  }
423
424
425
 /******************************************************************************
426
  * This functions clears the value of a variable.
427
  *
428
  * It may be called with either a varname as a string or an array with the
429
  * values being the varnames to be cleared.
430
  *
431
  * The function sets the value of the variable in the $varkeys and $varvals
432
  * hashes to "". It is not necessary for a variable to exist in these hashes
433
  * before calling this function.
434
  *
435
  *
436
  * usage: clear_var(string $varname)
437
  * or
438
  * usage: clear_var(array $varname = (string $varname))
439
  *
440
 * @param     $varname      either a string containing a varname or an array of varnames.
441
 * @access    public
442
 * @return    void
443
  */
444
  public function clear_var($varname) {
445
    if (!is_array($varname)) {
446
      if (!empty($varname)) {
447
        if ($this->debug & 1) {
448
          printf("<b>clear_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
449
        }
450
        $this->set_var($varname, "");
451
      }
452
    } else {
453
      reset($varname);
454
      while (list($k, $v) = each($varname)) {
455
        if (!empty($v)) {
456
          if ($this->debug & 1) {
457
            printf("<b>clear_var:</b> (with array) <b>%s</b><br>\n", $v);
458
          }
459
          $this->set_var($v, "");
460
        }
461
      }
462
    }
463
  }
464
465
466
 /******************************************************************************
467
  * This functions unsets a variable completely.
468
469
  * It may be called with either a varname as a string or an array with the
470
  * values being the varnames to be cleared.
471
  *
472
  * The function removes the variable from the $varkeys and $varvals hashes.
473
  * It is not necessary for a variable to exist in these hashes before calling
474
  * this function.
475
  *
476
  *
477
  * usage: unset_var(string $varname)
478
  * or
479
  * usage: unset_var(array $varname = (string $varname))
480
  *
481
 * @param     $varname      either a string containing a varname or an array of varnames.
482
 * @access    public
483
 * @return    void
484
  */
485
  public function unset_var($varname) {
486
    if (!is_array($varname)) {
487
      if (!empty($varname)) {
488
        if ($this->debug & 1) {
489
          printf("<b>unset_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
490
        }
491
        unset($this->varkeys[$varname]);
492
        unset($this->varvals[$varname]);
493
      }
494
    } else {
495
      reset($varname);
496
      while (list($k, $v) = each($varname)) {
497
        if (!empty($v)) {
498
          if ($this->debug & 1) {
499
            printf("<b>unset_var:</b> (with array) <b>%s</b><br>\n", $v);
500
          }
501
          unset($this->varkeys[$v]);
502
          unset($this->varvals[$v]);
503
        }
504
      }
505
    }
506
  }
507
508
509
 /******************************************************************************
510
  * This function fills in all the variables contained within the variable named
511
  * $varname. The resulting value is returned as the function result and the
512
  * original value of the variable varname is not changed. The resulting string
513
  * is not "finished", that is, the unresolved variable name policy has not been
514
  * applied yet.
515
  *
516
  * Returns: the value of the variable $varname with all variables substituted.
517
  *
518
  * usage: subst(string $varname)
519
  *
520
 * @param     $varname      the name of the variable within which variables are to be substituted
521
 * @access    public
522
 * @return    string
523
  */
524
    protected function subst($varname) {
525
    $varvals_quoted = array();
526
    if ($this->debug & 4) {
527
      echo "<p><b>subst:</b> varname = $varname</p>\n";
528
    }
529
    if (!$this->loadfile($varname)) {
530
      $this->halt("subst: unable to load $varname.");
531
      return false;
532
    }
533
534
    // quote the replacement strings to prevent bogus stripping of special chars
535
    reset($this->varvals);
536
    while (list($k, $v) = each($this->varvals)) {
537
      $varvals_quoted[$k] = preg_replace(array('/\\\\/', '/\$/'), array('\\\\\\\\', '\\\\$'), $v);
538
    }
539
    $str = $this->get_var($varname);
540
    $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
541
    if (class_exists('ParseError')) {
542
        $bRetval = true;
543
        try{
544
            $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
545
        } catch(ParseError $e) {
546
            echo "<p><b>subst:</b> varname = $varname</p>\n";
547
        }
548
    } else {
549
        $str = @preg_replace($this->varkeys, $varvals_quoted, $str);
550
    }
551
    return $str;
552
  }
553
554
555
 /******************************************************************************
556
  * This is shorthand for print $this->subst($varname). See subst for further
557
  * details.
558
  *
559
  * Returns: always returns false.
560
  *
561
  * usage: psubst(string $varname)
562
  *
563
 * @param     $varname      the name of the variable within which variables are to be substituted
564
 * @access    public
565
 * @return    false
566
 * @see       subst
567
  */
568
  public function psubst($varname) {
569
    if ($this->debug & 4) {
570
      echo "<p><b>psubst:</b> varname = $varname</p>\n";
571
    }
572
    print $this->subst($varname);
573
574
    return false;
575
  }
576
577
578
 /******************************************************************************
579
  * The function substitutes the values of all defined variables in the variable
580
  * named $varname and stores or appends the result in the variable named $target.
581
  *
582
  * It may be called with either a target and a varname as two strings or a
583
  * target as a string and an array of variable names in varname.
584
  *
585
  * The function inserts the new value of the variable into the $varkeys and
586
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
587
  * before calling this function.
588
  *
589
  * An optional third parameter allows the value for each varname to be appended
590
  * to the existing target variable instead of replacing it. The default is to
591
  * replace.
592
  *
593
  * If $target and $varname are both strings, the substituted value of the
594
  * variable $varname is inserted into or appended to $target.
595
  *
596
  * If $handle is an array of variable names the variables named by $handle are
597
  * sequentially substituted and the result of each substitution step is
598
  * inserted into or appended to in $target. The resulting substitution is
599
  * available in the variable named by $target, as is each intermediate step
600
  * for the next $varname in sequence. Note that while it is possible, it
601
  * is only rarely desirable to call this function with an array of varnames
602
  * and with $append = true. This append feature was introduced after the 7.2d
603
  * release.
604
  *
605
  * Returns: the last value assigned to $target.
606
  *
607
  * usage: parse(string $target, string $varname, [boolean $append])
608
  * or
609
  * usage: parse(string $target, array $varname = (string $varname), [boolean $append])
610
  *
611
 * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
612
 * @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
613
 * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
614
 * @access    public
615
 * @return    string
616
 * @see       subst
617
  */
618
  public function parse($target, $varname, $append = false) {
619
    if (!is_array($varname)) {
620
      if ($this->debug & 4) {
621
        echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";
622
      }
623
      $str = $this->subst($varname);
624
      if ($append) {
625
        $this->set_var($target, $this->get_var($target) . $str);
626
      } else {
627
        $this->set_var($target, $str);
628
      }
629
    } else {
630
      reset($varname);
631
      while (list($i, $v) = each($varname)) {
632
        if ($this->debug & 4) {
633
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";
634
        }
635
        $str = $this->subst($v);
636
        if ($append) {
637
          $this->set_var($target, $this->get_var($target) . $str);
638
        } else {
639
          $this->set_var($target, $str);
640
        }
641
      }
642
    }
643
644
    if ($this->debug & 4) {
645
      echo "<p><b>parse:</b> completed</p>\n";
646
    }
647
    return $this->get_var($target);
648
  }
649
650
651
 /******************************************************************************
652
  * This is shorthand for print $this->parse(...) and is functionally identical.
653
  * See parse for further details.
654
  *
655
  * Returns: always returns false.
656
  *
657
  * usage: pparse(string $target, string $varname, [boolean $append])
658
  * or
659
  * usage: pparse(string $target, array $varname = (string $varname), [boolean $append])
660
  *
661
 * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
662
 * @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
663
 * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
664
 * @access    public
665
 * @return    false
666
 * @see       parse
667
  */
668
  public function pparse($target, $varname, $append = false, $clear = true) { // added $clear: whether to delete undefined vars or not (needed for wb-module code) - thorn
669
    if ($this->debug & 4) {
670
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
671
    }
672
        if(!$clear) {
673
            $unknowns = $this->unknowns;
674
            $this->set_unknowns('keep');
675
            print $this->finish($this->parse($target, $varname, $append));
676
            $this->set_unknowns($unknowns);
677
        } else {
678
            print $this->finish($this->parse($target, $varname, $append));
679
        }
680
        return false;
681
  }
682
683
684
 /******************************************************************************
685
  * This function returns an associative array of all defined variables with the
686
  * name as the key and the value of the variable as the value.
687
  *
688
  * This is mostly useful for debugging. Also note that $this->debug can be used
689
  * to echo all variable assignments as they occur and to trace execution.
690
  *
691
  * Returns: a hash of all defined variable values keyed by their names.
692
  *
693
  * usage: get_vars()
694
  *
695
 * @access    public
696
 * @return    array
697
 * @see       $debug
698
  */
699
  public function get_vars() {
700
    if ($this->debug & 4) {
701
      echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";
702
    }
703
    reset($this->varkeys);
704
    while (list($k, $v) = each($this->varkeys)) {
705
      $result[$k] = $this->get_var($k);
706
    }
707
    return $result;
708
  }
709
710
711
 /******************************************************************************
712
  * This function returns the value of the variable named by $varname.
713
  * If $varname references a file and that file has not been loaded yet, the
714
  * variable will be reported as empty.
715
  *
716
  * When called with an array of variable names this function will return a a
717
  * hash of variable values keyed by their names.
718
  *
719
  * Returns: a string or an array containing the value of $varname.
720
  *
721
  * usage: get_var(string $varname)
722
  * or
723
  * usage: get_var(array $varname)
724
  *
725
 * @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
726
 * @access    public
727
 * @return    string or array
728
  */
729
  public function get_var($varname) {
730
    if (!is_array($varname)) {
731
      if (isset($this->varvals[$varname])) {
732
        $str = $this->varvals[$varname];
733
      } else {
734
        $str = "";
735
      }
736
      if ($this->debug & 2) {
737
        printf ("<b>get_var</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($str));
738
      }
739
      return $str;
740
    } else {
741
      reset($varname);
742
      while (list($k, $v) = each($varname)) {
743
        if (isset($this->varvals[$v])) {
744
          $str = $this->varvals[$v];
745
        } else {
746
          $str = "";
747
        }
748
        if ($this->debug & 2) {
749
          printf ("<b>get_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $v, htmlentities($str));
750
        }
751
        $result[$v] = $str;
752
      }
753
      return $result;
754
    }
755
  }
756
757
758
 /******************************************************************************
759
  * This function returns a hash of unresolved variable names in $varname, keyed
760
  * by their names (that is, the hash has the form $a[$name] = $name).
761
  *
762
  * Returns: a hash of varname/varname pairs or false on error.
763
  *
764
  * usage: get_undefined(string $varname)
765
  *
766
 * @param     $varname     a string containing the name the name of the variable to scan for unresolved variables
767
 * @access    public
768
 * @return    array
769
  */
770
  public function get_undefined($varname) {
771
    if ($this->debug & 4) {
772
      echo "<p><b>get_undefined:</b> varname = $varname</p>\n";
773
    }
774
    if (!$this->loadfile($varname)) {
775
      $this->halt("get_undefined: unable to load $varname.");
776
      return false;
777
    }
778
779
    preg_match_all(
780
        (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
781
        $this->get_var($varname),
782
        $m);
783
    $m = $m[1];
784
    if (!is_array($m)) {
785
      return false;
786
    }
787
788
    reset($m);
789
    while (list($k, $v) = each($m)) {
790
      if (!isset($this->varkeys[$v])) {
791
        if ($this->debug & 4) {
792
         echo "<p><b>get_undefined:</b> undefined: $v</p>\n";
793
        }
794
        $result[$v] = $v;
795
      }
796
    }
797
798
    if (count($result)) {
799
      return $result;
800
    } else {
801
      return false;
802
    }
803
  }
804
805
806
 /******************************************************************************
807
  * This function returns the finished version of $str. That is, the policy
808
  * regarding unresolved variable names will be applied to $str.
809
  *
810
  * Returns: a finished string derived from $str and $this->unknowns.
811
  *
812
  * usage: finish(string $str)
813
  *
814
 * @param     $str         a string to which to apply the unresolved variable policy
815
 * @access    public
816
 * @return    string
817
 * @see       set_unknowns
818
  */
819
  public function finish($str) {
820
    switch ($this->unknowns) {
821
      case "keep":
822
      break;
823
824
      case "remove":
825
        $str = preg_replace(
826
            (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
827
            "",
828
            $str);
829
      break;
830
831
      case "comment":
832
        $str = preg_replace(
833
             (("loose" == $this->unknown_regexp) ? "/{([^ \t\r\n}]+)}/" : "/{([_a-zA-Z]\\w+)}/"),
834
            "<!-- Template variable \\1 undefined -->",
835
            $str);
836
      break;
837
    }
838
839
    return $str;
840
  }
841
842
843
 /******************************************************************************
844
  * This function prints the finished version of the value of the variable named
845
  * by $varname. That is, the policy regarding unresolved variable names will be
846
  * applied to the variable $varname then it will be printed.
847
  *
848
  * usage: p(string $varname)
849
  *
850
 * @param     $varname     a string containing the name of the variable to finish and print
851
 * @access    public
852
 * @return    void
853
 * @see       set_unknowns
854
 * @see       finish
855
  */
856
  public function p($varname) {
857
    print $this->finish($this->get_var($varname));
858
  }
859
860
861
 /******************************************************************************
862
  * This function returns the finished version of the value of the variable named
863
  * by $varname. That is, the policy regarding unresolved variable names will be
864
  * applied to the variable $varname and the result returned.
865
  *
866
  * Returns: a finished string derived from the variable $varname.
867
  *
868
  * usage: get(string $varname)
869
  *
870
 * @param     $varname     a string containing the name of the variable to finish
871
 * @access    public
872
 * @return    void
873
 * @see       set_unknowns
874
 * @see       finish
875
  */
876
  public function get($varname) {
877
    return $this->finish($this->get_var($varname));
878
  }
879
880
881
 /******************************************************************************
882
  * When called with a relative pathname, this function will return the pathname
883
  * with $this->root prepended. Absolute pathnames are returned unchanged.
884
  *
885
  * Returns: a string containing an absolute pathname.
886
  *
887
  * usage: filename(string $filename)
888
  *
889
 * @param     $filename    a string containing a filename
890
 * @access    private
891
 * @return    string
892
 * @see       set_root
893
  */
894
  public function filename($filename) {
895
    if ($this->debug & 4) {
896
      echo "<p><b>filename:</b> filename = $filename</p>\n";
897
    }
898
    if (substr($filename, 0, 1) != "/"
899
       && substr($filename, 0, 1) != "\\"
900
       && substr($filename, 1, 2) != ":\\"
901
       && substr($filename, 1, 2) != ":/"
902
    ) {
903
      $filename = $this->root."/".$filename;
904
    }
905
906
    if (!file_exists($filename)) {
907
      $this->halt("filename: file $filename does not exist.");
908
    }
909
    return $filename;
910
  }
911
912
913
 /******************************************************************************
914
  * This function will construct a regexp for a given variable name with any
915
  * special chars quoted.
916
  *
917
  * Returns: a string containing an escaped variable name.
918
  *
919
  * usage: varname(string $varname)
920
  *
921
 * @param     $varname    a string containing a variable name
922
 * @access    private
923
 * @return    string
924
  */
925
  public function varname($varname) {
926
    return preg_quote("{" . $varname . "}");
927
  }
928
929
930
 /******************************************************************************
931
  * If a variable's value is undefined and the variable has a filename stored in
932
  * $this->file[$varname] then the backing file will be loaded and the file's
933
  * contents will be assigned as the variable's value.
934
  *
935
  * Note that the behaviour of this function changed slightly after the 7.2d
936
  * release. Where previously a variable was reloaded from file if the value
937
  * was empty, now this is not done. This allows a variable to be loaded then
938
  * set to "", and also prevents attempts to load empty variables. Files are
939
  * now only loaded if $this->varvals[$varname] is unset.
940
  *
941
  * Returns: true on success, false on error.
942
  *
943
  * usage: loadfile(string $varname)
944
  *
945
 * @param     $varname    a string containing the name of a variable to load
946
 * @access    private
947
 * @return    boolean
948
 * @see       set_file
949
  */
950
  public function loadfile($varname) {
951
    if ($this->debug & 4) {
952
      echo "<p><b>loadfile:</b> varname = $varname</p>\n";
953
    }
954
955
    if (!isset($this->file[$varname])) {
956
      // $varname does not reference a file so return
957
      if ($this->debug & 4) {
958
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
959
      }
960
      return true;
961
    }
962
963
    if (isset($this->varvals[$varname])) {
964
      // will only be unset if varname was created with set_file and has never been loaded
965
      // $varname has already been loaded so return
966
      if ($this->debug & 4) {
967
        echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";
968
      }
969
      return true;
970
    }
971
    $filename = $this->file[$varname];
972
973
    /* use @file here to avoid leaking filesystem information if there is an error */
974
    $str = implode("", @file($filename));
975
    if (empty($str)) {
976
      $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");
977
      return false;
978
    }
979
980
    if ($this->filename_comments) {
981
      $str = "<!-- START FILE $filename -->\n$str<!-- END FILE $filename -->\n";
982
    }
983
    if ($this->debug & 4) {
984
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
985
    }
986
    $this->set_var($varname, $str);
987
988
    return true;
989
  }
990
991
992
 /******************************************************************************
993
  * This function is called whenever an error occurs and will handle the error
994
  * according to the policy defined in $this->halt_on_error. Additionally the
995
  * error message will be saved in $this->last_error.
996
  *
997
  * Returns: always returns false.
998
  *
999
  * usage: halt(string $msg)
1000
  *
1001
 * @param     $msg         a string containing an error message
1002
 * @access    private
1003
 * @return    void
1004
 * @see       $halt_on_error
1005
  */
1006
  public function halt($msg) {
1007
    $this->last_error = $msg;
1008
1009
    if ($this->halt_on_error != "no") {
1010
      $this->haltmsg($msg);
1011
    }
1012
1013
    if ($this->halt_on_error == "yes") {
1014
      die("<b>Halted.</b>");
1015
    }
1016
1017
    return false;
1018
  }
1019
1020
1021
 /******************************************************************************
1022
  * This function prints an error message.
1023
  * It can be overridden by your subclass of Template. It will be called with an
1024
  * error message to display.
1025
  *
1026
  * usage: haltmsg(string $msg)
1027
  *
1028
 * @param     $msg         a string containing the error message to display
1029
 * @access    public
1030
 * @return    void
1031
 * @see       halt
1032
  */
1033
  public function haltmsg($msg) {
1034
    printf("<b>Template Error:</b> %s<br>\n", $msg);
1035
  }
1036
1037
}