Wikiのページが時々,表示されない

Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
返信数: 13

moodle1.8.1+を使用しています.
以前から気になっていたのですが,Wikiのデータを表示する際に,時折,添付したファイル(上は正常な時,下は表示されない時の画面)のように選択したページの中身が表示されないことがあります.[編集]タブを一旦,選択してから[表示]タブを選び直すと表示されますので,「まぁ,いいか」と気にしないことにしていました.しかし,近頃,かなりの作業をWiki上で行なうようになってきてからは,この現象があまり無視できなくなってきました.日本語を使用しているのが原因だとすると放置しておく訳にはいかないでしょう.

この現象,他の方々の環境でも発生しているのでしょうか?


根本的な原因ではありませんが,どのようなメカニズムに関係しているのか,までは分かりました.キャッシュです.
画面に表示するテキストデータをそのまま出力するのではなく,選択したオプションに従って余計な文字を取り除いたり,付加したりするフィルタ処理を行うformat_text()関数に組み込まれている機能です.format_text()関数のオーバーヘッドを抑えるために,既に一回,同じデータを同じオプションで一定時間以内に処理したのであれば,その処理結果をMySQLに(MD5ハッシュ文字列をキーとして)キャッシュしておくことで,同じ整形処理をもう一度行なわずに,キャッシュのデータをデータベースから読み出して再利用します.

ewiki_page()でデータベースから獲得した$contentを単にprint()している箇所でこの現象が発生しています.データベースから獲得したWikiのデータを画面に表示する前に,lib/weblib.php中のformat_text()でフィルタリングする際に,まずデータベース上に成型済みのデータがキャッシュされていないかどうかを調べています.そしてmd5ハッシュが同一であるデータがデータベース中にキャッシュされているのを見付けたら,整形処理は行わず,そのデータをformat_text()の戻り値としてmod/wiki/view.phpに返します.このキャッシュから受け取ったデータがおかしい.

厳密に言うと,まず$pagenameに対応するwikiデータをデータベースからewiki_page()で獲得してきます.どうやらこの関数の奥の方で,一旦,format_text()を呼んでいるようです.この段階では$contentはWikiタイトルなどは含まれず,単に本文だけのデータでした.その後,ewiki_page()から戻ってくるまでの間に$contentには他の情報(タイトルなど)が追加されて戻ってきます.ヘッダー情報やシンプルボックスを出力した後に,print(format_text($content, $moodle_format));で$contentを出力します.この段階で$contentは正しい情報を持っているにも関わらず,format_text()からの戻り値が期待通りではありません.キャッシュが無効な時は正しく表示され,キャッシュが有効になるとhtmlタグの一部のみが表示されるだけです.

キャッシュの格納段階でおかしいのか,それとも読み出しでおかしいのか,まだ分かりません.ただ,消極的な対処方法だけは見つけました.wikiの本文を表示する時だけはキャッシュを無効にする方法です.以下にその修正箇所を示します.

print_simple_box_start('center', '100%', '', '20');

/// Don't filter any pages containing wiki actions (except view). A wiki page containing
/// actions will have the form [action]/[pagename]. If the action is 'view' or the '/'
/// isn't there (so the action defaults to 'view'), filter it.
/// If the page does not yet exist, the display will default to 'edit'.
if((count($actions) < 2 || $actions[0] == "view") && $wiki_entry &&
record_exists('wiki_pages', 'pagename', addslashes($page), 'wiki', $wiki_entry->id)) {
// print(format_text($content, $moodle_format));
$options->nocache = true;
print(format_text($content, $moodle_format, $options));
} else if($actions[0]=='edit' && $reallyedit) {


繰り返しますが,根本的な解決では無いでしょう.キャッシュを使用しないで毎回,Wikiのページを表示するたびにテキストデータの整形処理を行うため効率は落ちるのだと思います(うちの環境ではデータベースへのアクセスの方が負担が大きいのでは?).長々とすみません.もし他の方の環境でも発生する問題ならば,もう少し詳しく調べてみます.
添付 Wiki_nodisp.jpg
Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
といいつつももう少し調べてみたら,htmlソースで問題の原因になりそうな部分を発見しました.

<div class="wiki view EveryRemoConの仕様-��開発者用-��">

正しくは,
EveryRemoConの仕様-(開発者用-) です.(と)が化けていますね.キャッシュとしてデータベースに登録され,それを読み出す時に”
<div class="wiki view EveryRemoConの仕様-”までしかreturnされていません.いつどこで化けたのか.整形する際に何か問題があるのか.
ともかくこれがキャッシュが正しく機能していない原因です.


#-- html post processing
if ($pf_a = $ewiki_plugins["page_final"]) {
ksort($pf_a);
foreach ($pf_a as $pf) {
$pf($o, $id, $data, $action);
}
}

mod/wiki/ewiki.php中,ewiki_page()の以上の処理で
<div class="wiki view EveryRemoConの仕様-��開発者用-��">

を追加しているようです.
 

プラグインのところは良く分からないのですが,どうやら,
#-- encloses whole page output with a descriptive <div>
function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
$o = "<div class=\"wiki $action "
. strtr($id, ' ./ --_!"?$%&()=???{[]}`+#*;:,<>| @????????^???\'\\',
'- -----------------------------------------------')
. "\">\n"
. $o . "\n</div>\n";
}
これが怪しそうです.このstrtr()のせいで,"(”と”)”が化けているのでしょう!
これをマルチバイト対応の関数に変えれば直りそうです.

