首页 > 开发 > PHP > 正文

class.rFastTemplate.php(二)

2024-05-04 22:55:54
字体:
来源:转载
供稿:网友
,欢迎访问网页设计爱好者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);
   }

// 未完待续
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表