Yuriko.Net 個別記事

2008-03-28
晴れ

WordPress で日本語タグ重複問題解決パッチ案

ゆりこ による 11:16:09 の投稿
カテゴリー: WordPressハック

WordPress 2.3 から標準機能となったキーワードタグですが、日本語タグに英数字のスラッグを割り当てると、同じタグが重複してしまう問題があります (チケット#6313tai さんの記事)。例えば、「変なモノ」というタグに「funny」というスラッグを割り当てた場合、そのタグを付与した記事を編集すると、同じ「変なモノ」タグでありながら、UTF-8 なスラッグ「%e5%a4%89%e3%81%aa%e3%83%a2%e3%83%8e」を持つタグを新たに作ってしまいます。タグ管理画面では、「変なモノ」タグが重複しています (1つはスラッグが「funny」で、もう1つはスラッグが「%e5%a4%89%e3%81%aa%e3%83%a2%e3%83%8e」のもの)。つまり、スラッグが「funny」である「変なモノ」タグの存在を認識せず、新たに「変なモノ」タグを作っているわけです。タグ名とスラッグを違うものにしたら発生するため、現状のタグ実装では、スラッグを変更する機能が使えないことを意味します。

で、WordPress 2.5-RC2 のソースを調査してみたのですが、どうやら、wp-includes/taxonomy.php の is_term() (同じタグが存在するかのチェック関数) でデータベースクエリーの WHERE 節を組み立てる部分がまずいのが原因でした。

if ( '' === $term = sanitize_title($term) )
	return 0;
$where = $wpdb->prepare( "t.slug = %s", $term );

要するに、同一タグの存在チェックを、タグスラッグでしか比較していないのです!! これでは、スラッグをタグ名から変更した場合、重複するのは当然です。

とりあえず、taxonomy が post_tag の場合はタグ名でも比較チェックを行うパッチを考えてみました。手元のテストでは重複問題には対処できましたが、副作用がどれだけあるかは不明です……。

if ( '' === $sanitized = sanitize_title($term) )
	return 0;
if ( $taxonomy = 'post_tag' ) {
	$where = $wpdb->prepare( "(t.slug = %s OR t.name = %s)", $sanitized , $term );
} else {
	$where = $wpdb->prepare( "t.slug = %s", $sanitized );
}

[追記] 続報があります。

トラックバック・コメント »

  1. すばらしい!パッチを適用してみましたがばっちりです。
    ぜひあのチケットにバッチを投げてください。

    taiからのコメント
  2. track へのコメントとしてパッチを投げてみました。これで理解してもらえるかちょっと不安ですが、遅くとも 2.6 に取り込まれるといいですね。

    yurikoからのコメント
  3. WordPress 2.5 のタグ重複について追う
    RC 3 までいっている WordPress 2.5 ですが、現在のところをタグ管理について不可解な動作があるようです。 ぼくも気になったのでちょっと調べてみました。
    わーどぷれすっ! » WP 2.5 の…

    hiromasa.another :o)からのトラックバック
  4. こんにちは。
    日本語タグ重複問題解決パッチ案なのですが
    これは、WordPress 2.3.3でも効果はありますでしょうか?

    WordPress 2.3.3のtaxonomy.phpはWordPress 2.5と内容が若干
    違っていたので、WordPress 2.3.3用の日本語タグ重複問題解決パッチ案を
    教えてもらえるとありがたいです。

    よろしくお願いします。

    ミニチュアダックスからのコメント
  5. ロジックは同じなのですが、SQL 文を組み立てる部分が違いますね。WP 2.5 からはプリペアードステートメントを使って、変数部分が適切にエスケープされるのですが、WP 2.3.3 では自前でエスケープしないといけません。おそらく、以下のコードで大丈夫でしょう。

    if ( '' === $sanitized = sanitize_title($term) )
    	return 0;
    if ( $taxonomy = 'post_tag' ) {
    	$term_sql = $wpdb->escape($term);
    	$where = "(t.slug = '$sanitized' OR t.name = '$term_sql')";
    } else {
    	$where = "t.slug = '$sanitized'";
    }
    ゆりこからのコメント
  6. どうもです。
    テストしてみたところ、無事に使えています。
    どうもありがとうございました。

    ミニチュアダックスからのコメント
  7. テストありがとうございます。念のため、シングルクォート(‘) を含むようなタグ名を追加した場合にどうなるか確認しておいてください。エスケープ回りであやしい動作が起きるのはこういう文字ですので。

    ゆりこからのコメント
  8. 2バイトタグの重複パッチ

    WordPressで運営始めて1ヶ月。プラグインを入れてみたり外してみたり、テーマファイルをカスタマイズしたり、色々いじっていますが、どうもおかしいのが「タグ」。
    日本語タグには「タ…

    Quuノタワゴトからのトラックバック
  9. [メモ][wordpress]wordpress2.6タグ重複問題とパッチと見落とし

    今日はwordpressで記事にたくさんタグをつけるという作業をしなければならなかった。ヒヨコのオスメスを分ける仕事もあるので、タグを入力する作業があってもおかしくないぞ。 知って…

    count_0の日記からのトラックバック
  10. ゆりこさん、初めまして!
    私はWordPress 2.5.1でブログを公開しているのですが、こちらのエントリーに書かれていらっしゃる問題に悩まされ、検索エンジンより来させていただきました。

    ありがたいことにパッチを載せてくださっていたので、taxonomy.phpの該当部分を書き換えてアップロードしてみたのですが、残念ながら私の環境ではパッチを当てる前後で変化が見られませんでした。
    (パッチを当てた後も新規投稿時、記事編集時ともタグが重複して作成されてしまいました)

    プラグインを全て停止した状態でも試してみましたが、それでも変わりません。
    是非この日本語タグの重複問題を解決したいと思っているので、何かアドバイスいただけたら幸いです。
    厚かましいお願いで申し訳ありませんが、どうぞよろしくお願いいたします。

  11. ティージーさん:

    ありがたいことにパッチを載せてくださっていたので、taxonomy.phpの該当部分を書き換えてアップロードしてみたのですが、残念ながら私の環境ではパッチを当てる前後で変化が見られませんでした。

    うーん。パッチの当て方が悪いのか、パッチが WordPress 2.5.1 では無効なのかどちらかですね。WP 2.5-RC 時代に作ったものなので、2.5.1 では使えない可能性は考えられます。よく分からなければ、WordPress 2.6.1 にアップグレードしてしまうのが手軽でしょう。

    ゆりこからのコメント
  12. ゆりこさん、お返事ありがとうございました!
    パッチを当てる箇所は何度も確認したので多分合っていたと思うのですが、2.5.1では無効な可能性があったのですね。
    WordPressをアップグレードすることで解決させました。どうもありがとうございました。

上に戻る

※スパム対策プラグインの影響により、すぐにトラックバックが反映されない場合があります。お手数ですが、半日ほど待ってみてください。

コメント投稿

※発言の責任を明確にするため「名無し」「通りすがり」「匿名希望」等の匿名は不可とします。捨てハンドルでもいいので必ず名乗ってください。
XHTML (使えるタグ): <a href="" title="" ktai=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <img localsrc="" alt=""> .
※スパム対策プラグインの影響により、すぐにコメント内容が表示されない場合があります。お手数ですが、半日ほど待ってみてください。

上に戻る