Overview

Namespaces

  • None
  • opensourceame

Classes

  • form_state
  • sql_query
  • sql_query_builder
  • stash_bean
  • stash_collection
  • stash_framework
  • stash_mysql
  • stash_mysql_collection
  • stash_mysql_framework
  • XTemplate
  • ztemplate

Functions

  • get_arguments
  • get_form_state
  • print_help
  • print_version
  • processTime
  • register_form_state
  • unregister_form_state
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * zTemplate
  4:  * 
  5:  * This is a class which emulates XTemplate (http://www.phpxtemplate.org)
  6:  * All methods work exactly as they do with XTemplate, however this template engine performs far better
  7:  * 
  8:  * http://opensourceame.com
  9:  * 
 10:  * @package         opensourceame
 11:  * @author          David Kelly
 12:  * @copyright       David Kelly 2007
 13:  * @description     zTemplate is a high performance replacement for xTemplate
 14:  * @version         1.1.8
 15:  * 
 16:  * distributed under the GPL 2.0, licensing info at http://www.gnu.org/licenses/gpl-2.0.html
 17:  */
 18: 
 19: if(! class_exists("xtemplate"))
 20: {
 21:     // extend the ztemplate class with some backwards compatible functions for xtemplate
 22:     //
 23:     // note that at 2 dec 2005 these are the only functions used by sugar
 24:     // determined by matching /xtpl->.*(/U in all source pages
 25:     
 26:     class xtemplate extends ztemplate
 27:     {
 28:         function __construct($file, $alt_include = null, $mainblock='main')
 29:         {
 30:             $this->mainblock = $mainblock;
 31:             
 32:             parent::__construct($file);
 33:         }
 34:         
 35:         function var_exists($block, $var)
 36:         {
 37:             return isset($this->parselines->vbindex[$var]);
 38:         }
 39: 
 40:         function exists($block)
 41:         {
 42:             return (! empty($this->parsed[$block])) || (! empty($this->blocks[$block]));
 43:         }
 44:         
 45:     
 46:         function append ($varname, $name, $val = null)
 47:         {
 48:             $this->assign($varname.'.'.$name, $val);
 49:         }
 50: 
 51:     }
 52: }
 53: 
 54: /**
 55:  * zTemplate class
 56:  */
 57: class ztemplate
 58: {
 59:     const       version         = '1.1.8';          // the version of this class
 60:     
 61:     private     $template       = true;
 62:     private     $cachedblocks   = array();          // an array of cached blocks
 63:     private     $blocks         = array();          // an array of blocks
 64:     private     $parsed         = array();          // an array of parsed blocks
 65:     
 66:     protected   $stblocks       = array();
 67:     
 68:     /**
 69:      * Class constructor
 70:      * 
 71:      * @param   string      $file       the filename to open and parse
 72:      * @param   array       $options    an array of config options
 73:      * @return  boolean                 true on successul load and parse of the template, otherwise false
 74:      */
 75:     public  function __construct($file = null, $options = null)
 76:     {
 77:         // block delimeters kept in an object
 78:         $this->delim                    = new stdClass;
 79:         $this->delim->block             = new stdClass;
 80:         $this->delim->start             = '<!--';
 81:         $this->delim->end               = '-->';
 82:         $this->delim->block->start      = 'BEGIN:';
 83:         $this->delim->block->end        = 'END:';
 84: 
 85:         $this->_parse_options           = new stdClass;
 86:         $this->_parse_options->line_end = "\n";
 87:         
 88:         $this->count                    = new stdClass;
 89:         $this->count->parsefile         = false;
 90:         $this->block_order              = array();
 91:         
 92:         $this->options                  = new stdClass;
 93:         $this->options->condensed       = false;
 94:         $this->options->debug           = false;
 95:         $this->options->cache           = false;
 96:         $this->options->strict          = false;
 97: 
 98:         $this->parselines               = new stdClass;
 99:         $this->parselines->subtemplates = array();
100:         
101:         $this->log                      = new stdClass;
102:         $this->log->errors              = array();
103:         $this->log->debug               = array();
104:         
105:         if(! empty($options))
106:             $this->set_option($options);
107:         
108:         if($file != null)
109:         {
110:             return $this->parse_template_file($file);
111:         }
112: 
113:         return true;
114:     }
115: 
116:     /**
117:      * used to to manually load a template if one is not specified when constructing
118:      */
119:     public  function load_template($file)
120:     {
121:         $this->parse_template_file($file);
122:     }
123: 
124:     /**
125:      * Set an option
126:      */
127:     public  function set_option($opt, $val = null)
128:     {
129:         if( is_array($opt) or is_object($opt))
130:             foreach($opt as $key=>$val)
131:                 $this->set_option($key, $val);
132:                 
133:         switch($opt)
134:         {
135:             // condense by stripping out unnecessary whitespace
136:             case "condensed":
137:                 $this->_parse_options->line_end = null;
138:                 $this->options->condensed = true;
139:                 break;
140:             
141:             // cache parsed results
142:             case "cache":
143:                 $this->options->cache = true;
144:                 break;
145:             
146:             // add debugging
147:             case "debug":
148:                 $this->options->debug = true;
149:                 $this->debug = array();
150:                 break;
151: 
152:             // break on any error (e.g. reference to an unassigned template var)
153:             case "strict":
154:                 $this->options->strict = true;
155:                 break;
156:         }
157:         
158:         return true;
159:         
160:     }
161:     
162:     /**
163:      * @return array a list of errors that have occurred
164:      */
165:     public  function    errors()
166:     {
167:         return $this->log->errors;
168:     }
169:     
170:     /**
171:      * log an error
172:      */
173:     private function add_error($message)
174:     {
175:         $this->log->errors[] = $message;
176:     }
177:     
178:     /**
179:      * clear a cached block
180:      */
181:     private function clear_cache($block)
182:     {
183:         $this->add_debug("clear cache called for $block");
184:         
185:         // recursively clear blocks         
186:         // remove any preparsed block this will affect
187:         if( isset($this->cachedblocks[$block]))
188:         {
189:             {
190:                 $this->add_debug("delete cache block $block");
191:                 unset($this->cachedblocks[$block]);
192:                 
193:                 while( isset($this->cachedblocks[$this->parents[$block]]))
194:                 {
195:                     $this->add_debug("delete cache block $block parent {$this->parents[$block]}");
196:                     unset($this->cachedblocks[$this->parents[$block]]);
197:                     $block = $this->parents[$block];
198:                 }
199:             }
200:         } else {
201:             // return false if no blocks to delete
202:             return false;
203:         }
204:         
205:         
206:     }
207:     
208:     /**
209:      * assign a variable
210:      */
211:     public  function assign($var, $val)
212:     {
213:         
214:         if(is_array($val) or is_object($val))
215:         {
216:             foreach($val as $k=>$v)
217:                 $this->assign("$var.$k", $v);
218:                 
219:             return true;
220:         }
221:         
222: 
223:         if( ($this->options->strict) and ! in_array($var, $this->parselines->vars))
224:         {
225:             $this->add_error("tried to assign non-existent var $var");
226:             return false;
227:         }
228:         
229:         // assign the var       
230:         settype($val, 'string');                // force string to fix problems with 0 values interpreted as null
231:         $this->vars[$var] = $val;
232: 
233:         // recursively delete cached blocks if we are doing caching     
234:         if($this->options->cache)
235:         {
236:             foreach($this->parselines->vbindex[$var] as $block)
237:                 $this->clear_cache($block);
238:         }
239: 
240:         return true;
241:     }
242:     
243:     /**
244:      * assign a file that can be included into the current template
245:      */
246:     public  function assign_file($var, $file)
247:     {
248:         $this->parse_template_file($file, $this->stblocks[$var]);
249:         $this->filevars[$var] = $file;
250:     }
251: 
252:     /**
253:      * output a block, optionally to a file
254:      * 
255:      * @param       string      $blockname      name of the block to output
256:      * @param       string      $file           optional filename to write output to
257:      */
258:     public  function out($blockname = null, $file = null)
259:     {
260:         if( isset($this->parsed[$blockname]))
261:         {
262:             if($file == null)
263:             {
264:                 echo($this->parsed[$blockname]);
265:                 return true;
266:             } else {
267:                 $fh = fopen($file, 'w');
268:                 
269:                 if($fh === false)
270:                 {
271:                     $this->add_error("could not write $blockname to $file");
272:                     return false;
273:                 }
274:                     
275:                 fwrite($fh, $this->parsed[$blockname]);
276:                 //fclose($fh);
277:                 
278:                 return true;
279:             }
280:         } else {
281:             $this->add_error("tried to output unparsed block $blockname");
282:         }
283:         
284:         return false;
285:     }
286:     
287:     /**
288:      * get a parsed block
289:      * 
290:      * @param string $blockname the name of the block to return
291:      */
292:     public  function get($blockname = null)
293:     {
294:         return($this->parsed[$blockname]);
295:     }
296: 
297:     /**
298:      * print errors inside preformatted tags
299:      */
300:     public  function print_errors()
301:     {
302:         if(! is_array($this->log->errors))
303:             return false;
304:         
305:         echo '<pre>';
306:         foreach($this->log->errors as $line)
307:         {
308:             print($line."\n");
309:         }
310:         echo "</pre>";
311:     }
312:     
313:     /**
314:      * log a debugging message
315:      */
316:     private function add_debug($message)
317:     {
318:         if($this->options->debug)
319:             $this->log->debug[] = $message;
320:     }
321:     
322:     /**
323:      * parse a block
324:      * 
325:      * @param       string      $blockname      name of the block to parse
326:      * @return      boolean
327:      */
328:     public  function parse($blockname)
329:     {
330:         if(! is_string($blockname))
331:         {
332:             print_r($blockname);
333:             exit;
334:         }
335:         
336:         // parse blocks
337:         if(! isset($this->parsed[$blockname]))
338:             $this->parsed[$blockname] = null;
339:             
340:         if( isset($this->cachedblocks[$blockname]))
341:         {
342:             // cached block exists, use it
343:             $this->parsed[$blockname] .= $this->cachedblocks[$blockname];
344:             $this->add_debug("using cached $blockname");
345:             return true;
346:         }
347:         
348:         if( empty($this->blocks[$blockname]))
349:         {
350:             $this->add_error("could not parse missing block $blockname");
351:             return false;
352:         }
353:             
354:         foreach($this->blocks[$blockname] as $key=>$line)
355:         {
356:             $append = $this->_parse_options->line_end;
357:             
358:             if( isset($this->parselines->subtemplates[$key]))
359:             {
360:                 $v =& $this->parselines->subtemplates[$key];
361:                 if( isset($this->filevars[$v]))
362:                 {
363:                     $this->reset($this->filevars[$v]);
364:                     $this->parse($this->filevars[$v]);
365:                     $this->parsed[$blockname] .= $this->parsed[$this->filevars[$v]];                
366:                 } else {
367:                     $this->add_error("missing included template $v while parsing block $blockname");
368:                 }
369: 
370:                 $line = null;
371: 
372:             }
373:             
374:             if( isset($this->parselines->vars[$key + 1]))
375:                 $append = null;
376: 
377:             if( isset($this->parselines->vars[$key]))
378:             {
379:                 if( isset($this->vars[$this->parselines->vars[$key]]))
380:                 {
381:                     $line = $this->vars[$this->parselines->vars[$key]]; 
382:                     $append = null;
383:                 } else {
384:                     $line = null;
385:                     $append = null;
386:                     $this->add_debug("missing var {$this->parselines->vars[$key]} while parsing block {$blockname}");
387:                 }   
388:             }
389:             
390:             if( isset($this->parselines->blocks[$key]))
391:             {
392:                 if( isset($this->parsed[$this->parselines->blocks[$key]]))
393:                 {
394:                     $this->parsed[$blockname] .= $this->parsed[$this->parselines->blocks[$key]];
395:                     unset($this->parsed[$this->parselines->blocks[$key]]);
396:                 } else {
397:                     //$this->add_error("no block parsed $match[1]");
398:                 }   
399:                 $line = null;
400:             }
401:             
402:             if($line != null)
403:                 $this->parsed[$blockname] .= $line . $append;
404:         }
405:         
406:         if($this->options->cache)
407:         {
408:             $this->cachedblocks[$blockname] = $this->parsed[$blockname];
409:             $this->add_debug("cache block $blockname");
410:         }
411:         
412:         $this->add_debug("parsed block $blockname");
413:         
414:         return true;
415:     }
416: 
417:     /**
418:      * Reset a block
419:      * 
420:      * @param       string      $block      name of the block
421:      * @return      boolean
422:      */
423:     public  function reset ($block)
424:     {
425:         if(! isset($this->parsed[$block]))
426:             return false;
427:             
428:         $this->parsed[$block] = null;
429:         
430:         return true;
431:     }
432:     
433:     /**
434:      * Check if a variable has been set
435:      *
436:      * @param       string      $var            variable name
437:      * @return      boolean
438:      */
439:     public  function var_is_set($var)
440:     {
441:         return ! empty($this->vars[$var]);
442:     }
443:     
444:     /**
445:      *  Get variables from lines in each block
446:      */
447:     private function parser_get_vars()
448:     {
449:         foreach(array_keys($this->blocks) as $blockname)
450:             if(is_array($this->blocks[$blockname]))
451:                 foreach($this->blocks[$blockname] as $count=>$line)
452:                 {
453:                     do
454:                     {
455:                         $reparse = false;
456:                         
457:                         if(preg_match("/^(.*)\{([\w_\.]*)\}(.*)$/U", $line, $match))
458:                         {
459:                             // found a var, get busy
460:                             $this->blocks[$blockname][$count] = $match[1];              // replace the line with the left side match
461:                             $this->blocks[$blockname][++$count] = $match[2];            // new line with the var name
462:     
463:                             $this->parselines->vars[$count] = $match[2];                // keep track of var position
464:                             $this->parselines->vbindex[$match[2]][$blockname] = $blockname;         // variable block index
465:                             $line = $match[3];
466:     
467:                             $reparse = true;
468:                             $count++;
469:     
470:                         } else {
471:                             $this->blocks[$blockname][$count] = $line;
472:                         }
473:                         
474:                     } while($reparse);
475:                     
476:                     ksort($this->blocks[$blockname]);
477:                 }
478:     }
479:     
480:     /**
481:      * Add a line to the parsed block
482:      * 
483:      * @param       string      $block      the block name
484:      * @param       string      $line       the line of text to add
485:      * @return      boolean
486:      */
487:     private function parse_add_line($block, $line)
488:     {
489:         if(empty($line))
490:             return false;
491:         
492:         if($this->options->condensed)
493:         {
494:             $line=preg_replace("/^\s*/", null, $line);
495:             $line=preg_replace("/\s*$/", null, $line);
496:         }
497: 
498:         $this->count->parsefile += 100;
499:         
500:         $this->blocks[$block][$this->count->parsefile] = $line;
501:         
502:         return true;
503:     }
504:     
505:     /**
506:      * Parse a template
507:      * 
508:      * @param       string      $file       filename to open and parse
509:      * @param       string      $bp         the block path (e.g. main.block1.block2)
510:      * @return      boolean
511:      */
512:     private function parse_template_file($file, $bp = null)
513:     {
514:     
515:         if(! is_readable($file))
516:         {
517:             $this->add_error("could not read $file to parse it");
518:             return false;
519:         }
520:         
521:         if(filesize($file) == 0)
522:         {
523:             $this->add_error("file has zero size");
524:             return false;
525:         }
526:         
527:         // init vars
528:         $blockpath = null;
529:         
530:         // read the file
531:         $handle = fopen($file, "r");
532:         
533:         if($handle == false)
534:         {
535:             die("couldn't open $file");
536:         }
537:         
538:         $this->contents[$file] = explode("\n", fread($handle, filesize($file)));
539:         fclose($handle);
540:         
541:         // break file into blocks
542:         foreach($this->contents[$file] as $line)
543:         {
544:             do
545:             {
546:                 $blockprefix = $bp;
547:                 if( ($blockpath != null) and ($bp != null))
548:                     $blockprefix = "{$blockprefix}.";
549:     
550:                 $reparse = false;
551: 
552:                 if(preg_match("/(.*)\{FILE {(.*)\}\}(.*)$/U", $line, $match))
553:                 {
554:                     if($blockpath == null)
555:                     {
556:                         $this->parse_add_line($file, $match[1]);
557:                         $this->parse_add_line($file, "%$match[2]%");
558:                         
559:                     } else {
560:                         
561:                         $this->parse_add_line($blockprefix.$blockpath, $match[1]);
562:                         $this->parse_add_line($blockprefix.$blockpath, "%$match[2]%");
563:                     }
564:                     
565:                     $this->parselines->subtemplates[$this->count->parsefile] = $match[2];
566: 
567:                     $this->stblocks[$match[2]] = $blockprefix.$blockpath;
568:                     
569:                     $line = $match[3];
570:                     
571:                     $reparse = true;
572:                 }
573: 
574:                 // start a block                        
575:                 if(preg_match("/^(.*)".$this->delim->start." ".$this->delim->block->start." (.*) ".$this->delim->end."(.*)$/U", $line, $match))
576:                 {
577:                     if($blockpath == null)
578:                     {
579:                         $this->parse_add_line($file, $match[1]);
580:                         $this->parse_add_line($file, "@{$blockprefix}{$blockpath}.$match[2]@");
581:                     } else {
582:                         $this->parse_add_line($blockprefix.$blockpath, $match[1]);
583:                         $this->parse_add_line($blockprefix.$blockpath, "@{$blockprefix}{$blockpath}.$match[2]@");
584:                     }
585:                     
586:                     if($blockpath != null)
587:                     {
588:                         $this->parents["{$blockpath}.{$match[2]}"] = $blockprefix.$blockpath;
589:                         $blockpath .= ".";
590:                     }
591:                     $blockpath .= $match[2];
592: 
593:                     $blockprefix = $bp;
594:                     if( ($blockpath != null) and ($bp != null))
595:                         $blockprefix = "{$blockprefix}.";
596: 
597:                     $this->parselines->blocks[$this->count->parsefile] = $blockprefix.$blockpath;
598:                     $this->parselines->bindex[$blockprefix.$blockpath] = $this->count->parsefile;
599:                     
600:                     array_unshift($this->block_order, $blockprefix.$blockpath);
601:                     $line = $match[3];
602: 
603:                     $reparse = true;
604:                 }
605: 
606:                 // match a block end    
607:                 if(preg_match("/^(.*)".$this->delim->start." ".$this->delim->block->end." (.*) ".$this->delim->end."(.*)$/U", $line, $match))
608:                 {
609:                     if(preg_match("/$match[2]$/", $blockpath))
610:                     {
611:                         if($blockpath == null)                      
612:                             $this->parse_add_line($file, $match[1]);
613:                         else
614:                             $this->parse_add_line($blockprefix.$blockpath, $match[1]);
615:                         
616:                         $blockpath = substr($blockpath, 0, -(strlen($match[2]))-1);
617:                         
618:                         $line = $match[3];
619:                     } else {
620:                         $this->add_error("tried to end block $match[2] within {$blockprefix}{$blockpath}");
621:                         $this->print_errors();
622:                         die;
623:                     }
624:                     $reparse = true;
625:                 }
626:             
627:             } while($reparse);
628: 
629:             if($blockpath == null)  
630:                 $this->parse_add_line($file, $line);                
631:             else
632:                 $this->parse_add_line($blockprefix.$blockpath, $line);
633:         }
634: 
635:         // add file block to block order list
636:         $this->block_order[]= $file;            
637:             
638:         // now get the variables
639:         $this->parser_get_vars();
640:         
641:         // free up some ram if not debugging
642:         if($this->options->debug)
643:             unset($this->contents[$file]);
644:     }
645: 
646:     /**
647:      * Return the text of a block
648:      * 
649:      * @param       string      $blockname          name of the block
650:      * @return      string
651:      */
652:     public  function text($blockname)
653:     {
654:         return $this->parsed[ isset($blockname) ? $blockname : $this->mainblock ];
655:     }
656: 
657: }
658: 
659: 
OpenSourceAme API Documentation API documentation generated by ApiGen.
Generated using the TokenReflection library.