web-dev-qa-db-ja.com

Wordpress APIメニュー/サブメニューの順序

私は Wordpress 3.4.2 Options Frameworkの開発版 / David Price を使って子テーマを開発しています。これが私の最初のテーマで、これは比較的新しいので、 Wordpress Codex を見て、アイテムをAPIに登録することを確認しました。

私のテーマ以外の外部ファイルを改ざんすることなく、 テーマオプション ページが 外観 メニューの階層内のどこに配置されているかを再調整する方法があるかどうか疑問に思いましたが有効になっている場合、位置は最初の画像のようではなく、2番目の画像のようになります。

oldnew

メニュー( 外観 タブ、 プラグイン ユーザー など)またはサブメニュー( テーマ ウィジェット など)を作成できることを私は知っています。 、 メニュー etc)しかし、どうやってサブメニューの設定を上から2番目にするのでしょうか。

私が集めたものから、どこかで呼び出されている注文があり、functions.phpファイル内の他の追加ページがそれらの後に置かれていますか?

私のfunctions.phpファイルで:

// Add our "Theme Options" page to the Wordpress API admin menu.
if ( !function_exists( 'optionsframework_init' ) ) {
    define( 'OPTIONS_FRAMEWORK_DIRECTORY', get_template_directory_uri() . '/inc/' );
    require_once dirname( __FILE__ ) . '/inc/options-framework.php';
}

ありがとう。

11
user1752759

これが例です。

まず、配列キーに基づいてサブメニュー項目の順序を把握するために、$ submenuグローバル変数にvar_dumpを実行すると、次のように出力されます。

(私は例として投稿メニューとサブメニューを使用しています)

  //shortened for brevity....

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
    [17]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
  }

私のサブメニュー項目は、デフォルト項目の後に17のキーで配列に追加されることがわかります。

たとえば、 All Posts サブメニュー項目の直後にサブメニュー項目を追加する場合は、配列キーを6、7、8、または9に設定する必要があります(5の後から10の前まで)。それぞれ。

これがあなたのやり方です….

function change_submenu_order() {

    global $menu;
    global $submenu;

     //set our new key
    $new_key['edit.php'][6] = $submenu['edit.php'][17];

    //unset the old key
    unset($submenu['edit.php'][17]);

    //get our new key back into the array
    $submenu['edit.php'][6] = $new_key['edit.php'][6];


    //sort the array - important! If you don't the key will be appended
    //to the end of $submenu['edit.php'] array. We don't want that, we
    //our keys to be in descending order
    ksort($submenu['edit.php']);

}

結果、

  ["edit.php"]=>
  array(6) {
    [5]=>
    array(3) {
      [0]=> string(9) "All Posts"
      [1]=> string(10) "edit_posts"
      [2]=> string(8) "edit.php"
    }
    [6]=>
    array(3) {
      [0]=> string(14) "Sub Menu Title"
      [1]=> string(10) "edit_posts"
      [2]=> string(17) "sub_menu_page.php"
    }
    [10]=>
    array(3) {
      [0]=> string(7) "Add New"
      [1]=> string(10) "edit_posts"
      [2]=> string(12) "post-new.php"
    }
    [15]=>
    array(3) {
      [0]=> string(10) "Categories"
      [1]=> string(17) "manage_categories"
      [2]=> string(31) "edit-tags.php?taxonomy=category"
    }
  }

...試してみて、どうやって行くのか教えてください。

更新1:

これをあなたのfunctions.phpファイルに追加してください。

function change_post_menu_label() {

    global $menu;
    global $submenu;

    $my_menu  = 'example_page'; //set submenu page via its ID
    $location = 1; //set the position (1 = first item etc)
    $target_menu = 'edit.php'; //the menu we are adding our item to

    /* ----- do not edit below this line ----- */


    //check if our desired location is already used by another submenu item
    //if TRUE add 1 to our value so menu items don't clash and override each other
    $existing_key = array_keys( $submenu[$target_menu] );
    if ($existing_key = $location)
    $location = $location + 1;

    $key = false;
    foreach ( $submenu[$target_menu] as $index => $values ){

        $key = array_search( $my_menu, $values );

        if ( false !== $key ){
            $key = $index;
            break;
        }
    }

     $new['edit.php'][$location] = $submenu[$target_menu][$key];
     unset($submenu[$target_menu][$key]);
     $submenu[$target_menu][$location] = $new[$target_menu][$location];

    ksort($submenu[$target_menu]);

}