...しかし,strtr()関数は初めて使います.この変換,一体どのようにマルチバイト対応の関数に置き換えたら良いのでしょう??? 詳しい方,お助け下さい.(そもそも何をどう置き換えようとしているのか理解できません)

Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Mitsuhiro Yoshida の投稿
画像 Developers 画像 Particularly helpful Moodlers 画像 Translators
MoodleのWikiモジュールではErfurtWikiのバージョンR1.01d (08-Feb-2004 13:53) を使用しているようです。

ErfurtWikiの最新バージョンR1.02b (16-Jun-2005 09:05) を確認しましたところ、下記のように同じ関数「ewiki_page_css_container」が大きく変わっているようです。
新しいバージョンのErfurtWikiを使用しても動作すると思いますので、こちらをお試しになられてはいかがでしょうか。ウインク

対象プログラム: ewiki-R1.02b/ewiki.php
対象箇所: 691行目

#-- encloses whole page output with a descriptive <div>
function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
$sterilized_id = trim(preg_replace('/[^\w\d]+/', "-", $id), "-");
$sterilized_id = preg_replace('/^(\d)/', 'page$1', $sterilized_id);
$o = "<div class=\"wiki $action $sterilized_id\">\n" . $o . "\n</div>\n";
}

Mitsuhiro Yoshida への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
ありがとうございます.
wikiモジュール自体を入れ替えるのは勇気が必要ですので,ewiki_page_css_container()関数のみ入れ替えてみようと思います.

しかし,元々の関数の処理はやはり謎です.実験したわけでは無いのですが,strtr()関数の私の理解では,
strtr($str, 'abcd', 'ABCD');
というのは,$str中のaをAに,bをBに,cをCに,dをDに置換するのではなく,
a → A
ab → AB
abc → ABC
abcd → ABCD
であり,b はbのまま,bcdもbcdのまま,という風に理解しています.

オリジナルの
strtr($id,
' ./ --_!"?$%&()=???{[]}`+#*;:,<>| @????????^???\'\\',
'- -----------------------------------------------')
は,禁止文字を'-'に置き換えようという意図を感じます.もしそのような変換を行ないたいならばarrayを使用して連想記憶で対応しないとダメですよね. "????????"あたりは特に理解できません.

$sterilized_id = trim(preg_replace('/[^\w\d]+/', "-", $id), "-");
$sterilized_id = preg_replace('/^(\d)/', 'page$1', $sterilized_id);
こちらのpreg_replace()ならばUTF-8に対応しているので問題は無さそうです.
後ほど,試して見ます.

Mitsuhiro Yoshida への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
一応,新しいバージョンのewiki_page_css_container()に変えてみたところ,そのままではNG(余計に悪化)で,さらに修正を加えたら動きました.

#-- encloses whole page output with a descriptive <div>
function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
// $sterilized_id = trim(preg_replace('/[^\w\d]+/', "-", $id), "-");
$sterilized_id = trim(preg_replace('/^[\w\d]+/', "-", $id), "-");
$sterilized_id = preg_replace('/^(\d)/', 'page$1', $sterilized_id);
$o = "<div class=\"wiki $action $sterilized_id\">\n" . $o . "\n</div>\n";
}

分かりにくいのですが,preg_replace()の検索パターン,[^\w\d]を^[\w\d]にしてあります.Perl互換の正規表現が良く分からないのですが,前者ですと”(開発者用)”という文字列がカッコも含めて全て化けました.後者にすると化けません.「^ :検索対象の開始を言明する」とPHPの参考書には書いてありますので,^が文字クラス[]の中にあるのは不自然に感じたので,頭に出しました(よく理解できていません).

ただ,化けない=なにもしていない,ということで,本来の機能を果たしていない恐れがあります.私が作成しているwikiでは”/ほにゃらら/”という$idが発生していません.何かWikiの書き方でそのようなことが可能なのか?
(例えば同じ見出し語を別のカテゴリーのようなものに分けて別ページとして扱う方法があるのかな?と予想しています)

なお,以上のようにewiki_page_css_container()関数を入れ替えた場合,それ以前に示したキャッシュを無効にする修正は必要ありません.


少々気になるのは,この新しい関数ではオリジナルの関数が行なおうとしていた(と思われる)禁止文字の排除が行なわれていません.問題が発生しないのでしょうか...可能かどうか分かりませんが,$idにhtmlタグが含まれていたりすると問題が出そうです.もしかして禁止文字を取り除く作業を他の関数が代行するように変更されているのだとすると危険かも知れません.

