|
|
¡¡for ($offend = $pos + strlen($dynend[1]); $offend < $l; $offend++) {
¡¡¡¡$c = $rest{$offend};
¡¡¡¡if ($c == "
¡¡¡¡") {
¡¡¡¡$offend++;
¡¡¡¡break;
¡¡¡¡}
¡¡¡¡if (($c != ' ') && ($c != " ")) {
¡¡¡¡$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 />
¡¡¡¡" .
¡¡¡¡"$dynbeg[1]<BR />
¡¡¡¡", 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 />
¡¡¡¡" .
¡¡¡¡//
¡¡¡¡"$dynend[1]<BR />
¡¡¡¡", 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);
¡¡¡¡}
¡¡¡¡//
¡¡¡¡// Description
¡¡¡¡//
¡¡¡¡Perform substitution on the template.
¡¡¡¡We do not really recurse
¡¡¡¡//
¡¡¡¡downward in the sense that we do not do subsitutions on inferior
¡¡¡¡//
¡¡¡¡templates.
¡¡¡¡For each inferior template which is a part of this
¡¡¡¡//
¡¡¡¡template, we insert the current value of their results.
¡¡¡¡//
¡¡¡¡// Notes
¡¡¡¡//
¡¡¡¡Do I want to make this return a reference?
¡¡¡¡function subst ($handle, $tag, $autoload = true) {
¡¡¡¡$append = false;
¡¡¡¡$debug = $this->DEBUGALL || $this->DEBUG['subst'];
¡¡¡¡$this->LAST = $handle;
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload)");
¡¡¡¡// For compatibility with FastTemplate, the results need to overwrite
¡¡¡¡// for an array.
¡¡¡¡This really only seems to be useful in the case of
¡¡¡¡// something like
¡¡¡¡//
¡¡¡¡$t->parse ('MAIN', array ('array', 'main'));
¡¡¡¡// Where the 'main' template has a variable named MAIN which will be
¡¡¡¡// set on the first pass (i.e., when parasing 'array') and used on the
¡¡¡¡// second pass (i.e., when parsing 'main').
¡¡¡¡if (gettype($tag) == 'array') {
¡¡¡¡foreach (array_values($tag) as $t) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: calling subst($handle,$t,$autoload)");
¡¡¡¡$this->subst ($handle, $t, $autoload);
¡¡¡¡}
¡¡¡¡return $this->HANDLE[$handle];
¡¡¡¡}
¡¡¡¡// Period prefix means append result to pre-existing value.
¡¡¡¡if (substr($tag,0,1) == '.') {
¡¡¡¡$append = true;
¡¡¡¡$tag = substr ($tag, 1);
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in append mode");
¡¡¡¡}
¡¡¡¡// $this->TEMPLATE[$tag] will only be set if it was explicitly
¡¡¡¡// declared via define(); i.e., inferior templates will not have an
¡¡¡¡// entry.
¡¡¡¡if (isset($this->TEMPLATE[$tag])) {
¡¡¡¡if (!isset($this->TEMPLATE[$tag]['parsed'])
¡¡¡¡|| !$this->TEMPLATE[$tag]['parsed'])
¡¡¡¡$this->parse_internal ($tag);
¡¡¡¡} else {
¡¡¡¡if (!$this->DYNAMIC) {
¡¡¡¡$this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload): " .
¡¡¡¡'no such tag and dynamic templates are turned off', true);
¡¡¡¡}
¡¡¡¡if ($autoload) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: TEMPLATE[tag=$tag] not found, trying autoload");
¡¡¡¡foreach (array_keys($this->TEMPLATE) as $t) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: calling parse_internal (tag=$t)");
¡¡¡¡if (!isset($this->TEMPLATE[$tag]['parsed'])
¡¡¡¡|| !$this->TEMPLATE[$tag]['parsed'])
¡¡¡¡$this->parse_internal ($t);
¡¡¡¡}
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ('subst: retrying with autoload = false');
¡¡¡¡$this->subst ($handle, $tag, false);
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ('subst: completed with autoload = false');
¡¡¡¡return;
¡¡¡¡} else {
¡¡¡¡$this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload):
¡¡¡¡no such tag", true);
¡¡¡¡}
¡¡¡¡}
¡¡¡¡if (!$append) {
¡¡¡¡$this->TEMPLATE[$tag]['result'] = ';
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in overwrite mode");
¡¡¡¡}
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ('subst: type(this->TEMPLATE[$tag]['part']) => ' .
¡¡¡¡gettype($this->TEMPLATE[$tag]['part']));
¡¡¡¡// Hmmm, clear() called before subst() seems to result in this not
¡¡¡¡// being defined which leaves me a bit confused....
¡¡¡¡$result = ';
¡¡¡¡if (isset($this->TEMPLATE[$tag]['part'])) {
¡¡¡¡reset ($this->TEMPLATE[$tag]['part']);
¡¡¡¡foreach (array_keys($this->TEMPLATE[$tag]['part']) as $p) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: looking at TEMPLATE[$tag]['part'][$p]");
¡¡¡¡$tmp = $this->TEMPLATE[$tag]['part'][$p];
¡¡¡¡// Don't try if ($p == 'parent')....
¡¡¡¡if (strcmp ($p, 'parent') == 0) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: skipping part $p");
¡¡¡¡$tmp = ';
¡¡¡¡} else if (gettype($this->TEMPLATE[$tag]['part'][$p]) == 'string') {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: using part $p");
¡¡¡¡reset ($this->VAR);
¡¡¡¡// Because we treat VAR and HANDLE separately (unlike
¡¡¡¡// class.FastTemplate.php3), we have to iterate over both or we
¡¡¡¡// miss some substitutions and are not 100% compatible.
¡¡¡¡while (list($key,$val) = each ($this->VAR)) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: substituting VAR $key = $val in $tag");
¡¡¡¡$key = '{'.$key.'}';
¡¡¡¡$tmp = str_replace ($key, $val, $tmp);
¡¡¡¡}
¡¡¡¡reset ($this->HANDLE);
¡¡¡¡while (list($key,$val) = each ($this->HANDLE)) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: substituting HANDLE $key = $val in $tag");
¡¡¡¡$key = '{'.$key.'}';
¡¡¡¡$tmp = str_replace ($key, $val, $tmp);
¡¡¡¡}
¡¡¡¡$result .= $tmp;
¡¡¡¡} else {
¡¡¡¡$xtag = $this->TEMPLATE[$tag]['part'][$p]['tag'];
¡¡¡¡if ($debug) {
¡¡¡¡$this->logwrite ("subst: substituting other tag $xtag result in $tag");
¡¡¡¡}
¡¡¡¡// The assignment is a no-op if the result is not set, but when
¡¡¡¡// E_ALL is in effect, a warning is generated without the
¡¡¡¡// isset() test.
¡¡¡¡if (isset ($this->TEMPLATE[$xtag]['result']))
¡¡¡¡$result .= $this->TEMPLATE[$xtag]['result'];
¡¡¡¡}
¡¡¡¡}
¡¡¡¡}
¡¡¡¡if ($this->STRICT) {
¡¡¡¡// If quiet-mode is turned on, skip the check since we're not going
¡¡¡¡// to do anything anyway.
¡¡¡¡if (!$this->QUIET) {
¡¡¡¡if (preg_match ($this->REGEX_VAR, $result)) {
¡¡¡¡$this->error ("<B>unmatched tags still present in $tag</B><BR />");
¡¡¡¡}
¡¡¡¡}
¡¡¡¡} else {
¡¡¡¡$result = preg_replace ($this->REGEX_VAR, ', $result);
¡¡¡¡}
¡¡¡¡if ($append) {
¡¡¡¡if ($debug) {
¡¡¡¡$this->logwrite ("subst: appending TEMPLATE[$tag]['result'] = $result");
¡¡¡¡$this->logwrite ("subst: old HANDLE[$handle] = {$this->HANDLE[$handle]}");
¡¡¡¡$this->logwrite ("subst: old TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");
¡¡¡¡}
¡¡¡¡// The isset() tests are to suppresss warning when E_ALL is in effect
¡¡¡¡// and the variables have not actually been set yet (even though the
¡¡¡¡// user specified append-mode).
¡¡¡¡if (isset ($this->HANDLE[$handle]))
¡¡¡¡$this->HANDLE[$handle] .= $result;
¡¡¡¡else
¡¡¡¡$this->HANDLE[$handle] = $result;
¡¡¡¡if (isset ($this->TEMPLATE[$tag]['result']))
¡¡¡¡$this->TEMPLATE[$tag]['result'] .= $result;
¡¡¡¡else
¡¡¡¡$this->TEMPLATE[$tag]['result'] = $result;
¡¡¡¡if ($debug) {
¡¡¡¡$this->logwrite ("subst: new HANDLE[$handle] = {$this->HANDLE[$handle]}");
¡¡¡¡$this->logwrite ("subst: new TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");
¡¡¡¡}
¡¡¡¡} else {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("subst: setting TEMPLATE[$tag]['result'] = $result");
¡¡¡¡$this->HANDLE[$handle]
¡¡¡¡= $result;
¡¡¡¡$this->TEMPLATE[$tag]['result'] = $result;
¡¡¡¡}
¡¡¡¡return $this->HANDLE[$handle];
¡¡¡¡}
¡¡¡¡//
¡¡¡¡// Description
¡¡¡¡//
¡¡¡¡Clear a block from a template.
¡¡¡¡The intent is to remove an inferior
¡¡¡¡//
¡¡¡¡template from a parent.
¡¡¡¡This works even if the template has already
¡¡¡¡//
¡¡¡¡been parsed since we go straight to the specified template and clear
¡¡¡¡//
¡¡¡¡the results element.
¡¡¡¡If the given template has not yet been
¡¡¡¡//
¡¡¡¡loaded, the load is forced by calling parse_internal().
¡¡¡¡//
¡¡¡¡function clear_dynamic ($tag = NULL) {
¡¡¡¡$debug = $this->DEBUGALL || $this->DEBUG['clear_dynamic'];
¡¡¡¡if (is_null ($tag)) {
¡¡¡¡// Clear all result elements.
¡¡¡¡Uhm, needs to be tested.
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("clear_dynamic (NULL)");
¡¡¡¡foreach (array_values ($this->TEMPLATE) as $t) {
¡¡¡¡$this->clear_dynamic ($t);
¡¡¡¡}
¡¡¡¡return;
¡¡¡¡} else if (gettype($tag) == 'array') {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("clear_dynamic ($tag)");
¡¡¡¡foreach (array_values($tag) as $t) {
¡¡¡¡$this->clear_dynamic ($t);
¡¡¡¡}
¡¡¡¡return;
¡¡¡¡}
¡¡¡¡else if (!isset($this->TEMPLATE[$tag])) {
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("clear_dynamic ($tag) --> $tag not set, calling parse_internal");
¡¡¡¡$this->parse_internal ($tag);
¡¡¡¡// $this->TEMPLATE[$tag] = array ();
¡¡¡¡}
¡¡¡¡if ($debug)
¡¡¡¡$this->logwrite ("clear_dynamic ($tag)");
¡¡¡¡// $this->TEMPLATE[$tag]['loaded']
¡¡¡¡= true;
¡¡¡¡// $this->TEMPLATE[$tag]['string']
¡¡¡¡= ';
¡¡¡¡$this->TEMPLATE[$tag]['result'] = ';
¡¡¡¡// $this->TEMPLATE[$tag]['clear']
¡¡¡¡= true;
¡¡¡¡}
¡¡¡¡//
¡¡¡¡// Description
¡¡¡¡//
¡¡¡¡Clear the results of a handle set by parse().
¡¡¡¡The input handle can
¡¡¡¡//
¡¡¡¡be a single value, an array, or the PHP constant NULL.
¡¡¡¡For the
|
|