私の更新はあなたのメニュー位置の設定を処理するためのもう少し簡単な方法を含んでいます、あなたはあなたのサブメニューページの名前とあなたがメニューの中で欲しい位置を明記するだけでよいです。 ただし、既存のキーと同じサブメニューページ$locationを選択した場合は、そのキーが自分のキーで上書きされるため、メニュー項目はメニュー項目の代わりに表示されなくなります。その場合は、メニューを正しく順序付けるために番号を増減します。同様に、誰かがその同じメニュー領域に影響を与え、あなたのサブメニュー項目と同じ$locationを持つプラグインをインストールすると、同じ問題が発生します。 それを回避するために、カイザーの例ではそのためのいくつかの基本的なチェックを提供しています。

更新2:

配列内に存在するすべてのキーを目的の$locationと照合し、一致するものが見つかった場合はメニュー項目が互いにオーバーライドされないように$locationの値を1ずつ増やすコードブロックを追加しました。これはそれに責任があるコードです、

   //excerpted snippet only for example purposes (found in original code above)
   $existing_key = array_keys( $submenu[$target_menu] );
   if ($existing_key = $location)
   $location = $location + 1;

更新3 :(スクリプトは複数のサブメニュー項目のソートを可能にするために改訂された)

add_action('admin_init', 'move_theme_options_label', 999);

function move_theme_options_label() {
    global $menu;
    global $submenu;

$target_menu = array(
    'themes.php' => array(
        array('id' => 'optionsframework', 'pos' => 2),
        array('id' => 'bp-tpack-options', 'pos' => 4),
        array('id' => 'multiple_sidebars', 'pos' => 3),
        )
);

$key = false;

foreach ( $target_menu as $menus => $atts ){

    foreach ($atts as $att){

        foreach ($submenu[$menus] as $index => $value){

        $current = $index;  

        if(array_search( $att['id'], $value)){ 
        $key = $current;
        }

            while (array_key_exists($att['pos'], $submenu[$menus]))
                $att['pos'] = $att['pos'] + 1;

            if ( false !== $key ){

                if (array_key_exists($key, $submenu[$menus])){
                    $new[$menus][$key] = $submenu[$menus][$key];
                    unset($submenu[$menus][$key]);
                    $submenu[$menus][$att['pos']] = $new[$menus][$key];

                } 
            }
        }
    }
}

ksort($submenu[$menus]);
return $submenu;

}

上記の例では、多次元の値の配列を保持する$target_menu変数内でパラメータを適切に設定することで、複数のサブメニューとサブメニューごとに複数の項目をターゲットにすることができます。

$target_menu = array(
//menu to target (e.g. appearance menu)
'themes.php' => array(
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'optionsframework', 'pos' => 2),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'bp-tpack-options', 'pos' => 3),
    //id of menu item you want to target followed by the position you want in sub menu
    array('id' => 'multiple_sidebars', 'pos' => 4),
    )
 //etc....
);

この改訂は、存在しない利用可能なキー(位置)が見つかるまで循環するので、それらが同じキー(位置)を持っているならば、サブメニュー項目が互いに上書きするのを防ぎます。

3
userabuser

管理メニュー(およびその問題)

管理メニューにはフックやパブリックAPI(項目を移動できるようにする)が真剣に欠けているので、いくつかの回避策を使用する必要があります。次の答えは、あなたが将来あなたを待っていることと、私たちがコアの現状を持っている限りあなたがどのように回避できるかをあなたに示しています。

最初に注意しなければならないのは、 scribuは管理メニューパッチに取り組んでいます これにより処理がずっと簡単になります。現在の構造はかなりめちゃくちゃになっています、そして 私はそれについての記事を書きました それはまもなく時代遅れになるでしょう。事を完全に変えるためにはWP 3.6が必要です。

