If this is what you want:
… you can do it like so:
Step #1: Add the custom menu item (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' );
Notes:
-
I’m using
add_menu_page()
to add the menu (which is a top-level menu) with the permissionedit_pages
and the icondashicons-admin-page
โ just check the reference for more details about the syntax and parameters, but the position (the 7th parameter) is set to19
which would put the menu above thePages
menu. -
If you change the name of the query string
template
, you also need to change it in both steps #2 and #3 below. But if you change just the value, you only need to also change it in step #2 below.
Step #2: Highlight the menu item (this adds current
to the item/li
class
) after you clicked on the link.
Because the ‘Pages’ and ‘Pages ยป All Pages’ menu slug is edit.php?post_type=page
, we have to make sure WordPress doesn’t override the $parent_file
(i.e. the above $slug
value) as set in highlight_retailer_sendout_admin_menu()
below, so the fix_admin_parent_file_override()
, although is a hack/trick, is needed โ you could just add the CSS class current
to the Retailer Sendout
menu, but you’d end up with two/three highlighted menus..
And even though I’m not changing the CSS class
, you can use the function to add your custom class(es) and/or remove/edit existing ones. Also, just so you know, the $menu
is an array of the top-level menus only, so I use the $submenu
to access the sub-menus. I also use $pagenow
because at this point, the current screen (see get_current_screen()
) hasn’t been setup yet.
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' );
And next, we set the $parent_file
โ note that in the above, we don’t set the $parent_file
, we only make sure WordPress doesn’t override the value afterwards. So for this part, we should use the parent_file
hook:
function highlight_retailer_sendout_admin_menu( $parent_file ) {
// Make sure the PARENT slug is the one for the 'Pages"https://wordpress.stackexchange.com/"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' );
Step #3: Filter the pages by the template.
The template name is stored in a private metadata named _wp_page_template
, so we filter the posts/pages query by adding a meta query for that metadata.
And we’re using the pre_get_posts
hook which also runs on the public side of the site, so we perform checks like is_admin()
and is_main_query()
to prevent messing with other WP_Query
calls (or posts requests).
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' );
And actually, you can use the code to filter any templates.. not just the page-retailer-sendout.php
as in the question. ๐