5. 1 アドミニメニュー メニュー設定

 アドミニメニュー設定画面です。次の機能があります。
  ・並べ替え順序設定
  ・カテゴリ別投稿一覧(簡易版)をメニューに追加
  ・個別ページをメニューに追加
  ・セパレータの追加

 表示順序を空欄にするとメニューから削除します。ただし、コアメニューは削除すると操作不能になる恐れがあるので削除できないようにしています。一般メニューはプラグインでメニュー登録しているので、メニューから削除するにはそのプラグインを停止すればすみます。
 “変更を保存”では、リフレッシュ用JavaScriptを書き込み、メニュー表示をリフレッシュしています。
 DB読み出し・書き込みする際、一般メニューにはIDがついていないので、タイトルをIDとして使用しています。

 【独自用語の説明】
  ・コアメニュー:WordPress のメニュー
  ・一般メニュー:コアメニュー、カテゴリメニュー、ページメニュー以外のメニュー

 下記関数に関しては“共通関数”をご覧ください。
  ・hk_func_hex2spchar
  ・hk_func_spchar2hex
  ・hk_func_post_read
 コアメニューチェックは、別途説明します。

コード

// ================================
// アドミニメニュー設定
// ================================
class Hk_Admin_Menu_Order {
    // ------ プロパティ ------
    private $id_strs     = array();        // 全id_str データ : group => id_str
    private $idstr_data  = array();        // 全id_str 詳細データ : id_str => array( group, id, title, order, type )
    private $title_idstr = array();        // 一般メニューのデータ :  title => id_str
    private $idstr_order = array();        // 並び替え順序データ : id_str => order 

