«
class.rFastTemplate(2)

时间:2008-5-31    作者:Deri    分类: 分享


   <p>  <code>   for ($offend = $pos + strlen($dynend[1]); $offend < $l; $offend++) {<br />            $c = $rest{$offend};<br />            if ($c == "\n") {<br />             &#160;$offend++;<br />             &#160;break;<br />            }<br />            if (($c != ' ') && ($c != "\t")) {<br />             &#160;$offend = $pos + strlen($dynend[1]);<br />             &#160;break;<br />            }<br />          &#160;}<br />         }<br />         // if ($debug)<br />         // $this->logwrite ("parse_internal_1: DYNAMIC BEGIN: (pos,len,beg,end) => ($pos, " . strlen($dynbeg[1]) . ", $offbeg, $offend)<br />         // This includes the contents of the REGEX_DYNEND in the output<br />         // $rest = substr ($rest, $pos);<br />         // This preserves whitespace on the END block line(s).<br />         // $rest = substr ($rest, $pos+strlen($dynend[1]));<br />         // $sub .= substr ($rest, 0, $pos);<br />         $sub .= substr ($rest, 0, $offbeg);<br />         $rest = substr ($rest, $offend);<br />         // Already loaded templates will not be reloaded. The<br />         // 'clear' test was actually hiding a bug in the clear()<br />         // logic....<br />         if (false && isset($this->TEMPLATE[$dynend[2]]['clear'])<br />           && $this->TEMPLATE[$dynend[2]]['clear']) {<br />          &#160;$this->TEMPLATE[$dynend[2]]['string'] = '';<br />          &#160;$this->TEMPLATE[$dynend[2]]['result'] = '';<br />          &#160;$this->TEMPLATE[$dynend[2]]['part']  =<br />            $this->parse_internal_1 ($dynend[2], ' ');<br />         } else if (!isset($this->TEMPLATE[$dynend[2]]['loaded'])<br />              &#160;|| !$this->TEMPLATE[$dynend[2]]['loaded']) {<br />          &#160;// Omit pathological case of empty dynamic template.<br />          &#160;if (strlen($sub) > 0) {<br />            $this->TEMPLATE[$dynend[2]]['string'] = $sub;<br />            $this->TEMPLATE[$dynend[2]]['part'] &#160;=<br />             &#160;$this->parse_internal_1 ($dynend[2], $sub);<br />            $this->TEMPLATE[$dynend[2]]['part']['parent'] = $tag;<br />          &#160;}<br />         }<br />         $this->TEMPLATE[$dynend[2]]['loaded'] = true;<br />         $part[] = &$this->TEMPLATE[$dynend[2]];<br />         $this->TEMPLATE[$dynend[2]]['tag']  = $dynend[2];<br />         break;<br />       &#160;} else {<br />         $sub .= substr ($rest, 0, $pos+strlen($dynend[1]));<br />         $rest = substr ($rest, $pos+strlen($dynend[1]));<br />         if ($debug)<br />          &#160;$this->logwrite ("parse_internal_1: $dynbeg[2] != $dynend[2]");<br />       &#160;}<br />      }<br />      if (!$found) {<br />       &#160;$this->error ("malformed dynamic template, missing END<BR />\n" .<br />              &#160;"$dynbeg[1]<BR />\n", true);<br />      }<br />    &#160;} else {<br />      // Although it would appear to make sense to check that we don't<br />      // have a dangling END block, we will, in fact, ALWAYS appear to<br />      // have a dangling END block. We stuff the BEGIN string in the<br />      // part before the inferior template and the END string in the<br />      // part after the inferior template. So for this test to work,<br />      // we would need to look just past the final match.<br />      if (preg_match ($this->REGEX_DYNEND, $rest, $dynend)) {<br />       &#160;// $this->error ("malformed dynamic template, dangling END<BR />\n" .<br />       &#160;//      "$dynend[1]<BR />\n", 1);<br />      }<br />      $part[] = $rest;<br />      $rest = '';<br />    &#160;}<br />   }<br />   return $part;<br /> &#160;}<br /> &#160;//<br /> &#160;// Description<br /> &#160;//  Parse the template. If $tag is actually an array, we iterate over<br /> &#160;//  the array elements. If it is a simple string tag, we may still<br /> &#160;//  recursively parse the template if it contains dynamic templates and<br /> &#160;//  we are configured to automatically load those as well.<br /> &#160;//<br /> &#160;function parse_internal ($tag) {<br />   $debug = $this->DEBUGALL || $this->DEBUG['parse_internal'];<br />   $append = false;<br />   if ($debug)<br />    &#160;$this->logwrite ("parse_internal (tag=$tag)");<br />   // If we are handed an array of tags, iterate over all of them. This<br />   // is really a holdover from the way class.FastTemplate.php3 worked;<br />   // I think subst() already pulls that array apart for us, so this<br />   // should not be necessary unless someone calls the internal member<br />   // function directly.<br />   if (gettype($tag) == 'array') {<br />    &#160;reset ($tag);<br />    &#160;foreach ($tag as $t) {<br />      $this->parse_internal ($t);<br />    &#160;}<br />   } else {<br />    &#160;// Load the file if it hasn't already been loaded. It might be<br />    &#160;// nice to put in some logic that reloads the file if it has<br />    &#160;// changed since we last loaded it, but that probably gets way too<br />    &#160;// complicated and only makes sense if we start keeping it floating<br />    &#160;// around between page loads as a persistent variable.<br />    &#160;if (!isset($this->TEMPLATE[$tag]['loaded'])) {<br />      if ($this->TEMPLATE[$tag]['dynamic']) {<br />       &#160;// Template was declared via define_dynamic().<br />       &#160;if ($this->TEMPLATE[$tag]['parent'])<br />         $tag = $this->TEMPLATE[$tag]['parent'];<br />       &#160;else {<br />         // Try to find a non-dynamic template with the same file.<br />         // This would have been defined via define(array(), true)<br />         reset ($this->TEMPLATE);<br />         foreach (array_keys($this->TEMPLATE) as $ptag) {<br />          &#160;if ($debug)<br />            $this->logwrite ("parse_internal: looking for non-dynamic parent, $ptag");<br />          &#160;if (!$this->TEMPLATE[$ptag]['dynamic']<br />            &#160;&& ($this->TEMPLATE[$ptag]['file'] == $this->TEMPLATE[$tag]['file'])) {<br />            $tag = $ptag;<br />            break;<br />          &#160;}<br />         }<br />       &#160;}<br />      }<br />      $this->TEMPLATE[$tag]['string'] = &$this->load($this->TEMPLATE[$tag]['file']);<br />      $this->TEMPLATE[$tag]['loaded'] = 1;<br />    &#160;}<br />    &#160;// If we are supposed to automatically detect dynamic templates and the dynamic<br />    &#160;// flag is not set, scan the template for dynamic sections. Dynamic sections<br />    &#160;// markers have a very rigid syntax as HTML comments....<br />    &#160;if ($this->DYNAMIC) {<br />      $this->TEMPLATE[$tag]['tag'] = $tag;<br />      if (!isset($this->TEMPLATE[$tag]['parsed'])<br />        || !$this->TEMPLATE[$tag]['parsed']) {<br />       &#160;$this->TEMPLATE[$tag]['part'] = $this->parse_internal_1 ($tag, $this->TEMPLATE[$tag]['string']);<br />       &#160;$this->TEMPLATE[$tag]['parsed'] = true;<br />      }<br />    &#160;}<br />   }<br /> &#160;}<br /> &#160;//<br /> &#160;// Description<br /> &#160;//  class.FastTemplate.php3 compatible interface.<br /> &#160;//<br /> &#160;// Notes<br /> &#160;//  I prefer the name `subst' to `parse' since during this phase we are<br /> &#160;//  really doing variable substitution into the template. However, at<br /> &#160;//  some point we have to load and parse the template and `subst' will<br /> &#160;//  do that as well...<br /> &#160;//<br /> &#160;function parse ($handle, $tag, $autoload = true) {<br />   return $this->subst ($handle, $tag, $autoload);<br /> &#160;}<br /> &#160;//<br /> &#160;// Description<br /> &#160;//  Perform substitution on the template. We do not really recurse<br /> &#160;//  downward in the sense that we do not do subsitutions on inferior<br /> &#160;//  templates. For each inferior template which is a part of this<br /> &#160;//  template, we insert the current value of their results.<br /> &#160;//<br /> &#160;// Notes<br /> &#160;//  Do I want to make this return a reference?<br /> &#160;function subst ($handle, $tag, $autoload = true) {<br />   $append = false;<br />   $debug = $this->DEBUGALL || $this->DEBUG['subst'];<br />   $this->LAST = $handle;<br />   if ($debug)<br />    &#160;$this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload)");<br />   // For compatibility with FastTemplate, the results need to overwrite<br />   // for an array. This really only seems to be useful in the case of<br />   // something like<br />   //  &#160;$t->parse ('MAIN', array ('array', 'main'));<br />   // Where the 'main' template has a variable named MAIN which will be<br />   // set on the first pass (i.e., when parasing 'array') and used on the<br />   // second pass (i.e., when parsing 'main').<br />   if (gettype($tag) == 'array') {<br />    &#160;foreach (array_values($tag) as $t) {<br />      if ($debug)<br />       &#160;$this->logwrite ("subst: calling subst($handle,$t,$autoload)");<br />      $this->subst ($handle, $t, $autoload);<br />    &#160;}<br />    &#160;return $this->HANDLE[$handle];<br />   }<br />   // Period prefix means append result to pre-existing value.<br />   if (substr($tag,0,1) == '.') {<br />    &#160;$append = true;<br />    &#160;$tag = substr ($tag, 1);<br />    &#160;if ($debug)<br />      $this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in append mode");<br />   }<br />   // $this->TEMPLATE[$tag] will only be set if it was explicitly<br />   // declared via define(); i.e., inferior templates will not have an<br />   // entry.<br />   if (isset($this->TEMPLATE[$tag])) {<br />    &#160;if (!isset($this->TEMPLATE[$tag]['parsed'])<br />      &#160;|| !$this->TEMPLATE[$tag]['parsed'])<br />      $this->parse_internal ($tag);<br />   } else {<br />    &#160;if (!$this->DYNAMIC) {<br />      $this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload): " .<br />             'no such tag and dynamic templates are turned off', true);<br />    &#160;}<br />    &#160;if ($autoload) {<br />      if ($debug)<br />       &#160;$this->logwrite ("subst: TEMPLATE[tag=$tag] not found, trying autoload");<br />      foreach (array_keys($this->TEMPLATE) as $t) {<br />       &#160;if ($debug)<br />         $this->logwrite ("subst: calling parse_internal (tag=$t)");<br />       &#160;if (!isset($this->TEMPLATE[$tag]['parsed'])<br />         &#160;|| !$this->TEMPLATE[$tag]['parsed'])<br />         $this->parse_internal ($t);<br />      }<br />      if ($debug)<br />       &#160;$this->logwrite ('subst: retrying with autoload = false');<br />      $this->subst ($handle, $tag, false);<br />      if ($debug)<br />       &#160;$this->logwrite ('subst: completed with autoload = false');<br />      return;<br />    &#160;} else {<br />      $this->error ("subst (handle=$handle, tag=$tag, autoload=$autoload): no such tag", true);<br />    &#160;}<br />   }<br />   if (!$append) {<br />    &#160;$this->TEMPLATE[$tag]['result'] = '';<br />    &#160;if ($debug)<br />      $this->logwrite ("subst (handle=$handle, tag=$tag, autoload=$autoload) in overwrite mode");<br />   }<br />   if ($debug)<br />    &#160;$this->logwrite ('subst: type(this->TEMPLATE[$tag][\'part\']) => ' .<br />             gettype($this->TEMPLATE[$tag]['part']));<br />   // Hmmm, clear() called before subst() seems to result in this not<br />   // being defined which leaves me a bit confused....<br />   $result = '';<br />   if (isset($this->TEMPLATE[$tag]['part'])) {<br />    &#160;reset ($this->TEMPLATE[$tag]['part']);<br />    &#160;foreach (array_keys($this->TEMPLATE[$tag]['part']) as $p) {<br />      if ($debug)<br />       &#160;$this->logwrite ("subst: looking at TEMPLATE[$tag]['part'][$p]");<br />      $tmp = $this->TEMPLATE[$tag]['part'][$p];<br />      // Don't try if ($p == 'parent')....<br />      if (strcmp ($p, 'parent') == 0) {<br />       &#160;if ($debug)<br />         $this->logwrite ("subst: skipping part $p");<br />       &#160;$tmp = '';<br />      } else if (gettype($this->TEMPLATE[$tag]['part'][$p]) == 'string') {<br />       &#160;if ($debug)<br />         $this->logwrite ("subst: using part $p");<br />       &#160;reset ($this->VAR);<br />       &#160;// Because we treat VAR and HANDLE separately (unlike<br />       &#160;// class.FastTemplate.php3), we have to iterate over both or we<br />       &#160;// miss some substitutions and are not 100% compatible.<br />       &#160;while (list($key,$val) = each ($this->VAR)) {<br />         if ($debug)<br />          &#160;$this->logwrite ("subst: substituting VAR $key = $val in $tag");<br />         $key = '{'.$key.'}';<br />         $tmp = str_replace ($key, $val, $tmp);<br />       &#160;}<br />       &#160;reset ($this->HANDLE);<br />       &#160;while (list($key,$val) = each ($this->HANDLE)) {<br />         if ($debug)<br />          &#160;$this->logwrite ("subst: substituting HANDLE $key = $val in $tag");<br />         $key = '{'.$key.'}';<br />         $tmp = str_replace ($key, $val, $tmp);<br />       &#160;}<br />       &#160;$result .= $tmp;<br />      } else {<br />       &#160;$xtag = $this->TEMPLATE[$tag]['part'][$p]['tag'];<br />       &#160;if ($debug) {<br />         $this->logwrite ("subst: substituting other tag $xtag result in $tag");<br />       &#160;}<br />       &#160;// The assignment is a no-op if the result is not set, but when<br />       &#160;// E_ALL is in effect, a warning is generated without the<br />       &#160;// isset() test.<br />       &#160;if (isset ($this->TEMPLATE[$xtag]['result']))<br />         $result .= $this->TEMPLATE[$xtag]['result'];<br />      }<br />    &#160;}<br />   }<br />   if ($this->STRICT) {<br />  &#160;// If quiet-mode is turned on, skip the check since we're not going<br />  &#160;// to do anything anyway.<br />  &#160;if (!$this->QUIET) {<br />    if (preg_match ($this->REGEX_VAR, $result)) {<br />     &#160;$this->error ("<B>unmatched tags still present in $tag</B><BR />");<br />    }<br />  &#160;}<br />   } else {<br />    &#160;$result = preg_replace ($this->REGEX_VAR, '', $result);<br />   }<br />   if ($append) {<br />    &#160;if ($debug) {<br />      $this->logwrite ("subst: appending TEMPLATE[$tag]['result'] = $result");<br />      $this->logwrite ("subst: old HANDLE[$handle] = {$this->HANDLE[$handle]}");<br />      $this->logwrite ("subst: old TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");<br />    &#160;}<br />    &#160;// The isset() tests are to suppresss warning when E_ALL is in effect<br />    &#160;// and the variables have not actually been set yet (even though the<br />    &#160;// user specified append-mode).<br />    &#160;if (isset ($this->HANDLE[$handle]))<br />      $this->HANDLE[$handle] .= $result;<br />    &#160;else<br />      $this->HANDLE[$handle] = $result;<br />    &#160;if (isset ($this->TEMPLATE[$tag]['result']))<br />      $this->TEMPLATE[$tag]['result'] .= $result;<br />    &#160;else<br />      $this->TEMPLATE[$tag]['result'] = $result;<br />    &#160;if ($debug) {<br />      $this->logwrite ("subst: new HANDLE[$handle] = {$this->HANDLE[$handle]}");<br />      $this->logwrite ("subst: new TEMPLATE[$tag]['result'] = {$this->TEMPLATE[$tag]['result']}");<br />    &#160;}<br />   } else {<br />    &#160;if ($debug)<br />      $this->logwrite ("subst: setting TEMPLATE[$tag]['result'] = $result");<br />    &#160;$this->HANDLE[$handle] = $result;<br />    &#160;$this->TEMPLATE[$tag]['result'] = $result;<br />   }<br />   return $this->HANDLE[$handle];<br /> &#160;}<br /> &#160;//<br /> &#160;// Description<br /> &#160;//  Clear a block from a template. The intent is to remove an inferior<br /> &#160;//  template from a parent. This works even if the template has already<br /> &#160;//  been parsed since we go straight to the specified template and clear<br /> &#160;//  the results element. If the given template has not yet been<br /> &#160;//  loaded, the load is forced by calling parse_internal().<br /> &#160;//<br /> &#160;function clear_dynamic ($tag = NULL) {<br />   $debug = $this->DEBUGALL || $this->DEBUG['clear_dynamic'];<br />   if (is_null ($tag)) {<br />    &#160;// Clear all result elements. Uhm, needs to be tested.<br />    &#160;if ($debug)<br />      $this->logwrite ("clear_dynamic (NULL)");<br />    &#160;foreach (array_values ($this->TEMPLATE) as $t) {<br />      $this->clear_dynamic ($t);<br />    &#160;}<br />    &#160;return;<br />   } else if (gettype($tag) == 'array') {<br />    &#160;if ($debug)<br />      $this->logwrite ("clear_dynamic ($tag)");<br />    &#160;foreach (array_values($tag) as $t) {<br />      $this->clear_dynamic ($t);<br />    &#160;}<br />    &#160;return;<br />   }<br />   else if (!isset($this->TEMPLATE[$tag])) {<br />    &#160;if ($debug)<br />      $this->logwrite ("clear_dynamic ($tag) --> $tag not set, calling parse_internal");<br />    &#160;$this->parse_internal ($tag);<br />    &#160;// $this->TEMPLATE[$tag] = array ();<br />   }<br />   if ($debug)<br />    &#160;$this->logwrite ("clear_dynamic ($tag)");<br />   // $this->TEMPLATE[$tag]['loaded'] = true;<br />   // $this->TEMPLATE[$tag]['string'] = '';<br />   $this->TEMPLATE[$tag]['result'] = '';<br />   // $this->TEMPLATE[$tag]['clear'] &#160;= true;<br /> &#160;}<br /> &#160;//<br /> &#160;// Description<br /> &#160;//  Clear the results of a handle set by parse(). The input handle can<br /> &#160;//  be a single value, an array, or the PHP constant NULL. For the<br /></p>