,欢迎访问网页设计爱好者web开发。 //
// description
// recursive internal parse routine. this will recursively parse a
// template containing dynamic inferior templates. each of these
// inferior templates gets their own entry in the template array.
//
function &parse_internal_1 ($tag, $rest = '') {
$debug = $this->debugall || $this->debug['parse_internal_1'];
if (empty($tag)) {
$this->error ("parse_internal_1: empty tag invalid", true);
}
if ($debug)
$this->logwrite ("parse_internal_1 (tag=$tag, rest=$rest)");
while (!empty($rest)) {
if ($debug)
$this->logwrite ('parse_internal_1: regex_dynbeg search: rest => ' . $rest);
if (preg_match ($this->regex_dynbeg, $rest, $dynbeg)) {
// found match, now split into two pieces and search the second
// half for the matching end. the string which goes into the
// next element includes the html comment which forms the begin
// block.
if ($debug)
$this->logwrite ('parse_internal_1: match beg => ' . $dynbeg[1]);
$pos = strpos ($rest, $dynbeg[1]);
// see if the text on either side of the begin comment is only
// whitespace. if so, we delete the entire line.
$okay = false;
for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) {
$c = $rest{$offbeg};
if ($c == "/n") {
$okay = true;
$offbeg++;
break;
}
if (($c != ' ') && ($c != "/t")) {
$offbeg = $pos;
break;
}
}
if (! $okay) {
$offend = $pos + strlen($dynbeg[1]);
} else {
$l = strlen ($rest);
for ($offend = $pos + strlen($dynbeg[1]); $offend < $l; $offend++) {
$c = $rest{$offend};
if ($c == "/n") {
$offend++;
break;
}
if (($c != ' ') && ($c != "/t")) {
$offend = $pos + strlen($dynbeg[1]);
break;
}
}
}
// this includes the contents of the regex_dynbeg in the output
// $part[] = substr ($rest, 0, $pos);
// this preserves whitespace on the end block line(s).
// $part[] = substr ($rest, 0, $pos+strlen($dynbeg[1]));
// $rest = substr ($rest, $pos+strlen($dynbeg[1]));
// catch case where begin block is at position 0.
if ($offbeg > 0)
$part[] = substr ($rest, 0, $offbeg);
$rest = substr ($rest, $offend);
$sub = '';
if ($debug)
$this->logwrite ("parse_internal_1: found at pos = $pos");
// okay, here we are actually not interested in just the next
// end block. we are only interested in the next end block that
// matches this begin block. this is not the most efficient
// because we really could do this in one pass through the
// string just marking begin and end blocks. but the recursion
// makes for a simple algorithm (if there was a reverse
// preg...).
$found = false;
while (preg_match ($this->regex_dynend, $rest, $dynend)) {
if ($debug)
$this->logwrite ('parse_internal_1: regex_dynend search: rest => ' . $rest);
if ($debug)
$this->logwrite ('parse_internal_1: match beg => ' . $dynend[1]);
$pos = strpos ($rest, $dynend[1]);
if ($dynbeg[2] == $dynend[2]) {
$found = true;
// see if the text on either side of the end comment is
// only whitespace. if so, we delete the entire line.
$okay = false;
for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) {
$c = $rest{$offbeg};
if ($c == "/n") {
$offbeg++;
$okay = true;
break;
}
if (($c != ' ') && ($c != "/t")) {
$offbeg = $pos;
break;
}
}
if (! $okay) {
$offend = $pos + strlen($dynend[1]);
} else {
$l = strlen ($rest);
for ($offend = $pos + strlen($dynend[1]); $offend < $l; $offend++) {
$c = $rest{$offend};
if ($c == "/n") {
$offend++;
break;
}
if (($c != ' ') && ($c != "/t")) {
$offend = $pos + strlen($dynend[1]);
break;
}
}
}
// if ($debug)
// $this->logwrite ("parse_internal_1: dynamic begin: (pos,len,beg,end) => ($pos, " . strlen($dynbeg[1]) . ", $offbeg, $offend)
// this includes the contents of the regex_dynend in the output
// $rest = substr ($rest, $pos);
// this preserves whitespace on the end block line(s).
// $rest = substr ($rest, $pos+strlen($dynend[1]));
// $sub .= substr ($rest, 0, $pos);
$sub .= substr ($rest, 0, $offbeg);
$rest = substr ($rest, $offend);
// already loaded templates will not be reloaded. the
// 'clear' test was actually hiding a bug in the clear()
// logic....
if (false && isset($this->template[$dynend[2]]['clear'])
&& $this->template[$dynend[2]]['clear']) {
$this->template[$dynend[2]]['string'] = '';
$this->template[$dynend[2]]['result'] = '';
$this->template[$dynend[2]]['part'] =
$this->parse_internal_1 ($dynend[2], ' ');
} else if (!isset($this->template[$dynend[2]]['loaded'])
|| !$this->template[$dynend[2]]['loaded']) {
// omit pathological case of empty dynamic template.
if (strlen($sub) > 0) {
$this->template[$dynend[2]]['string'] = $sub;
$this->template[$dynend[2]]['part'] =
$this->parse_internal_1 ($dynend[2], $sub);
$this->template[$dynend[2]]['part']['parent'] = $tag;
}
}
$this->template[$dynend[2]]['loaded'] = true;
$part[] = &$this->template[$dynend[2]];
$this->template[$dynend[2]]['tag'] = $dynend[2];
break;
} else {
$sub .= substr ($rest, 0, $pos+strlen($dynend[1]));
$rest = substr ($rest, $pos+strlen($dynend[1]));
if ($debug)
$this->logwrite ("parse_internal_1: $dynbeg[2] != $dynend[2]");
}
}
if (!$found) {
$this->error ("malformed dynamic template, missing end<br />/n" .
"$dynbeg[1]<br />/n", true);
}
} else {
// although it would appear to make sense to check that we don't
// have a dangling end block, we will, in fact, always appear to
// have a dangling end block. we stuff the begin string in the
// part before the inferior template and the end string in the
// part after the inferior template. so for this test to work,
// we would need to look just past the final match.
if (preg_match ($this->regex_dynend, $rest, $dynend)) {
// $this->error ("malformed dynamic template, dangling end<br />/n" .
// "$dynend[1]<br />/n", 1);
}
$part[] = $rest;
$rest = '';
}
}
return $part;
}
//
// description
// parse the template. if $tag is actually an array, we iterate over
// the array elements. if it is a simple string tag, we may still
// recursively parse the template if it contains dynamic templates and
// we are configured to automatically load those as well.
//
function parse_internal ($tag) {
$debug = $this->debugall || $this->debug['parse_internal'];
$append = false;
if ($debug)
$this->logwrite ("parse_internal (tag=$tag)");
// if we are handed an array of tags, iterate over all of them. this
// is really a holdover from the way class.fasttemplate.php3 worked;
// i think subst() already pulls that array apart for us, so this
// should not be necessary unless someone calls the internal member
// function directly.
if (gettype($tag) == 'array') {
reset ($tag);
foreach ($tag as $t) {
$this->parse_internal ($t);
}
} else {
// load the file if it hasn't already been loaded. it might be
// nice to put in some logic that reloads the file if it has
// changed since we last loaded it, but that probably gets way too
// complicated and only makes sense if we start keeping it floating
// around between page loads as a persistent variable.
if (!isset($this->template[$tag]['loaded'])) {
if ($this->template[$tag]['dynamic']) {
// template was declared via define_dynamic().
if ($this->template[$tag]['parent'])
$tag = $this->template[$tag]['parent'];
else {
// try to find a non-dynamic template with the same file.
// this would have been defined via define(array(), true)
reset ($this->template);
foreach (array_keys($this->template) as $ptag) {
if ($debug)
$this->logwrite ("parse_internal: looking for non-dynamic parent, $ptag");
if (!$this->template[$ptag]['dynamic']
&& ($this->template[$ptag]['file'] == $this->template[$tag]['file'])) {
$tag = $ptag;
break;
}
}
}
}
$this->template[$tag]['string'] = &$this->load($this->template[$tag]['file']);
$this->template[$tag]['loaded'] = 1;
}
// if we are supposed to automatically detect dynamic templates and the dynamic
// flag is not set, scan the template for dynamic sections. dynamic sections
// markers have a very rigid syntax as html comments....
if ($this->dynamic) {
$this->template[$tag]['tag'] = $tag;
if (!isset($this->template[$tag]['parsed'])
|| !$this->template[$tag]['parsed']) {
$this->template[$tag]['part'] = $this->parse_internal_1 ($tag, $this->template[$tag]['string']);
$this->template[$tag]['parsed'] = true;
}
}
}
}
//
// description
// class.fasttemplate.php3 compatible interface.
//
// notes
// i prefer the name `subst' to `parse' since during this phase we are
// really doing variable substitution into the template. however, at
// some point we have to load and parse the template and `subst' will
// do that as well...
//
function parse ($handle, $tag, $autoload = true) {
return $this->subst ($handle, $tag, $autoload);
}
// 未完待续