    // --- メイン ---------------------
    // 管理画面メイン
    // --------------------------------
    function admin_main() {
        global $hk_core_menu_check;
        // コアメニューチェック
        if ( ! $hk_core_menu_check ) {
            // コアメニューの構造異常
            echo "\n\n".'<div class="hk_plugin_admin">'."\n";
            echo '  <h1>管理画面メニュー設定</h1>'."\n";
            echo '  <div class="hk_message">'."\n";
            echo 'WordPress の管理メニューのデータ構造に異常があり実行できません。'."\n";
            echo '  </div>'."\n";
            echo "</div>\n";
            return;
        }
        // 配列初期設定
        $this->set_initial_id_data();
        // 送信ボタン
        $admin_next = '';
        if ( isset( $_POST['admin_next'] ) )
            $admin_next = hk_func_post_read( 'admin_next', 1 );
        // メッセージ初期化
        $admin_message = '';
        // 初期画面
        if ( $admin_next == '' ) {
            // リフレッシュmessage
            if (( isset( $_REQUEST['hk_message'] ) ) && ( $_REQUEST['hk_message'] == 'saved' ))
                $admin_message = '変更を保存しました。';
            // DB読み出し 初期値を置き換え
            $this->db_read();
            // 並び替え順序データ作成
            $this->set_idstr_order();
        }
        // 変更を保存
        else if ( $admin_next == '変更を保存' ) {
            // フォームデータ取り込み
            $this->admin_post_data();
            // 並び替え順序データ作成
            $this->set_idstr_order();
            // メニューDB書き込み
            $this->db_write_menu();
            $admin_message = '変更を保存しました。';
            // アドミニメニュー表示更新 リフレッシュURL
            if (( isset( $_SERVER['HTTPS'] ) ) && ( $_SERVER['HTTPS'] == 'on' ))
                $protocol = 'https://';
            else
                $protocol = 'http://';
            $url = $protocol.$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"].'&hk_message=saved';
            // リフレッシュ用JavaScript
            echo "\n\n".'<script type="text/javascript">'."\n";
            echo '    setTimeout("redirect_url()", 0)'."\n";
            echo '    function redirect_url(){'."\n";
            echo '        location.href="'.$url.'";'."\n";
            echo '    }'."\n";
            echo '</script>';
        }
        // 初期化
        else if ( $admin_next == '初期化' ) {
            // 並び替え順序データ作成
            $this->set_idstr_order();
            $admin_message = '初期化しました。';
        }
        // 並べ替え
        else if ( $admin_next == '並べ替え' ) {
            // フォームデータ取り込み
            $this->admin_post_data();
            // 並び替え順序データ作成
            $this->set_idstr_order();
            $admin_message = '並べ替えました。';
        }
        // その他
        else    wp_die('ERROR:admin_next');
        // 画面に表示
        echo "\n\n".'<div class="hk_plugin_admin">'."\n";
        echo '  <h1>管理画面メニュー設定</h1>'."\n";
        if ( $admin_message != '' ) {
            $admin_message = trim( $admin_message );
            $admin_message = nl2br( $admin_message );
            echo '  <div class="hk_message">'."\n";
            echo $admin_message."\n";
            echo '  </div>'."\n";
        }
        // フォーム表示開始
        echo '<form method="post">'."\n";
        echo '  <h2>管理画面メニュー</h2>'."\n";
        echo '  <div class="hk_chap">'."\n";
        // 管理画面メニュー表示順序
        echo '    <h3>管理画面メニュー表示順序</h3>'."\n";
        echo '    <p>表示順序を変更できます。<br />'."\n";
        echo '・表示順序を空欄あるいは表示順序に数字以外を入力するとメニューから除外できます。<br />'."\n";
        echo '・WordPress本来のメニュー<span class="hk_italic">(斜体)</span>は操作不能になる危険があるため削除できません。<br />'."\n";
        echo '・一般のメニュー(*印)は削除できません。</p>'."\n";
        // 表示
        echo '    <div class="hk_admin_menu_order">'."\n";
        echo "<ul>\n";
        foreach( $this->idstr_order as $id_str => $order ) {
            $group = $this->idstr_data[ $id_str ]['group'];
            $title = $this->idstr_data[ $id_str ]['title'];
            echo '  <li>';
            // 順序
            echo '<input type="text" name="order_'.$id_str.'" size="3" maxlength="3" value="'.$order.'" /> ';
            // タイトル
            if      ( $group == 'other' )   $title = '* '.$title;
            else if ( $group == 'cat' )     $title = 'CAT '.$title;
            else if ( $group == 'page' )    $title = 'PAGE '.$title;
            $title = htmlspecialchars( $title );
            if ( $group == 'core' )
                echo '<span class="hk_italic">'.$title.'</span>';
            else
                echo $title;
            echo "</li>\n";
        }
        echo "</ul>\n";
        unset( $id_str );
        unset( $order );
        echo "    </div>\n";
        echo "  </div>\n";
        // SUBMIT ボタン
        echo '  <p><input type="submit" name="admin_next" value="並べ替え" />   '."\n";
        echo '<input type="submit" name="admin_next" value="初期化" /></p>'."\n";
        echo '  <p><input type="submit" name="admin_next" value="変更を保存" /></p>'."\n";
        // 未選択メニュー
        echo '  <h2>未選択メニュー</h2>'."\n";
        echo '  <div class="hk_chap hk_clear">'."\n";
        // 左側
        echo '    <div class="alignleft hk_width50">'."\n";
        // 区切り
        $this->echo_free_list( '区切り', 'sepa' );
        // カテゴリ
        $this->echo_free_list( 'カテゴリ', 'cat' );
        echo "    </div>\n";
        // 右側
        echo '    <div class="alignright hk_width50">'."\n";
        // ページ
        $this->echo_free_list( 'ページ', 'page' );
        echo "    </div>\n";
        echo "  </div>\n";
        // END
        echo "</form>\n";
        echo "</div>\n";
        return;
    }