それから、テーマのためにオプションページをもう使うべきではないという点もあります。 - - 今日では - "テーマカスタマイザ" /があります。

プラグイン

TwentyEleven/Tenオプションページのデフォルトの "Theme Options"ページでこれをテストするプラグインを書きました。お分かりのように、どんな立場を可能にする本当のAPIはありません。だから我々は世界を傍受しなければなりません。

一言で言えば:コメントに従って、管理者の通知を見てください。私はあなたにデバッグ出力をするために追加しました。

<?php
/** Plugin Name: (#70916) Move Submenu item */

add_action( 'plugins_loaded', array( 'wpse70916_admin_submenu_items', 'init' ) );

class wpse70916_admin_submenu_items
{
    protected static $instance;

    public $msg;

    public static function init()
    {
        is_null( self :: $instance ) AND self :: $instance = new self;
        return self :: $instance;
    }

    public function __construct()
    {
        add_action( 'admin_notices', array( $this, 'add_msg' ) );

        add_filter( 'parent_file', array( $this, 'move_submenu_items' ) );
    }

    public function move_submenu_items( $parent_file )
    {
        global $submenu;
        $parent = $submenu['themes.php'];

        $search_for = 'theme_options';

        // Find current position
        $found = false;
        foreach ( $parent as $pos => $item )
        {
            $found = array_search( $search_for, $item );
            if ( false !== $found )
            {
                $found = $pos;
                break;
            }
        }
        // DEBUG: Tell if we didn't find it.
        if ( empty( $found ) )
            return $this->msg = 'That search did not work out...';

        // Now we need to determine the first and second item position
        $temp = array_keys( $parent );
        $first_item  = array_shift( $temp );
        $second_item = array_shift( $temp );

        // DEBUG: Check if it the item fits between the first two items:
        $distance = ( $second_item - $first_item );
        if ( 1 >= $distance )
            return $this->msg = 'We do not have enough space for your item';

        // Temporary container for our item data
        $target_data = $parent[ $found ];

        // Now we can savely remove the current options page
        if ( false === remove_submenu_page( 'themes.php', $search_for ) )
            return $this->msg = 'Failed to remove the item';

        // Shuffle items (insert options page)
        $submenu['themes.php'][ $first_item + 1 ] = $target_data;
        // Need to resort the items by their index/key
        ksort( $submenu['themes.php'] );
    }

    // DEBUG Messages
    public function add_msg()
    {
        return print sprintf(
             '<div class="update-nag">%s</div>'
            ,$this->msg
        );
    }
} // END Class wpse70916_admin_submenu_items

頑張って楽しんでね。

2
kaiser

カスタムフィルタ

これを達成するための別の可能性があります。なぜ私がそれについて早く考えなかったのか私に聞かないでください。とにかく、カスタムメニューオーダー専用のフィルタがあります。カスタム注文を許可するには、単にtrueに設定します。その後、メインメニュー項目を注文するための2番目のフックを得ました。そこではglobal $submenuをインターセプトしてサブメニュー項目を切り替えます。

enter image description here

この例では、 メニュー項目 the ウィジェット項目 に移動して、その機能を説明します。あなたはあなたが好きなものにそれを調整することができます。

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (#70916) Custom Menu Order
 * Description: Changes the menu order of a submenu item.
 */

// Allow a custom order
add_filter( 'custom_menu_order', '__return_true' );
add_filter( 'menu_order', 'wpse70916_custom_submenu_order' );
function wpse70916_custom_submenu_order( $menu )
{
    // Get the original position/index
    $old_index = 10;
    // Define a new position/index
    $new_index = 6;

    // We directly interact with the global
    $submenu = &$GLOBALS['submenu'];
    // Assign our item at the new position/index
    $submenu['themes.php'][ $new_index ] = $submenu['themes.php'][ $old_index ];
    // Get rid of the old item
    unset( $submenu['themes.php'][ $old_index ] );
    // Restore the order
    ksort( $submenu['themes.php'] );

    return $menu;
}
2
kaiser