<?php
function pt_recursive_implode ($array) {
if (!is_array($array)) return $array;
foreach ($array as $key => $value) $array[$key] = pt_recursive_implode($value);
return implode($array);
}
function pt_find_tag ($template, $initial) {
$result = strpos($template, "<!-- ##", $initial);
if ($result === false) return null;
return (int) $result;
}
function pt_check_tag ($template, $initial, $depth) {
$endtag = str_repeat('#', $depth);
$endpos = strpos($template, "<!-- ###$endtag -->", $initial);
if ($endpos === false) return false;
$taglen = ($endpos + 12 + $depth) - $initial;
if ($taglen == 0) return false;
$startpos = strpos($template, " -->", $initial);
if ($startpos >= $endpos) return false;
$startpos += 4;
$paramlist = substr($template, $initial + 7, $startpos - $initial - 11);
$contents = substr($template, $startpos, $endpos - $startpos);
$mask = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
$ppos = strspn($paramlist, $mask);
if ($ppos == 0) return false;
$name = substr($paramlist, 0, $ppos);
if ((ord($name[0]) >= 48) and (ord($name[0]) <= 57)) return false;
$ppos += strcspn($paramlist, $mask, $ppos);
$plen = strlen($paramlist);
$params = array();
$paramcount = 0;
while ($ppos < $plen) {
$next = strspn($paramlist, $mask, $ppos);
if ($next == 0) break;
$params[++ $paramcount] = substr($paramlist, $ppos, $next);
if ((ord($params[$paramcount][0]) >= 48) and (ord($params[$paramcount][0]) <= 57)) return false;
$ppos += $next;
$ppos += strcspn($paramlist, $mask, $ppos);
}
if ($paramcount > 1)
for ($p1 = 1, $p2 = 2; $p1 < $paramcount; $p2 = 1 + (($p2 == $paramcount) ? (++ $p1) : $p2))
if (strpos($params[$p2], $params[$p1]) === 0)
return false;
return array($name, $taglen, $params, $contents);
}
function pt_parse_tag ($contents, $params, $replace, $header, $footer, $parse_callbacks, $depth, $data) {
if (!is_string($contents)) $contents = (string) $contents;
if ($params === null) return array($header, $contents, $footer);
if (is_bool($params))
return ((bool) $params) ? pt_parse_template($contents, $parse_callbacks, $depth + 1, $data) : "";
if (is_int($params)) {
if ($params <= 0) return "";
if ($params == 1) return pt_parse_template($contents, $parse_callbacks, $depth + 1, $data);
$recurse = (pt_find_tag($contents, 0) !== null);
if ($recurse) {
$result = array();
for ($pos = 0; $pos < $params; $pos ++)
$result[$pos] = pt_parse_template($contents, $parse_callbacks, $depth + 1, $data);
return $result;
} else return (((int) $params) > 0) ? array_fill(0, (int) $params, $contents) : "";
}
if (is_string($params))
return pt_parse_template($params, $parse_callbacks, $depth + 1, $data);
if (is_array($params)) {
if (isset($params[0])) {
if (!is_int($params[0])) return "";
if ($params[0] <= 0) return "";
$result = array_fill(1, $params[0], "");
for ($index = 1; $index <= $params[0]; $index ++)
if (isset($params[$index]))
$result[$index] = pt_parse_tag($contents, $params[$index], $replace, $header, $footer,
$parse_callbacks, $depth, $data);
return $result;
} else {
$contents = pt_parse_template($contents, $parse_callbacks, $depth + 1, $data);
foreach ($replace as $pos => $name)
if (isset($params[$name]))
$contents = str_replace("$$" . $name, $params[$name], $contents);
else if (isset($params[$pos]))
$contents = str_replace("$$" . $name, $params[$pos], $contents);
return $contents;
}
}
return array($header, $contents, $footer);
}
function pt_parse_template ($template, $parse_callbacks, $depth, $data) {
$result = array();
$next = 0;
$tpos = 0;
$tlen = strlen($template);
while (($tpos < $tlen) and (($nexttag = pt_find_tag($template, $tpos)) !== null)) {
if ($nexttag > $tpos)
$result[$next ++] = substr($template, $tpos, $nexttag - $tpos);
$tag_data = pt_check_tag($template, $nexttag, $depth);
if ($tag_data === false) {
$result[$next ++] = substr($template, $nexttag, $tlen - $nexttag);
$tpos = $tlen;
continue;
}
$tpos = $nexttag + $tag_data[1];
$theader = substr($template, $nexttag, strpos($template, "-->", $nexttag) + 3 - $nexttag);
$tfooter = substr($template, $tpos - $depth - 12, $depth + 12);
if (is_callable($parse_callbacks)) {
$result[$next ++] = is_callable($parse_callbacks) ?
pt_parse_tag($tag_data[3], call_user_func_array($parse_callbacks, array_merge(array($tag_data[0]), $data)),
$tag_data[2], $theader, $tfooter, $parse_callbacks, $depth, $data) :
$theader . $tag_data[3] . $tfooter;
} else if (is_array($parse_callbacks)) {
$callback = @$parse_callbacks[$tag_data[0]];
$result[$next ++] = is_callable($callback) ?
pt_parse_tag($tag_data[3], call_user_func_array($callback, array_merge($data)), $tag_data[2], $theader, $tfooter,
$parse_callbacks, $depth, $data) :
$theader . $tag_data[3] . $tfooter;
} else
$result[$next ++] = $theader . $tag_data[3] . $tfooter;
}
if ($tpos < $tlen)
$result [$next ++] = substr($template, $tpos, $tlen - $tpos);
return pt_recursive_implode($result);
}
function parse_template ($template, $parse_callbacks) {
if (!is_string($template)) $template = (string) $template;
if (!(is_callable($parse_callbacks) or is_array($parse_callbacks))) return $template;
$data = func_get_args();
array_splice($data, 0, 2);
return pt_parse_template($template, $parse_callbacks, 0, $data);
}
?>
Comments