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, $clear = true) { // added $clear: whether to delete undefined vars or not (needed for wb-module code) - thorn
657
    if ($this->debug & 4) {
658
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
659
    }
660
		if($clear)
661
			print $this->finish($this->parse($target, $varname, $append));
662
		else
663
			print $this->parse($target, $varname, $append);
664
    return false;
665
  }
666

    
667

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

    
694

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

    
741

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

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

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

    
782
    if (count($result)) {
783
      return $result;
784
    } else {
785
      return false;
786
    }
787
  }
788

    
789

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

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

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

    
823
    return $str;
824
  }
825

    
826

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

    
844

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

    
864

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

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

    
896

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

    
913

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

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

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

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

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

    
972
    return true;
973
  }
974

    
975

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

    
993
    if ($this->halt_on_error != "no") {
994
      $this->haltmsg($msg);
995
    }
996

    
997
    if ($this->halt_on_error == "yes") {
998
      die("<b>Halted.</b>");
999
    }
1000

    
1001
    return false;
1002
  }
1003

    
1004

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

    
1021
}
1022
?>
(2-2/2)