LoginSignup
0
0

More than 5 years have passed since last update.

記事作成画面、投稿者のドロップダウンリストを自由に並び替える

Posted at

とてもニッチなお話ですが、

WordPressで記事を投稿する際に、
上位のアカウントだと自分以外の投稿者を選ぶ事ができる。
ただこの項目、全てのユーザーを表示名順に並べただけのドロップダウンリストになっていて、
沢山のユーザー登録があるとエライコッチャな事になってしまう。
せめて、このリストを綺麗な順番に並び替えておきたい。

目標

漢字を含む、投稿者のドロップダウンリストを綺麗な五十音順にする。

さっそく初めます

フリガナを保存するフィールドを作る

WordPressのユーザー情報は wp_users というテーブルに保存されている。
五十音順の第一歩として、ここにフリガナを保存する kana というフィールドを作る。

本来であれば、ユーザー登録画面でフリガナも入力できる様にするべきだけど、
今回はまず現状を打破したくて、とりあえずフリガナの入力も含めて直接済ませた。

プルダウンリストのソートを変更する

管理画面のHTMLを覗くと post_author_override という名前でリストを生成しているらしい。
それをWordPressの本体で検索して辿って行くと、wp-includes/user.php にそれらしい物をみつけた。

wp-includes/user.php
//1498行目付近
function wp_dropdown_users( $args = '' ) {
    $defaults = array(
        'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',
        'orderby' => 'display_name', 'order' => 'ASC',
        'include' => '', 'exclude' => '', 'multi' => 0,
        'show' => 'display_name', 'echo' => 1,
        'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',
        'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false,
        'option_none_value' => -1
    );
//以下略

'orderby' => 'display_name' とある!
display_namewp_users で見たところズバリ表示名の様で、ここを kana に修正すれば解決するのでは!

wp-includes/user.php
//修正後
function wp_dropdown_users( $args = '' ) {
    $defaults = array(
        'show_option_all' => '', 'show_option_none' => '', 'hide_if_only_one_author' => '',
        'orderby' => 'kana', 'order' => 'ASC',
        'include' => '', 'exclude' => '', 'multi' => 0,
        'show' => 'display_name', 'echo' => 1,
        'selected' => 0, 'name' => 'user', 'class' => '', 'id' => '',
        'blog_id' => $GLOBALS['blog_id'], 'who' => '', 'include_selected' => false,
        'option_none_value' => -1
    );
//以下略

解決しなかった

すると、フリガナでも表示名でもなく、何故か user_login (ログインID)でソートされる様になった。
コードをそのまま読み進めると、どうも get_users という物の中で指定の要素以外の場合 user_login に修正する処理が行われている様だった。

改めてCodexを読むと、ちゃんと説明が書かれていた。

orderby - ソート順を決める項目。有効な値は 'ID', 'login', 'nicename', 'email', 'url', 'registered', 'display_name', 'post_count', または 'meta_value'。
WordPress Codex 日本語版 関数リファレンス/get users

後から追加したフィールド kana が含まれているハズもなく。
なんとか有効な値以外でも見逃してくれる様にしたい。

kanaを有効な値にする

調べていくと、parse_orderby という物をみつけた。
その時の $orderby に合わせて正しいものを入れなおす物らしい。

wp-includes/user.php
//960行目付近
    protected function parse_orderby( $orderby ) {
        global $wpdb;

        $meta_query_clauses = $this->meta_query->get_clauses();

        $_orderby = '';
        if ( in_array( $orderby, array( 'login', 'nicename', 'email', 'url', 'registered' ) ) ) {
            $_orderby = 'user_' . $orderby;
        } elseif ( in_array( $orderby, array( 'user_login', 'user_nicename', 'user_email', 'user_url', 'user_registered' ) ) ) {
            $_orderby = $orderby;
        } elseif ( 'name' == $orderby || 'display_name' == $orderby ) {
            $_orderby = 'display_name';
        } elseif ( 'post_count' == $orderby ) {
            // todo: avoid the JOIN
            $where = get_posts_by_author_sql( 'post' );
            $this->query_from .= " LEFT OUTER JOIN (
                SELECT post_author, COUNT(*) as post_count
                FROM $wpdb->posts
                $where
                GROUP BY post_author
            ) p ON ({$wpdb->users}.ID = p.post_author)
            ";
            $_orderby = 'post_count';
        } elseif ( 'ID' == $orderby || 'id' == $orderby ) {
            $_orderby = 'ID';
        } elseif ( 'meta_value' == $orderby || $this->get( 'meta_key' ) == $orderby ) {
            $_orderby = "$wpdb->usermeta.meta_value";
        } elseif ( 'meta_value_num' == $orderby ) {
            $_orderby = "$wpdb->usermeta.meta_value+0";
        } elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
            $include = wp_parse_id_list( $this->query_vars['include'] );
            $include_sql = implode( ',', $include );
            $_orderby = "FIELD( $wpdb->users.ID, $include_sql )";
        } elseif ( isset( $meta_query_clauses[ $orderby ] ) ) {
            $meta_clause = $meta_query_clauses[ $orderby ];
            $_orderby = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
        }

        return $_orderby;
    }

