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


Я хочу добавить новый пользовательский пункт меню на боковую панель администратора WordPress, который отображает страницы, использующие определенный шаблон. Например: группа страниц использует шаблон под названием "Рассылка розничной торговли" (page-retailer-sendout.php ) будет отображаться под пунктом меню верхнего уровня "Страницы" по умолчанию.

Я пробовал следующие комбинации URL-адресов, но ни одна из них не сработала так далеко.

Я также протестировал некоторые плагины настройки меню администратора, но они не дают возможности ссылаться на страницы с определенным именем шаблона.

Я мне удобно добавлять пользовательскую функцию в тему functions.php файл, но я не знаю, с чего начать.

Мы будем очень признательны за любую помощь.

Author: Mike Hermary, 2020-03-26

1 answers

Если это то, что вы хотите:

Sample Output

... вы можете сделать это так:

Шаг №1: Добавьте пользовательский пункт меню (Retailer Sendout).

function add_retailer_sendout_admin_menu() {
    $slug = 'edit.php?post_type=page&template=page-retailer-sendout.php';

    add_menu_page( 'Retailer Sendout', 'Retailer Sendout', 'edit_pages', $slug,
        '', 'dashicons-admin-page', 19 );
}
add_action( 'admin_menu', 'add_retailer_sendout_admin_menu' );

Примечания:

  1. Я использую add_menu_page() чтобы добавить меню (которое является меню верхнего уровня) с разрешением edit_pages и значком dashicons-admin-page - просто проверьте ссылку для получения более подробной информации о синтаксисе и параметрах, но позиция (7-й параметр) установлена на 19, которая поместил бы меню над Pages меню.

  2. Если вы измените имя строки запроса template, вам также необходимо изменить его в на обоих шагах #2 и #3 ниже. Но если вы измените только значение , вам нужно будет также изменить его на шаге №2 ниже.

Шаг №2: Выделите пункт меню (это добавит current к пункту/li class) после того, как вы нажали на ссылку.

Потому что "Страницы" и "Страницы" Меню всех страниц slug edit.php?post_type=page, мы должны убедиться, что WordPress не переопределяет $parent_file (т.Е. Указанное выше значение $slug), как указано в highlight_retailer_sendout_admin_menu() ниже, поэтому fix_admin_parent_file_override(), хотя это хак/трюк, необходим - вы могли бы просто добавить класс CSS current в меню Retailer Sendout, но в итоге у вас будет два/три выделенных меню..

И хотя я не изменяю CSS class, вы можете использовать эту функцию для добавления своих пользовательских классов и/или удаления/редактирования существующих. Кроме того, просто так вы знаете, что $menu представляет собой массив меню верхнего уровня только , поэтому я использую $submenu для доступа к подменю. Я также использую $pagenow, потому что на данный момент текущий экран (см. get_current_screen()) еще не был настроен.

function fix_admin_parent_file_override( $menu ) {
    global $pagenow, $submenu;

    // If we're NOT on the edit.php page, do nothing.
    if ( ! is_admin() || 'edit.php' !== $pagenow ) {
        return $menu;
    }

    // Same as in the above add_retailer_sendout_admin_menu().
    $slug = 'edit.php?post_type=page&template=page-retailer-sendout.php';

    // We have to make sure the $parent_file is not overriden (by WordPress) to
    // the 'Pages' menu.
    if ( ! empty( $_GET['template'] ) &&
        'page-retailer-sendout.php' === $_GET['template'] ) {
        // Change the 'Pages' URL.
        $menu[20][2] .= '&template=';
        $submenu[ $menu[20][2] ] = $submenu['edit.php?post_type=page'];

        // Change the 'All Pages' URL.
        $submenu[ $menu[20][2] ][5][2] = $menu[20][2];

        unset( $submenu['edit.php?post_type=page'] );
    }

    return $menu;
}
add_filter( 'add_menu_classes', 'fix_admin_parent_file_override' );

И далее мы устанавливаем $parent_file - обратите внимание, что в приведенном выше примере мы не устанавливаем $parent_file, мы только следим за тем, чтобы WordPress впоследствии не переопределял значение. Поэтому для этой части мы должны использовать parent_file крюк:

function highlight_retailer_sendout_admin_menu( $parent_file ) {
    // Make sure the PARENT slug is the one for the 'Pages' / 'All Pages' menu.
    if ( 'edit.php?post_type=page' === $parent_file &&
        ( ! empty( $_GET['template'] ) )            &&
        // ..and make sure the template being queried is page-retailer-sendout.php.
        'page-retailer-sendout.php' === $_GET['template'] )
    {
        // Return the $slug value as in the above add_retailer_sendout_admin_menu()
        return 'edit.php?post_type=page&template=page-retailer-sendout.php';
    }
    return $parent_file;
}
add_filter( 'parent_file', 'highlight_retailer_sendout_admin_menu' );

Шаг № 3: Отфильтруйте страницы по шаблону.

Имя шаблона хранится в частных метаданных с именем _wp_page_template, поэтому мы фильтруем запрос сообщений/страниц, добавляя мета-запрос для этих метаданных.

И мы используем pre_get_posts крюк, который также работает на общедоступной стороне сайта, поэтому мы выполняем проверки, такие как is_admin() и is_main_query() чтобы предотвратить вмешательство в другие WP_Query вызовы (или сообщения запросы).

function filter_admin_pages_by_template( $query ) {
    // Make sure we run the filter only on the admin side of the site (wp-admin)
    // and that the query is the main query.
    if ( is_admin() && $query->is_main_query() &&
        ( ! empty( $_GET['template'] ) )       &&
        // ..and also, check if we're on the edit.php?post_type=page screen.
        'edit-page' === get_current_screen()->id )
    {
        $meta_query = (array) $query->get( 'meta_query' );
        $meta_query[] = array(
            'key'   => '_wp_page_template',
            'value' => $_GET['template'],
        );
        $query->set( 'meta_query', $meta_query );
    }
}
add_action( 'pre_get_posts', 'filter_admin_pages_by_template' );

И на самом деле, вы можете использовать код для фильтрации любых шаблонов.. не только page-retailer-sendout.php, как в вопросе. :)

 3
Author: Sally CJ, 2020-03-28 03:50:07