]>
git.p6c8.net - form-email.git/blob - form-email/class.Template.php
4 # Template (Version 2.5)
6 # Klasse zum Parsen von Templates
8 # Autor: Patrick Canterino <patrick@patshaping.de>
9 # Letzte Aenderung: 25.11.2011
11 # Copyright (C) 2002-2011 Patrick Canterino
13 # Diese Datei kann unter den Bedingungen der "Artistic License 2.0"
14 # weitergegeben und / oder veraendert werden.
16 # http://www.opensource.org/licenses/artistic-license-2.0
25 var $defined_vars = array();
26 var $loop_vars = array();
30 # Kompletten Vorlagentext zurueckgeben
34 # Rueckgabe: Kompletter Vorlagentext (String)
36 function get_template() {
37 return $this->template
;
42 # Kompletten Vorlagentext aendern
44 # Parameter: Vorlagentext
46 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
48 function set_template($text) {
49 $this->template
= $text;
54 # Vorlagentext ans Template-Objekt anhaengen
56 # Parameter: Vorlagentext
58 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
60 function add_text($text) {
61 $this->set_template($this->get_template().$text);
66 # Einlesen einer Vorlagendatei und {INCLUDE}-Anweisungen ggf. verarbeiten
67 # (Text wird an bereits vorhandenen Text angehaengt)
69 # Parameter: 1. Datei zum Einlesen
70 # 2. Status-Code (Boolean):
71 # true => {INCLUDE}-Anweisungen nicht verarbeiten
72 # false => {INCLUDE}-Anweisungen verarbeiten (Standard)
74 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
76 function read_file($file,$not_include=0) {
79 if(filesize($file) > 0) {
80 $fp = fopen($file,'r');
82 $content = fread($fp,filesize($file));
87 $this->add_text($content);
90 if(!$not_include) $this->parse_includes();
95 # Wert einer Variable setzen
97 # Parameter: 1. Name der Variable
98 # 2. Wert, den die Variable erhalten soll
100 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
102 function set_var($var,$content) {
103 $this->vars
[$var] = $content;
108 # Wert einer Variable zurueckgeben
110 # Parameter: (optional) Variablenname
112 # Rueckgabe: Wert der Variable;
113 # wenn die Variable nicht existiert, false;
114 # wenn kein Variablenname angegeben wurde, wird ein
115 # Array mit den Variablennamen zurueckgegeben
117 function get_var($var=false) {
119 if(isset($this->vars
[$var])) {
120 return $this->vars
[$var];
127 return array_keys($this->vars
);
133 # Komplettes Variablen-Array mit einem anderen Array ueberschreiben
137 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
139 function set_vars($vars) {
145 # Zum bestehenden Variablen-Array weitere Variablen in Form eines Arrays
150 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
152 function add_vars($vars) {
153 $this->vars
= array_merge($this->vars
,$vars);
158 # Daten fuer eine Schleife setzen
160 # Parameter: 1. Name der Schleife
161 # 2. Array mit den Arrays mit den Variablen fuer
162 # die Schleifendurchgaenge
164 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
166 function set_loop_data($loop,$data) {
167 $this->loop_vars
[$loop] = $data;
172 # Daten fuer einen Schleifendurchgang hinzufuegen
174 # Parameter: 1. Name der Schleife
175 # 2. Array mit den Variablen fuer den
178 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
180 function add_loop_data($loop,$data) {
181 if(isset($this->loop_vars
[$loop]) && is_array($this->loop_vars
[$loop])) {
182 array_push($this->loop_vars
[$loop],$data);
185 $this->loop_vars
[$loop] = array($data);
191 # In der Template definierte Variablen auslesen, Variablen
192 # ersetzen, {IF}- und {TRIM}-Bloecke parsen
194 # Parameter: -nichts-
196 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
199 if($this->old_parsing
) return $this->parse_old();
201 # Zuerst die Schleifen parsen
203 if(is_array($this->loop_vars
) && ($loops = array_keys($this->loop_vars
))) {
204 foreach($loops as $loop) {
205 $this->parse_loop($loop);
209 # In Template-Datei definierte Variablen auslesen
211 $this->get_defined_vars();
215 if(($vars = $this->get_var()) !== false && is_array($vars)) {
216 $this->parse_if_blocks();
217 $this->replace_vars();
220 # {TRIM}-Bloecke entfernen
222 $this->parse_trim_blocks();
227 # In der Template definierte Variablen auslesen, Variablen
228 # ersetzen, {IF}- und {TRIM}-Bloecke parsen
231 # Parameter: -nichts-
233 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
235 function parse_old() {
236 # Zuerst die Schleifen parsen
238 if(is_array($this->loop_vars
) && ($loops = array_keys($this->loop_vars
))) {
239 foreach($loops as $loop) {
240 $this->parse_loop($loop);
244 # Normale Variablen durchgehen
246 if(($vars = $this->get_var()) !== false && is_array($vars)) {
247 foreach($vars as $var) {
248 $val = $this->get_var($var);
250 $this->parse_if_block($var,$val);
253 $this->fillin_array($var,$val);
256 $this->fillin($var,$val);
263 # Jetzt dasselbe mit denen, die direkt in der Template-Datei definiert
264 # sind, machen. Ich weiss, dass das eine ziemlich unsaubere Loesung ist,
265 # aber es funktioniert
267 $this->get_defined_vars();
269 foreach($this->defined_vars
as $var) {
270 $val = $this->get_var($var);
272 $this->parse_if_block($var,$val);
273 $this->fillin($var,$val);
278 # {TRIM}-Bloecke entfernen
280 $this->parse_trim_blocks();
285 # Variablen durch Text ersetzen
287 # Parameter: 1. Variable zum Ersetzen
288 # 2. Text, durch den die Variable ersetzt werden soll
290 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
292 function fillin($var,$text) {
293 $template = $this->get_template();
294 $template = str_replace('{'.$var.'}',$text,$template);
296 $this->set_template($template);
301 # Variable durch Array ersetzen
303 # Parameter: 1. Variable zum Ersetzen
304 # 2. Array, durch das die Variable ersetzt werden soll
305 # 3. Zeichenkette, mit der das Array verbunden werden soll
308 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
310 function fillin_array($var,$array,$glue='') {
311 $this->fillin($var,implode($glue,$array));
316 # Variablen eine nach der anderen ersetzen. Sollte in einer Variable eine
317 # andere Variable auftauchen, so wird diese nicht ersetzt.
319 # Parameter: Array mit zu parsenden Variablen (optional)
321 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
323 function replace_vars($valid=array()) {
324 $template = $this->get_template();
326 $valid_vars = (empty($valid)) ?
$this->get_var() : $valid;
328 for($x=0;$x<strlen($template);$x++
) {
329 if($template[$x] == '{') {
330 foreach($valid_vars as $var) {
331 # Pruefen, ob hier eine gueltige Variable beginnt
333 if(substr($template,$x+
1,strlen($var)+
1) == $var.'}') {
334 if(is_array($this->get_var($var))) {
335 $content = implode('',$this->get_var($var));
338 $content = $this->get_var($var);
341 # Daten vor und nach der Variable
343 $pre = substr($template,0,$x);
344 $post = substr($template,strlen($pre)+
2+
strlen($var));
346 # Alles neu zusammensetzen
348 $template = $pre.$content.$post;
352 $x = strlen($pre.$content)-1;
358 $this->set_template($template);
363 # Template in Datei schreiben
365 # Parameter: Datei-Handle
367 # Rueckgabe: Status-Code (Boolean)
369 function to_file($handle) {
370 return @fwrite
($handle,$this->get_template());
375 # Den gesicherten Stand des Template-Textes wiederherstellen
377 # Parameter: -nichts-
379 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
382 $this->template
= $this->original
;
387 # Aktuellen Stand des Template-Textes sichern
388 # (alte Sicherung wird ueberschrieben)
390 # Parameter: -nichts-
392 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
394 function save_state() {
395 $this->original
= $this->template
;
400 # Eine Schleife parsen
402 # Parameter: Name der Schleife
404 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
406 function parse_loop($name) {
407 $template = $this->get_template();
408 if(strpos($template,'{LOOP '.$name.'}') === false) return;
411 $name_len = strlen($name);
413 while(($begin = strpos($template,'{LOOP '.$name.'}',$offset)) !== false) {
414 if(($end = strpos($template,'{ENDLOOP}',$begin+
6+
$name_len)) !== false) {
415 $block = substr($template,$begin,$end+
9-$begin);
416 $content = substr($block,$name_len+
7,-9);
420 for($x=0;$x<count($this->loop_vars
[$name]);$x++
) {
421 $loop_data = $this->loop_vars
[$name][$x];
422 $loop_vars = array_keys($loop_data);
424 $ctpl = new Template
;
425 $ctpl->set_template($content);
427 foreach($loop_vars as $loop_var) {
428 $ctpl->set_var($name.'.'.$loop_var,$loop_data[$loop_var]);
431 if($this->old_parsing
) {
438 $parsed_block .= $ctpl->get_template();
443 $template = str_replace($block,$parsed_block,$template);
444 $offset = $begin+
strlen($parsed_block);
449 $this->set_template($template);
454 # In der Template-Datei definierte Variablen auslesen
456 # Parameter: -nichts-
458 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
460 function get_defined_vars() {
461 $template = $this->get_template();
462 if(strpos($template,'{DEFINE ') === false) return;
466 while(strpos($template,'{DEFINE ',$offset) !== false) {
467 $begin = strpos($template,'{DEFINE ',$offset)+
8;
477 for($x=$begin;$x<strlen($template);$x++
) {
478 if($template[$x] == "\012" ||
$template[$x] == "\015") {
479 # Wenn in einem {DEFINE}-Block ein Zeilenumbruch gefunden wird,
480 # brechen wir mit dem Parsen des Blockes ab
486 if($template[$x] == '"') {
487 # Der Inhalt der Variable ist hier zu Ende
491 if($template[$x+
1] == '}') {
492 # Hier ist der Block zu Ende
494 if($this->get_var($name) === false) {
495 # Die Variable wird nur gesetzt, wenn sie nicht bereits gesetzt ist
497 $this->set_var($name,$content);
498 array_push($this->defined_vars
,$name);
501 # {DEFINE}-Block entfernen
503 $pre = substr($template,0,$begin-8);
504 $post = substr($template,$x+
2);
506 $template = $pre.$post;
510 $offset = strlen($pre);
514 elseif($template[$x] == '\\') {
515 # Ein Backslash wurde gefunden, er dient zum Escapen von Zeichen
517 if($template[$x+
1] == 'n') {
518 # "\n" in Zeilenumbrueche umwandeln
522 else $content .= $template[$x+
1];
526 else $content .= $template[$x];
529 if($name_found == 1) {
531 if($template[$x] == '"') $var_open = 1;
536 # Variablennamen auslesen
538 if($template[$x] == '}' && $name != '') {
539 # Wir haben einen {DEFINE}-Block
544 # Alles ab hier sollte mit dem Teil verbunden werden, der das
545 # {DEFINE} in einer Zeile verarbeitet
547 # Der Parser fuer {DEFINE}-Bloecke ist nicht rekursiv, was auch
548 # nicht noetig sein sollte
550 if(($end = strpos($template,'{ENDDEFINE}',$x)) !== false) {
553 $content = substr($template,$x,$end-$x);
555 if($this->get_var($name) === false) {
556 # Die Variable wird nur gesetzt, wenn sie nicht bereits gesetzt ist
558 $this->set_var($name,$content);
559 array_push($this->defined_vars
,$name);
562 $pre = substr($template,0,$begin-8);
563 $post = substr($template,$end+
11);
565 $template = $pre.$post;
569 $offset = strlen($pre);
574 elseif($template[$x] != ' ') {
575 $name .= $template[$x];
577 elseif($name != '') {
586 $this->set_template($template);
591 # IF-Bloecke verarbeiten
593 # Parameter: 1. Name des IF-Blocks (das, was nach dem IF steht)
594 # 2. Status-Code (true => Inhalt anzeigen
595 # false => Inhalt nicht anzeigen
596 # 3. true => Verneinten Block nicht parsen
597 # false => Verneinten Block parsen (Standard)
599 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
601 function parse_if_block($name,$state,$no_negate=0) {
602 $template = $this->get_template();
606 while(strpos($template,'{IF '.$name.'}') !== false) {
607 # Das alles hier ist nicht wirklich elegant geloest...
608 # ... aber solange es funktioniert... ;-)
612 $start = strpos($template,'{IF '.$name.'}');
613 $tpl_tmp = substr($template,$start);
614 $splitted = explode('{ENDIF}',$tpl_tmp);
616 $block = ''; # Kompletter bedingter Block
617 $ifs = 0; # IF-Zaehler (wird fuer jedes IF erhoeht und fuer jedes ENDIF erniedrigt)
621 for($x=0;$x<count($splitted);$x++
) {
622 if($x == count($splitted)-1) die('Nesting error found while parsing IF block "'.$name.'" nr. '.$count.' in template file "'.$this->file
.'"');
624 $ifs +
= substr_count($splitted[$x],'{IF '); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
625 $ifs--; # Zaehler um 1 erniedrigen
626 $block .= $splitted[$x].'{ENDIF}'; # Daten zum Block hinzufuegen
629 # Zaehler wieder 0, also haben wir das Ende des IF-Blocks gefunden :-))
635 $if_block = substr($block,strlen($name)+
5,-7); # Alles zwischen {IF} und {ENDIF}
639 $else_block = ''; # Alles ab {ELSE}
640 $ifs = 0; # IF-Zaehler
642 $splitted = explode('{ELSE}',$if_block);
644 for($x=0;$x<count($splitted);$x++
) {
645 $ifs +
= substr_count($splitted[$x],'{IF '); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen
646 $ifs -= substr_count($splitted[$x],'{ENDIF}'); # Vom Zaehler jedes Vorkommen von ENDIF abziehen
649 # Zaehler 0, also haben wir das Ende des IF-Abschnitts gefunden
651 # Aus dem Rest den ELSE-Block zusammenbauen
653 for($y=$x+
1;$y<count($splitted);$y++
) {
654 $else_block .= '{ELSE}'.$splitted[$y];
658 $if_block = substr($if_block,0,strlen($if_block)-strlen($else_block));
659 $else_block = substr($else_block,6);
666 # Block durch die jeweiligen Daten ersetzen
668 $replacement = ($state) ?
$if_block : $else_block;
670 $template = str_replace($block,$replacement,$template);
673 $this->set_template($template);
675 # Evtl. verneinte Form parsen
678 $this->parse_if_block('!'.$name,!$state,1);
684 # IF-Bloecke zu allen definierten Variablen verarbeiten
686 # Parameter: Array mit zu verarbeitenden IF-Bloecken (optional)
688 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
690 function parse_if_blocks($valid=array()) {
691 $valid_vars = (empty($valid)) ?
$this->get_var() : $valid;
693 foreach($valid_vars as $valid_var) {
694 $this->parse_if_block($valid_var,$this->get_var($valid_var));
698 # parse_trim_blocks()
700 # {TRIM}-Bloecke parsen
702 # Dieser Parser ist nicht rekursiv, was auch nicht
703 # noetig sein sollte.
705 # Parameter: -nichts-
707 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
709 function parse_trim_blocks() {
710 $template = $this->get_template();
711 if(strpos($template,'{TRIM}') === false) return;
715 while(($begin = strpos($template,'{TRIM}',$offset)) !== false) {
716 if(($end = strpos($template,'{ENDTRIM}',$begin+
6)) !== false) {
717 $block = substr($template,$begin,$end+
9-$begin);
718 $content = substr($block,6,-9);
720 $trimmed = trim($content);
722 $template = str_replace($block,$trimmed,$template);
724 $offset = $begin+
strlen($trimmed);
729 $this->set_template($template);
734 # Bedingungstags in einem Vorlagentext verarbeiten
736 # Parameter: 1. Tagname
737 # 2. Status-Code (true => Tag-Inhalt anzeigen
738 # false => Tag-Inhalt nicht anzeigen
740 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
742 function parse_condtag($condtag,$state) {
743 $template = $this->get_template();
745 while(strpos($template,'<'.$condtag.'>') !== false) {
746 $start = strpos($template,'<'.$condtag.'>'); # Beginn des Blocks
747 $end = strpos($template,'</'.$condtag.'>')+
strlen($condtag)+
3; # Ende des Blocks
749 $extract = substr($template,$start,$end-$start); # Kompletten Bedingungsblock extrahieren...
751 $replacement = ($state) ?
substr($extract,strlen($condtag)+
2,0-strlen($condtag)-3) : '';
753 $template = str_replace($extract,$replacement,$template); # Block durch neue Daten ersetzen
756 $this->set_template($template);
761 # {INCLUDE}-Anweisungen verarbeiten
763 # Parameter: -nichts-
765 # Rueckgabe: -nichts- (Template-Objekt wird modifiziert)
767 function parse_includes() {
768 $template = $this->get_template();
769 if(strpos($template,'{INCLUDE ') === false) return;
775 while(($begin = strpos($template,'{INCLUDE ',$offset)) !== false) {
782 if($template[$start] == '"') {
790 for($x=$start;$x<strlen($template);$x++
) {
791 if($template[$x] == "\012" ||
$template[$x] == "\015") {
795 elseif($long == 0 && $template[$x] == ' ') {
799 elseif($long == 1 && $template[$x] == '"') {
800 if($template[$x+
1] != '}') $skip = 1;
803 elseif($long == 0 && $template[$x] == '}') {
807 $file .= $template[$x];
811 if($skip == 1) continue;
816 $is_absolute = (strtoupper(substr(PHP_OS
,0,3)) === 'WIN')
817 ?
preg_match('!^([a-z]:)?/!i',$file)
818 : preg_match('!^/!',$file);
821 if(!empty($this->file
)) $dir = dirname($this->file
);
824 $dir = str_replace('\\','/',$dir);
826 if(!preg_match('!/+$!',$dir)) $dir .= '/';
828 $filepath = $dir.$file;
831 if(is_file($filepath)) {
833 $inc->read_file($filepath);
836 ?
$start +
strlen($file) +
2
837 : $start +
strlen($file) +
1;
839 $pre = substr($template,0,$begin);
840 $post = substr($template,$end);
842 $template = $pre.$inc->get_template().$post;
843 $offset = strlen($pre)+
strlen($inc->get_template());
850 $this->set_template($template);
patrick-canterino.de