it-swarm.com.ru

Wordpress API Menu/Порядок подменю

Я разрабатываю дочернюю тему, используя Wordpress 3.4.2 и версию для разработки Options Framework by Дэвид Прайс . Это моя первая тема, и я относительно новичок в этом, поэтому я заглянул в Wordpress Codex и проверил регистрацию элементов в API.

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

oldnew

Я знаю, что вы можете создать меню (например, Внешний вид вкладка, Плагины , Пользователи и т.д.) Или подменю ( Темы , Виджеты , Меню и т.д.), Но как мне настроить подменю, скажем, второе сверху?

Из того, что я понял, где-то происходит вызов, и после них размещаются любые другие дополнительные страницы в файле 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

Вот пример;

Сначала, чтобы выяснить порядок пунктов подменю на основе его ключа массива, вы можете сделать 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....
);

Эта ревизия предотвратит перезапись элементов подменю, если они имеют одинаковый ключ (положение), поскольку она будет циклически проходить, пока не найдет доступный ключ (положение), который не существует.

3
userabuser

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

Поскольку в меню администратора отсутствуют какие-либо хуки и общедоступный 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
kaiser

Пользовательские фильтры

Для этого есть еще одна возможность. Не спрашивайте меня, почему я раньше не думал об этом. Во всяком случае, есть фильтр, предназначенный для пользовательского порядка меню. Просто установите true, чтобы разрешить индивидуальный заказ. Тогда вы получили второй крючок для заказа пунктов главного меню. Там мы просто перехватываем global $submenu и переключаемся между нашими пунктами подменю.

enter image description here

В этом примере перемещается элемент Меню выше элемент Виджеты , чтобы продемонстрировать его функциональность. Вы можете настроить его так, как вам нравится.

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