Skip to content

Instantly share code, notes, and snippets.

@johnregan3
Last active December 3, 2022 07:32
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save johnregan3/6133389 to your computer and use it in GitHub Desktop.
Save johnregan3/6133389 to your computer and use it in GitHub Desktop.
Add Custom Post Type to WordPress Plugin Submenu (Hack)
<?php
/*
Plugin Name: Nerfherder Plugin
Plugin URI: https://gist.github.com/johnregan3/6133389
Description: Demonstration of how to add Custom Post Types to Submenu Items
Author: John Regan
Author URI: http://johnregan3.com
Version: 1.0
*/
/**
* Create a post type ("Nerfherders") and add it to the Submenu Page under a Plugin's top-level Menu Page on the WordPress Dashboard.
*
* The main part of this technique is using redirects to send users to the Custom Post Type screens, while hiding the CPT from the main menu.
*
* Save this as a PHP file, maybe named "nerferder-plugin.php" and put it in a folder with the same name.
* Upload it to your wp-content/plugins directory and ativate the Plugin to see it in action.
*/
/**
* Set up Custom Post Type "Nerfherders."
* Nothing significant here.
*/
add_action( 'init', 'create_post_type' );
function create_post_type() {
$labels = array(
'name' => _x( 'Nerfherders', 'Plural Name' ),
'singular_name' => _x( 'Nerfherder', 'Singular Name' ),
'add_new' => _x( 'Add New', 'nerfherder' ),
'add_new_item' => __( 'Add New Nerfherder' ),
'edit_item' => __( 'Edit Nerfherder' ),
'new_item' => __( 'New Nerfherder' ),
'all_items' => __( 'All Nerfherders' ),
'view_item' => __( 'View Nerfherder' ),
'search_items' => __( 'Search Nerfherders' ),
'not_found' => __( 'No Nerfherders found' ),
'not_found_in_trash' => __( 'No Nerfherders found in the Trash' ),
'parent_item_colon' => '',
'menu_name' => 'Nerfherders',
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
);
register_post_type( 'nerfherder_post_type', $args );
}
/**
* Normally, this would appear as a top-level "Menu Page" in the WordPress Admin
* We're going to reposition it underneath our in our Menu Page's ("Nerferder Plugin") Sub Menu Page
*/
/**
* Create the top-level Admin Menu Page "Nerfherder Plugin"
* Nothing significant here.
*/
add_action( 'admin_menu', 'register_nerfherder_menu_page' );
function register_nerfherder_menu_page(){
add_menu_page( __( 'Nerfherder Plugin', 'nerfherder' ), __( 'Nerfherder Plugin', 'nerfherder' ), 'manage_options', basename(__FILE__), 'nerfherder_render_menu_page' );
}
function nerfherder_render_menu_page(){
?>
<div class="wrap">
<div class="icon32" id="icon-options-general">
<br />
</div>
<?php _e( '<h2>Nerfherder Plugin Settings</h2>', 'gamwp'); ?>
<p>Click on one of the links in the "Nerfherder Plugin" Submenu to see the Custom Post Type Listing/Edit screens.</p>
</div>
<?php
}
/**
* Create the Submenu items containing redirects to the Custom Post Type Pages
* This is where the magic happens.
*/
//Add To Menu
add_action( 'admin_menu', 'nerfherder_add_submenu_pages' );
function nerfherder_add_submenu_pages() {
add_submenu_page( 'nerfherder-plugin.php', __( 'All Nerfherders', 'nerfherders' ), __( 'All Nerfherders', 'nerfherders' ), 'manage_options', 'nerfherder_plugin_show_posts', 'nerfherder_render_nerferhders' );
add_submenu_page( 'nerfherder-plugin.php', __( 'Add New Nerfherder', 'nerfherders' ), __( 'Add New Nerfherder', 'nerfherders' ), 'manage_options', 'nerfherder_plugin_add_post', 'nerfherder_render_new_nerferhders' );
}
function nerfherder_render_nerferhders(){
$url = admin_url().'edit.php?post_type=nerfherder_post_type';
?>
<script>location.href='<?php echo $url;?>';</script>
<?php
}
function nerfherder_render_new_nerferhders(){
$url = admin_url().'post-new.php?post_type=nerfherder_post_type';
?>
<script>location.href='<?php echo $url;?>';</script>
<?php
}
/**
* Hide default Custom Post Type Menu Item from Admin Menu
*/
add_action( 'admin_menu', 'nerfherder_remove_cpt_menu_items' );
function nerfherder_remove_cpt_menu_items() {
remove_menu_page( 'edit.php?post_type=nerfherder_post_type' );
}
/**
* Add/Remove appropriate CSS classes to Menu so Submenu displays open and the Menu link is styled appropriately.
*/
function nerfherder_correct_current_menu(){
$screen = get_current_screen();
if ( $screen->id == 'nerfherder_post_type' || $screen->id == 'edit-nerfherder_post_type' ) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#toplevel_page_nerfherder-plugin').addClass('wp-has-current-submenu wp-menu-open menu-top menu-top-first').removeClass('wp-not-current-submenu');
$('#toplevel_page_nerfherder-plugin > a').addClass('wp-has-current-submenu').removeClass('wp-not-current-submenu');
});
</script>
<?php
}
if ( $screen->id == 'nerfherder_post_type' ) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('a[href$="nerfherder_plugin_add_post"]').parent().addClass('current');
$('a[href$="nerfherder_plugin_add_post"]').addClass('current');
});
</script>
<?php
}
if ( $screen->id == 'edit-nerfherder_post_type' ) {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('a[href$="nerfherder_plugin_show_posts"]').parent().addClass('current');
$('a[href$="nerfherder_plugin_show_posts"]').addClass('current');
});
</script>
<?php
}
}
add_action('admin_head', 'nerfherder_correct_current_menu', 50);
@maurisrx
Copy link

Thank you for the hack. In WP 4.0 which I'm using, I can simply set 'show_in_menu' in custom post type args to $menu_slug that I set in add_menu_page() that I want to set the CPT as sub menu of and set the priority of a top-level menu function to 9 or lower.

@studio404pl
Copy link

studio404pl commented Jan 11, 2017

Thanks for that snippet but to handle custom urls you don't have to use javascript redirection. You can go with something like that:

add_menu_page( __( 'Cposts', $this->plugin_name ), __( 'Cposts', $this->plugin_name ), 'manage_options', '/edit.php?post_type=cpost_post_type', '', 'dashicons-format-gallery', 6 );
add_submenu_page( '/edit.php?post_type=cpost_post_type', __( 'All Cposts', $this->plugin_name ), __( 'All Cposts', $this->plugin_name ), 'manage_options', '/edit.php?post_type=cpost_post_type', '');
add_submenu_page( '/edit.php?post_type=cpost_post_type', __( 'Add New Cpost', $this->plugin_name ), __( 'Add New Cpost', $this->plugin_name ), 'manage_options', '/post-new.php?post_type=cpost_post_type', '');

so you can declare fixed url as menu slug and pass null for function param. Current menu is handled natively in that case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment