I am adding items to a CPT Admin menu using add_submenu_page
which works great, but they are added to the bottom of the sub-menu after the CPT options. I want to be able to have them on top , but I suppose this question can also apply to ordering all Admin based sub-menu items.
What I tried ( not working, I tried several variations),
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array(
'edit.php?post_type=page' =>array(
'edit.php?post_type=note',
'edit_pages',
'notes',
)
);
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
Would this be because menu_order
filter does not take sub-menu's into account?
I am adding items to a CPT Admin menu using add_submenu_page
which works great, but they are added to the bottom of the sub-menu after the CPT options. I want to be able to have them on top , but I suppose this question can also apply to ordering all Admin based sub-menu items.
What I tried ( not working, I tried several variations),
function custom_menu_order($menu_ord) {
if (!$menu_ord) return true;
return array(
'edit.php?post_type=page' =>array(
'edit.php?post_type=note',
'edit_pages',
'notes',
)
);
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
Would this be because menu_order
filter does not take sub-menu's into account?
3 Answers
Reset to default 3The filter 'custom_menu_order' will not work on the menu order because apply_filters in wp-admin/includes/menu.php supplies false as the filtered content. You can try changing false to $menu and the filter works grand.
Since we obviously can't touch the core, here's how I got it to work:
function custom_menu_order(){
global $submenu;
$find_page = 'edit.php';
$find_sub = 'Post Tags';
foreach($submenu as $page => $items):
if($page == $find_page):
foreach($items as $id => $meta):
if($meta[0] == $find_sub):
$submenu[$find_page][0] = $meta;
unset ($submenu[$find_page][$id]);
ksort($submenu[$find_page]);
endif;
endforeach;
endif;
endforeach;
}
add_action('_admin_menu', 'custom_menu_order');
I know I'm necro-posting but I recently had the same issue. Please note that I used Rao's solution on SO to get to this answer.
Assuming your CPT is called "notes".
/**
* @see https://codex.wordpress/Plugin_API/Filter_Reference/menu_order
*/
add_filter( 'custom_menu_order', 'change_note_submenu_order' );
/**
* Change the submenu order for the Note CPT in the Admin panel
*
* @param [type] $menu_ord I don't think this is actually used for anything...
* @return [type] $menu_ord
* @see https://stackoverflow/questions/18766477/wordpress-change-admin-submenu-order
*/
function change_note_submenu_order( $menu_ord ) {
global $submenu;
/* Uncomment the line below to see all menu orders */
// echo '<pre>'.print_r($submenu,true).'</pre>';
/**
* NOTE: Original note submenu order should be:
* 5 (note list),
* 10 (Add new),
* 15 (Categories),
* 16 (Tags),
* 17 (Your Custom Page added via add_submenu_page) */
$arr = array();
$arr[] = $submenu['edit.php?post_type=note'][17]; // Custom menu page (Omit if unused)
$arr[] = $submenu['edit.php?post_type=note'][5]; // Note List
$arr[] = $submenu['edit.php?post_type=note'][10]; // Add New Note
$arr[] = $submenu['edit.php?post_type=note'][15]; // Categories
$arr[] = $submenu['edit.php?post_type=note'][16]; // Tags
$submenu['edit.php?post_type=note'] = $arr;
return $menu_ord;
}
Definitely comment out the echo '<pre>'.print_r($submenu,true).'</pre>';
if your having trouble. Also remember you can manually set the array too in the change_note_submenu_order
function.
$notes_list = array("Notes", "edit_posts", "edit.php?post_type=notes");
$custom_page = array("Custom Menu Page Title", "Capability", "Menu Slug", "Page Title");
$new_note = array("Add New", "edit_posts", "post-new.php?post_type=note");
$arr = array($custom_page, $notes_list, $new_note);
$submenu['edit.php?post_type=note'] = $arr;
Hope this helps somebody!
Another necro for a simpler issue.
I just wanted to move my custom link to the bottom (added comment on how it could be used to address original question as well):
public function change_wc_submenu_order( $menu_order ) {
global $submenu;
foreach ( $submenu['woocommerce'] as $index => $item ) {
if ('My Custom Submenu Title' === $item[0] ) {
$custom = $item;
unset( $submenu['woocommerce'][$index] );
break;
}
}
if ( ! empty( $custom ) ) {
// If we want it at the beginning, use array_unshift() instead
array_push( $submenu['woocommerce'], $custom );
}
return $menu_order;
}