]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Template.pm
3 ################################################################################
5 # File: shared/Template.pm #
7 # Authors: André Malo <nd@o3media.de>, 2001-07-01 #
8 # Frank Schoenmann <fs@tower.de>, 2001-06-04 #
10 # Description: Handle XML based HTML-Templates #
12 ################################################################################
26 $xml_dom_used = eval q
[
33 ################################################################################
37 $VERSION = do { my @r =(q
$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x
$#r, @r };
40 ### sub new ####################################################################
46 # Return: Template object
51 my $self = bless {} => ref($instance) || $instance;
53 $self -> file
(+shift);
59 ### sub file ###################################################################
61 # assign new template file to object
62 # parse the template file
64 # Params: $new - (optional) new template file
66 # Return: scalar - old filename or if there's no old filename given
71 my $old = $self -> {file
};
73 $self -> {file
} = $new if (defined $new);
80 ### sub insert #################################################################
82 # return the placeholder surrounded by meta delimiters
84 # Params: $name - name of placeholder
86 # Return: scalar - placeholder surrounded by meta delimiters
92 croak
"no template file specified"
93 unless (defined $self -> {file
});
96 $self -> {metaon
} . $name . $self -> {metaoff
};
99 ### sub list ###################################################################
101 # fill in a complete list
103 # Params: $name - name of the atomic scrap
104 # $array - list of hashes (same strcuture like the hash used by 'scrap')
106 # Return: scalar reference - filled in list
111 croak
"no template file specified"
112 unless (defined $self -> {file
});
114 $self -> joinlist
('' => @_);
117 ### sub joinlist ###############################################################
119 # fill in a complete list, using a scrap between the list elements
121 # Params: $join - joining string (or stringref)
122 # $name - name of the atomic list scrap
123 # $array - list of hashes (same strcuture like the hash used by 'scrap')
125 # Return: scalar reference - filled in list
130 $join = $$join if ref($join);
133 my $list = join $join => map { ${ $self -> scrap
($name, $_) } } @
{ +shift };
139 ### sub scrap ##################################################################
141 # fill in a template scrap
143 # Params: $name name of the scrap
145 # $no_nl 1 - remove newlines (\n)
146 # 0 - do no such thing
148 # Return: scalar reference - filled in scrap
159 croak
"no template file specified"
160 unless (defined $self -> {file
});
162 return \'' unless (defined $name and defined ($self -> {parsed} -> {$name}));
165 # (and normalize - save only the references in %params)
173 ? (defined ${$ref -> {$_}} ? $ref -> {$_} : \'')
174 : \
(defined $ref -> {$_} ?
$ref -> {$_} : ''))
181 my $scrap = $self -> {parsed
} -> {$name};
182 my $qmon = quotemeta $self -> {metaon
};
183 my $qmoff = quotemeta $self -> {metaoff
};
185 # ...until we've replaced all placeholders
194 [ (exists ( $params{$1} ) )
196 : ( exists ( $self -> {parsed
} -> {$1} )
197 ?
$self -> {parsed
} -> {$1}
203 # parse conditional blocks
212 $scrap =~ s/\015\012|\015|\012//g if ($no_nl);
218 ### printscrap () ##############################################################
220 # fill in a template scrap and print to STDOUT
222 # Params: $name name of the scrap
224 # $no_nl 1 - remove newlines (\n)
225 # 0 - do no such thing
227 # Return: success code (boolean)
232 $self -> scrap2file
(\
*STDOUT
, @_);
235 ### scrap2file () ##############################################################
237 # fill in a template scrap and print to a file handle
239 # Params: $handle filehandle
240 # $name name of the scrap
242 # $no_nl 1 - remove newlines (\n)
243 # 0 - do no such thing
245 # Return: success code (boolean)
251 print $handle ${$self->scrap(@_)};
254 ### sub parse_file #############################################################
256 # read in and parse template file
260 # Return: Status Code (Boolean)
264 my $filename = $self -> {file
};
268 # parse template using XML::DOM
272 new XML
::DOM
::Parser
-> parsefile
($filename);
274 croak
"error while parsing template file '$filename': $@" if ($@
);
276 my $template = $xml -> getElementsByTagName
('Template', 0) -> item
(0);
278 # extract meta delimiters
280 $self -> {metaon
} = $template -> getAttribute
('metaon');
281 $self -> {metaoff
} = $template -> getAttribute
('metaoff');
283 croak
"missing meta defintion(s) in template file '$filename'." unless ($self -> {metaon
} and $self -> {metaoff
});
285 $self -> {parsed
} = {};
286 foreach ($template -> getElementsByTagName
('Scrap', 0)) {
287 my $name = $_ -> getAttribute
('id');
289 croak
"Element 'Scrap' requires attribute 'id' in template file '$filename'." unless (length ($name));
290 croak
"double defined id '$name' in template file '$filename'." if (exists ($self -> {parsed
} -> {$name}));
291 croak
"use '/^[_a-zA-Z]\\S*\$/' for 'Scrap'-ids in template file '$filename' (wrong: '$name')." unless ($name =~ /^[_a-zA-Z]\S*$/);
293 $self -> {parsed
} -> {$name} = $_ -> getFirstChild
-> getData
;
294 $self -> {parsed
} -> {$name} =~ s/^\s+|\s+$//g;}
296 return 1; # looks fine
299 # XML::DOM not available...
300 # parse the template using both hands ;)
303 my ($xml, $root, $template);
306 open FILE
, "< $filename" or croak
"error while reading template file '$filename': $!";
308 close FILE
or croak
"error while closing template file '$filename' after reading: $!";
310 ($root, $template) = ($1, $2) if ($xml =~ m
|(<Template\s
+[^>"]*(?:"[^"]*"[^>"]*)*>)(.*)</Template\s*>|s);
311 croak "error
while parsing template file
'$filename': missing root element
'Template'"
312 unless (defined $root and defined $template);
314 # extract meta delimiters
316 $self -> {metaon} = $1 if ($root =~ /\smetaon\s*=\s*"([^"]+)"/);
317 $self -> {metaoff
} = $1 if ($root =~ /\smetaoff\s*=\s*"([^"]+)"/);
319 croak
"missing meta defintion(s) in template file '$filename'." unless ($self -> {metaon
} and $self -> {metaoff
});
321 # don't use any other entities than " ' < > and &
322 # (while using non XML::DOM - version)
324 for ('metaon', 'metaoff') {
325 $self -> {$_} =~ s/"/"/g; $self -> {$_} =~ s/'/'/g;
326 $self -> {$_} =~ s/</</g; $self -> {$_} =~ s/>/>/g;
327 $self -> {$_} =~ s/&/&/g;
330 $self -> {parsed
} = {};
331 while ($template =~ m
|<Scrap\s
+(?
:id\s
*=\s
*"([^"]+)")?\s*>\s*<!\[CDATA\[([^\]]*(?:\](?!\]>)[^\]]*)*)\]\]>\s*</Scrap\s*>|g) {
333 my ($name, $content) = ($1, $2);
335 croak "Element
'Scrap' requires attribute
'id' in template file
'$filename'"
336 unless (defined $name and length $name);
338 croak "double
defined id
'$name' in template file
'$filename'"
339 if (exists ($self -> {parsed} -> {$name}));
341 croak "use '/^[_a-zA-Z]\\S*\$/' for 'Scrap'-ids
in template file
'$filename' (wrong
: '$name')"
342 unless ($name =~ /^[_a-zA-Z]\S*$/);
344 $content =~ s/^\s+//; $content =~ s/\s+$//;
345 $self -> {parsed} -> {$name} = $content;
348 return 1; # looks fine
351 return; # anything failed (??)
354 ### sub parse_if ###############################################################
356 # parse conditional blocks
358 # Params: $scrap - scalar reference of the template scrap
359 # $params - hash reference: values from the application
361 # Return: ~none~, ($$scrap will be modified)
365 my ($scrap, $params) = @_;
367 my $qmon = quotemeta $self -> {metaon};
368 my $qmoff = quotemeta $self -> {metaoff};
370 # the following regex is just not optimized,
373 1 while ($$scrap =~ s {
374 ($qmon\s*%(?:IF|ELSE)\s+.+?\s*$qmoff.*?) # skip this part
375 (?=$qmon\s*%IF\s+.+?\s*$qmoff) # if %IF or %ELSE are followed by %IF
378 $qmon\s*%IF\s+(.+?)\s*$qmoff # %IF
381 $qmon\s*%ENDIF\s*$qmoff # followed by %ENDIF
383 $qmon\s*%ELSE\s*$qmoff # %ELSE...
385 $qmon\s*%ENDIF\s*$qmoff # ...and ENDIF
391 my ($t3, $t4, $t5) = ($3, $4, $5);
393 for (split /\s+/,$t3) {
395 exists($params->{$_})
396 and defined ${$params->{$_}}
397 and length ${$params->{$_}}
403 $ret = $t5 || '' unless (defined $ret);
415 # keep 'require' happy
420 ### end of Template ############################################################
patrick-canterino.de