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


11

Wordpress 3.4.2David FrameworkによるOptions Frameworkの開発バージョンを使用して、子テーマを開発しています。これは私の最初のテーマで、私はこれに比較的慣れていないので、Wordpress Codexを調べて、APIへの登録アイテムをチェックアウトしました。

テーマ外の外部ファイルを改ざんすることなく、[ テーマのオプション]ページが[ 外観 ]メニューの階層内のどこにあるかを再調整する方法があるかどうか疑問に思っていました。最初の画像ですが2番目の画像が好きです。

古い新着

私はあなたが(のようないずれかのメニューを作成することができます知っている外観 ]タブ、プラグインユーザーまたはサブメニュー(など)のテーマウィジェットメニューなど)が、どのように私は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';
}

ありがとう。


更新された機能を試しましたか?
アダム

@userabuserにご返信いただきありがとうございます。更新されたスクリプトをコピーして貼り付けましたが、他のアイテムを上書きせずにアイテムをリストの上下に移動しているようです...しかし、新しい更新では、ウィジェットメニューにいくつかのエラーが表示されます。Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Line 1444: foreach ($submenu[$menus] as $index => $value){およびWarning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Line 1468: ksort($submenu[$menus]);
user1752759

これをご覧になっていただければ幸いです。
user1752759 2013年

回答:


3

ここに例があります。

最初に、配列キーに基づいてサブメニュー項目の順序を把握するにはvar_dump、$ submenuグローバル変数で次のように出力します。

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

  //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で配列に追加されていることがわかります。

たとえば、サブメニュー項目を追加する場合は、[ すべての投稿 ]サブメニュー項目の直後に、配列キーを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....
);

このリビジョンは、サブメニュー項目が同じキー(位置)を持っている場合、サブメニュー項目が互いに上書きされるのを防ぎます。これは、存在しない使用可能なキー(位置)が見つかるまで循環するためです。


迅速な対応userabuserに感謝しますが、私はこれすべてにかなり新しいので、ご容赦ください。上記のスクリプト/コードをどのように実装するか、またどのようにファイルを配置する必要があるかは正確にわかりません。詳しく説明してください。この例は機能し、必要な数を出力します...ユーザーがプラグインを後でインストールする場合、内部にいくつかのサブレベル(eコマースソリューションなど)を含む追加のトップレベルメニューが作成された場合、これはアレイキーに影響を与えて、それが何をするように設定されているのかブレーキをかけますか
user1752759 2012年

1
@Robメニュー項目が互いに上書きされる状況を回避するのに役立つはずのわずかな調整を行いました。
アダム

@ user1752759これは上記とどう関係していますか?上記のコメントで指定したfunctions.phpファイルへのフルパスは何ですか?そのファイル内のコードは何ですか?最後の会話でこれはあなたのために働いた。それも私のために働きます。したがって、前回2つのコードスニペットを複製し、関数の前後に中括弧がなかった場合、ここで何か他のことがコード内のミスになっているのではないかと思います。
アダム

@userabuserにご返信いただきありがとうございます。更新されたスクリプトをコピーして貼り付けましたが、他のアイテムを上書きせずにアイテムをリストの上下に移動しているようです...しかし、新しい更新では、ウィジェットメニューでいくつかのエラーが発生します。Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Line 1444: foreach ($submenu[$menus] as $index => $value){およびWarning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Line 1468: ksort($submenu[$menus]);
user1752759

これをご覧になっていただければ幸いです。
user1752759 2013年

2

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

管理メニューにはフックとパブリックAPI(アイテムの移動を可能にする)が非常に不足しているため、いくつかの回避策を使用する必要があります。次の回答は、将来的に何が待ち受けているか、そして現在のコアの状態を維持している限り、どのように対処できるかを示しています。

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

次に、テーマのオプションページを使用しないようにする必要もあります。-今日-そのための»Theme Customizer«があります。

プラグイン

TwentyEleven / Tenオプションページのデフォルトの「テーマオプション」ページでこれをテストするプラグインを作成しました。ご覧のとおり、任意の位置を許可する実際の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

カスタムフィルター

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

ここに画像の説明を入力してください

この例では、移動メニュー項目を 上にウィジェットアイテムその機能を発揮します。好みに合わせて調整できます。

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

PHP @kaiserの使用に関してはあまり自信がありませんが、同じスクリプト内に複数の項目を含めるために上記のスクリプトを実装する方法を知っているでしょうか。メニューfunction wpse70916_custom_submenu_order( $menu )だけでなく、テーマも並べ替えてくださいオプションウィジェットエディタなどにより、非常に柔軟になり、アイテムが互いにオーバーライドしないようにしていますか?ありがとうございました。
user1752759 2013年

@ user1752759プラグインにはすでにこの柔軟性があります。競合の安全性(上書きを避ける)も別の問題です。100%のシナリオでは、アクションを最後に割り当てることができないため、これは不可能です。後で実行できるものは常にあります。とにかく:新しい質問を開いて、この質問にリンクしてください。
カイザー2013年

ありがとう、カイザーをします。質問が多すぎない場合は、上記のスクリプトを更新して、複数の項目がどのように行われるか(例:メニューウィジェット)を示してください。他の項目と同じようにするためのガイドとして使用できますか?PHPはかなり新しいので、おそらく数値が原因で、正しく実行しているとは思いません。歓声
user1752759 2013年

新しい質問をして、これにリンクしてください。ありがとう。
kaiser 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.