Как управлять позицией пунктов меню, добавленных плагинами, в панели администратора?
Прочитав в других местах Stack о двух плагинах WordPress, принудительно использующих одинаковые позиции меню (с вероятностью того, что один из них может не отображаться), я задаюсь вопросом, как можно управлять позицией пунктов меню, добавленных плагинами.
Я уже использую функцию, которая, похоже, обрабатывает такие подпункты меню в 'settings', и другую функцию для переупорядочивания стандартных элементов 'верхнего уровня' (записи, страницы, темы, плагины, настройки и т.д.) - но которая не меняет позиционирование элементов, добавленных плагинами.
function custom_menu_order() {
return array(
//Добавьте элементы здесь в желаемом порядке.
);
}
add_filter( 'custom_menu_order', '__return_true' );
add_filter( 'menu_order', 'custom_menu_order' );
Например, из двух пунктов меню верхнего уровня, добавленных WooCommerce, один появляется выше элемента, добавленного ContactForm7, а другой - ниже, и было бы неплохо переупорядочить их соответствующим образом - а также иметь возможность лучше переупорядочивать элементы, которые не принудительно задают позицию в меню и вместо этого появляются внизу.
Я заметил, что обычно это хорошо работает для переупорядочивания стандартных элементов и элементов типа 'edit.php?post_type=...', но элементы с 'admin.php?page=...' не переупорядочиваются.
Когда моя функция переупорядочивания отключена, два элемента WooCommerce ('edit.php?post_type=product' и 'edit.php?post_type=shop_order') группируются вместе, как и предполагалось, но когда функция активируется, они разделяются элементом ContactForm7 ('admin.php?page=wpcf7').
И один ('edit.php?post_type=shop_order') из пользовательских типов записей WooCommerce не переупорядочивается - хотя другой ('edit.php?post_type=product') переупорядочивается.

Существующие ответы вполне подходят, но если вы добавите новый пользовательский тип записи, вам придется снова и снова редактировать эти функции.
Чтобы решить эту проблему, я разработал небольшую функцию. Просто определите ваш массив $new_positions
внутри функции my_new_menu_order
:
/**
* Активирует фильтр 'menu_order' и подключается к 'menu_order'
*/
add_filter('custom_menu_order', function() { return true; });
add_filter('menu_order', 'my_new_admin_menu_order');
/**
* Фильтрует стандартный порядок меню в WordPress
*/
function my_new_admin_menu_order( $menu_order ) {
// здесь определите желаемые позиции меню
// например, переместите 'upload.php' на позицию #9, а встроенные страницы на позицию #1
$new_positions = array(
'upload.php' => 9,
'edit.php?post_type=page' => 1
);
// вспомогательная функция для перемещения элемента внутри массива
function move_element(&$array, $a, $b) {
$out = array_splice($array, $a, 1);
array_splice($array, $b, 0, $out);
}
// перебираем новые позиции и перемещаем
// элементы, если они найдены в оригинальном menu_order
foreach( $new_positions as $value => $new_index ) {
if( $current_index = array_search( $value, $menu_order ) ) {
move_element($menu_order, $current_index, $new_index);
}
}
return $menu_order;
};

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

При создании типа записи с помощью функции register_post_type() вы можете задать позицию в меню:
menu_position (целое число) (необязательно) Позиция в порядке меню, где должен появиться тип записи. Параметр show_in_menu должен быть true.
По умолчанию: null - располагается ниже пункта "Комментарии" 5 - ниже "Записи" 10 - ниже "Медиафайлы" 15 - ниже "Ссылки" 20 - ниже "Страницы" 25 - ниже "Комментарии" 59 - ниже первого разделителя 60 - ниже "Внешний вид" 65 - ниже "Плагины" 70 - ниже "Пользователи" 75 - ниже "Инструменты" 80 - ниже "Настройки" 99 - ниже второго разделителя
Если элементы имеют одинаковую позицию в меню, они сортируются в алфавитном порядке.
В собственном плагине вы можете задать уровень. Если вы пытаетесь изменить позицию меню плагина, который не создавали, многие из них могут быть переопределяемыми (pluggable), или вы можете отредактировать их вызовы.

@ rudtek... спасибо. В своих собственных CPT я избегал установки позиций меню, предпочитая вместо этого использовать переупорядочивание меню и таким образом "держать все в одном месте", что облегчает последующие изменения. Поскольку у меня нет собственных плагинов, для которых я пытаюсь установить позицию меню, это касается сторонних плагинов — о них я знаю недостаточно в плане "подключаемости" или редактирования их вызовов (которые, предположительно, будут перезаписаны при обновлении).

Исходный файл ядра WordPress, подтверждающий этот ответ (и, возможно, требующий обновления со временем): /wp-admin/menu.php

