Custom Post Type Link from Plugin

I’m currently working on a plugin that creates a custom post type. The issue I’m strugging with at the moment is that the custom post type is created fine, but when I go to add a new post I receive an “Invalid Post Type” error.

The ui is hidden and I’m trying to link to it from add_submenu_page. I need assistance for how to properly link it.

Read More

Here is what I have in the submenu declaration:

add_submenu_page( 'restaurant-orders', 'Menu Management', 'Menu Management', 'manage_options', 'edit.php?post_type=menu-item');

My post type:

function restaurant_menu_items() {

    $labels = array(
        'name' => __('Restaurant Menu Items', 'post type general name'),
        'singular_name' => __('Restaurant Menu Item', 'post type singular name'),
        'add_new' => __('Add New', 'product page'),
        'add_new_item' => __('Add New Menu Item'),
        'edit_item' => __('Edit Menu Item'),
        'new_item' => __('New Menu Item'),
        'view_item' => __('View Menu Item'),
        'search_items' => __('Search Menu Items'),
        'not_found' =>  __('Nothing found'),
        'not_found_in_trash' => __('Nothing found in Trash'),
        'parent_item_colon' => ''
    );

    $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => false,
        'query_var' => true,
        'menu_icon' => get_stylesheet_directory_uri() . '/article16.png',
        'rewrite' => true,
        'capability_type' => 'post',
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array('title','editor','thumbnail'),
      ); 

    register_post_type( 'menu-item' , $args );
}

I can add a new post if I show the ui and do it the conventional way. However I do not want it this way, the post menu has to be under the plugin menu.

Thanks!

Related posts

Leave a Reply

3 comments

  1. Magic here is:

    'show_ui' => true,
    'show_in_menu' => 'plugins.php',
    

    Try this:

    function restaurant_menu_items() {
    
        $labels = array(
            'name' => __('Restaurant Menu Items', 'post type general name'),
            'singular_name' => __('Restaurant Menu Item', 'post type singular name'),
            'add_new' => __('Add New', 'product page'),
            'add_new_item' => __('Add New Menu Item'),
            'edit_item' => __('Edit Menu Item'),
            'new_item' => __('New Menu Item'),
            'view_item' => __('View Menu Item'),
            'search_items' => __('Search Menu Items'),
            'not_found' =>  __('Nothing found'),
            'not_found_in_trash' => __('Nothing found in Trash'),
            'parent_item_colon' => ''
        );
    
        $args = array(
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => 'plugins.php',
            'query_var' => true,
            'menu_icon' => get_stylesheet_directory_uri() . '/article16.png',
            'rewrite' => true,
            'capability_type' => 'post',
            'hierarchical' => false,
            'menu_position' => null,
            'supports' => array('title','editor','thumbnail'),
          ); 
    
        register_post_type( 'menu-item' , $args );
    }
    
  2. As @ÜnsalKorkmaz already pointed out in his solution, one needs to use show_in_menu. I’m trying to explain what the problem with NULL or FALSE values is, when you’re registering a custom post type or a custom taxonomy: There’re defaults that you have to know… or have to know how to get enough feedback to understand what happens.

    Inspect core

    Take a look at register_post_type() internals. In the following example, which is taken from that API function, you’ll see what happens.

    // If not set, default to the setting for public.
    if ( null === $args->show_ui )
        $args->show_ui = $args->public;
    
    // If not set, default to the setting for show_ui.
    if ( null === $args->show_in_menu || ! $args->show_ui )
        $args->show_in_menu = $args->show_ui;
    

    Conclusions you can make after reading core internals

    Most core functions have a default value that makes work even if you don’t specify every value. And some of those parameters have a lower priority as others. You can see that with the public argument that will have a default only if show_ui was not defined.

    How to gather enough feedback?

    Most core functions have a hook to intercept the arguments and that runs before the actual task as well as another one that runs immediately afterwards. In this situation the later hook looks like this:

    do_action( 'registered_post_type', $post_type, $args );
    

    So you make yourself a little…

    …plugin that helps you doing live debugging

    This will now output/dump the full set of arguments, after core has thrown in its defaults. From my own experience: This is a massive helper as you can monitor every single change without getting down the rabbit hole and making your hands dirty in core. Enjoy.

    <?php
    defined( 'ABSPATH' ) OR exit;
    /**
     * Plugin Name: (#89066) Debug Register Post Type Args
     */
    add_action( 'registered_post_type', 'wpse89066_debug_cpt_args', 10, 2 );
    function wpse89066_debug_cpt_args( $post_type, $args )
    {
        printf( '<h1>%s</h1>', $post_type );
        var_dump( $args );
    }
    

    Full Plugin

    You can grab the full version of this plugin over here at GitHub as Gist.

  3. The helper plugin for developer Debug Objects list the arguments of custom post types, easy to use. But for this output part use the current development version on github, she have more features.

    Example output of arguments to custom post type.
    enter image description here