何にも当てはまらない場合、空の要素を返す様で、
呼び出し元のほうで、空の場合 user_login を入れる様な仕組みになっていた。
かなり強引だけど、ここに kana の場合の処理を入れたら動きそうだ。

wp-includes/user.php
//960行目付近
    protected function parse_orderby( $orderby ) {
        global $wpdb;

        $meta_query_clauses = $this->meta_query->get_clauses();

        $_orderby = '';
        if ( in_array( $orderby, array( 'login', 'nicename', 'email', 'url', 'registered' ) ) ) {
            $_orderby = 'user_' . $orderby;
        } elseif ( in_array( $orderby, array( 'user_login', 'user_nicename', 'user_email', 'user_url', 'user_registered' ) ) ) {
            $_orderby = $orderby;
        } elseif ( 'name' == $orderby || 'display_name' == $orderby ) {
            $_orderby = 'display_name';
        } elseif ( 'post_count' == $orderby ) {
            // todo: avoid the JOIN
            $where = get_posts_by_author_sql( 'post' );
            $this->query_from .= " LEFT OUTER JOIN (
                SELECT post_author, COUNT(*) as post_count
                FROM $wpdb->posts
                $where
                GROUP BY post_author
            ) p ON ({$wpdb->users}.ID = p.post_author)
            ";
            $_orderby = 'post_count';
        } elseif ( 'ID' == $orderby || 'id' == $orderby ) {
            $_orderby = 'ID';
        } elseif ( 'meta_value' == $orderby || $this->get( 'meta_key' ) == $orderby ) {
            $_orderby = "$wpdb->usermeta.meta_value";
        } elseif ( 'meta_value_num' == $orderby ) {
            $_orderby = "$wpdb->usermeta.meta_value+0";
        } elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) {
            $include = wp_parse_id_list( $this->query_vars['include'] );
            $include_sql = implode( ',', $include );
            $_orderby = "FIELD( $wpdb->users.ID, $include_sql )";
        } elseif ( isset( $meta_query_clauses[ $orderby ] ) ) {
            $meta_clause = $meta_query_clauses[ $orderby ];
            $_orderby = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
        } elseif ( 'kana' == $orderby ) { //追加
            $_orderby = $orderby; //追加
        }

        return $_orderby;
    }

こんな感じかな。

一応ちゃんと動いた

ここまで行うと、なんとか想定通りにうごいてくれた。
とはいえコアを弄ってしまっている上に、かなり手探りだったのでちょっと怪しいところ。

最後に

これからの目標

  • コアを弄らずに同じ動作を実装したい
  • ユーザー登録/編集でフリガナを変更できる様にしたい

という訳で、まだまだ手探りなストックにはなりますが、
忌憚の無いご意見や、アドバイスなどお聞きできれば有難いです。
引き続き勉強して、何か気がついた所があれば追記・編集していきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0