Изменение порядка разделов в меню администратора
Я немного разочарован тем, что потратил несколько часов, пытаясь выполнить эту довольно простую задачу без какого-либо успеха.
По сути, у меня есть 5 пользовательских типов записей, которые я создал, и всё, что я хочу сделать, это показать каждый из них в определенном порядке прямо под разделом "консоль".
Согласно документации WordPress, похоже, что это невозможно сделать, потому что самый высокий порядок меню, кажется, равен "5". И выше.
Я предполагаю, что кто-то из экспертов, читающих это, может показать мне простой способ упорядочить административное меню именно так, как я хочу, используя файл functions.php и не прибегая к плагинам (которые, как я знаю, существуют).
Пожалуйста, попробуйте создать 5 отдельных типов записей и расположить их в определенном порядке прямо под консолью... кажется, это невозможно... может быть, кто-то мог бы поделиться каким-то хаком на jQuery, чтобы это работало, или предпочтительно без использования jQuery?

Привет, @BinaryBit:
Неудивительно, что ты немного разочарован; реализация меню админки в WordPress — одна из самых запутанных и раздражающих в ядре системы. Честно говоря, непонятно, о чём думали разработчики, когда проектировали её таким образом.
@EAMann проделал отличную работу, объяснив, как работают административные меню в WordPress (хотел бы я прочитать это 4 месяца назад... :)
Тем не менее, даже разобравшись в принципах работы, я всё равно терялся, пытаясь выполнить простые действия без значительных временных затрат. Поэтому я создал Menu API, который упрощает и ускоряет работу с меню админки WordPress.
Эти функции на 100% совместимы с существующей структурой WordPress, но всё ещё находятся в альфа-версии, так как использовались только мной. Уверен, есть сценарии, которые они пока не охватывают. Но я выложу код, чтобы ты и другие могли его опробовать.
Ты можешь скачать файл для размещения в директории своей темы здесь: wp-admin-menu-classes.php. Ниже показано, как можно вызывать эти функции в файле functions.php
твоей темы:
<?php
require_once('wp-admin-menu-classes.php');
add_action('admin_menu','my_admin_menu');
function my_admin_menu() {
swap_admin_menu_sections('Pages','Posts'); // Поменять местами разделы "Записи" и "Страницы"
rename_admin_menu_section('Media','Фото и видео'); // Переименовать раздел "Медиафайлы" в "Фото и видео"
delete_admin_menu_section('Links'); // Удалить раздел "Ссылки"
$movie_tags_item_array = get_admin_menu_item_array('Movies','Movie Tags'); // Сохранить пункт меню "Метки фильмов"
update_admin_menu_section('Movies',array( // Переименовать два пункта меню и удалить "Метки фильмов"
array('rename-item','item'=>'Movies','new_title'=>'Список фильмов'),
array('rename-item','item'=>'Add New','new_title'=>'Добавить фильм'),
array('delete-item','item'=>'Movie Tags'),
));
copy_admin_menu_item('Movies',array('Actors','Add New')); // Скопировать пункт "Добавить новый" из раздела "Актёры"
renamed_admin_menu_item('Movies','Add New','Добавить актёра'); // Переименовать скопированный пункт в "Добавить актёра"
add_admin_menu_item('Movies',array( // Альтернативный способ добавить пункт "Добавить актёра"
'title' => 'Альтернативное добавление актёра',
'slug' => 'post-new.php?post_type=actor',
), array(// Вернуть "Метки фильмов" в конец раздела.
'where'=>'end'
));
add_admin_menu_item('Movies',$movie_tags_item_array,array(// Вернуть "Метки фильмов" в конец раздела.
'where'=>'end'
));
delete_admin_menu_section('Actors'); // Наконец, просто удалить раздел "Актёры"
}
Более того, эти функции даже рассматриваются (как основа) для включения в WordPress 3.1, так что, если повезёт, они могут стать стандартными!

Отличное дополнение к API! У меня ушли месяцы, чтобы добавить свой первый пользовательский раздел меню с существующей структурой (именно поэтому я так глубоко изучал код)... но ваш API кажется гораздо более интуитивным в использовании!

@EAMann - Спасибо! Если у вас есть предложения или даже желание поучаствовать в улучшении API, я буду рад создать что-то, что упростит работу для всех, а не только для тех немногих, кто увидит этот Q&A.

