Project

General

Profile

1
<?php
2
/*
3
 * Session Management for PHP3
4
 *
5
 * (C) Copyright 1999-2000 NetUSE GmbH
6
 *                    Kristian Koehntopp
7
 *
8
 * $Id: template.inc,v 1.1.1.1 2005/01/30 10:32:06 rdjurovich Exp $
9
 *
10
 */
11

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

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

    
61
class Template
62
{
63
 /**
64
  * Serialization helper, the name of this class.
65
  *
66
  * @var       string
67
  * @access    public
68
  */
69
  var $classname = "Template";
70

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

    
87
 /**
88
  * The base directory from which template files are loaded.
89
  *
90
  * @var       string
91
  * @access    private
92
  * @see       set_root
93
  */
94
  var $root     = ".";
95

    
96
 /**
97
  * A hash of strings forming a translation table which translates variable names
98
  * into names of files containing the variable content.
99
  * $file[varname] = "filename";
100
  *
101
  * @var       array
102
  * @access    private
103
  * @see       set_file
104
  */
105
  var $file     = array();
106

    
107
 /**
108
  * A hash of strings forming a translation table which translates variable names
109
  * into regular expressions for themselves.
110
  * $varkeys[varname] = "/varname/"
111
  *
112
  * @var       array
113
  * @access    private
114
  * @see       set_var
115
  */
116
  var $varkeys  = array();
117

    
118
 /**
119
  * A hash of strings forming a translation table which translates variable names
120
  * into values for their respective varkeys.
121
  * $varvals[varname] = "value"
122
  *
123
  * @var       array
124
  * @access    private
125
  * @see       set_var
126
  */
127
  var $varvals  = array();
128

    
129
 /**
130
  * Determines how to output variable tags with no assigned value in templates.
131
  *
132
  * @var       string
133
  * @access    private
134
  * @see       set_unknowns
135
  */
136
  var $unknowns = "remove";
137

    
138
 /**
139
  * Determines how Template handles error conditions.
140
  * "yes"      = the error is reported, then execution is halted
141
  * "report"   = the error is reported, then execution continues by returning "false"
142
  * "no"       = errors are silently ignored, and execution resumes reporting "false"
143
  *
144
  * @var       string
145
  * @access    public
146
  * @see       halt
147
  */
148
  var $halt_on_error  = "yes";
149

    
150
 /**
151
  * The last error message is retained in this variable.
152
  *
153
  * @var       string
154
  * @access    public
155
  * @see       halt
156
  */
157
  var $last_error     = "";
158

    
159
 /******************************************************************************
160
  * Class constructor. May be called with two optional parameters.
161
  * The first parameter sets the template directory the second parameter
162
  * sets the policy regarding handling of unknown variables.
163
  *
164
  * usage: Template([string $root = "."], [string $unknowns = "remove"])
165
  *
166
  * @param     $root        path to template directory
167
  * @param     $string      what to do with undefined variables
168
  * @see       set_root
169
  * @see       set_unknowns
170
  * @access    public
171
  * @return    void
172
  */
173
  function Template($root = ".", $unknowns = "remove") {
174
    if ($this->debug & 4) {
175
      echo "<p><b>Template:</b> root = $root, unknowns = $unknowns</p>\n";
176
    }
177
    $this->set_root($root);
178
    $this->set_unknowns($unknowns);
179
  }
180

    
181

    
182
 /******************************************************************************
183
  * Checks that $root is a valid directory and if so sets this directory as the
184
  * base directory from which templates are loaded by storing the value in
185
  * $this->root. Relative filenames are prepended with the path in $this->root.
186
  *
187
  * Returns true on success, false on error.
188
  *
189
  * usage: set_root(string $root)
190
  *
191
  * @param     $root         string containing new template directory
192
  * @see       root
193
  * @access    public
194
  * @return    boolean
195
  */
196
  function set_root($root) {
197
    if ($this->debug & 4) {
198
      echo "<p><b>set_root:</b> root = $root</p>\n";
199
    }
200
    if (!is_dir($root)) {
201
      $this->halt("set_root: $root is not a directory.");
202
      return false;
203
    }
204

    
205
    $this->root = $root;
206
    return true;
207
  }
208

    
209

    
210
 /******************************************************************************
211
  * Sets the policy for dealing with unresolved variable names.
212
  *
213
  * unknowns defines what to do with undefined template variables
214
  * "remove"   = remove undefined variables
215
  * "comment"  = replace undefined variables with comments
216
  * "keep"     = keep undefined variables
217
  *
218
  * Note: "comment" can cause unexpected results when the variable tag is embedded
219
  * inside an HTML tag, for example a tag which is expected to be replaced with a URL.
220
  *
221
  * usage: set_unknowns(string $unknowns)
222
  *
223
  * @param     $unknowns         new value for unknowns
224
  * @see       unknowns
225
  * @access    public
226
  * @return    void
227
  */
228
  function set_unknowns($unknowns = "remove") {
229
    if ($this->debug & 4) {
230
      echo "<p><b>unknowns:</b> unknowns = $unknowns</p>\n";
231
    }
232
    $this->unknowns = $unknowns;
233
  }
234

    
235

    
236
 /******************************************************************************
237
  * Defines a filename for the initial value of a variable.
238
  *
239
  * It may be passed either a varname and a file name as two strings or
240
  * a hash of strings with the key being the varname and the value
241
  * being the file name.
242
  *
243
  * The new mappings are stored in the array $this->file.
244
  * The files are not loaded yet, but only when needed.
245
  *
246
  * Returns true on success, false on error.
247
  *
248
  * usage: set_file(array $filelist = (string $varname => string $filename))
249
  * or
250
  * usage: set_file(string $varname, string $filename)
251
  *
252
  * @param     $varname      either a string containing a varname or a hash of varname/file name pairs.
253
  * @param     $filename     if varname is a string this is the filename otherwise filename is not required
254
  * @access    public
255
  * @return    boolean
256
  */
257
  function set_file($varname, $filename = "") {
258
    if (!is_array($varname)) {
259
      if ($this->debug & 4) {
260
        echo "<p><b>set_file:</b> (with scalar) varname = $varname, filename = $filename</p>\n";
261
      }
262
      if ($filename == "") {
263
        $this->halt("set_file: For varname $varname filename is empty.");
264
        return false;
265
      }
266
      $this->file[$varname] = $this->filename($filename);
267
    } else {
268
      reset($varname);
269
      while(list($v, $f) = each($varname)) {
270
        if ($this->debug & 4) {
271
          echo "<p><b>set_file:</b> (with array) varname = $v, filename = $f</p>\n";
272
        }
273
        if ($f == "") {
274
          $this->halt("set_file: For varname $v filename is empty.");
275
          return false;
276
        }
277
        $this->file[$v] = $this->filename($f);
278
      }
279
    }
280
    return true;
281
  }
282

    
283

    
284
 /******************************************************************************
285
  * A variable $parent may contain a variable block defined by:
286
  * &lt;!-- BEGIN $varname --&gt; content &lt;!-- END $varname --&gt;. This function removes
287
  * that block from $parent and replaces it with a variable reference named $name.
288
  * The block is inserted into the varkeys and varvals hashes. If $name is
289
  * omitted, it is assumed to be the same as $varname.
290
  *
291
  * Blocks may be nested but care must be taken to extract the blocks in order
292
  * from the innermost block to the outermost block.
293
  *
294
  * Returns true on success, false on error.
295
  *
296
  * usage: set_block(string $parent, string $varname, [string $name = ""])
297
  *
298
  * @param     $parent       a string containing the name of the parent variable
299
  * @param     $varname      a string containing the name of the block to be extracted
300
  * @param     $name         the name of the variable in which to store the block
301
  * @access    public
302
  * @return    boolean
303
  */
304
  function set_block($parent, $varname, $name = "") {
305
    if ($this->debug & 4) {
306
      echo "<p><b>set_block:</b> parent = $parent, varname = $varname, name = $name</p>\n";
307
    }
308
    if (!$this->loadfile($parent)) {
309
      $this->halt("set_block: unable to load $parent.");
310
      return false;
311
    }
312
    if ($name == "") {
313
      $name = $varname;
314
    }
315

    
316
    $str = $this->get_var($parent);
317
    $reg = "/[ \t]*<!--\s+BEGIN $varname\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $varname\s+-->\s*?\n?/sm";
318
    preg_match_all($reg, $str, $m);
319
    $str = preg_replace($reg, "{" . "$name}", $str);
320
    $this->set_var($varname, $m[1][0]);
321
    $this->set_var($parent, $str);
322
    return true;
323
  }
324

    
325

    
326
 /******************************************************************************
327
  * This functions sets the value of a variable.
328
  *
329
  * It may be called with either a varname and a value as two strings or an
330
  * an associative array with the key being the varname and the value being
331
  * the new variable value.
332
  *
333
  * The function inserts the new value of the variable into the $varkeys and
334
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
335
  * before calling this function.
336
  *
337
  * An optional third parameter allows the value for each varname to be appended
338
  * to the existing variable instead of replacing it. The default is to replace.
339
  * This feature was introduced after the 7.2d release.
340
  *
341
  *
342
  * usage: set_var(string $varname, [string $value = ""], [boolean $append = false])
343
  * or
344
  * usage: set_var(array $varname = (string $varname => string $value), [mixed $dummy_var], [boolean $append = false])
345
  *
346
  * @param     $varname      either a string containing a varname or a hash of varname/value pairs.
347
  * @param     $value        if $varname is a string this contains the new value for the variable otherwise this parameter is ignored
348
  * @param     $append       if true, the value is appended to the variable's existing value
349
  * @access    public
350
  * @return    void
351
  */
352
  function set_var($varname, $value = "", $append = false) {
353
    if (!is_array($varname)) {
354
      if (!empty($varname)) {
355
        if ($this->debug & 1) {
356
          printf("<b>set_var:</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($value));
357
        }
358
        $this->varkeys[$varname] = "/".$this->varname($varname)."/";
359
        if ($append && isset($this->varvals[$varname])) {
360
          $this->varvals[$varname] .= $value;
361
        } else {
362
          $this->varvals[$varname] = $value;
363
        }
364
      }
365
    } else {
366
      reset($varname);
367
      while(list($k, $v) = each($varname)) {
368
        if (!empty($k)) {
369
          if ($this->debug & 1) {
370
            printf("<b>set_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $k, htmlentities($v));
371
          }
372
          $this->varkeys[$k] = "/".$this->varname($k)."/";
373
          if ($append && isset($this->varvals[$k])) {
374
            $this->varvals[$k] .= $v;
375
          } else {
376
            $this->varvals[$k] = $v;
377
          }
378
        }
379
      }
380
    }
381
  }
382

    
383

    
384
 /******************************************************************************
385
  * This functions clears the value of a variable.
386
  *
387
  * It may be called with either a varname as a string or an array with the 
388
  * values being the varnames to be cleared.
389
  *
390
  * The function sets the value of the variable in the $varkeys and $varvals 
391
  * hashes to "". It is not necessary for a variable to exist in these hashes
392
  * before calling this function.
393
  *
394
  *
395
  * usage: clear_var(string $varname)
396
  * or
397
  * usage: clear_var(array $varname = (string $varname))
398
  *
399
  * @param     $varname      either a string containing a varname or an array of varnames.
400
  * @access    public
401
  * @return    void
402
  */
403
  function clear_var($varname) {
404
    if (!is_array($varname)) {
405
      if (!empty($varname)) {
406
        if ($this->debug & 1) {
407
          printf("<b>clear_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
408
        }
409
        $this->set_var($varname, "");
410
      }
411
    } else {
412
      reset($varname);
413
      while(list($k, $v) = each($varname)) {
414
        if (!empty($v)) {
415
          if ($this->debug & 1) {
416
            printf("<b>clear_var:</b> (with array) <b>%s</b><br>\n", $v);
417
          }
418
          $this->set_var($v, "");
419
        }
420
      }
421
    }
422
  }
423

    
424

    
425
 /******************************************************************************
426
  * This functions unsets a variable completely.
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 removes the variable from the $varkeys and $varvals hashes.
432
  * It is not necessary for a variable to exist in these hashes before calling
433
  * this function.
434
  *
435
  *
436
  * usage: unset_var(string $varname)
437
  * or
438
  * usage: unset_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
  function unset_var($varname) {
445
    if (!is_array($varname)) {
446
      if (!empty($varname)) {
447
        if ($this->debug & 1) {
448
          printf("<b>unset_var:</b> (with scalar) <b>%s</b><br>\n", $varname);
449
        }
450
        unset($this->varkeys[$varname]);
451
        unset($this->varvals[$varname]);
452
      }
453
    } else {
454
      reset($varname);
455
      while(list($k, $v) = each($varname)) {
456
        if (!empty($v)) {
457
          if ($this->debug & 1) {
458
            printf("<b>unset_var:</b> (with array) <b>%s</b><br>\n", $v);
459
          }
460
          unset($this->varkeys[$v]);
461
          unset($this->varvals[$v]);
462
        }
463
      }
464
    }
465
  }
466

    
467

    
468
 /******************************************************************************
469
  * This function fills in all the variables contained within the variable named
470
  * $varname. The resulting value is returned as the function result and the
471
  * original value of the variable varname is not changed. The resulting string
472
  * is not "finished", that is, the unresolved variable name policy has not been
473
  * applied yet.
474
  *
475
  * Returns: the value of the variable $varname with all variables substituted.
476
  *
477
  * usage: subst(string $varname)
478
  *
479
  * @param     $varname      the name of the variable within which variables are to be substituted
480
  * @access    public
481
  * @return    string
482
  */
483
  function subst($varname) {
484
    $varvals_quoted = array();
485
    if ($this->debug & 4) {
486
      echo "<p><b>subst:</b> varname = $varname</p>\n";
487
    }
488
    if (!$this->loadfile($varname)) {
489
      $this->halt("subst: unable to load $varname.");
490
      return false;
491
    }
492

    
493
    // quote the replacement strings to prevent bogus stripping of special chars
494
    reset($this->varvals);
495
    while(list($k, $v) = each($this->varvals)) {
496
      $varvals_quoted[$k] = preg_replace(array('/\\\\/', '/\$/'), array('\\\\\\\\', '\\\\$'), $v);
497
    }
498

    
499
    $str = $this->get_var($varname);
500
    $str = preg_replace($this->varkeys, $varvals_quoted, $str);
501
    return $str;
502
  }
503

    
504

    
505
 /******************************************************************************
506
  * This is shorthand for print $this->subst($varname). See subst for further
507
  * details.
508
  *
509
  * Returns: always returns false.
510
  *
511
  * usage: psubst(string $varname)
512
  *
513
  * @param     $varname      the name of the variable within which variables are to be substituted
514
  * @access    public
515
  * @return    false
516
  * @see       subst
517
  */
518
  function psubst($varname) {
519
    if ($this->debug & 4) {
520
      echo "<p><b>psubst:</b> varname = $varname</p>\n";
521
    }
522
    print $this->subst($varname);
523

    
524
    return false;
525
  }
526

    
527

    
528
 /******************************************************************************
529
  * The function substitutes the values of all defined variables in the variable
530
  * named $varname and stores or appends the result in the variable named $target.
531
  *
532
  * It may be called with either a target and a varname as two strings or a
533
  * target as a string and an array of variable names in varname.
534
  *
535
  * The function inserts the new value of the variable into the $varkeys and
536
  * $varvals hashes. It is not necessary for a variable to exist in these hashes
537
  * before calling this function.
538
  *
539
  * An optional third parameter allows the value for each varname to be appended
540
  * to the existing target variable instead of replacing it. The default is to
541
  * replace.
542
  *
543
  * If $target and $varname are both strings, the substituted value of the
544
  * variable $varname is inserted into or appended to $target.
545
  *
546
  * If $handle is an array of variable names the variables named by $handle are
547
  * sequentially substituted and the result of each substitution step is
548
  * inserted into or appended to in $target. The resulting substitution is
549
  * available in the variable named by $target, as is each intermediate step
550
  * for the next $varname in sequence. Note that while it is possible, it
551
  * is only rarely desirable to call this function with an array of varnames
552
  * and with $append = true. This append feature was introduced after the 7.2d
553
  * release.
554
  *
555
  * Returns: the last value assigned to $target.
556
  *
557
  * usage: parse(string $target, string $varname, [boolean $append])
558
  * or
559
  * usage: parse(string $target, array $varname = (string $varname), [boolean $append])
560
  *
561
  * @param     $target      a string containing the name of the variable into which substituted $varnames are to be stored
562
  * @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
563
  * @param     $append      if true, the substituted variables are appended to $target otherwise the existing value of $target is replaced
564
  * @access    public
565
  * @return    string
566
  * @see       subst
567
  */
568
  function parse($target, $varname, $append = false) {
569
    if (!is_array($varname)) {
570
      if ($this->debug & 4) {
571
        echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";
572
      }
573
      $str = $this->subst($varname);
574
      if ($append) {
575
        $this->set_var($target, $this->get_var($target) . $str);
576
      } else {
577
        $this->set_var($target, $str);
578
      }
579
    } else {
580
      reset($varname);
581
      while(list($i, $v) = each($varname)) {
582
        if ($this->debug & 4) {
583
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";
584
        }
585
        $str = $this->subst($v);
586
        if ($append) {
587
          $this->set_var($target, $this->get_var($target) . $str);
588
        } else {
589
          $this->set_var($target, $str);
590
        }
591
      }
592
    }
593

    
594
    if ($this->debug & 4) {
595
      echo "<p><b>parse:</b> completed</p>\n";
596
    }
597
    return $str;
598
  }
599

    
600

    
601
 /******************************************************************************
602
  * This is shorthand for print $this->parse(...) and is functionally identical.
603
  * See parse for further details.
604
  *
605
  * Returns: always returns false.
606
  *
607
  * usage: pparse(string $target, string $varname, [boolean $append])
608
  * or
609
  * usage: pparse(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    false
616
  * @see       parse
617
  */
618
  function pparse($target, $varname, $append = false) {
619
    if ($this->debug & 4) {
620
      echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";
621
    }
622
    print $this->finish($this->parse($target, $varname, $append));
623
    return false;
624
  }
625

    
626

    
627
 /******************************************************************************
628
  * This function returns an associative array of all defined variables with the
629
  * name as the key and the value of the variable as the value.
630
  *
631
  * This is mostly useful for debugging. Also note that $this->debug can be used
632
  * to echo all variable assignments as they occur and to trace execution.
633
  *
634
  * Returns: a hash of all defined variable values keyed by their names.
635
  *
636
  * usage: get_vars()
637
  *
638
  * @access    public
639
  * @return    array
640
  * @see       $debug
641
  */
642
  function get_vars() {
643
    if ($this->debug & 4) {
644
      echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";
645
    }
646
    reset($this->varkeys);
647
    while(list($k, $v) = each($this->varkeys)) {
648
      $result[$k] = $this->get_var($k);
649
    }
650
    return $result;
651
  }
652

    
653

    
654
 /******************************************************************************
655
  * This function returns the value of the variable named by $varname.
656
  * If $varname references a file and that file has not been loaded yet, the
657
  * variable will be reported as empty.
658
  *
659
  * When called with an array of variable names this function will return a a
660
  * hash of variable values keyed by their names.
661
  *
662
  * Returns: a string or an array containing the value of $varname.
663
  *
664
  * usage: get_var(string $varname)
665
  * or
666
  * usage: get_var(array $varname)
667
  *
668
  * @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
669
  * @access    public
670
  * @return    string or array
671
  */
672
  function get_var($varname) {
673
    if (!is_array($varname)) {
674
      if (isset($this->varvals[$varname])) {
675
        $str = $this->varvals[$varname];
676
      } else {
677
        $str = "";
678
      }
679
      if ($this->debug & 2) {
680
        printf ("<b>get_var</b> (with scalar) <b>%s</b> = '%s'<br>\n", $varname, htmlentities($str));
681
      }
682
      return $str;
683
    } else {
684
      reset($varname);
685
      while(list($k, $v) = each($varname)) {
686
        if (isset($this->varvals[$v])) {
687
          $str = $this->varvals[$v];
688
        } else {
689
          $str = "";
690
        }
691
        if ($this->debug & 2) {
692
          printf ("<b>get_var:</b> (with array) <b>%s</b> = '%s'<br>\n", $v, htmlentities($str));
693
        }
694
        $result[$v] = $str;
695
      }
696
      return $result;
697
    }
698
  }
699

    
700

    
701
 /******************************************************************************
702
  * This function returns a hash of unresolved variable names in $varname, keyed
703
  * by their names (that is, the hash has the form $a[$name] = $name).
704
  *
705
  * Returns: a hash of varname/varname pairs or false on error.
706
  *
707
  * usage: get_undefined(string $varname)
708
  *
709
  * @param     $varname     a string containing the name the name of the variable to scan for unresolved variables
710
  * @access    public
711
  * @return    array
712
  */
713
  function get_undefined($varname) {
714
    if ($this->debug & 4) {
715
      echo "<p><b>get_undefined:</b> varname = $varname</p>\n";
716
    }
717
    if (!$this->loadfile($varname)) {
718
      $this->halt("get_undefined: unable to load $varname.");
719
      return false;
720
    }
721

    
722
    preg_match_all("/{([^ \t\r\n}]+)}/", $this->get_var($varname), $m);
723
    $m = $m[1];
724
    if (!is_array($m)) {
725
      return false;
726
    }
727

    
728
    reset($m);
729
    while(list($k, $v) = each($m)) {
730
      if (!isset($this->varkeys[$v])) {
731
        if ($this->debug & 4) {
732
         echo "<p><b>get_undefined:</b> undefined: $v</p>\n";
733
        }
734
        $result[$v] = $v;
735
      }
736
    }
737

    
738
    if (count($result)) {
739
      return $result;
740
    } else {
741
      return false;
742
    }
743
  }
744

    
745

    
746
 /******************************************************************************
747
  * This function returns the finished version of $str. That is, the policy
748
  * regarding unresolved variable names will be applied to $str.
749
  *
750
  * Returns: a finished string derived from $str and $this->unknowns.
751
  *
752
  * usage: finish(string $str)
753
  *
754
  * @param     $str         a string to which to apply the unresolved variable policy
755
  * @access    public
756
  * @return    string
757
  * @see       set_unknowns
758
  */
759
  function finish($str) {
760
    switch ($this->unknowns) {
761
      case "keep":
762
      break;
763

    
764
      case "remove":
765
        $str = preg_replace('/{[^ \t\r\n}]+}/', "", $str);
766
      break;
767

    
768
      case "comment":
769
        $str = preg_replace('/{([^ \t\r\n}]+)}/', "<!-- Template variable \\1 undefined -->", $str);
770
      break;
771
    }
772

    
773
    return $str;
774
  }
775

    
776

    
777
 /******************************************************************************
778
  * This function prints the finished version of the value of the variable named
779
  * by $varname. That is, the policy regarding unresolved variable names will be
780
  * applied to the variable $varname then it will be printed.
781
  *
782
  * usage: p(string $varname)
783
  *
784
  * @param     $varname     a string containing the name of the variable to finish and print
785
  * @access    public
786
  * @return    void
787
  * @see       set_unknowns
788
  * @see       finish
789
  */
790
  function p($varname) {
791
    print $this->finish($this->get_var($varname));
792
  }
793

    
794

    
795
 /******************************************************************************
796
  * This function returns the finished version of the value of the variable named
797
  * by $varname. That is, the policy regarding unresolved variable names will be
798
  * applied to the variable $varname and the result returned.
799
  *
800
  * Returns: a finished string derived from the variable $varname.
801
  *
802
  * usage: get(string $varname)
803
  *
804
  * @param     $varname     a string containing the name of the variable to finish
805
  * @access    public
806
  * @return    void
807
  * @see       set_unknowns
808
  * @see       finish
809
  */
810
  function get($varname) {
811
    return $this->finish($this->get_var($varname));
812
  }
813

    
814

    
815
 /******************************************************************************
816
  * When called with a relative pathname, this function will return the pathname
817
  * with $this->root prepended. Absolute pathnames are returned unchanged.
818
  *
819
  * Returns: a string containing an absolute pathname.
820
  *
821
  * usage: filename(string $filename)
822
  *
823
  * @param     $filename    a string containing a filename
824
  * @access    private
825
  * @return    string
826
  * @see       set_root
827
  */
828
  function filename($filename) {
829
    if ($this->debug & 4) {
830
      echo "<p><b>filename:</b> filename = $filename</p>\n";
831
    }
832
    if (substr($filename, 0, 1) != "/") {
833
      $filename = $this->root."/".$filename;
834
    }
835

    
836
    if (!file_exists($filename)) {
837
      $this->halt("filename: file $filename does not exist.");
838
    }
839
    return $filename;
840
  }
841

    
842

    
843
 /******************************************************************************
844
  * This function will construct a regexp for a given variable name with any
845
  * special chars quoted.
846
  *
847
  * Returns: a string containing an escaped variable name.
848
  *
849
  * usage: varname(string $varname)
850
  *
851
  * @param     $varname    a string containing a variable name
852
  * @access    private
853
  * @return    string
854
  */
855
  function varname($varname) {
856
    return preg_quote("{".$varname."}");
857
  }
858

    
859

    
860
 /******************************************************************************
861
  * If a variable's value is undefined and the variable has a filename stored in
862
  * $this->file[$varname] then the backing file will be loaded and the file's
863
  * contents will be assigned as the variable's value.
864
  *
865
  * Note that the behaviour of this function changed slightly after the 7.2d
866
  * release. Where previously a variable was reloaded from file if the value
867
  * was empty, now this is not done. This allows a variable to be loaded then
868
  * set to "", and also prevents attempts to load empty variables. Files are
869
  * now only loaded if $this->varvals[$varname] is unset.
870
  *
871
  * Returns: true on success, false on error.
872
  *
873
  * usage: loadfile(string $varname)
874
  *
875
  * @param     $varname    a string containing the name of a variable to load
876
  * @access    private
877
  * @return    boolean
878
  * @see       set_file
879
  */
880
  function loadfile($varname) {
881
    if ($this->debug & 4) {
882
      echo "<p><b>loadfile:</b> varname = $varname</p>\n";
883
    }
884

    
885
    if (!isset($this->file[$varname])) {
886
      // $varname does not reference a file so return
887
      if ($this->debug & 4) {
888
        echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";
889
      }
890
      return true;
891
    }
892

    
893
    if (isset($this->varvals[$varname])) {
894
      // will only be unset if varname was created with set_file and has never been loaded
895
      // $varname has already been loaded so return
896
      if ($this->debug & 4) {
897
        echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";
898
      }
899
      return true;
900
    }
901
    $filename = $this->file[$varname];
902

    
903
    /* use @file here to avoid leaking filesystem information if there is an error */
904
    $str = implode("", @file($filename));
905
    if (empty($str)) {
906
      $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");
907
      return false;
908
    }
909

    
910
    if ($this->debug & 4) {
911
      printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");
912
    }
913
    $this->set_var($varname, $str);
914

    
915
    return true;
916
  }
917

    
918

    
919
 /******************************************************************************
920
  * This function is called whenever an error occurs and will handle the error
921
  * according to the policy defined in $this->halt_on_error. Additionally the
922
  * error message will be saved in $this->last_error.
923
  *
924
  * Returns: always returns false.
925
  *
926
  * usage: halt(string $msg)
927
  *
928
  * @param     $msg         a string containing an error message
929
  * @access    private
930
  * @return    void
931
  * @see       $halt_on_error
932
  */
933
  function halt($msg) {
934
    $this->last_error = $msg;
935

    
936
    if ($this->halt_on_error != "no") {
937
      $this->haltmsg($msg);
938
    }
939

    
940
    if ($this->halt_on_error == "yes") {
941
      die("<b>Halted.</b>");
942
    }
943

    
944
    return false;
945
  }
946

    
947

    
948
 /******************************************************************************
949
  * This function prints an error message.
950
  * It can be overridden by your subclass of Template. It will be called with an
951
  * error message to display.
952
  *
953
  * usage: haltmsg(string $msg)
954
  *
955
  * @param     $msg         a string containing the error message to display
956
  * @access    public
957
  * @return    void
958
  * @see       halt
959
  */
960
  function haltmsg($msg) {
961
    printf("<b>Template Error:</b> %s<br>\n", $msg);
962
  }
963

    
964
}
965
?>
    (1-1/1)