Для изменения порядка элементов верхнего уровня в меню администратора вам понадобятся два хука
, два фильтра
и одна функция
. Поместите следующий код в файл functions.php
вашей текущей темы:
function wpse_custom_menu_order( $menu_ord ) {
if ( !$menu_ord ) return true;
return array(
'index.php', // Консоль
'separator1', // Первый разделитель
'edit.php', // Записи
'upload.php', // Медиафайлы
'link-manager.php', // Ссылки
'edit-comments.php', // Комментарии
'edit.php?post_type=page', // Страницы
'separator2', // Второй разделитель
'themes.php', // Внешний вид
'plugins.php', // Плагины
'users.php', // Пользователи
'tools.php', // Инструменты
'options-general.php', // Настройки
'separator-last', // Последний разделитель
);
}
add_filter( 'custom_menu_order', 'wpse_custom_menu_order', 10, 1 );
add_filter( 'menu_order', 'wpse_custom_menu_order', 10, 1 );
Возвращаемый массив элементов верхнего уровня меню администратора, приведённый выше, представляет элементы меню, добавленные ядром WordPress, в их стандартном порядке. Чтобы включить элементы меню, добавленные плагинами, мы должны добавить их в этот массив. Допустим, у нас есть два плагина, которые добавлены и активированы (например: Wordfence
и NextCellent Gallery
). Сначала нам нужно найти названия этих элементов меню. Когда мы кликаем на элемент верхнего уровня плагина Wordfence
, итоговый URL будет заканчиваться на ?page=Wordfence
. Часть после ?page=
— это наше название (Wordfence
). Для NextCellent Gallery
название будет nextcellent-gallery-nextgen-legacy
. Теперь добавим эти элементы в наш массив:
return array(
'index.php', // Консоль
'separator1', // Первый разделитель
'edit.php', // Записи
'upload.php', // Медиафайлы
'link-manager.php', // Ссылки
'edit-comments.php', // Комментарии
'edit.php?post_type=page', // Страницы
'separator2', // Второй разделитель
'themes.php', // Внешний вид
'plugins.php', // Плагины
'users.php', // Пользователи
'tools.php', // Инструменты
'separator3', // Третий разделитель
'options-general.php', // Настройки
'separator-last', // Последний разделитель
'Wordfence', // Wordfence
'nextcellent-gallery-nextgen-legacy', // NextCellent Gallery
);
Теперь мы можем перемещать элементы этого массива вверх и вниз, чтобы получить окончательный порядок.
Примечание: вы также можете использовать плагин Admin Menu Editor для удобного перетаскивания элементов.

@ Frank P. Walentynowicz ...спасибо за развернутый ответ. Я обновил свой исходный пост для уточнения, и ваше предложение использовать 'часть после ?page=' очень помогло и решает мою проблему - за исключением одного из двух элементов WooCommerce.

Быстрое дополнение к моему предыдущему комментарию: я ранее использовал Admin Menu Editor, но предпочитаю жестко закодированную функцию.

Каково значение параметров 10,1? Как в add_filter( 'menu_order', 'wpse_custom_menu_order', 10, 1 ); Я не могу найти никакой информации об этом. Наверное, что-то простое. Но я не могу заставить WooCommerce сдвинуться с места и думаю, может ли это быть связано с этим.

Спасибо rassoh за отличное решение.
Вот переработанная версия, которая содержит список страниц, которые, вероятно, всегда должны оставаться вверху...
/**
* Эти 2 фильтра и 1 функция перемещают встроенные страницы админки WordPress
* вверх, чтобы они не опускались в меню при установке каждого нового плагина.
* Активирует фильтр 'menu_order' и затем подключается к 'menu_order'
*/
add_filter('custom_menu_order', function() { return true; });
add_filter('menu_order', 'my_new_admin_menu_order');
/**
* Фильтрует стандартный порядок меню WordPress
*/
function my_new_admin_menu_order( $menu_order ) {
// здесь задаются новые желаемые позиции меню
// например, переместить 'upload.php' на позицию #9, а встроенные страницы на позицию #1
$new_positions = array(
'index.php' => 1, // Консоль
'edit.php' => 2, // Записи
'upload.php' => 3, // Медиафайлы
'edit.php?post_type=page' => 4, // Страницы
'edit-comments.php' => 5 // Комментарии
);
// вспомогательная функция для перемещения элемента внутри массива
function move_element(&$array, $a, $b) {
$out = array_splice($array, $a, 1);
array_splice($array, $b, 0, $out);
}
// проходим по новым позициям и перемещаем
// элементы, если они найдены в исходном menu_positions
foreach( $new_positions as $value => $new_index ) {
if( $current_index = array_search( $value, $menu_order ) ) {
move_element($menu_order, $current_index, $new_index);
}
}
return $menu_order;
};