было ли это включено в ядро или всё ещё требуется этот или подобный метод для изменения порядка пунктов меню в админке?

Привет, Майк - wp_debug выдает ошибку в этой функции: -------- function swap_admin_menu_sections($from_section,$to_section) { $from_section = get_admin_menu_section($from_section); if ($from_section) $from_section->swap_with($to_section); return $section; }
Notice: Неопределенная переменная: section

Вот краткий обзор того, как создается меню админ-панели WordPress — я говорю не о add_menu_page
API, а о стандартном меню WordPress.
Загрузка файла меню
Меню, очевидно, загружается через wp-admin/admin.php
. Однако оно загружается не через стандартный API, описанный в документации WordPress. Вместо этого все меню (все возможные пункты, подменю и т.д.) загружаются через простой массив, определенный в wp-admin/menu.php
.
Таким образом, для загрузки системы меню admin.php
просто делает require
файла menu.php
... примерно на строке 99 в WordPress 3.0.
Загрузка меню
Само меню хранится в глобальном массиве $menu
. Согласно встроенной документации, массив меню содержит следующие элементы:
Элементы массива:
* 0: Название пункта меню
* 1: Минимальный уровень или требуемая способность.
* 2: URL файла пункта
* 3: Класс
* 4: ID
* 5: Иконка для верхнего уровня меню
Например, панель управления выглядит так:
$menu[2] = array( __('Dashboard'), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'div' );
Файл последовательно загружает каждый пункт меню в массив, а все подпункты — в массив $submenu
, который индексируется по URL родительского меню. Например, подпункт "Панель управления" выглядит так:
$submenu[ 'index.php' ][0] = array( __('Dashboard'), 'read', 'index.php' );
После загрузки всех пунктов меню (их не так много, но система проходит по индексу с шагом 5 или 10... обратите внимание, что "Панель управления", несмотря на то, что это первый пункт, все равно имеет индекс "2" — массивы PHP начинаются с индекса 0, что дает некоторую свободу маневра).
На этом этапе система вызывает wp-admin/includes/menu.php
.
Обработка меню
Этот третий файл проходит по каждому пункту меню и, основываясь на правах текущего пользователя, либо использует его, либо удаляет. Сначала он проходит по всем подменю и удаляет страницы, к которым у пользователя нет доступа. Затем он делает то же самое для родительских страниц. После этого удаляются дублирующиеся разделители, которые могли остаться после удаления пунктов.
Наконец, меню сортируется в соответствии с заданным порядком.
Сортировка пользовательских меню
Хук admin_menu
вызывается после настройки меню, но до их сортировки. Это позволяет упорядочить всю систему меню WordPress без "взлома" API.
После срабатывания действия admin_menu
ваши пользовательские страницы загружаются в систему. Затем WordPress проверяет фильтр custom_menu_order
... этот фильтр всегда возвращает false
и указывает, хотите ли вы использовать пользовательский порядок.
Добавьте следующий код в свою тему, чтобы установить флаг в true
и определить явный порядок меню:
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array('index.php', 'edit.php', 'edit-comments.php');
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
Укажите желаемый порядок для всех меню (я привел ссылки на файл загрузки меню, чтобы вы могли получить список имен файлов), и этого будет достаточно.
ОБНОВЛЕНИЕ (02.09.2010):
Чтобы указать порядок экрана редактирования пользовательского типа записи этим методом, нужно знать URL этого экрана. В большинстве случаев он будет выглядеть как http://blog.url/wp-admin/edit.php?post_type=POST_TYPE
. Это зависит от настройки WordPress (установлен ли он в корне или подпапке) и слага вашего пользовательского типа записи.
Например...
Допустим, у вас есть пользовательский тип записи "Вопросы Stack Exchange", и вы хотите, чтобы редактор отображался в том же разделе, что и панель управления, сразу под ней. Используйте следующий код в файле functions.php
вашей темы:
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array('index.php', 'edit.php?post_type=stack_exchange_questions');
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
Остальное меню останется без изменений, но ваша страница редактирования переместится в раздел панели управления и появится сразу после нее. Это можно использовать для перемещения пользовательских типов записей в любой раздел админ-меню и установки любого порядка. Стандартные пункты меню также можно перемещать аналогичным образом.
Главное, указывайте порядок всех пунктов в данном разделе, иначе меню может вести себя неожиданно.

