#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# This is a simple template-handling system. You pass it a big data
# structure with key/value pairs, and a template string to fill out.
#
# Within a template, it recognizes tags of the form ~name [arg...]~,
# optionally wrapped in HTML comments (which will be removed along with
# the tag markers when the template is filled out).
#
# { and } as the final argument mark those tags as being the start and
# end of a sub-template (for optional or repeated sections). All other
# tags represent slots to be directly filled by data values. On a }
# tag, the name is optional, but must match the corresponding { tag if
# present.
#
# For a value tag, arguments represent encodings to be applied
# successively. For instance, ~foo html~ will encode it to be safe in
# HTML ('&' to '&', '<' to '<', and so on).
#
# { tags can take one argument, which will call the corresponding
# tem_auto_* function to munge the data, automating certain common use
# cases. See the comments on the tem_auto functions for more details.
require_once('code/wfpl/encode.php');
require_once('code/wfpl/file.php');
require_once('code/wfpl/misc.php');
# Top-Level Functions
# -------------------
function template($template, $data) {
return fill_template(parse_template($template), $data);
}
function template_file($filename, $data) {
return fill_template(parse_template_file($filename), $data);
}
function parse_template_file($filename) {
return parse_template(file_get_contents($filename));
}
# We parse the template string into a tree of strings and sub-templates.
# A template is a hash with a name string, a pieces array, and possibly
# an args array.
function parse_template($string) {
$tem =& tem_push();
$tem['pieces'] = array();
# note: for some reason this captures ''.
$matches = preg_split("/()/", $string, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach($matches as $match) {
if(substr($match,0,1) == '~') {
$args = explode(' ', substr($match,1,-1));
if(count($args) == 1 and $args[0] == '}') $name = '';
else $name = array_shift($args);
if(last($args) == '{') { # open block
array_pop($args);
# create a new sub-template
# and add it to the parent.
$tem =& tem_push($tem);
$tem['parent']['pieces'][] =& $tem;
$tem['name'] = $name;
$tem['pieces'] = array();
$tem['args'] = $args;
} elseif(last($args) == '}') { # close block
array_pop($args);
$cur = $tem['name'];
if($name && $name != $cur) {
die("Invalid template: tried to close '$name', but '$cur' is current.");
}
$tem =& $tem['parent'];
} else { # value slot
$tem['pieces'][] = array('name' => $name, 'args' => $args);
}
} elseif($match and $match != '
#
# row content...
#
#
#
#
function tem_auto_sep($key, $context) {
$rows =& $context['parent']['rows'];
if(key($rows)) return true;
# else we are on the last row (cursor has hit the end and reset).
}
# 'show' sections will be shown unless the corresponding data value
# is false. We check only for false; 0 or '' will not work.
function tem_auto_show($key, $context) {
if($context['data'][$key] !== false)
return tem_data_as_rows(true);
}
# 'evenodd' sections are given an 'evenodd' attribute whose value
# alternates between 'even' and 'odd'.
function tem_auto_evenodd($key, $context) {
$rows = $context['data'][$key];
$even = 0;
$text = array('even', 'odd');
foreach($rows as $key => $value) {
$rows[$key]['evenodd'] = $text[$even];
$even = 1 - $even;
}
return tem_data_as_rows($rows);
}
?>