1 |
<? |
2 |
|
3 |
/* |
4 |
Class FastTemplate w/ caching extensions |
5 |
|
6 |
PHP extension for managing templates and performing variable interpolation with cached results. |
7 |
|
8 |
This program is free software; you can redistribute it and/or modify it under |
9 |
the GNU Library General Public License, with the following stipulations; |
10 |
|
11 |
Changes or modifications must retain these Copyright statements. |
12 |
Changes or modifications must be submitted to both AUTHORS. |
13 |
|
14 |
This program is released under the GNU Library General Public License. |
15 |
( http://www.gnu.org/copyleft/lgpl.html ) |
16 |
|
17 |
This program is distributed in the hope that it will be useful, |
18 |
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
19 |
FOR A PARTICULAR PURPOSE. See the Artistic License for more details. |
20 |
This software is distributed AS-IS. |
21 |
|
22 |
Some caching functions by Benjamin Kahn <xkahn@cybersites.com> |
23 |
http://www.zoned.net/~xkahn/php/fasttemplate |
24 |
Portions written by Benjamin Kahn Copyright (c) 2000 CyberSites, Inc; xkahn@cybersites.com, All Rights Reserved |
25 |
|
26 |
originally by: "JP" <jprins@dds.nl> |
27 |
http://www.phpbuilder.com/columns/jprins20000201.php3 |
28 |
|
29 |
with code by: Spencer D. Mindlin <smindlin@beaconeast.com> |
30 |
http://www.phpbuilder.com/columns/spencer20000208.php3 |
31 |
|
32 |
PHP3 port by CDI cdi@thewebmasters.net |
33 |
PHP3 Version Copyright (c) 1999 CDI, cdi@thewebmasters.net, All Rights Reserved. |
34 |
Perl Version Copyright (c) 1998 Jason Moore jmoore@sober.com. All Rights Reserved. |
35 |
Original Perl module CGI::FastTemplate by Jason Moore jmoore@sober.com |
36 |
|
37 |
*/ |
38 |
|
39 |
class FastTemplate { |
40 |
|
41 |
var $FILELIST = array(); // Holds the array of filehandles |
42 |
// FILELIST[HANDLE] == "fileName" |
43 |
|
44 |
var $DYNAMIC = array(); // Holds the array of dynamic |
45 |
// blocks, and the fileHandles they |
46 |
// live in. |
47 |
|
48 |
var $PARSEVARS = array(); // Holds the array of Variable |
49 |
// handles. |
50 |
// PARSEVARS[HANDLE] == "value" |
51 |
|
52 |
var $LOADED = array(); // We only want to load a template |
53 |
// once - when it's used. |
54 |
// LOADED[FILEHANDLE] == 1 if loaded |
55 |
// undefined if not loaded yet. |
56 |
|
57 |
var $HANDLE = array(); // Holds the handle names assigned |
58 |
// by a call to parse() |
59 |
|
60 |
var $ROOT = ""; // Holds path-to-templates |
61 |
|
62 |
var $WIN32 = false; // Set to true if this is a WIN32 server |
63 |
|
64 |
var $ERROR = ""; // Holds the last error message |
65 |
|
66 |
var $LAST = ""; // Holds the HANDLE to the last |
67 |
// template parsed by parse() |
68 |
|
69 |
var $STRICT = true; // Strict template checking. |
70 |
// Unresolved vars in templates will |
71 |
// generate a warning when found. |
72 |
|
73 |
// ************************************************************ |
74 |
|
75 |
function FastTemplate ($pathToTemplates = "") { |
76 |
global $php_errormsg; |
77 |
|
78 |
if(!empty($pathToTemplates)) { |
79 |
$this->set_root($pathToTemplates); |
80 |
} |
81 |
|
82 |
} // end (new) FastTemplate () |
83 |
|
84 |
|
85 |
// New call: cache_expire (HANDLE, number of seconds); which allows you to cache a template |
86 |
// New call: cache_refresh (HANDLE, how often); which allows you to cache a template |
87 |
// New call: is_cached(RETURN, FileHandle); true if a valid cache file is available |
88 |
// New call: write_cache(HANDLE, FileHandle); call when a handle is done. |
89 |
|
90 |
// ********************* |
91 |
// Function: is_cached |
92 |
// Input: RETURN, FileHandle (FIXME: Plural FileHandles are not supported.) |
93 |
// Return: true or false depending on whether a cache file is available. |
94 |
// Side Effects: assigns variables as if a parse call had been made |
95 |
// |
96 |
// Notes: |
97 |
// Find the cache name, and see if the file exists |
98 |
// If it doesn't, return FALSE |
99 |
// If it does, check is the file is current (see ~/src/php-cache.php) |
100 |
// If is isn't, return FALSE |
101 |
// check if the section is dynamic. If so, use clear_dynamic to insert contents of file |
102 |
// If not, assign file contents to ReturnVar |
103 |
// return TRUE |
104 |
function is_cached ( $ReturnVar, $FileTags ) { |
105 |
|
106 |
// Fixme: We should do something smart if $FileTags is an array |
107 |
|
108 |
$str_cache_file = $this->cache_file_name( $ReturnVar, $FileTags ); |
109 |
|
110 |
// This function will wait until a cache has been created. (Lock file cleared.) |
111 |
clearstatcache($str_cache_file); |
112 |
// Here we perform some error correction. If a lock file |
113 |
// is left over from a previous request, this ensures that |
114 |
// it is deleted. |
115 |
// FIXME: If this takes too long, we should turn caching off for this file, and return FALSE; |
116 |
while (file_exists($str_cache_file . '.lock')) { |
117 |
sleep(2); |
118 |
clearstatcache(); |
119 |
continue; |
120 |
} |
121 |
clearstatcache(); |
122 |
|
123 |
// If the cache file doesn't exist, it isn't cached. QED. |
124 |
if (!file_exists($str_cache_file)) { |
125 |
return FALSE; |
126 |
} |
127 |
|
128 |
// Now we need to find out if we are caching. |
129 |
$refresh = $this->CACHE[$FileTags]["refresh"]; |
130 |
$expires = $this->CACHE[$FileTags]["expire"]; |
131 |
$cache_read = 0; // Default to no read |
132 |
if (!refresh && !expires) // Do we have any set time? |
133 |
$expires = 600; |
134 |
|
135 |
if (isset ($expires)) { |
136 |
if ((filectime ($str_cache_file) + $expires) > date ( "U")) { |
137 |
$cache_read = 1; |
138 |
} |
139 |
} |
140 |
|
141 |
if (isset ($refresh)) { |
142 |
switch (strtoupper($refresh)) { |
143 |
case 'MINUTE': |
144 |
if (checkRefreshMinute(mktime(), filemtime($str_cache_file))) { |
145 |
$cache_read = 1; |
146 |
} |
147 |
break; |
148 |
case 'QUARTERHOUR': |
149 |
if (checkRefreshQuarterHour(mktime(), filemtime($str_cache_file))) { |
150 |
$cache_read = 1; |
151 |
} |
152 |
break; |
153 |
case 'HALFHOUR': |
154 |
if (checkRefreshHalfHour(mktime(), filemtime($str_cache_file))) { |
155 |
$cache_read = 1; |
156 |
} |
157 |
break; |
158 |
case 'HOUR': |
159 |
if (checkRefreshHour(mktime(), filemtime($str_cache_file))) { |
160 |
$cache_read = 1; |
161 |
} |
162 |
break; |
163 |
case 'HALFDAY': |
164 |
if (checkExpiredHalfDay(mktime(), filemtime($str_cache_file))) { |
165 |
$cache_read = 1; |
166 |
} |
167 |
break; |
168 |
case 'DAY': |
169 |
if (checkRefreshDay(mktime(), filemtime($str_cache_file))) { |
170 |
$cache_read = 1; |
171 |
} |
172 |
break; |
173 |
case 'MONTH': |
174 |
if (checkRefreshMonth(mktime(), filemtime($str_cache_file))) { |
175 |
$cache_read = 1; |
176 |
} |
177 |
} |
178 |
} |
179 |
|
180 |
if ($cache_read == 1) { |
181 |
|
182 |
// We have a cache file and we should read from it! |
183 |
if ($f = fopen ($str_cache_file, "r")) { |
184 |
$buf = ""; |
185 |
while ($str = fgets ($f, 4096)) { |
186 |
$buf .= $str; |
187 |
} |
188 |
fclose ($f); |
189 |
|
190 |
$this->LAST = $ReturnVar; |
191 |
|
192 |
// This is the part that actually does all the work. |
193 |
// The template and the parsed version are the same when caching |
194 |
$this->assign( array( $ReturnVar => $buf ) ); |
195 |
$this->$ReturnVar = $buf; |
196 |
$this->$FileTags = $buf; |
197 |
$this->LOADED[$FileTags] = "1"; // Make sure the template doesn't get loaded. |
198 |
|
199 |
// If we were supposed to be appending, maybe we should assume a dynamic block |
200 |
if ( (substr ($FileTags, 0, 1)) == '.' ) { |
201 |
$this->add_cache_dynamic ($ReturnVar, $buf); |
202 |
} |
203 |
|
204 |
return TRUE; |
205 |
} |
206 |
} |
207 |
|
208 |
|
209 |
return FALSE; |
210 |
} |
211 |
|
212 |
// ********************* |
213 |
// Function: write_cache |
214 |
// Input: RETURN, FileHandle (FIXME: Plural FileHandles are not supported.) |
215 |
// Return: true or false depending on whether a cache file could be created |
216 |
// Side Effects: None |
217 |
// |
218 |
// Notes: |
219 |
// Find the cache name. |
220 |
// Write out the ReturnVar contents to the file |
221 |
// Return |
222 |
function write_cache ( $ReturnVar, $FileTags ) { |
223 |
|
224 |
// FIXME: I should do something clever if $FileTags is an array. |
225 |
|
226 |
$str_cache_file = $this->cache_file_name ( $ReturnVar, $FileTags ); |
227 |
|
228 |
$new = $this->parse_template_messy ($this->$FileTags, $this->PARSEVARS); |
229 |
|
230 |
// Time to write the cache -- but we need to look out for lock files |
231 |
// FIXME: I'm SURE there is a race condition here. |
232 |
while (file_exists($str_cache_file . '.lock')) { |
233 |
sleep(2); |
234 |
clearstatcache(); |
235 |
continue; |
236 |
} |
237 |
clearstatcache(); |
238 |
|
239 |
// We pray that nothing bad happens after this point. |
240 |
touch ($str_cache_file . '.lock'); |
241 |
|
242 |
$f = fopen ($str_cache_file, "w"); |
243 |
if (!$f) |
244 |
return FALSE; |
245 |
|
246 |
fputs ($f, $new); |
247 |
fclose ($f); |
248 |
|
249 |
// And remove the lock file. |
250 |
$this->remove_cache_lock ($str_cache_file); |
251 |
|
252 |
return TRUE; |
253 |
|
254 |
} |
255 |
|
256 |
// ********************* |
257 |
// Function: cache_expire |
258 |
// Input: RETURN, number_of_seconds |
259 |
// Return: None |
260 |
// Side Effects: Stores time to expire |
261 |
// |
262 |
// Notes: |
263 |
// tells in how many seconds the cached data will expire |
264 |
|
265 |
function cache_expire ( $ReturnVar, $seconds = 3000) { |
266 |
$this->CACHE[$ReturnVar]["expire"] = $seconds; |
267 |
} |
268 |
|
269 |
// ********************* |
270 |
// Function: cache_refresh |
271 |
// Input: RETURN, frequency |
272 |
// Return: None |
273 |
// Side Effects: Stores time to refresh |
274 |
// |
275 |
// Notes: |
276 |
// sets an event (turn of day) at which cache will expire |
277 |
function cache_refresh ( $ReturnVar, $freq = 'HOUR') { |
278 |
$this->CACHE[$ReturnVar]["refresh"] = $freq; |
279 |
} |
280 |
|
281 |
// ************************************************************ |
282 |
// All templates will be loaded from this "root" directory |
283 |
// Can be changed in mid-process by re-calling with a new |
284 |
// value. |
285 |
|
286 |
function set_root ($root) { |
287 |
|
288 |
$trailer = substr($root,-1); |
289 |
|
290 |
if(!$this->WIN32) { |
291 |
|
292 |
if( (ord($trailer)) != 47 ) { |
293 |
$root = "$root". chr(47); |
294 |
} |
295 |
|
296 |
if(is_dir($root)) { |
297 |
$this->ROOT = $root; |
298 |
} else { |
299 |
$this->ROOT = ""; |
300 |
$this->error("Specified ROOT dir [$root] is not a directory"); |
301 |
} |
302 |
} else { |
303 |
// WIN32 box - no testing |
304 |
if( (ord($trailer)) != 92 ) { |
305 |
$root = "$root" . chr(92); |
306 |
} |
307 |
$this->ROOT = $root; |
308 |
} |
309 |
|
310 |
} // End set_root() |
311 |
|
312 |
|
313 |
// ************************************************************** |
314 |
// Calculates current microtime |
315 |
// I throw this into all my classes for benchmarking purposes |
316 |
// It's not used by anything in this class and can be removed |
317 |
// if you don't need it. |
318 |
|
319 |
|
320 |
function utime () { |
321 |
$time = explode( " ", microtime()); |
322 |
$usec = (double)$time[0]; |
323 |
$sec = (double)$time[1]; |
324 |
return $sec + $usec; |
325 |
} |
326 |
|
327 |
// ************************************************************** |
328 |
// Strict template checking, if true sends warnings to STDOUT when |
329 |
// parsing a template with undefined variable references |
330 |
// Used for tracking down bugs-n-such. Use no_strict() to disable. |
331 |
|
332 |
function strict () { |
333 |
$this->STRICT = true; |
334 |
} |
335 |
|
336 |
// ************************************************************ |
337 |
// Silently discards (removes) undefined variable references |
338 |
// found in templates |
339 |
|
340 |
function no_strict () { |
341 |
$this->STRICT = false; |
342 |
} |
343 |
|
344 |
// ************************************************************ |
345 |
// A quick check of the template file before reading it. |
346 |
// This is -not- a reliable check, mostly due to inconsistencies |
347 |
// in the way PHP determines if a file is readable. |
348 |
|
349 |
function is_safe ($filename) { |
350 |
if(!file_exists($filename)) { |
351 |
$this->error("[$filename] does not exist",0); |
352 |
return false; |
353 |
} |
354 |
return true; |
355 |
} |
356 |
|
357 |
// ************************************************************ |
358 |
// Grabs a template from the root dir and |
359 |
// reads it into a (potentially REALLY) big string |
360 |
|
361 |
function get_template ($template) { |
362 |
if(empty($this->ROOT)) { |
363 |
$this->error("Cannot open template. Root not valid.",1); |
364 |
return false; |
365 |
} |
366 |
|
367 |
$filename = "$this->ROOT"."$template"; |
368 |
|
369 |
$contents = implode("",(@file($filename))); |
370 |
if( (!$contents) or (empty($contents)) ) { |
371 |
$this->error("get_template() failure: [$filename] $php_errormsg",1); |
372 |
} |
373 |
|
374 |
return $contents; |
375 |
|
376 |
} // end get_template |
377 |
|
378 |
// ************************************************************ |
379 |
// Prints the warnings for unresolved variable references |
380 |
// in template files. Used if STRICT is true |
381 |
|
382 |
function show_unknowns ($Line) { |
383 |
$unknown = array(); |
384 |
if (ereg("({[A-Z0-9_]+})",$Line,$unknown)) { |
385 |
$UnkVar = $unknown[1]; |
386 |
if(!(empty($UnkVar))) { |
387 |
@error_log("[FastTemplate] Warning: no value found for variable: $UnkVar ",0); |
388 |
} |
389 |
} |
390 |
} // end show_unknowns() |
391 |
|
392 |
// ************************************************************ |
393 |
// This routine get's called by parse() and does the actual |
394 |
// {VAR} to VALUE conversion within the template. |
395 |
|
396 |
function parse_template ($template, $tpl_array) { |
397 |
$a = strtok($template,"{"); |
398 |
$oldtemp = $template; |
399 |
while($a || $t) { |
400 |
$t = strtok("}"); |
401 |
|
402 |
if($t){ |
403 |
settype($tpl_array[$t],"string"); |
404 |
//if(empty($tpl_array[$t])){ |
405 |
// print($t . '<BR>'); |
406 |
//} |
407 |
$toprint = $toprint . $a . $tpl_array[$t]; |
408 |
} else { |
409 |
$toprint = $toprint . $a; |
410 |
} |
411 |
//print('T-' . $t . '<BR>'); |
412 |
//print('value' . htmlentities($tpl_array[$t]) . '<BR>'); |
413 |
//print('A-' . htmlentities($a) . '<BR>'); |
414 |
$a = strtok("{"); |
415 |
|
416 |
} |
417 |
|
418 |
$template = $toprint; |
419 |
|
420 |
return $template; |
421 |
|
422 |
} // end parse_template(); |
423 |
|
424 |
function parse_template_messy ($template, $tpl_array) { |
425 |
$a = strtok($template,"{"); |
426 |
$oldtemp = $template; |
427 |
while($a || $t) { |
428 |
$t = strtok("}"); |
429 |
|
430 |
if($t){ |
431 |
settype($tpl_array[$t],"string"); |
432 |
|
433 |
if(empty($tpl_array[$t])){ |
434 |
$toprint = $toprint . $a . "{". $t . "}"; // Recreate the substitution. |
435 |
} else { |
436 |
$toprint = $toprint . $a . $tpl_array[$t]; |
437 |
} |
438 |
|
439 |
} else { |
440 |
$toprint = $toprint . $a; |
441 |
} |
442 |
//print('T-' . $t . '<BR>'); |
443 |
//print('value' . htmlentities($tpl_array[$t]) . '<BR>'); |
444 |
//print('A-' . htmlentities($a) . '<BR>'); |
445 |
$a = strtok("{"); |
446 |
|
447 |
} |
448 |
|
449 |
$template = $toprint; |
450 |
|
451 |
return $template; |
452 |
|
453 |
} // end parse_template(); |
454 |
|
455 |
// ************************************************************ |
456 |
// The meat of the whole class. The magic happens here. |
457 |
|
458 |
function parse ( $ReturnVar, $FileTags ) { |
459 |
$append = false; |
460 |
$this->LAST = $ReturnVar; |
461 |
$this->HANDLE[$ReturnVar] = 1; |
462 |
|
463 |
if (gettype($FileTags) == "array") { |
464 |
|
465 |
unset($this->$ReturnVar); // Clear any previous data |
466 |
|
467 |
while ( list ( $key , $val ) = each ( $FileTags ) ) { |
468 |
if ( (!isset($this->$val)) || (empty($this->$val)) ) { |
469 |
$this->LOADED["$val"] = 1; |
470 |
if(isset($this->DYNAMIC["$val"])) { |
471 |
$this->parse_dynamic($val,$ReturnVar); |
472 |
} else { |
473 |
$fileName = $this->FILELIST["$val"]; |
474 |
$this->$val = $this->get_template($fileName); |
475 |
|
476 |
} |
477 |
} |
478 |
|
479 |
// Array context implies overwrite |
480 |
|
481 |
$this->$ReturnVar = $this->parse_template($this->$val,$this->PARSEVARS); |
482 |
|
483 |
// For recursive calls. |
484 |
|
485 |
$this->assign( array( $ReturnVar => $this->$ReturnVar ) ); |
486 |
|
487 |
} |
488 |
} else { // end if FileTags is array() |
489 |
// FileTags is not an array |
490 |
|
491 |
$val = $FileTags; |
492 |
|
493 |
|
494 |
if( (substr($val,0,1)) == '.' ) { |
495 |
// Append this template to a previous ReturnVar |
496 |
|
497 |
$append = true; |
498 |
$val = substr($val,1); |
499 |
} |
500 |
|
501 |
if ( (!isset($this->$val)) || (empty($this->$val)) ) { |
502 |
$this->LOADED["$val"] = 1; |
503 |
if(isset($this->DYNAMIC["$val"])) { |
504 |
$this->parse_dynamic($val,$ReturnVar); |
505 |
} else { |
506 |
$fileName = $this->FILELIST["$val"]; |
507 |
$this->$val = $this->get_template($fileName); |
508 |
} |
509 |
} |
510 |
|
511 |
if($append) { |
512 |
$this->$ReturnVar .= $this->parse_template($this->$val,$this->PARSEVARS); |
513 |
} else { |
514 |
$this->$ReturnVar = $this->parse_template($this->$val,$this->PARSEVARS); |
515 |
} |
516 |
|
517 |
// For recursive calls. |
518 |
|
519 |
$this->assign(array( $ReturnVar => $this->$ReturnVar) ); |
520 |
|
521 |
} |
522 |
return; |
523 |
} // End parse() |
524 |
|
525 |
|
526 |
// ************************************************************ |
527 |
|
528 |
function FastPrint ( $template = "" ) { |
529 |
if(empty($template)) { |
530 |
$template = $this->LAST; |
531 |
} |
532 |
|
533 |
if( (!(isset($this->$template))) || (empty($this->$template)) ) { |
534 |
$this->error("Nothing parsed, nothing printed",0); |
535 |
return; |
536 |
} else { |
537 |
print $this->$template; |
538 |
} |
539 |
return; |
540 |
} |
541 |
|
542 |
// ************************************************************ |
543 |
|
544 |
|
545 |
function fetch ( $template = "" ) { |
546 |
if(empty($template)) { |
547 |
$template = $this->LAST; |
548 |
} |
549 |
if( (!(isset($this->$template))) || (empty($this->$template)) ) { |
550 |
$this->error("Nothing parsed, nothing printed",0); |
551 |
return ""; |
552 |
} |
553 |
|
554 |
return($this->$template); |
555 |
} |
556 |
|
557 |
|
558 |
// ************************************************************ |
559 |
|
560 |
function define_dynamic ($Macro, $ParentName) { |
561 |
// A dynamic block lives inside another template file. |
562 |
// It will be stripped from the template when parsed |
563 |
// and replaced with the {$Tag}. |
564 |
|
565 |
$this->DYNAMIC["$Macro"] = $ParentName; |
566 |
return true; |
567 |
} |
568 |
|
569 |
// ************************************************************ |
570 |
|
571 |
function parse_dynamic ($Macro,$MacroName) { |
572 |
// The file must already be in memory. |
573 |
|
574 |
$ParentTag = $this->DYNAMIC["$Macro"]; |
575 |
if( (!$this->$ParentTag) or (empty($this->$ParentTag)) ) { |
576 |
$fileName = $this->FILELIST[$ParentTag]; |
577 |
$this->$ParentTag = $this->get_template($fileName); |
578 |
$this->LOADED[$ParentTag] = 1; |
579 |
} |
580 |
if($this->$ParentTag) { |
581 |
$template = $this->$ParentTag; |
582 |
$DataArray = split("\n",$template); |
583 |
$newMacro = ""; |
584 |
$newParent = ""; |
585 |
$outside = true; |
586 |
$start = false; |
587 |
$end = false; |
588 |
while ( list ($lineNum,$lineData) = each ($DataArray) ) { |
589 |
$lineTest = trim($lineData); |
590 |
if("<!-- BEGIN DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
591 |
$start = true; |
592 |
$end = false; |
593 |
$outside = false; |
594 |
} |
595 |
if("<!-- END DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
596 |
$start = false; |
597 |
$end = true; |
598 |
$outside = true; |
599 |
} |
600 |
if( (!$outside) and (!$start) and (!$end) ) { |
601 |
$newMacro .= "$lineData\n"; // Restore linebreaks |
602 |
} |
603 |
if( ($outside) and (!$start) and (!$end) ) { |
604 |
$newParent .= "$lineData\n"; // Restore linebreaks |
605 |
} |
606 |
if($end) { |
607 |
// $newParent .= "{$MacroName}\n"; |
608 |
$newParent .= '{'."$MacroName}\n"; |
609 |
} |
610 |
// Next line please |
611 |
if($end) { $end = false; } |
612 |
if($start) { $start = false; } |
613 |
} // end While |
614 |
|
615 |
$this->$Macro = $newMacro; |
616 |
$this->$ParentTag = $newParent; |
617 |
return true; |
618 |
|
619 |
} else {// $ParentTag NOT loaded - MAJOR oopsie |
620 |
@error_log("ParentTag: [$ParentTag] not loaded!",0); |
621 |
$this->error("ParentTag: [$ParentTag] not loaded!",0); |
622 |
} |
623 |
return false; |
624 |
} |
625 |
|
626 |
// ************************************************************ |
627 |
// Strips a DYNAMIC BLOCK from a template. |
628 |
|
629 |
function clear_dynamic ($Macro="") { |
630 |
if(empty($Macro)) { return false; } |
631 |
|
632 |
// The file must already be in memory. |
633 |
|
634 |
$ParentTag = $this->DYNAMIC["$Macro"]; |
635 |
|
636 |
if( (!$this->$ParentTag) or (empty($this->$ParentTag)) ) { |
637 |
$fileName = $this->FILELIST[$ParentTag]; |
638 |
$this->$ParentTag = $this->get_template($fileName); |
639 |
$this->LOADED[$ParentTag] = 1; |
640 |
} |
641 |
|
642 |
if($this->$ParentTag) { |
643 |
$template = $this->$ParentTag; |
644 |
$DataArray = split("\n",$template); |
645 |
$newParent = ""; |
646 |
$outside = true; |
647 |
$start = false; |
648 |
$end = false; |
649 |
while ( list ($lineNum,$lineData) = each ($DataArray) ) { |
650 |
$lineTest = trim($lineData); |
651 |
if("<!-- BEGIN DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
652 |
$start = true; |
653 |
$end = false; |
654 |
$outside = false; |
655 |
} |
656 |
if("<!-- END DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
657 |
$start = false; |
658 |
$end = true; |
659 |
$outside = true; |
660 |
} |
661 |
if( ($outside) and (!$start) and (!$end) ) { |
662 |
$newParent .= "$lineData\n"; // Restore linebreaks |
663 |
} |
664 |
// Next line please |
665 |
if($end) { $end = false; } |
666 |
if($start) { $start = false; } |
667 |
} // end While |
668 |
|
669 |
$this->$ParentTag = $newParent; |
670 |
return true; |
671 |
|
672 |
} else {// $ParentTag NOT loaded - MAJOR oopsie |
673 |
@error_log("ParentTag: [$ParentTag] not loaded!",0); |
674 |
$this->error("ParentTag: [$ParentTag] not loaded!",0); |
675 |
} |
676 |
return false; |
677 |
} |
678 |
|
679 |
// ************************************************************ |
680 |
// Adds cached data to a DYNAMIC BLOCK from a template. |
681 |
|
682 |
function add_cache_dynamic ($Macro="", $cache_data="" ) { |
683 |
if(empty($Macro)) { return false; } |
684 |
|
685 |
// The file must already be in memory. |
686 |
|
687 |
$ParentTag = $this->DYNAMIC["$Macro"]; |
688 |
|
689 |
if( (!$this->$ParentTag) or (empty($this->$ParentTag)) ) { |
690 |
$fileName = $this->FILELIST[$ParentTag]; |
691 |
$this->$ParentTag = $this->get_template($fileName); |
692 |
$this->LOADED[$ParentTag] = 1; |
693 |
} |
694 |
|
695 |
if($this->$ParentTag) { |
696 |
$template = $this->$ParentTag; |
697 |
$DataArray = split("\n",$template); |
698 |
$newParent = ""; |
699 |
$outside = true; |
700 |
$start = false; |
701 |
$end = false; |
702 |
while ( list ($lineNum,$lineData) = each ($DataArray) ) { |
703 |
$lineTest = trim($lineData); |
704 |
if("<!-- BEGIN DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
705 |
$start = true; |
706 |
$end = false; |
707 |
$outside = false; |
708 |
} |
709 |
if("<!-- END DYNAMIC BLOCK: $Macro -->" == "$lineTest" ) { |
710 |
$start = false; |
711 |
$end = true; |
712 |
$outside = true; |
713 |
} |
714 |
if( ($outside) and (!$start) and (!$end) ) { |
715 |
$newParent .= "$lineData\n"; // Restore linebreaks |
716 |
} |
717 |
if ($end) { |
718 |
$newParent .= $cache_data; |
719 |
} |
720 |
// Next line please |
721 |
if($end) { $end = false; } |
722 |
if($start) { $start = false; } |
723 |
} // end While |
724 |
|
725 |
$this->$ParentTag = $newParent; |
726 |
return true; |
727 |
|
728 |
} else {// $ParentTag NOT loaded - MAJOR oopsie |
729 |
@error_log("ParentTag: [$ParentTag] not loaded!",0); |
730 |
$this->error("ParentTag: [$ParentTag] not loaded!",0); |
731 |
} |
732 |
return false; |
733 |
} |
734 |
|
735 |
|
736 |
// ************************************************************ |
737 |
|
738 |
function define ($fileList) { |
739 |
while ( list ($FileTag,$FileName) = each ($fileList) ) { |
740 |
$this->FILELIST["$FileTag"] = $FileName; |
741 |
} |
742 |
return true; |
743 |
} |
744 |
|
745 |
// ************************************************************ |
746 |
|
747 |
function clear_parse ( $ReturnVar = "") { |
748 |
$this->clear($ReturnVar); |
749 |
} |
750 |
|
751 |
// ************************************************************ |
752 |
|
753 |
function clear ( $ReturnVar = "" ) { |
754 |
// Clears out hash created by call to parse() |
755 |
|
756 |
if(!empty($ReturnVar)) { |
757 |
if( (gettype($ReturnVar)) != "array") { |
758 |
unset($this->$ReturnVar); |
759 |
return; |
760 |
} else { |
761 |
while ( list ($key,$val) = each ($ReturnVar) ) { |
762 |
unset($this->$val); |
763 |
} |
764 |
return; |
765 |
} |
766 |
} |
767 |
|
768 |
// Empty - clear all of them |
769 |
|
770 |
while ( list ( $key,$val) = each ($this->HANDLE) ) { |
771 |
$KEY = $key; |
772 |
unset($this->$KEY); |
773 |
} |
774 |
return; |
775 |
|
776 |
} // end clear() |
777 |
|
778 |
// ************************************************************ |
779 |
|
780 |
function clear_all () { |
781 |
$this->clear(); |
782 |
$this->clear_assign(); |
783 |
$this->clear_define(); |
784 |
$this->clear_tpl(); |
785 |
|
786 |
return; |
787 |
|
788 |
} // end clear_all |
789 |
|
790 |
// ************************************************************ |
791 |
|
792 |
function clear_tpl ($fileHandle = "") { |
793 |
if(empty($this->LOADED)) { |
794 |
// Nothing loaded, nothing to clear |
795 |
|
796 |
return true; |
797 |
} |
798 |
if(empty($fileHandle)) { |
799 |
// Clear ALL fileHandles |
800 |
|
801 |
while ( list ($key, $val) = each ($this->LOADED) ) { |
802 |
unset($this->$key); |
803 |
} |
804 |
unset($this->LOADED); |
805 |
|
806 |
return true; |
807 |
} else { |
808 |
if( (gettype($fileHandle)) != "array") { |
809 |
if( (isset($this->$fileHandle)) || (!empty($this->$fileHandle)) ) { |
810 |
unset($this->LOADED[$fileHandle]); |
811 |
unset($this->$fileHandle); |
812 |
return true; |
813 |
} |
814 |
} else { |
815 |
while ( list ($Key, $Val) = each ($fileHandle) ) { |
816 |
unset($this->LOADED[$Key]); |
817 |
unset($this->$Key); |
818 |
} |
819 |
return true; |
820 |
} |
821 |
} |
822 |
|
823 |
return false; |
824 |
|
825 |
} // end clear_tpl |
826 |
|
827 |
// ************************************************************ |
828 |
|
829 |
function clear_define ( $FileTag = "" ){ |
830 |
if(empty($FileTag)) { |
831 |
unset($this->FILELIST); |
832 |
return; |
833 |
} |
834 |
|
835 |
if( (gettype($Files)) != "array") { |
836 |
unset($this->FILELIST[$FileTag]); |
837 |
return; |
838 |
} else { |
839 |
while ( list ( $Tag, $Val) = each ($FileTag) ) { |
840 |
unset($this->FILELIST[$Tag]); |
841 |
} |
842 |
return; |
843 |
} |
844 |
} |
845 |
|
846 |
// ************************************************************ |
847 |
// Aliased function - used for compatibility with CGI::FastTemplate |
848 |
function clear_parse () { |
849 |
$this->clear_assign(); |
850 |
} |
851 |
|
852 |
// ************************************************************ |
853 |
// Clears all variables set by assign() |
854 |
|
855 |
function clear_assign () { |
856 |
if(!(empty($this->PARSEVARS))) { |
857 |
while(list($Ref,$Val) = each ($this->PARSEVARS) ) { |
858 |
unset($this->PARSEVARS["$Ref"]); |
859 |
} |
860 |
} |
861 |
} |
862 |
|
863 |
// ************************************************************ |
864 |
|
865 |
function clear_href ($href) { |
866 |
if(!empty($href)) { |
867 |
if( (gettype($href)) != "array") { |
868 |
unset($this->PARSEVARS[$href]); |
869 |
return; |
870 |
} else { |
871 |
while (list ($Ref,$val) = each ($href) ) { |
872 |
unset($this->PARSEVARS[$Ref]); |
873 |
} |
874 |
return; |
875 |
} |
876 |
} else { |
877 |
// Empty - clear them all |
878 |
|
879 |
$this->clear_assign(); |
880 |
} |
881 |
return; |
882 |
} |
883 |
|
884 |
// ************************************************************ |
885 |
|
886 |
function assign ($tpl_array, $trailer="") { |
887 |
if(gettype($tpl_array) == "array") { |
888 |
while ( list ($key,$val) = each ($tpl_array) ) { |
889 |
if (!(empty($key))) { |
890 |
// Empty values are allowed |
891 |
// Empty Keys are NOT |
892 |
|
893 |
$this->PARSEVARS["$key"] = $val; |
894 |
} |
895 |
} |
896 |
|
897 |
|
898 |
//if(empty($this->PARSEVARS)){ |
899 |
//$this->PARSEVARS = $tpl_array; |
900 |
//}else{ |
901 |
//$this->PARSEVARS = $this->PARSEVARS + $tpl_array; |
902 |
//} |
903 |
|
904 |
} else { |
905 |
// Empty values are allowed in non-array context now. |
906 |
if (!empty($tpl_array)) { |
907 |
$this->PARSEVARS["$tpl_array"] = $trailer; |
908 |
} |
909 |
} |
910 |
} |
911 |
|
912 |
// ************************************************************ |
913 |
// Return the value of an assigned variable. |
914 |
// Christian Brandel cbrandel@gmx.de |
915 |
|
916 |
function get_assigned($tpl_name = "") { |
917 |
if(empty($tpl_name)) { return false; } |
918 |
if(isset($this->PARSEVARS["$tpl_name"])) { |
919 |
return ($this->PARSEVARS["$tpl_name"]); |
920 |
} else { |
921 |
return false; |
922 |
} |
923 |
} |
924 |
|
925 |
// ************************************************************ |
926 |
|
927 |
function error ($errorMsg, $die = 0) { |
928 |
$this->ERROR = $errorMsg; |
929 |
echo "ERROR: $this->ERROR <BR> \n"; |
930 |
if ($die == 1) { |
931 |
exit; |
932 |
} |
933 |
|
934 |
return; |
935 |
|
936 |
} // end error() |
937 |
|
938 |
|
939 |
// ************************************************************ |
940 |
|
941 |
|
942 |
|
943 |
// ************************************************************ |
944 |
// Caching system |
945 |
|
946 |
//*********************************/ |
947 |
// Some other functions |
948 |
function remove_cache_lock($str_cache_file) { |
949 |
clearstatcache(); |
950 |
if (file_exists($str_cache_file . '.lock')) { |
951 |
@unlink($str_cache_file . '.lock'); |
952 |
} |
953 |
} |
954 |
|
955 |
// Create the cache file name |
956 |
function cache_file_name ( $ReturnVar, $FileTags ) { |
957 |
|
958 |
// What are we going to do? |
959 |
$str_cache_root = "/tmp/"; |
960 |
$str_cache_dir = strtolower(getenv ("HTTP_HOST")) . getenv ("SCRIPT_URL"); |
961 |
if ( (substr ($FileTags, 0, 1)) == '.' ) { |
962 |
$str_cache_file = "/" . substr($FileTags,1); |
963 |
} else { |
964 |
$str_cache_file = "/" . $FileTags; |
965 |
} |
966 |
|
967 |
// First we need to make the directory the cache file is in if it doesn't already exist. |
968 |
if ($this->rmkdir ($str_cache_root . $str_cache_dir)) |
969 |
return $str_cache_root . $str_cache_dir . $str_cache_file; |
970 |
|
971 |
return; |
972 |
} |
973 |
|
974 |
// Create a directory tree |
975 |
function rmkdir ( $directory ) { |
976 |
|
977 |
// If we encounter this as a file, we can't make it a directory |
978 |
$type = filetype ( $directory ); |
979 |
if ($type != 'dir' && $type != 'FALSE' && !empty($type)) { |
980 |
return FALSE; |
981 |
} |
982 |
if ($type == 'dir') |
983 |
return TRUE; |
984 |
|
985 |
$pieces = explode ("/", $directory); |
986 |
|
987 |
for ($num = 0; $num < count($pieces); $num += 1) { |
988 |
$so_far = $so_far . "/" . $pieces[$num]; |
989 |
|
990 |
$type = filetype ( $so_far ); |
991 |
if ($type != 'dir' && $type != 'FALSE' && !empty($type)) { |
992 |
return FALSE; |
993 |
} |
994 |
|
995 |
if ($type == 'dir') { |
996 |
continue; |
997 |
} |
998 |
|
999 |
if (!mkdir ($so_far, 0700)) { |
1000 |
return FALSE; |
1001 |
} |
1002 |
} |
1003 |
|
1004 |
return TRUE; |
1005 |
|
1006 |
} |
1007 |
|
1008 |
//*********************************/ |
1009 |
// CACHE REFRESH CHECKING FUNCTIONS |
1010 |
// Each function checks the next interval higher for verification |
1011 |
|
1012 |
function checkRefreshYear($systime, $filetime) { |
1013 |
$sysYear = date( "y", $systime); |
1014 |
$fileYear = date( "y", $filetime); |
1015 |
if ($sysYear != $fileYear) { return false; } |
1016 |
return true; |
1017 |
} |
1018 |
|
1019 |
function checkRefreshMonth($systime, $filetime) { |
1020 |
$sysMonth = date( "M", $systime); |
1021 |
$fileMonth = date( "M", $filetime); |
1022 |
if ($sysMonth != $fileMonth) { return false; } |
1023 |
if (!(checkRefreshYear($systime, $filetime))) { return false; } |
1024 |
return true; |
1025 |
} |
1026 |
|
1027 |
function checkRefreshDay($systime, $filetime) { |
1028 |
$sysDay = date( "j", $systime); |
1029 |
$fileDay = date( "j", $filetime); |
1030 |
if ($sysDay != $fileDay) { return false; } |
1031 |
if (!(checkRefreshMonth($systime, $filetime))) { return false; } |
1032 |
return true; |
1033 |
} |
1034 |
|
1035 |
function checkRefreshDayHalf($systime, $filetime) { |
1036 |
$sysHour = date( "H", $systime); |
1037 |
$fileHour = date( "H", $filetime); |
1038 |
if (($sysHour % 12) < ($fileHour % 12)) { return false; } |
1039 |
if (!(checkRefreshDay($systime, $filetime))) { return false; } |
1040 |
return true; |
1041 |
} |
1042 |
|
1043 |
function checkRefreshHour($systime, $filetime) { |
1044 |
$sysHour = date( "H", $systime); |
1045 |
$fileHour = date( "H", $filetime); |
1046 |
if ($sysHour != $fileHour) { return false; } |
1047 |
if (!(checkRefreshDayHalf($systime, $filetime))) { return false; } |
1048 |
return true; |
1049 |
} |
1050 |
|
1051 |
function checkRefreshHalfHour($systime, $filetime) { |
1052 |
$sysMin = date( "i", $systime); |
1053 |
$fileMin = date( "i", $filetime); |
1054 |
if (($sysMin % 30) < ($fileMin % 30)) { return false; } |
1055 |
if (!(checkRefreshHour($systime, $filetime))) { return false; } |
1056 |
return true; |
1057 |
} |
1058 |
|
1059 |
function checkRefreshQuarterHour($systime, $filetime) { |
1060 |
$sysMin = date( "i", $systime); |
1061 |
$fileMin = date( "i", $filetime); |
1062 |
if (($sysMin % 15) < ($fileMin % 15)) { return false; } |
1063 |
if (!(checkRefreshHalfHour($systime, $filetime))) { return false; } |
1064 |
return true; |
1065 |
} |
1066 |
|
1067 |
function checkRefreshMinute($systime, $filetime) { |
1068 |
$sysMin = date( "i", $systime); |
1069 |
$fileMin = date( "i", $filetime); |
1070 |
if ($sysMin != $fileMin) { return false; } |
1071 |
if (!(checkRefreshQuarterHour($systime, $filetime))) { return false; } |
1072 |
return true; |
1073 |
} |
1074 |
|
1075 |
|
1076 |
|
1077 |
} // End class.FastTemplate |
1078 |
|
1079 |
?> |