Как управлять позицией пунктов меню, добавленных плагинами, в панели администратора?

8 авг. 2017 г., 21:12:43
Просмотры: 49.9K
Голосов: 16

Прочитав в других местах 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') переупорядочивается.

0
Все ответы на вопрос 4
3
23

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

Чтобы решить эту проблему, я разработал небольшую функцию. Просто определите ваш массив $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;
};
1 окт. 2018 г. 15:47:53
Комментарии

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

Brett Brett
2 янв. 2019 г. 23:19:25

@Brett Похоже, что так и будет работать.

Davey Davey
17 июл. 2019 г. 17:32:35

Всё ещё отлично работает - спасибо

Hannah Smith Hannah Smith
21 дек. 2021 г. 17:29:54
4
17

При создании типа записи с помощью функции register_post_type() вы можете задать позицию в меню:

menu_position (целое число) (необязательно) Позиция в порядке меню, где должен появиться тип записи. Параметр show_in_menu должен быть true.

    По умолчанию: null - располагается ниже пункта "Комментарии"

    5  - ниже "Записи"
    10 - ниже "Медиафайлы"
    15 - ниже "Ссылки"
    20 - ниже "Страницы"
    25 - ниже "Комментарии"
    59 - ниже первого разделителя
    60 - ниже "Внешний вид"
    65 - ниже "Плагины"
    70 - ниже "Пользователи"
    75 - ниже "Инструменты"
    80 - ниже "Настройки"
    99 - ниже второго разделителя

Если элементы имеют одинаковую позицию в меню, они сортируются в алфавитном порядке.

В собственном плагине вы можете задать уровень. Если вы пытаетесь изменить позицию меню плагина, который не создавали, многие из них могут быть переопределяемыми (pluggable), или вы можете отредактировать их вызовы.

9 авг. 2017 г. 01:31:51
Комментарии

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

glvr glvr
9 авг. 2017 г. 12:48:16

Отлично, работает прекрасно

Jodyshop Jodyshop
25 окт. 2021 г. 22:58:06

Можно также использовать десятичные числа: 25.3

Azamat Azamat
22 авг. 2022 г. 09:39:30

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

Talk Nerdy To Me Talk Nerdy To Me
28 июл. 2023 г. 18:57:02
3
16

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

9 авг. 2017 г. 01:40:36
Комментарии

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

glvr glvr
9 авг. 2017 г. 12:44:18

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

glvr glvr
9 авг. 2017 г. 12:51:16

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

WebDude0482 WebDude0482
3 дек. 2020 г. 20:16:54
0

Спасибо 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;
};
30 июл. 2020 г. 02:43:37