Меню / підменю Wordpress


11

Я розробляю дочірню тему за допомогою Wordpress 3.4.2 та версії для розробників Options Options від Девіда Прайса . Це моя перша тема, і я відносно новий в цьому, тому я заглянув у кодекс Wordpress і перевірив реєстрацію елементів в API.

Не підробляючи жодних зовнішніх файлів поза моєю темою, мені було цікаво, чи існує спосіб переупорядкувати, де розташована сторінка « Параметри теми» в межах ієрархії меню « Зовнішній вигляд » - тому коли моя тема активована, позиція не така перше зображення, але подобається друге.

старийнові

Я знаю, що ви можете створити або меню (наприклад, вкладка Зовнішній вигляд , плагіни , користувачі тощо), або підменю ( теми , віджети , меню тощо), але як би я пішов щодо налаштування підменю, скажімо, друге з вершини?

З того, що я збираю, десь є замовлення, яке викликається, а будь-які інші додаткові сторінки у functions.phpфайлі розміщуються після них?

У моєму файлі function.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 Рядок 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 Рядок 1468: ksort($submenu[$menus]);
користувач1752759

Якщо ви можете, будь ласка, поглянути на це, це було б чудово.
користувач1752759

Відповіді:


3

Ось приклад;

Спочатку з’ясуйте порядок елементів підменю на основі його клавіші масиву, ви можете зробити a 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 після елементів за замовчуванням.

Якщо, наприклад, я хочу додати свій пункт підменю, безпосередньо після пункту підменю « Усі повідомлення », мені потрібно зробити це, встановивши мою клавішу масиву на 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:

Додайте це до файлу function.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, але я досить новий у всьому цьому, тому будь ласка, будь ласка, майте мене Я не точно впевнений, як реалізувати ваш сценарій / код вище та в який файл його потрібно розмістити через те, наскільки стисло його написано - будь ласка, уточни. Якщо цей приклад працює, і виводиться необхідне число ... якщо користувач повинен був встановити плагін пізніше, який створив додаткове меню верхнього рівня з кількома підрівнями всередині (наприклад, рішення електронної комерції), чи буде це впливати на ключ масиву і гальмувати те, що його було зроблено?
користувач1752759

1
@Rob Внесло невелике коригування, яке допоможе уникнути ситуацій, коли пункти меню перекривають один одного.
Адам

@ user1752759 Що це стосується вищезазначеного? Який повний шлях до файлу function.php, який ви надаєте у своєму коментарі вище? Який код у цьому файлі? На останній розмові це спрацювало для вас. Це також працює для мене. Тож я підозрюю, що щось інше тут може бути пропуском у вашому коді, якщо я пригадаю правильно, коли ви дублювали два фрагменти коду і не мали правильних дужок навколо вашої функції.
Адам

Дякуємо, що повернулися до мене @userabuser. Я скопіював ваш оновлений сценарій, і, здається, переміщуйте елементи вгору та вниз по списку, не змінюючи жодних інших ... однак, з новим оновленням я все-таки отримую кілька помилок у меню Віджетів. Warning: Invalid argument supplied for foreach() in /wp-content/themes/mythemename/functions.php on line 1444 Рядок 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 Лінія 1468: ksort($submenu[$menus]);
користувач1752759

Якщо ви можете, будь ласка, поглянути на це, це було б чудово.
користувач1752759

2

Меню адміністратора (та його проблеми)

Оскільки в меню адміністратора серйозно не вистачає гачків та загальнодоступного API (які дозволяють переміщувати елементи навколо), вам доведеться скористатися деякими обхідними шляхами. Наступна відповідь показує, що вас чекає в майбутньому і як ви можете обійтись, поки у нас є поточний стан ядра.

По-перше, я маю зазначити, що scribu працює над патчем меню адміністратора, який повинен значно полегшити обробку. Нинішня структура досить заплутана, і я написав про неї статтю, яка незабаром застаріла. Очікуйте, що WP 3.6 повністю змінить речі.

Тоді також є сенс, що ви більше не повинні використовувати сторінки "Опції" для тем. Для цього існує «Настроювач тем» для цього.

Плагін

Я написав плагін, який тестує це зі сторінкою "Параметри теми" за сторінкою параметрів 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дозволити спеціальне замовлення. Потім ви отримали другий гачок, щоб замовити елементи головного меню. Там ми просто перехоплюємо global $submenuі перемикаємо навколо наших пунктів підменю.

введіть тут опис зображення

Цей приклад переміщує елемент по меню вище в Widgets пункту , щоб продемонструвати свою функціональність. Ви можете налаштувати його на те, що вам подобається.

<?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 )і те ж, скажімо, переупорядкувати не лише меню , а й тему Параметри , віджети , редактор тощо, що робить його досить гнучким, а також, щоб елементи не перекривали один одного? Дякую.
користувач1752759

@ user1752759 Плагін вже має таку гнучкість. Безпека конфліктів (уникайте переосмислення) - це ще одна проблема. У 100% сценарії це неможливо, оскільки ви не можете призначити свою дію останньою. Завжди щось може працювати пізніше. У будь-якому разі: будь ласка, відкрийте нове запитання та посилання на це.
кайзер

дякую і зробимо кайзер. якщо вас не надто багато запитувати, чи можете ви, будь-ласка, оновити сценарій вище, щоб показати, як робиться декілька елементів (наприклад, меню та віджети ), які я повинен мати можливість використовувати як керівництво для того, щоб робити те ж саме з іншими пунктами? Будучи досить новим для PHP, я не думаю, що я роблю це правильно, можливо, через цифри. ура
користувач1752759

Будь ласка, задайте нове запитання та посилання на це. Спасибі.
кайзер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.