From: cvs2git <> Date: Thu, 5 May 2005 11:14:32 +0000 (+0000) Subject: This commit was manufactured by cvs2svn to create branch 'version_2_3_x'. X-Git-Url: https://git.p6c8.net/devedit.git/commitdiff_plain/66a0e189aefc23e71cc55ced6d19d048edb8c4d7 This commit was manufactured by cvs2svn to create branch 'version_2_3_x'. --- diff --git a/modules/Template.pm b/modules/Template.pm new file mode 100644 index 0000000..ea2a9cc --- /dev/null +++ b/modules/Template.pm @@ -0,0 +1,373 @@ +package Template; + +# +# Template (Version 1.5) +# +# Klasse zum Parsen von Templates +# +# Autor: Patrick Canterino +# Letzte Aenderung: 4.5.2005 +# + +use strict; + +use Carp qw(croak); + +# new() +# +# Konstruktor +# +# Parameter: -keine- +# +# Rueckgabe: Template-Objekt + +sub new +{ + my $class = shift; + my $self = {file => '', template => ''}; + return bless($self,$class); +} + +# get_template() +# +# Kompletten Vorlagentext zurueckgeben +# +# Parameter: -keine- +# +# Rueckgabe: Kompletter Vorlagentext (String) + +sub get_template +{ + return shift->{'template'}; +} + +# set_template() +# +# Kompletten Vorlagentext aendern +# +# Parameter: Vorlagentext +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub set_template($) +{ + # Geht nur so... + + my ($self,$template) = @_; + $self->{'template'} = $template; +} + +# add_text() +# +# Vorlagentext ans Template-Objekt anhaengen +# +# Parameter: Vorlagentext +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub add_text($) +{ + my ($self,$text) = @_; + $self->set_template($self->get_template.$text); +} + +# read_file() +# +# Einlesen einer Vorlagendatei und {INCLUDE}-Anweisungen ggf. verarbeiten +# (Text wird an bereits vorhandenen Text angehaengt) +# +# Parameter: 1. Datei zum Einlesen +# 2. Status-Code (Boolean): +# true => {INCLUDE}-Anweisungen nicht verarbeiten +# false => {INCLUDE}-Anweisungen verarbeiten (Standard) +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub read_file($;$) +{ + my ($self,$file,$not_include) = @_; + local *FILE; + + $self->{'file'} = $file; + + open(FILE,'<'.$file) or croak "Open $file: $!"; + read(FILE, my $content, -s $file); + close(FILE) or croak "Closing $file: $!"; + + $self->add_text($content); + $self->parse_includes unless($not_include); +} + +# fillin() +# +# Variablen durch Text ersetzen +# +# Parameter: 1. Variable zum Ersetzen +# 2. Text, durch den die Variable ersetzt werden soll +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub fillin($$) +{ + my ($self,$var,$text) = @_; + + $var = quotemeta($var); + $text = '' unless defined $text; # Um Fehler zu vermeiden + + my $template = $self->get_template; + $template =~ s/\{$var\}/$text/g; + + $self->set_template($template); +} + +# fillin_array() +# +# Variable durch Array ersetzen +# +# Parameter: 1. Variable zum Ersetzen +# 2. Array-Referenz, durch die die Variable ersetzt werden soll +# 3. Zeichenkette, mit der das Array verbunden werden soll +# (Standard: '') +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub fillin_array($$;$) +{ + my ($self,$var,$array,$glue) = @_; + $glue = '' unless defined $glue; + + $self->fillin($var,join($glue,@$array)); +} + +# to_file() +# +# Template in Datei schreiben +# +# Parameter: Datei-Handle +# +# Rueckgabe: Status-Code (Boolean) + +sub to_file($) +{ + my ($self,$handle) = @_; + return print $handle $self->get_template; +} + +# parse_if_block() +# +# IF-Bloecke verarbeiten +# +# Parameter: 1. Name des IF-Blocks (das, was nach dem IF steht) +# 2. Status-Code (true => Inhalt anzeigen +# false => Inhalt nicht anzeigen +# 3. true => Verneinten Block nicht parsen +# false => Verneinten Block parsen (Standard) +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub parse_if_block($$;$) +{ + my ($self,$name,$state,$no_negate) = @_; + my $template = $self->get_template; + + my $count = 0; + + while(index($template,'{IF '.$name.'}') >= 0) + { + # Das alles hier ist nicht wirklich elegant geloest... + # ... aber solange es funktioniert... ;-) + + $count++; + + my $start = index($template,'{IF '.$name.'}'); + my $tpl_tmp = substr($template,$start); + my @splitted = split(/\{ENDIF\}/,$tpl_tmp); + + # Wenn sich am Ende der Zeichenkette {ENDIF} befinden, werden diese + # von split() ignoriert, was zu einem Verschachtelungsfehler fuehrt + # Die fehlenden leeren Zeichenketten muessen von Hand eingefuegt werden + + my $x = 1; + + while(substr($tpl_tmp,-7*$x,7) eq '{ENDIF}') + { + push(@splitted,''); + $x++; + } + + my $block = ''; # Kompletter bedingter Block + my $ifs = 0; # IF-Zaehler (wird fuer jedes IF erhoeht und fuer jedes ENDIF erniedrigt) + + # {IF} + + for(my $x=0;$x<@splitted;$x++) + { + croak 'Nesting error found while parsing IF block "'.$name.'" nr. '.$count.' in template file "'.$self->{'file'}.'"' if($x == $#splitted); + + $ifs += substr_count($splitted[$x],'{IF '); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen + $ifs--; # Zaehler um 1 erniedrigen + $block .= $splitted[$x].'{ENDIF}'; # Daten zum Block hinzufuegen + + if($ifs == 0) + { + # Zaehler wieder 0, also haben wir das Ende des IF-Blocks gefunden :-)) + + last; + } + } + + my $if_block = substr($block,length($name)+5,-7); # Alles zwischen {IF} und {ENDIF} + + # {ELSE} + + my $else_block = ''; # Alles ab {ELSE} + $ifs = 0; # IF-Zaehler + + @splitted = split(/\{ELSE\}/,$if_block); + + for(my $x=0;$x<@splitted;$x++) + { + $ifs += substr_count($splitted[$x],'{IF '); # Zum Zaehler jedes Vorkommen von IF hinzuzaehlen + $ifs -= substr_count($splitted[$x],'{ENDIF}'); # Vom Zaehler jedes Vorkommen von ENDIF abziehen + + if($ifs == 0) + { + # Zaehler 0, also haben wir das Ende des IF-Abschnitts gefunden + + # Aus dem Rest den ELSE-Block zusammenbauen + + for(my $y=$x+1;$y<@splitted;$y++) + { + $else_block .= '{ELSE}'.$splitted[$y]; + } + + if($else_block) + { + $if_block = substr($if_block,0,length($if_block)-length($else_block)); + $else_block = (length($else_block) > 6) ? substr($else_block,6) : ''; # Ansonsten gibt es Fehler + } + + last; + } + } + + my $replacement = ($state) ? $if_block : $else_block; + + my $qmblock = quotemeta($block); + + $template =~ s/$qmblock/$replacement/; + } + + $self->set_template($template); + + # Evtl. verneinte Form parsen + + unless($no_negate) + { + $self->parse_if_block('!'.$name,not($state),1); + } +} + +# parse_condtag() +# +# Bedingungstags in einem Vorlagentext verarbeiten +# +# Parameter: 1. Tagname +# 2. Status-Code (true => Tag-Inhalt anzeigen +# false => Tag-Inhalt nicht anzeigen +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub parse_condtag($$) +{ + my ($self,$condtag,$state) = @_; + + my $template = $self->get_template; + + while(index($template,'<'.$condtag.'>') >= 0) + { + my $start = index($template,'<'.$condtag.'>'); # Beginn des Blocks + my $end = index($template,'')+length($condtag)+3; # Ende des Blocks + + my $extract = substr($template,$start,$end-$start); # Kompletten Bedingungsblock extrahieren... + + my $replacement = ($state) ? substr($extract,length($condtag)+2,0-length($condtag)-3) : ''; + + $extract = quotemeta($extract); + + $template =~ s/$extract/$replacement/g; # Block durch neue Daten ersetzen + } + $self->set_template($template); +} + +# parse_includes() +# +# {INCLUDE}-Anweisungen verarbeiten +# +# Parameter: -nichts- +# +# Rueckgabe: -nichts- (Template-Objekt wird modifiziert) + +sub parse_includes +{ + my $self = shift; + my $template = $self->get_template; + + while($template =~ /(\{INCLUDE (\S+?)\})/g) + { + my ($directive,$file) = ($1,$2); + my $qm_directive = quotemeta($directive); + + if(-f $file) + { + my $inc = new Template; + $inc->read_file($file); + + $template =~ s/$qm_directive/$inc->get_template/eg; + } + } + + $self->set_template($template); +} + +# ================== +# Private Funktion +# ================== + +# substr_count() +# +# Zaehlt, wie oft ein String in einem String vorkommt +# (Emulation der PHP-Funktion substr_count()) +# +# Parameter: 1. Zu durchsuchender String +# 2. Zu suchender String +# +# Rueckgabe: Anzahl der Vorkommnisse (Integer) + +sub substr_count($$) +{ + my ($haystack,$needle) = @_; + my $qmneedle = quotemeta($needle); + + my $count = 0; + + $count++ while($haystack =~ /$qmneedle/g); + + return $count; +} + +# ================== +# Alias-Funktionen +# ================== + +*addtext = \&add_text; +*as_string = \&get_template; +*condtag = \&parse_condtag; +*readin = \&read_file; + +# it's true, baby ;-) + +1; + +# +### Ende ### \ No newline at end of file