    // --- サブルーチン ---------------
    // 未選択表示
    // --------------------------------
    private function echo_free_list( $group_title, $group ) {
        echo '      <h3>'.$group_title.'</h3>'."\n";
        echo '      <div class="hk_admin_menu_order">'."\n";
        echo "<ul>\n";
        $count = 0;
        if ( ! empty( $this->id_strs[ $group ] ) ) {
            $id_strs = $this->id_strs[ $group ];
            foreach( $id_strs as $id_str ) {
                $title = $this->idstr_data[ $id_str ]['title'];
                $order = $this->idstr_data[ $id_str ]['order'];
                if ( $order !== '' )        continue;
                ++$count;
                echo '  <li><input type="text" name="order_'.$id_str.'" size="3" maxlength="3" value="" /> ';
                $title = htmlspecialchars( $title );
                echo $title;
                echo "</li>\n";
            }
            unset( $id_str );
        }
        if ( $count == 0 )
            echo "  <li>未選択はありません</li>\n";
        echo "</ul>\n";
        echo "      </div>\n";
        return;
    }

    // --- サブルーチン ---------------
    // データ配列初期設定
    //   コアメニュー
    //   一般メニュー
    //   カテゴリ
    //   固定ページ
    //   セパレータ
    // --------------------------------
    private function set_initial_id_data() {
        global $menu;
        // 初期化
        $this->id_strs     = array();
        $this->idstr_data  = array();
        $this->title_idstr = array();
        foreach( $menu as $order => $each_menu ) {
            if ( ! isset( $each_menu['hk_group'] ) )    continue;
            $group = $each_menu['hk_group'];
            // コアメニュー
            if ( $group == 'core' ) {
                $id     = $each_menu['hk_order_org'];
                $id_str = 'core_'.$id;
                // id_strs 配列に追加
                $this->id_strs['core'][] = $id_str;
                // タイトル
                $title = $each_menu['hk_title'];
                if ( $title == '' )        $title = '(区切り)';
                // データ配列に追加
                $this->idstr_data[ $id_str ]['group'] = 'core';
                $this->idstr_data[ $id_str ]['id']    = $id;
                $this->idstr_data[ $id_str ]['title'] = $title;
                $this->idstr_data[ $id_str ]['order'] = $order;
            }
            // 一般メニュー
            if ( $group == 'other' ) {
                $id     = $each_menu['hk_order_org'];
                $id_str = 'other_'.$id;
                $this->id_strs['other'][] = $id_str;
                $title = $each_menu[ 0 ];
                $this->idstr_data[ $id_str ]['group'] = 'other';
                $this->idstr_data[ $id_str ]['id']    = $id;
                $this->idstr_data[ $id_str ]['title'] = $title;
                $this->idstr_data[ $id_str ]['order'] = $order;
                // title id_str テーブル
                $this->title_idstr[ $title ] = $id_str;
            }
        }
        unset( $order );
        unset( $each_menu );
        // カテゴリ一覧取得
        $args = array(
            'orderby'    => 'id',
            'order'      => 'ASC',
            'hide_empty' => 0,
        );
        $categories = get_categories( $args );
        foreach( $categories as $category ) {
            $id = $category->cat_ID;
            $title = $category->cat_name;
            $id_str = 'cat_'.$id;
            $this->id_strs['cat'][] = $id_str;
            $this->idstr_data[ $id_str ]['group'] = 'cat';
            $this->idstr_data[ $id_str ]['id']    = $id;
            $this->idstr_data[ $id_str ]['title'] = $title;
            $this->idstr_data[ $id_str ]['order'] = '';
        }
        unset( $category );
        // 固定ページ一覧取得
        $args = array(
            'sort_column'  => 'ID',
            'sort_order'   => 'ASC',
            'hierarchical' => 0,
            'post_status'  => 'publish,draft',
        );
        $pages = get_pages( $args );
        foreach( $pages as $page ) {
            // パスワード保護の場合 スキップ
            $passwd = $page->post_password;
            if ( $passwd != '' )            continue;
            // データセット
            $id = $page->ID;
            $title = $page->post_title;
            if ( $title == '' )        $title = '(無題)';
            $id_str = 'page_'.$id;
            $this->id_strs['page'][] = $id_str;
            $this->idstr_data[ $id_str ]['group'] = 'page';
            $this->idstr_data[ $id_str ]['id']    = $id;
            $this->idstr_data[ $id_str ]['title'] = $title;
            $this->idstr_data[ $id_str ]['order'] = '';
        }
        unset( $page );
        // セパレータ
        for ( $id=1; $id<=5; $id++ ) {
            $id_str = 'sepa_'.$id;
            $this->id_strs['sepa'][] = $id_str;
            $this->idstr_data[ $id_str ]['group'] = 'sepa';
            $this->idstr_data[ $id_str ]['id']    = $id;
            $this->idstr_data[ $id_str ]['title'] = '(区切り '.$id.')';
            $this->idstr_data[ $id_str ]['order'] = '';
        }
        return;
    }

