前回のこの件に関連して。
以下の修正を必要とする人はあまりいないかもしれないけど
たまたま自分が遭遇したので一応書いておきます。
タイトルには
「一部のコメントとトラックバックが重複してしまう」
と書いたんだけど、
これが発生するのは同じ MT のエクスポートファイルを
繰り返し WordPress にインポートしたとき。
インポートが中断されてしまったからやりなおすとかいう場合ね。
普通にインポートが完了すればこの問題は起きません。
WordPress のインポーターはよくできていて、
このインポーターは優秀なので重複したファイルはインポートしません。したがって何らかの理由でインポート作業が終了できなくても、安心してこのインポーターを何度でも実行することができます。
というふうになっている。
既に読み込み済みの記事がインポートするファイルにあったら
ちゃんとそこだけスキップしてくれて、
[記事の名前]はすでに存在しています。
と表示される。
ところが一部のコメントとトラックバックだけは
重複して読み込まれてしまうみたいなので修正してみた。
問題を引き起こしているところ
インポートするデータを処理するとき
そのコメントが既に読み込まれているかどうか判定するところで
問題が起こっている。
コメントは282行目あたり(バージョン2.7の場合)のこの部分、
トラックバックは298行目のこの部分で処理されている。
要するに
同じ記事についたコメントで
コメント主の名前とコメント日時の両方が一致するものは
同一のコメントと判定するんだけど、
同じコメントのデータでも
既にデータベースに入っているコメント主の名前と
新たにインポートする$ping[‘comment_author’] の値が違うことがあるので
重複して書き込まれてしまうみたい。
同じデータを元にしているのに
値が違うことがあるのは、次の2つの理由から。
理由1: データベース内のコメント主の名前が HTML エスケープされている
WordPress のデータベースでは
コメント主の名前に含まれる特殊文字の一部を
HTML 用にエスケープして格納しているみたい。
具体的には & と < と > を
& と < と > に。
これは HTML 内に不正なコードが入るのを防ぐためにやるんだけど、
普通はデータベースには文字列をそのまま入れておいて
HTML に出力するときだけエスケープするんじゃないかな。
格納する前にエスケープするのには何か理由があるんだろうか。
ともかく、DB 内のデータがそうなっているので
比較するときもそれに合わせないといけない。
& と < と > だけエスケープするということはこうですか。
htmlspecialchars($comment[‘comment_author’], ENT_NOQUOTES)
理由2: 変数内のコメント主の名前がバックスラッシュでエスケープされている
今度は DB 内のデータじゃなくて、
処理に使う変数に入っている名前の方。
あとで DB に格納するときのために
$comment[‘comment_author’] には
addslashes がかかっている。
” とか ‘ とか \ とかにバックスラッシュをつけるやつね。
ところがこれは格納するときのためにつけているやつなので
既に格納された DB 内のデータには
このバックスラッシュがついてない。
なので、比較するときには
変数の値からバックスラッシュを取った形にしないといけませんね。
こうですか。
stripslashes($comment[‘comment_author’])
修正おわり
というわけで2つの修正を組み合わせるとこうですか。
挙動から判断しただけで
処理に使われる関数やメソッドの中まで全部は追っかけてないけど、
まあたぶん大丈夫なんじゃないですか。
そもそもこれが必要なのって
- MT から WordPress に移行する人で
- インポートを繰り返し行う人で
- 今までもらったコメントかトラックバックの主の名前に & か < か > か ” か ‘ か \ がついている人で
- 重複しちゃったらいやだとか気にする人
なので、割とレアですね。
誰か「これ探してたんだよ!」という人がいたら
ぜひコメントかトラバで教えてください。
当然、& や ” つきの名前で。