kawano

WordPress「よく使われているタグから選択」が「-1」表示になった

WordPressにそんなに慣れていない状態の人間がハマった表題の問題と、その対応についてです。

背景

WordPressのfunctions.phpでカスタム投稿タイプに紐づけたカスタム分類を設定したところ、
管理画面->該当のカスタム投稿画面「よく使われているタグから選択」をクリックした時に「-1」が表示される事案が発生しました。

環境

  • WordPress4.7.5
  • User Role Editor プラグインを使います
  • カスタム投稿タイプ(Custom Post Type)、カスタム分類(Custom taxonomy)はプラグインを使わず、functions.phpへ追記する形で追加します

原因

functions.phpへ追記をするときに、
カスタム分類(タグ) の capability(権限) 設定で, assign_terms => edit_post_hoge とし、
カスタム投稿 の capability_type(メタ権限コンストラクタ文字列) 設定で post_hoge とした設定が原因でした。

register_taxonomy() - codex.wordpress.org
register_post_type() - codex.wordpress.org

正しくなかった設定(サンプル)

      register_taxonomy( 'hoge_tag', array( 'hoge' ), array(
                'hierarchical' => false,
                'label' => 'タグ',
                'public' => true,
                'show_ui' => true,
                'query_var' => true,
                'rewrite' => array('with_front' => false,'slug' => 'hoge/hogetag'),
                'capabilities' => array( 'assign_terms' => 'edit_post_hoge',
                                         'manage_terms' => 'manage_hoge',
                                         'edit_terms' => 'manage_hoge',
                                         'delete_terms' => 'manage_hoge' )
        ));

        $hoge_labels = array(
                'name' => "HOGE",
                'singular_name' => "HOGE",
                'add_new' => "新規追加",
                'add_new_item' => "新規HOGE追加",
                'edit_item' => "HOGEを編集",
                'new_item' => "新規HOGE",
                'view_item' => "表示",
                'search_items' => "HOGEを検索",
                'not_found' => "見つかりません",
                'not_found_in_trash' =>"ゴミ箱にはありません",
                'parent_item_colon' => '親',
                'menu_name' => 'HOGE'
        );
        $hoge_args = array(
                'labels' => $hoge_labels,
                'public' => true,
                'publicly_queryable' => true,
                'show_ui' => true,
                'show_in_menu' => true,
                'query_var' => true,
                'rewrite' => array('with_front' => false),
                'capability_type' => 'post_hoge',
                'has_archive' => true,
                'hierarchical' => false,
                'menu_position' => 5,
                'map_meta_cap' => true,
                'supports' => array( 'title', 'author', 'thumbnail' ),
                'taxonomies' => array( 'hoge_cat' , 'hoge_tag' )
        );
        register_post_type( 'hoge', $hoge_args );

原因(深追い)

WordPressのコアのコードに踏み込み、一つ一つ原因を追っていきます。

もしかすると、WordPressに慣れている方は上のだめな設定例をみただけで、原因の見当がついているかもしれません。そんな方はこれ以降読む必要ないかもしれません。

投稿画面「よく使われているタグから選択」クリックで、タグクラウドから情報を引っ張ってくる処理を行える権限は、wp-admin/includes/ajax-actions.phpwp_ajax_get_tagcloud() にあるとおり、assign_terms という権限です。ここでこけていて「-1」を返していました。

wp_ajax_get_tagcloud - developer.wordpress.org

        if ( ! current_user_can( $tax->cap->assign_terms ) ) {
                wp_die( -1 );
        }

今回 、このカスタム分類の assign_terms という権限に指定したのは edit_post_hoge でした。
ところでこの edit_post_hogeedit + post_hoge であり
edit + カスタム投稿のcapability_typeで指定した文字列 です。

実は(codex > register_post_type の capability_typeの項をよく見ると) カスタム投稿のcapability_typeで指定した文字列 は、以下の3パターンで「メタ権限」として、WordPress側で自動的にマッピングされる仕様になっていました。

edit + capability_type => edit_post
read + capability_type => read_post
delete + capability_type => delete_post

メタ権限のマッピングで、 edit_post_hogeedit_post 権限に自動で紐づけられていたため、 wp-includes/capabilities.phpmap_meta_caps で、 edit_post_hogeedit_post と読み替えられてしまい、

本来タグクラウド取得処理で必要だった、 assign_terms の権限とは合致しなかったのが元凶でした。

current_user_can() - developer.wordpress.org
map_meta_cap() - developer.wordpress.org

メタ権限は以下の変数に格納されているようでした。

global $post_type_meta_caps

dumpするとこんな感じでした。

Array
(
    [edit_post] => edit_post,
    [read_post] => read_post,
    [delete_post] => delete_post,
    [edit_page] => edit_post,
    [read_page] => read_post,
    [delete_page] => delete_post,
    [customize] => delete_post,
    [edit_post_hoge] => edit_post,
    [read_post_hoge] => read_post,
    [delete_post_hoge] => delete_post
)

この関数でも取れそうです。

_post_type_meta_capabilities() - developer.wordpress.org

解決策

assign_terms にメタ権限にマッピングされる文字列と被らないものを適当に割り当てて、User Role Editor プラグインで「権限を追加」し、必要なロールに割り当てれば無事、表示されました。

まとめ

こんな奇跡的に、文字列がたまたま合致してしまったがために起きるパターン、そうはないと思いますが、調べてもあまり出てこなかったので、残しておきたいと思いました。

権限設定をする時に、メタ権限に利用されそうな文字列にはご注意を。

お問い合わせはこちら