0

Is it possible to display a list of the custom post type POSTS, not archive link, inside a meta box on the nav menus page?

Currently, it displays each CPT post inside it's own metabox, but I would like to group them all into one box, so the user can check as many posts as they want and only have to click "Add To menu" once.

I've seen a few plugins and code examples that allow you to display the CPT archive link in a metabox, but that's not what I'm looking for. I want to display the post that has been added under each parent CPT.

Any ideas on how to achieve this? Hopefully that all made sense...

1
  • Sorry, it's not a duplicate. I wrote a comment on Tom's Answer that I'm moving here as an answer.
    – brasofilo
    Commented May 22, 2013 at 21:05

1 Answer 1

2

From what I thought was a duplicate, we get a class to render the meta box in the Nav-Menus page.

Then I used this core function to render the meta box contents.

It works ok, but it's displaying some notices and may need a good cleanup. It's too much code to parse right now and I'll leave it here as starting point. The modifications I've done involve the vars $post_type_name and $post_types_list. There's a comment in the line that's not working and displaying the notice in the View All tab.

add_action( 'admin_init', array( 'call_someClass', 'init' ) );

/**
 * The Class
 */
class call_someClass {
    const LANG = 'exch_lang';

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
        global $pagenow;
        // Abort if not on the nav-menus.php admin UI page - avoid adding elsewhere
        if ( 'nav-menus.php' !== $pagenow )
                    return;

