Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm planning to use a couple of custom post types for a plugin of mine. The whole plugin should reside under 1 toplevel menu item. Thus I would prefer a menu structure like so:

  • Dashboard
  • Posts
  • [...]
  • My Plugin

    • Custom Post Type #1
    • Custom Post Type #2
    • [...]

This is possible by including 'show_in_menu' => 'my_plugin_toplevel_menu_item_slug' in register_post_type when registering my custom post types. Howerer, there are a few issues I've come across using this method.

  • I have no say in how the title should be outputted. I would prefer to use <h2 class="nav-tab-wrapper"> ... </h2>, but now post.php prints the h2 output for me, and I don't know an easy way of overriding this. It is possible to do this with javascript as soon as the page is loaded, but this is a bit ugly in my opinion.
  • When using 'show_in_menu', the submenu page order cannot be altered. The custom post types are placed at the top automatically, because I guess Wordpress just gets to it quicker than I do.
  • The h2 icon disappears for some reason (I haven't really looked into this yet though, it might be very easy to solve).

Does anybody have an idea how to tackle these issues elegantly?

Update

See temporary solution in my answer below.

share|improve this question
1  
AFAIK, manipulating the global $submenu is the only way to do this. You should add your solution as an Answer. –  brasofilo Feb 28 '13 at 5:56

1 Answer 1

The (temporary?) solution I've settled for, is the following:

  1. Use the show_in_menu parameter of register_post_type
  2. Use javascript to display custom title after page load
  3. Solve the submenu page order (which automatically puts the custom post types at the top, which is not my intention), with the following helper function:

...

// Sort the children of a given toplevel menu item
// Keep original order intact as much as possible, while
//  enforcing the [before => after] rules given by $force_order
function help_sort_submenu_items($toplevel_slug, $force_order) {
  global $submenu;

  $done = array();
  $hold = array();
  $newmenu = array();

  foreach ($submenu[$toplevel_slug] as $i => $item) {
    $force_after = array_search($item[2], $force_order);
    if ($force_after !== false && empty($done[$force_after])) {
      $hold[$item[2]] = $item;
    } else {
      $newmenu []= $item;
      $done[$item[2]] = true;

      $just_added_id = $item[2];
      while ($just_added_id = $force_order[$just_added_id]) {
        $next = $hold[$just_added_id];
        $newmenu []= $next;
        $done[$just_added_id] = true;
      }
    }
  }

  $submenu[$toplevel_slug] = $newmenu;
}

Usage like so:

help_sort_submenu_items('my_plugin_toplevel_menu_item_slug', array(
  'submenu_page_with_this_slug_comes_before' => 'submenu_page_with_this_slug',
  'another' => 'rule'
));
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.