В вашем примере кода под заголовком "Ordering custom menus" есть небольшая ошибка - в условном операторе if отсутствует символ $
перед именем переменной... (В остальном отличный ответ)..

Как можно добавить пользовательский тип записи "Stack Exchange Questions" в раздел ниже раздела Dashboard?

Привет EAMann - быстрый вопрос. Изменился ли этот процесс в последней версии WordPress или стал проще?

Как насчёт подменю? Есть ли аналогичный способ для изменения порядка элементов подменю?

@GiraldiMaggio Пожалуйста, задайте новый вопрос и укажите ссылку на этот.

Понимаю, что это старая тема, но считаю важным обновить её ГОРАЗДО более простым решением. Обратите внимание, что этот код работает с версией 3.5 и не тестировался на других версиях. Следующий код можно разместить в плагине или файле functions.php.
Смотрите: http://codex.wordpress.org/Plugin_API/Filter_Reference/menu_order. Немного модифицировано под нужды автора исходного поста (хотя, надеюсь, он уже нашёл решение...).
// Реорганизация меню админ-панели
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array(
'index.php', // Консоль
'edit.php?post_type=custom_type_one', // Пользовательский тип один
'edit.php?post_type=custom_type_two', // Пользовательский тип два
'edit.php?post_type=custom_type_three', // Пользовательский тип три
'edit.php?post_type=custom_type_four', // Пользовательский тип четыре
'edit.php?post_type=custom_type_five', // Пользовательский тип пять
'separator1', // Первый разделитель
'edit.php?post_type=page', // Страницы
'edit.php', // Записи
'upload.php', // Медиафайлы
'link-manager.php', // Ссылки
'edit-comments.php', // Комментарии
'separator2', // Второй разделитель
'themes.php', // Внешний вид
'plugins.php', // Плагины
'users.php', // Пользователи
'tools.php', // Инструменты
'options-general.php', // Настройки
'separator-last', // Последний разделитель
);
}
add_filter('custom_menu_order', 'custom_menu_order'); // Активировать custom_menu_order
add_filter('menu_order', 'custom_menu_order');
Элементы меню админ-панели, которые не указаны здесь, не будут удалены. Они будут добавлены в конец меню.

Для перемещения пунктов меню я использую глобальную переменную $menu
.
Например, если я хочу переместить меню "Страницы" вниз списка, я добавлю этот код в functions.php
или плагин:
function admin_menu_items() {
global $menu;
$menu[102]=$menu[20]; // делаем меню 102 таким же, как меню 20 (страницы)
$menu[20]=array(); // удаляем оригинальное меню страниц
}
add_action('admin_menu', 'admin_menu_items');
А если нужно поменять местами меню "Записи" и "Ссылки":
function admin_menu_items() {
global $menu;
$storemenu = $menu[15]; // сохраняем меню ссылок в $storemenu
$menu[15] = $menu[5]; // делаем меню ссылок = меню записей
$menu[5] = $storemenu; // делаем меню 5/записи = $storemenu/ссылки
}
add_action('admin_menu', 'admin_menu_items');
Использую этот трюк уже некоторое время, проверено на WP 3.4.1

Отлично. Большое спасибо. Я просто добавил несколько строк кода в свой functions.php
require_once('/extras/wp-admin-menu-classes.php');
add_action('admin_menu','my_admin_menu');
function my_admin_menu() {
swap_admin_menu_sections('Pages','Posts'); // Меняем местами разделы "Записи" и "Страницы"
}
Плюс разместил файл wp-admin-menu-classes.php в папке моей темы, и теперь кнопка "Записи" поменялась местами с кнопкой "Страницы".
Надеюсь, что это скоро станет частью ядра и в такой форме, чтобы нам не приходилось прописывать всё меню в функции только для того, чтобы поменять местами две кнопки.
На самом деле было немного сложнее задать более точный порядок для 4 кнопок. Чтобы изменить порядок 4 кнопок на: Страницы, Записи, Медиафайлы, Ссылки Мне пришлось использовать следующий код:
swap_admin_menu_sections('Pages','Posts');
swap_admin_menu_sections('Media','Links');
swap_admin_menu_sections('Posts','Links');