    // --- サブルーチン ---------------
    // 並び替え順序データ(ID-ORDER 配列)作成
    // --------------------------------
    private function set_idstr_order() {
        // 初期化
        $this->idstr_order = array();
        // コア
        $this->set_idstr_order_sub( 'core' );
        // 一般
        $this->set_idstr_order_sub( 'other' );
        // カテゴリ
        $this->set_idstr_order_sub( 'cat' );
        // ページ
        $this->set_idstr_order_sub( 'page' );
        // セパレータ
        $this->set_idstr_order_sub( 'sepa' );
        // ソート
        asort( $this->idstr_order );
        // order の再付番
        $order_last = 0;
        foreach( $this->idstr_order as $id_str => &$order ) {
            if ( $order <= $order_last )
                $order = $order_last + 1;
            $order_last = $order;
        }
        unset( $id_str );
        unset( $order );
        return;
    }

    // --- サブルーチン ---------------
    // ID-ORDER 配列作成 サブ
    // --------------------------------
    private function set_idstr_order_sub( $group ) {
        if ( empty( $this->id_strs[ $group ] ) )    return;
        $id_strs = $this->id_strs[ $group ];
        foreach( $id_strs as $id_str ) {
            $order = $this->idstr_data[ $id_str ]['order'];
            if ( $order === '' )        continue;
            $this->idstr_order[ $id_str ] = $order;
        }
        unset( $id_str );
        return;
    }

    // --- サブルーチン ---------------
    // DB読み出し
    // --------------------------------
    private function db_read() {
        $db_str = get_option( 'hk_admin_menu_order', '' );
        if ( $db_str == '' )        return;
        $lines = explode( '&', $db_str );
        foreach( $lines as $line ) {
            list( $id_str, $order ) = explode( ',', $line );
            list( $group, $id ) = explode( '_', $id_str, 2 );
            // コア・セパレータ・個別固定ページ・カテゴリ
            if (( $group == 'core' ) || ( $group == 'sepa' ) || ( $group == 'page' ) || ( $group == 'cat' )) {
                 // 初期配列にあるかチェック
                if ( ! isset( $this->idstr_data[ $id_str ] ) )    continue;
                // 順序を更新
                $this->idstr_data[ $id_str ]['order'] = $order;
            }
            // 一般
            else if ( $group == 'other' ) {
                // タイトル 逆文字変換
                $title = hk_func_hex2spchar( $id );
                 // 初期配列にあるかチェック
                if ( ! isset( $this->title_idstr[ $title ] ) )    continue;
                $id_str = $this->title_idstr[ $title ];
                // 順序を更新
                $this->idstr_data[ $id_str ]['order'] = $order;
            }
        }
        unset( $line );
        return;
    }

