Wordpress API Menu / Submenu Order

11

Saya sedang mengembangkan tema anak-anak menggunakan Wordpress 3.4.2 dan versi pengembangan dari Framework Pilihan oleh David Price . Ini adalah tema pertama saya dan saya relatif baru dalam hal ini, jadi saya telah melihat ke dalam Codex Wordpress dan memeriksa mendaftarkan item ke dalam API.

Tanpa merusak file eksternal di luar tema saya, saya bertanya-tanya apakah ada cara untuk mengatur ulang di mana halaman Opsi Tema terletak di dalam hierarki menu Penampilan - jadi ketika tema saya diaktifkan, posisinya tidak seperti gambar pertama tetapi seperti yang kedua.

tuabaru

Saya tahu Anda dapat membuat menu (seperti tab Penampilan , Plugin , Pengguna , dll.) Atau submenu ( Tema , Widget , Menu , dll.), Tetapi bagaimana cara mengatur sub-menu, katakan, kedua dari atas?

Dari apa yang saya kumpulkan, di suatu tempat ada pesanan yang dipanggil dan halaman tambahan lainnya dalam functions.phpfile ditempatkan setelah itu?

Dalam file functions.php saya:

// 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';
}

Terima kasih.

pengguna1752759
sumber
Apakah Anda mencoba fungsi yang diperbarui?
Adam
Terima kasih telah kembali ke saya @userabuser. Saya telah menyalin-tempel skrip Anda yang diperbarui dan tampaknya memindahkan item ke atas dan ke bawah daftar tanpa mengabaikan yang lain ... namun, dengan pembaruan baru, saya masih menerima beberapa kesalahan pada menu Widget . Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Baris 1444: foreach ($submenu[$menus] as $index => $value){ dan Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Jalur 1468: ksort($submenu[$menus]);
user1752759
Jika Anda bisa melihat ini, itu akan bagus.
user1752759

Jawaban:

3

Ini sebuah contoh;

Pertama-tama untuk mengetahui urutan item sub-menu berdasarkan pada kunci arraynya, Anda dapat melakukan var_dumppada variabel global $ submenu yang akan menampilkan yang berikut;

(Saya menggunakan menu Posting dan sub menu sebagai contoh)

  //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"
    }
  }

Kita dapat melihat bahwa item sub menu saya ditambahkan ke dalam array dengan kunci 17 setelah item default.

Jika misalnya saya ingin menambahkan item sub-menu saya, langsung setelah item sub-menu Semua Posting saya perlu melakukannya dengan mengatur kunci array saya ke masing-masing 6, 7, 8 atau 9 (apa pun setelah 5 dan sebelum 10 masing-masing.

Ini adalah bagaimana kamu melakukannya ...

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']);

}

Hasil,

  ["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"
    }
  }

... cobalah dan beri tahu kami bagaimana Anda pergi!

Pembaruan 1:

Tambahkan ini ke file functions.php Anda;

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]);

}

Pembaruan saya mencakup cara yang sedikit lebih mudah untuk menangani pengaturan posisi menu Anda, Anda hanya perlu menentukan nama halaman submenu Anda dan posisi yang Anda inginkan di dalam menu. Namun jika Anda memilih halaman submenu yang $locationsama dengan kunci yang ada, itu akan menimpa kunci itu dengan Anda, sehingga item menu akan hilang dengan item menu Anda di tempatnya. Menambah atau mengurangi nomor untuk memesan menu Anda dengan benar jika itu masalahnya. Mirip, jika seseorang menginstal plugin yang memengaruhi area menu yang sama, dan yang memiliki $locationitem submenu yang sama dengan Anda maka masalah yang sama akan terjadi. Untuk menghindari itu, contoh Kaiser menyediakan beberapa pemeriksaan dasar untuk itu.

Pembaruan 2:

Saya telah menambahkan blok kode tambahan yang memeriksa semua kunci yang ada dalam array terhadap keinginan kita $locationdan jika kecocokan ditemukan, kita akan menambah $locationnilai kita 1untuk menghindari item menu saling menimpa. Ini adalah kode yang bertanggung jawab untuk itu,

   //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;

Pembaruan 3: (skrip direvisi untuk memungkinkan pengurutan beberapa item sub-menu)

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;

}

Dalam contoh di atas Anda dapat menargetkan beberapa sub menu dan beberapa item per sub menu dengan mengatur parameter yang sesuai di dalam $target_menuvariabel yang menyimpan array nilai multi-dimensi.

$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....
);

Revisi ini akan mencegah saling bertukar item sub-menu satu sama lain jika mereka memiliki kunci (posisi) yang sama, karena akan siklus melalui sampai menemukan kunci yang tersedia (posisi) yang tidak ada.