        $this->add_some_meta_box();
    }

    /**
     * Adds the meta box container
     */
    public function add_some_meta_box(){
        add_meta_box(
            'info_meta_box_'
            ,__( 'Example metabox', self::LANG )
            ,array( $this, 'render_meta_box_content' )
            ,'nav-menus' // important !!!
            ,'side' // important, only side seems to work!!!
            ,'high'
        );
    }

    /**
     * Render Meta Box content
     */
    public function render_meta_box_content() {
        global $_nav_menu_placeholder, $nav_menu_selected_id;

        $post_type_name = 'all-cpts';
        $post_types_list = array_keys(get_post_types( array( 'show_in_nav_menus' => true ), 'array' ));

        // paginate browsing for large numbers of post objects
        $per_page = 50;
        $pagenum = isset( $_REQUEST[$post_type_name . '-tab'] ) && isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1;
        $offset = 0 < $pagenum ? $per_page * ( $pagenum - 1 ) : 0;

        $args = array(
            'offset' => $offset,
            'order' => 'ASC',
            'orderby' => 'title',
            'posts_per_page' => $per_page,
            'post_type' => $post_types_list,
            'suppress_filters' => true,
            'update_post_term_cache' => false,
            'update_post_meta_cache' => false
        );

        if ( isset( $post_type['args']->_default_query ) )
            $args = array_merge($args, (array) $post_type['args']->_default_query );

        // @todo transient caching of these results with proper invalidation on updating of a post of this type
        $get_posts = new WP_Query;
        $posts = $get_posts->query( $args );
        if ( ! $get_posts->post_count ) {
            echo '<p>' . __( 'No items.' ) . '</p>';
            return;
        }

        $post_type_object = get_post_type_object($post_type_name);

        $num_pages = $get_posts->max_num_pages;

        $page_links = paginate_links( array(
            'base' => add_query_arg(
                array(
                    $post_type_name . '-tab' => 'all',
                    'paged' => '%#%',
                    'item-type' => 'post_type',
                    'item-object' => $post_type_name,
                )
            ),
            'format' => '',
            'prev_text' => __('&laquo;'),
            'next_text' => __('&raquo;'),
            'total' => $num_pages,
            'current' => $pagenum
        ));

        if ( !$posts )
            $error = '<li id="error">'. $post_type['args']->labels->not_found .'</li>';

        $db_fields = false;
        if ( is_post_type_hierarchical( $post_type_name ) ) {
            $db_fields = array( 'parent' => 'post_parent', 'id' => 'ID' );
        }

        $walker = new Walker_Nav_Menu_Checklist( $db_fields );

        $current_tab = 'most-recent';
        if ( isset( $_REQUEST[$post_type_name . '-tab'] ) && in_array( $_REQUEST[$post_type_name . '-tab'], array('all', 'search') ) ) {
            $current_tab = $_REQUEST[$post_type_name . '-tab'];
        }

        if ( ! empty( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
            $current_tab = 'search';
        }

        $removed_args = array(
            'action',
            'customlink-tab',
            'edit-menu-item',
            'menu-item',
            'page-tab',
            '_wpnonce',
        );

        ?>
        <div id="posttype-<?php echo $post_type_name; ?>" class="posttypediv">
            <ul id="posttype-<?php echo $post_type_name; ?>-tabs" class="posttype-tabs add-menu-item-tabs">
                <li <?php echo ( 'most-recent' == $current_tab ? ' class="tabs"' : '' ); ?>><a class="nav-tab-link" href="<?php if ( $nav_menu_selected_id ) echo esc_url(add_query_arg($post_type_name . '-tab', 'most-recent', remove_query_arg($removed_args))); ?>#tabs-panel-posttype-<?php echo $post_type_name; ?>-most-recent"><?php _e('Most Recent'); ?></a></li>
                <li <?php echo ( 'all' == $current_tab ? ' class="tabs"' : '' ); ?>><a class="nav-tab-link" href="<?php if ( $nav_menu_selected_id ) echo esc_url(add_query_arg($post_type_name . '-tab', 'all', remove_query_arg($removed_args))); ?>#<?php echo $post_type_name; ?>-all"><?php _e('View All'); ?></a></li>
                <li <?php echo ( 'search' == $current_tab ? ' class="tabs"' : '' ); ?>><a class="nav-tab-link" href="<?php if ( $nav_menu_selected_id ) echo esc_url(add_query_arg($post_type_name . '-tab', 'search', remove_query_arg($removed_args))); ?>#tabs-panel-posttype-<?php echo $post_type_name; ?>-search"><?php _e('Search'); ?></a></li>
            </ul>

            <div id="tabs-panel-posttype-<?php echo $post_type_name; ?>-most-recent" class="tabs-panel <?php
                echo ( 'most-recent' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' );
            ?>">
                <ul id="<?php echo $post_type_name; ?>checklist-most-recent" class="categorychecklist form-no-clear">
                    <?php
                    $recent_args = array_merge( $args, array( 'orderby' => 'post_date', 'order' => 'DESC', 'posts_per_page' => 15 ) );
                    $most_recent = $get_posts->query( $recent_args );
                    $args['walker'] = $walker;
                    echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $most_recent), 0, (object) $args );
                    ?>
                </ul>
            </div><!-- /.tabs-panel -->

            <div class="tabs-panel <?php
                echo ( 'search' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' );
            ?>" id="tabs-panel-posttype-<?php echo $post_type_name; ?>-search">
                <?php
                if ( isset( $_REQUEST['quick-search-posttype-' . $post_type_name] ) ) {
                    $searched = esc_attr( $_REQUEST['quick-search-posttype-' . $post_type_name] );
                    $search_results = get_posts( array( 's' => $searched, 'post_type' => $post_types_list, 'fields' => 'all', 'order' => 'DESC', ) );
                } else {
                    $searched = '';
                    $search_results = array();
                }
                ?>
                <p class="quick-search-wrap">
                    <input type="search" class="quick-search input-with-default-title" title="<?php esc_attr_e('Search'); ?>" value="<?php echo $searched; ?>" name="quick-search-posttype-<?php echo $post_type_name; ?>" />
                    <span class="spinner"></span>
                    <?php submit_button( __( 'Search' ), 'button-small quick-search-submit button-secondary hide-if-js', 'submit', false, array( 'id' => 'submit-quick-search-posttype-' . $post_type_name ) ); ?>
                </p>

                <ul id="<?php echo $post_type_name; ?>-search-checklist" data-wp-lists="list:<?php echo $post_type_name?>" class="categorychecklist form-no-clear">
                <?php if ( ! empty( $search_results ) && ! is_wp_error( $search_results ) ) : ?>
                    <?php
                    $args['walker'] = $walker;
                    echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $search_results), 0, (object) $args );
                    ?>
                <?php elseif ( is_wp_error( $search_results ) ) : ?>
                    <li><?php echo $search_results->get_error_message(); ?></li>
                <?php elseif ( ! empty( $searched ) ) : ?>
                    <li><?php _e('No results found.'); ?></li>
                <?php endif; ?>
                </ul>
            </div><!-- /.tabs-panel -->

            <div id="<?php echo $post_type_name; ?>-all" class="tabs-panel tabs-panel-view-all <?php
                echo ( 'all' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' );
            ?>">
                <?php if ( ! empty( $page_links ) ) : ?>
                    <div class="add-menu-item-pagelinks">
                        <?php echo $page_links; ?>
                    </div>
                <?php endif; ?>
                <ul id="<?php echo $post_type_name; ?>checklist" data-wp-lists="list:<?php echo $post_type_name?>" class="categorychecklist form-no-clear">
                    <?php
                    $args['walker'] = $walker;

                    // if we're dealing with pages, let's put a checkbox for the front page at the top of the list
                    if ( 'page' == $post_type_name ) {
                        $front_page = 'page' == get_option('show_on_front') ? (int) get_option( 'page_on_front' ) : 0;
                        if ( ! empty( $front_page ) ) {
                            $front_page_obj = get_post( $front_page );
                            $front_page_obj->front_or_home = true;
                            array_unshift( $posts, $front_page_obj );
                        } else {
                            $_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? intval($_nav_menu_placeholder) - 1 : -1;
                            array_unshift( $posts, (object) array(
                                'front_or_home' => true,
                                'ID' => 0,
                                'object_id' => $_nav_menu_placeholder,
                                'post_content' => '',
                                'post_excerpt' => '',
                                'post_parent' => '',
                                'post_title' => _x('Home', 'nav menu home label'),
                                'post_type' => 'nav_menu_item',
                                'type' => 'custom',
                                'url' => home_url('/'),
                            ) );
                        }
                    }

                    // THIS HAS TO BE FIXED <----------
                    $posts = apply_filters( 'nav_menu_items_'.$post_type_name, $posts, $args, $post_type );
                    $checkbox_items = walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $posts), 0, (object) $args );

                    if ( 'all' == $current_tab && ! empty( $_REQUEST['selectall'] ) ) {
                        $checkbox_items = preg_replace('/(type=(.)checkbox(\2))/', '$1 checked=$2checked$2', $checkbox_items);

                    }

                    echo $checkbox_items;
                    ?>
                </ul>
                <?php if ( ! empty( $page_links ) ) : ?>
                    <div class="add-menu-item-pagelinks">
                        <?php echo $page_links; ?>
                    </div>
                <?php endif; ?>
            </div><!-- /.tabs-panel -->

            <p class="button-controls">
                <span class="list-controls">
                    <a href="<?php
                        echo esc_url(add_query_arg(
                            array(
                                $post_type_name . '-tab' => 'all',
                                'selectall' => 1,
                            ),
                            remove_query_arg($removed_args)
                        ));
                    ?>#posttype-<?php echo $post_type_name; ?>" class="select-all"><?php _e('Select All'); ?></a>
                </span>

                <span class="add-to-menu">
                    <input type="submit"<?php disabled( $nav_menu_selected_id, 0 ); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e('Add to Menu'); ?>" name="add-post-type-menu-item" id="submit-posttype-<?php echo $post_type_name; ?>" />
                    <span class="spinner"></span>
                </span>
            </p>

        </div><!-- /.posttypediv -->
        <?php
    }
}
4
  • This definitely is a huge push in the right direction. I appreciate the help! On the surface, it appears to work great except for the extra checkboxes. I'll look through the code and see what I can come up with. Thanks again brasofilo
    – Tory
    Commented May 22, 2013 at 21:35
  • Actually, I figured out the extra checkbox thing, which was my own fault, so other than that it does the job perfectly, other than it could be cleaned up as you suggested.
    – Tory
    Commented May 24, 2013 at 14:13
  • how would I exclude a couple pages using their page id from appearing in the metabox using this script. I guess I don't even see where the query for pages is.
    – Tory
    Commented Jun 6, 2013 at 13:58
  • I suppose you can set this in the arguments for $get_posts->query( $args );, check the docs.
    – brasofilo
    Commented Jun 16, 2013 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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