2008年3月28日の投稿

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 );
}

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