    // --- サブルーチン ---------------
    // DB書き込み
    // --------------------------------
    private function db_write_menu() {
        $db_strs = array();
        foreach( $this->idstr_order as $id_str => $order ) {
            list( $group, $id ) = explode( '_', $id_str, 2 );
            // コア・セパレータ・個別固定ページ・カテゴリ
            if (( $group == 'core' ) || ( $group == 'sepa' ) || ( $group == 'page' ) || ( $group == 'cat' ))
                $db_strs[] = $id_str.','.$order;
            // 一般
            else if ( $group == 'other' ) {
                // タイトル 文字変換
                $title = $this->idstr_data[ $id_str ]['title'];
                $title = hk_func_spchar2hex( $title );
                $db_strs[] = 'other_'.$title.','.$order;
            }
            // その他
            else wp_die('ERROR:group');
        }
        $db_str = implode( '&', $db_strs );
        unset( $id_str );
        unset( $order );
        update_option( 'hk_admin_menu_order', $db_str );
        return;
    }

    // --- サブルーチン ---------------
    // POSTされたデータ群の取り込み
    // --------------------------------
    private function admin_post_data() {
        // コア
        $this->admin_post_data_sub('core');
        // 一般
        $this->admin_post_data_sub('other');
        // ページ
        $this->admin_post_data_sub('page');
        // セパレータ
        $this->admin_post_data_sub('sepa');
        // カテゴリ
        $this->admin_post_data_sub('cat');
        return;
    }

    // --- サブルーチン ---------------
    // POSTされた順序データ
    // --------------------------------
    private function admin_post_data_sub( $group ) {
        foreach( $this->id_strs[ $group ] as $id_str ) {
            $order = $this->post_num_read( $id_str );
            if ( $order === '' ) {
                // コアメニュー、一般メニューは削除不可
                if (( $group == 'core') || ( $group == 'other'))
                    $order = $this->idstr_data[ $id_str ]['id'];
            }
            $this->idstr_data[ $id_str ]['order'] = $order;
        }
        unset( $id_str );
        return;
    }

    // --- サブルーチン ---------------
    // 順序データの取り込みとチェック
    // --------------------------------
    private function post_num_read( $id_str ) {
        // 数字だけで構成されていなければ削除扱い
        $key_str = 'order_'.$id_str;
        $order = hk_func_post_read( $key_str, 1 );
        if ( $order === '' )                            return '';
        if ( ! preg_match( "/^[0-9]+$/", $order ) )     return '';
        return $order;
    }
} // END OF class Hk_Admin_Menu_Order

$hk_admin_menu_order = new Hk_Admin_Menu_Order();

// --------------------------------
// 管理画面に設定メニューの追加
//   メニュー設定
// --------------------------------
function hk_admin_menu_order_setting() {
    global $hk_admin_menu_order;
    add_options_page( 'アドミニメニュー設定', 'アドミニメニュー設定', 'manage_options', 'hk_admin_menu_order', array( $hk_admin_menu_order, 'admin_main' ) );
    return;
}
add_action( 'admin_menu', 'hk_admin_menu_order_setting' );

// --------------------------------
// スタイル記述
// --------------------------------
function hk_admin_menu_order_admin_head() {
    global $pagenow;
    if ( $pagenow != 'options-general.php' )           return;
    if (( ! isset( $_GET['page'] ) )
     || ( $_GET['page'] != 'hk_admin_menu_order' ))    return;
?>
<style type="text/css">
    .hk_width50 {
        width: 50%;
    }
    .hk_admin_menu_order {
        margin: 0 0 24px 0;
        margin: 0 0 1.714285714rem 0;
    }
    .hk_admin_menu_order ul {
        list-style: none;
    }
    .hk_admin_menu_order li {
        margin: 6px 0 6px 12px;
        margin: 0.428571428rem 0 0.428571428rem 0.857142857rem;
    }
</style>
<?php
    return;
}
add_action( 'admin_head', 'hk_admin_menu_order_admin_head' );

 このプログラムをお使いになる場合は、お使いになる方の自己責任でお願いします。

関連

更新日:2016/03/25
掲載日:2016/01/15