試しに[テスト<a>]という見出し語をWikiに作成してみました.どこからもリンクされていないと言う.ただ,これはオリジナルのソースに戻しても生じる障害ですので,[ ] 内にhtmlタグを入れてはいけないのは仕様だ,と思えばwwiki_page_css_container()のせいではない,と割り切ることにしたのでしょうか.

Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Haruhiko Okumura の投稿
しばらくさぼっていてすみません。
このあたり,三重大版ではすでに

#-- encloses whole page output with a descriptive <div>
function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
// $o = "<div class=\"wiki $action "
//    . strtr($id, ' ./ --_!"§$%&()=?²³{[]}`+#*;:,<>| @µöäüÖÄÜߤ^°«»\'\\',
//                '-  -----------------------------------------------')
//    . "\">\n"
//    . $o . "\n</div>\n";
  $o = "<div class=\"wiki $action\">\n" . $o . "\n</div>\n";  // okumura
}

のようにばさっと削除してありました。どうしてこう直したかは覚えていません。^^;
Haruhiko Okumura への返信

Re: Wikiのページが時々,表示されない

- Haruhiko Okumura の投稿
あと,strtr は対応する文字を置き換えるので,
aはAに,bはBに,……となります。

いずれにしてもこういう処理はLatin-1以外は邪悪な文字だと思っている人たちがすることなので,見つけ次第,消すことにしています。例のOpera対応のは見逃していました。
Haruhiko Okumura への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿

ああ,なるほど.私の使用しているエディタ(秀丸エディタ)では@以降の文字が正しく表示できていなかった訳ですね.

strtr($id, ' ./ --_!"§$%&()=?²³{[]}`+#*;:,<>| @µöäüÖÄÜߤ^°«»\'\\', '- -----------------------------------------------')

これですと言わんとしていることが分かります.これは随分と危なっかしいコードですね.過渡期だったのでしょうか.

Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Haruhiko Okumura の投稿
念のため

preg_replace('/[^\w\d]+/', "-", $id)

について解説しますと,[^\w\d] は,
  \w (英字)
  \d (数字)
以外の任意の文字ということです。
[^何々] は何々以外ということです。
ですから ^ の位置はこれでいいわけです。
Haruhiko Okumura への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
こちらも了解しました.
私の最初の書き込みで,まず / がデリミタであることに気付いていませんでした.Perl互換の正規表現の場合は/でパターンを囲むのでしたね.

[^\w\d]も了解しました.これもイジワルなコードですね.図らずも/^[\w\d]+/としたことで一応,うまく動いていたのは幸いでしたが,このままではやはり不具合を発生する可能性が高いのでコードを見直します.

preg_replace()で/[^\w\d]+/のパターンがマルチバイトコードの一部を破壊した訳ですから,やはりUTF-8に対応しているというのは,私が用いている参考書のミス(=間違ってはいなくても完全に正しくは無い)ですね.

Haruhiko Okumura への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
少し考えてみたのですが,
全体的な整合性から考えて,吉田さんご紹介の最新バージョンR1.02bのコードの改造ではなく,奥村先生ご紹介の”バッサリ切り”版を使ってみます.と思ったのですが,随分と思い切ってバッサリされていますね満面の笑顔 $idはあまり意味を持たないのでしょうか? HTMLタグについて詳しくないので分からないのですが,<div >要素のclassは何か意味を持つのでしょうか.

http://www.seo-equation.com/html/html/class

によるとclass名に日本語を利用しても構わない,列記してクラスを重複させても構わない(これは意味が分からない),ということで,classは wiki と $action(viewなど)とWikiの$idを列記している訳ですよね.最後の$idは無くても問題ないのでしょうか.

Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Haruhiko Okumura の投稿
あらあらあら ^^;
$id が消えていましたね。^^;
どうしてこれで問題なかったのでしょうか。^^;;;;
Haruhiko Okumura への返信

Re: Wikiのページが時々,表示されない

- Tatsuya Shirai の投稿
<div>要素のclassにどの程度の意味を持たせているか次第かな?と予想しています.
HTMLソースを見てみると,とりあえず全ての<div>などのタグにはclassを付けてあります.CSSといった仕組みに詳しくないので分からないのですが,もし$idの名前でクラスが定義されているならば,この<div>ブロックではそのクラスが継承されるという理解をしています.でも,定義されている気配がありません思慮深い

それよりももし日本語のタグを苦手とするブラウザーでエラーが出る(いまはそういう時代ではない?)よりは消してしまえ,というのは悪くない判断かなぁとも思います.

HTMLソースを解析する際に,"wiki view (見出し語)"をキーにして検索する,というのであれば便利かも知れません.ここ以降が,データベースから読み出したWikiのデータをHTML表示用に整形したものなので.

Tatsuya Shirai への返信

Re: Wikiのページが時々,表示されない

- Haruhiko Okumura の投稿
そうか,そこまで考えて $id も消したのかもしれません。ちゃんとコメントに書いておかないとすぐ忘れちゃいますね。^^;

$id なしでやってみます。