Adam
sumber
Terima kasih atas respon pengguna yang cepat, tetapi saya cukup baru dalam hal ini, jadi tolong saja. Saya tidak yakin bagaimana cara mengimplementasikan skrip / kode Anda di atas dan file mana yang harus ditempatkan karena seberapa ringkasnya telah ditulis - tolong jelaskan. Dengan contoh ini berfungsi dan mengeluarkan angka yang diperlukan ... jika pengguna menginstal plugin nanti yang menciptakan menu tingkat atas tambahan dengan beberapa sub-level di dalamnya (seperti solusi e-commerce), apakah ini efek kunci array dan rem apa yang telah ditetapkan untuk dilakukan?
user1752759
1
@Rob Membuat sedikit penyesuaian yang seharusnya membantu menghindari situasi di mana item menu saling menimpa.
Adam
@ user1752759 Apa hubungannya ini dengan yang di atas? Apa path lengkap ke file functions.php yang Anda berikan di komentar di atas? Apa kode di dalam file itu? Pada percakapan terakhir ini berhasil untuk Anda. Ini juga berfungsi untuk saya. Jadi saya curiga ada sesuatu yang lain di sini yang mungkin terlewatkan dalam kode Anda, jika saya ingat dengan benar terakhir kali Anda menggandakan dua cuplikan kode dan tidak memiliki kawat gigi yang benar di sekitar fungsi Anda.
Adam
Terima kasih telah kembali ke saya @userabuser. Saya telah menyalin-tempel skrip Anda yang diperbarui dan sepertinya memindahkan item ke atas dan ke bawah daftar tanpa mengabaikan yang lain ... namun, dengan pembaruan baru, saya masih menerima beberapa kesalahan pada menu Widget. Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Jalur 1444: foreach ($submenu[$menus] as $index => $value){ dan Warning: ksort() expects parameter 1 to be array, null given in /wp-content/themes/mythemename/functions.php on line 1468 Jalur 1468: ksort($submenu[$menus]);
user1752759
Jika Anda bisa melihat ini, itu akan bagus.
user1752759
2

Menu admin (dan masalahnya)

Karena menu admin benar-benar tidak memiliki kait dan API publik (yang memungkinkan untuk memindahkan item), Anda harus menggunakan beberapa solusi. Jawaban berikut ini menunjukkan kepada Anda apa yang menunggu Anda di masa depan dan bagaimana Anda dapat bekerja selama kami memiliki kondisi inti saat ini.

Pertama-tama saya harus perhatikan, bahwa scribu bekerja pada patch menu admin yang seharusnya membuat penanganannya lebih mudah. Struktur saat ini cukup kacau dan saya telah menulis artikel tentang itu yang akan segera usang. Harapkan WP 3.6 untuk mengubah segalanya sepenuhnya.

Lalu ada juga intinya, bahwa Anda tidak harus menggunakan halaman Opsi untuk tema lagi. Ada - saat ini - «Penyesuai Tema« untuk itu.

Plugin

Saya menulis sebuah plugin yang menguji ini dengan halaman "Opsi Tema" default untuk halaman TwentyEleven / Ten options. Seperti yang Anda lihat, tidak ada API nyata yang memungkinkan posisi apa pun. Jadi kita harus mencegat global.

Singkatnya: Cukup ikuti komentar dan lihat pemberitahuan admin, yang saya tambahkan untuk memberikan Anda beberapa hasil debug.

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

Semoga berhasil dan selamat bersenang - senang.

kaisar
sumber
2

Filter khusus

Ada kemungkinan lain untuk mencapai ini. Jangan tanya kenapa saya belum memikirkannya sebelumnya. Lagi pula, ada filter yang didedikasikan untuk pesanan menu kustom. Cukup atur trueuntuk mengizinkan pesanan khusus. Kemudian Anda mendapat kait kedua untuk memesan item menu utama. Di sana kami hanya memotong global $submenudan beralih di sekitar item sub menu kami.

masukkan deskripsi gambar di sini

Contoh ini bergerak barang Menu di atas yang item yang Widgets untuk menunjukkan fungsionalitas. Anda dapat menyesuaikannya dengan apa yang Anda suka.

<?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;
}
kaisar
sumber
Saya tidak terlalu percaya diri ketika menggunakan PHP @kaiser, tetapi apakah Anda mungkin tahu cara untuk mengimplementasikan skrip di atas untuk memasukkan beberapa item yang sama function wpse70916_custom_submenu_order( $menu )dengan mengatakan, memesan ulang tidak hanya Menu , tetapi juga Tema Opsi , Widget , Editor dll. Membuatnya cukup fleksibel dan juga agar item tidak saling menimpa? Terima kasih.
user1752759
@ user1752759 Plugin ini sudah memiliki fleksibilitas ini. Keamanan konflik (menghindari penggantian) adalah masalah lain. Ini tidak akan mungkin dalam skenario 100% karena Anda tidak dapat menetapkan tindakan Anda yang terakhir. Selalu ada sesuatu yang bisa dijalankan nanti. Bagaimanapun: Silakan buka pertanyaan baru dan tautkan ke yang ini.
kaiser
terima kasih dan akan melakukan kaiser. jika tidak terlalu banyak bertanya, bisakah Anda memperbarui skrip di atas untuk menunjukkan bagaimana banyak item dilakukan (mis. Menu dan Widget ), yang harus saya dapat gunakan sebagai panduan untuk melakukan hal yang sama untuk item lain? Menjadi cukup baru untuk PHP, saya tidak berpikir saya melakukannya dengan benar, mungkin karena jumlahnya. sorak-sorai
user1752759
Tolong tanyakan saja pertanyaan baru dan tautkan ke pertanyaan ini. Terima kasih.
kaiser