Heim >php教程 >php手册 >class.rFastTemplate.php(二)

class.rFastTemplate.php(二)

WBOY
WBOYOriginal
2016-06-21 09:12:05781Durchsuche

  //
   // 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                   $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                         $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
\n" .
                             "$dynbeg[1]
\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
\n" .
               //            "$dynend[1]
\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);
   }

// 未完待续



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn