// // 説明 // 再帰的な内部解析ルーチン。これにより、 // 動的な下位テンプレートを含むテンプレートが再帰的に解析されます。 // これらの各下位テンプレートは、TEMPLATE 配列内に独自のエントリを取得します。 // function &parse_internal_1 ($tag, $rest = ) { $debug = $this->DEBUGALL || $this->DEBUG[parse_internal_1]; if (empty($tag)) { $this->error ("parse_internal_1: 空のタグが無効です", true); if ($debug) $this->logwrite ("parse_internal_1 (tag=$tag,rest=$rest)"); while (!empty($rest)) { if ($debug) $this->logwrite (parse_internal_1: REGEX_DYNBEG 検索:rest => . $rest); if (preg_match ($this->REGEX_DYNBEG, $rest, $dynbeg)) { // 一致が見つかったので、2 つの部分に分割し、 // 一致する END の後半を検索します。 // next 要素に入る文字列には、BEGIN // ブロックを形成する HTML コメントが含まれます。 if ($debug) $this->logwrite (parse_internal_1: match beg => . $dynbeg[1]); $pos = strpos ($rest, $dynbeg[1]); // BEGIN コメントの両側のテキストが // 空白のみであるかどうかを確認します。その場合は、その行全体を削除します。 $ok = false; for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) { $c = $rest{$offbeg}; if ($c == "
") { $okay = true; $offbeg++; Break; } if (($c != ) && ($c != " ")) { $offbeg = $pos; Break; } } if (! $okay) { $offend = $pos + strlen($dynbeg[1]); } else { $l = strlen ($rest) for ($offend = $pos + strlen($dynbeg[1]); $offend 0) part[] = substr ($rest, 0, $offbeg); $rest = substr ($rest, $offend); $sub = ; if ($debug) $this->logwrite ("parse_internal_1: pos = $ で見つかりました) pos"); // さて、ここでは実際には次の // END ブロックだけに興味があるのではありません。 // この BEGIN ブロックと一致する次の END ブロックだけに興味があります。 // これは最も効率的ではありません。実際には、BEGIN ブロックと END ブロックをマークするだけの // 文字列を 1 回のパスで実行できます。 // 単純なアルゴリズムになります (逆の preg があった場合)。 preg_match ($this->REGEX_DYNEND, $rest, $dynend)) { if ($debug) $this->logwrite (parse_internal_1: REGEX_DYNEND 検索:rest => . $rest); if ($debug) $this->logwrite (parse_internal_1: beg => . $dynend[1] に一致); $pos = strpos ($rest, $dynend[1]); if ($dynbeg[2] == $dynend[2]) { $found = true; // END コメントの両側のテキストが // 空白のみであるかどうかを確認します。その場合は、その行全体を削除します。 $ok = false; for ($offbeg = $pos - 1; $offbeg >= 0; $offbeg--) { $c = $rest{$offbeg}; if ($c == "
") { $offbeg++; $okay = true; Break; } if (($c != ) && ($c != " ")) { $offbeg = $pos; Break; } } if (! $okay) { $offend = $pos + strlen($dynend[1]); } else { $l = strlen ($rest); for ($offend = $pos + strlen($dynend[1]); $offend logwrite (" parse_internal_1: DYNAMIC BEGIN: (pos,len,beg,end) => ($pos, " . strlen($dynbeg[1]) . ", $offbeg, $offend) // これには、 // $rest = substr ($rest, $pos); // これにより、END ブロック行の空白が保持されます。 // $rest = substr ($rest, $pos+strlen($dynend[1]) ); // $sub .= substr ($rest, 0, $pos); $sub .= substr ($rest, $offbeg); // すでにロードされています// クリア テストは、実際には、clear() ロジックにバグを隠していました.... 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]) { // 空の異常なケースを省略動的なテンプレート。 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]][パーツ][親] = $tag; $this->TEMPLATE[$dynend[2]][loaded] = true; $part[] = &$this->TEMPLATE[$dynend[2]]; $this->TEMPLATE[$dynend[2]][タグ] = $dynend[2];壊す; } 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 ("不正な形式の動的テンプレート、END がありません
" . "$dynbeg[1]
", true); } } else { // ぶら下がり END ブロックがないことを確認するのは合理的であるように見えますが、 // 常にぶら下がり END ブロックがあるように見えます。 // 劣ったテンプレートの前の部分の BEGIN 文字列と、 // 劣ったテンプレートの後の部分の END 文字列 したがって、このテストが機能するには、 // 最後の一致の直前を調べる必要があります。 if (preg_match ( $this->REGEX_DYNEND, $rest, $dynend)) { // $this->error ("不正な形式の動的テンプレート、ぶら下がっている END
" . // "$dynend[1]
", 1); } $part[] = $rest; $rest = ; } } return $part; } // // 説明 // テンプレートを解析します。$tag が実際には配列の場合、 //単純な文字列タグの場合でも、 // 動的テンプレートが含まれている場合はテンプレートを再帰的に解析でき、 // それらも自動的にロードするように設定されています。 // function parse_internal ($tag) { $debug = $this->DEBUGALL || $this->DEBUG[parse_internal]; $append = false; if ($debug) $this->logwrite ("parse_internal (tag=$tag)"); // これは実際には class.FastTemplate.php3 の仕組みを引き継いだもので、 // subst() がすでにその配列を分解していると思うので、 // 必要ないはずです。誰かが内部メンバー // 関数を直接呼び出さない限り。 if (gettype($tag) == array) { reset ($tag); foreach ($tag as $t) { $this->parse_internal ($t) } } else { // ファイルがまだロードされていない場合はロードします。 // 最後にロードしてからファイルが変更された場合に、 // ファイルを再ロードするロジックを組み込むとよいかもしれませんが、 // 複雑になりすぎます。 // ページのロード間で永続変数として浮動状態に維持し始める場合にのみ意味を成します。 if (!isset($this->TEMPLATE[$tag][loaded])) { if ($this->TEMPLATE[$tag][dynamic]) { // テンプレートはdefine_dynamic()によって宣言されました。 if ($this->TEMPLATE[$tag][親]) $tag = $this->TEMPLATE[$tag][親]; else { // 同じファイルを持つ非動的テンプレートの検索を試みます。 // これは、define(array(), true) リセット ($this->TEMPLATE) によって定義されます。 foreach (array_keys($this->TEMPLATE) as $ptag) { if ($debug) $this->logwrite ("parse_internal: 非動的親 $ptag を探しています"); if (!$this->TEMPLATE[$ptag][dynamic] && ($this->TEMPLATE[$ptag][file] == $this->TEMPLATE[$tag][file])) { $tag = $ ptag;壊す; $this->TEMPLATE[$tag][string] = &$this->load($this->TEMPLATE[$tag][file]); $this->TEMPLATE[$tag][ロード済み] = 1; } // 動的テンプレートを自動的に検出することになっており、動的 // フラグが設定されていない場合は、動的セクションのテンプレートをスキャンします。動的セクション // マーカーは HTML コメントとして非常に厳密な構文を持ちます.... if ($this->DYNAMIC) { $this->TEMPLATE[$tag][tag] = $