Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tutorial: How to combine CPTs/Panels into one Top Admin menu #175

Open
webstractions opened this issue Feb 16, 2017 · 1 comment
Open

Tutorial: How to combine CPTs/Panels into one Top Admin menu #175

webstractions opened this issue Feb 16, 2017 · 1 comment

Comments

@webstractions
Copy link

webstractions commented Feb 16, 2017

Overview

This is a real-life sample of a plugin I am working on. It is called TVTrax, the inner workings is unimportant, this is just a clip of how to handle multiple custom post types and Herbert panels, all within one top-level Admin Menu.

What I am using for Custom Post Types

I am using an alternative custom post type library, other than the one in the Herbert docs. As of 0.9 the docs listed JJGraingers custom post class requirement as "jjgrainger/wp-custom-post-type-class": "dev-master" for a composer install.

There is a newer version from jjgrainger called PostTypes. You can include this in your plugin composer.json with $ composer require jjgrainger/posttypes.

Whether you use this package or not, there are only two CPT settings that you need concern yourself with ... they are the show_ui and show_in_menu arguments for registering your custom post type. More on this later.

First, Create Your Plugin Panel and subPanels

In this case, I have one main panel and a subpanel for settings. Eventually, I want the main panel on the top, and settings on the bottom of the top-level menu. Additionally, I want the main panel renamed to 'Dashboard'.

Add the following code to your `app/panels.php' file:

<?php namespace TVTrax;

/** @var \Herbert\Framework\Panel $panel */

$panel->add([
	'type'   => 'panel',
	'as'     => 'mainPanel',
	'title'  => 'TV Trax',
	'rename' => 'Dashboard',
	'slug'   => 'tvtrax-index',
	'icon'   => 'dashicons-desktop',
	'order'  => '35.555',
	'uses'   => __NAMESPACE__ . '\Controllers\AdminController@index'
]);

$panel->add([
	'type'   => 'sub-panel',
	'parent' => 'mainPanel',
	'as'     => 'settingsPanel',
	'title'  => 'Settings',
	'slug'   => 'tvtrax-settings',
	'order'  => '0',
	'uses'   => __NAMESPACE__ . '\Controllers\AdminController@settings'
]);

This code assumes that you have an AdminController with index and settings methods. Also, the two methods are to be seperated on the main plugin menu.

You will get an Admin Menu with TV Trax on the top and two submenu items labled 'Dashboard' and 'Settings'.

Register Your Custom Post Types

No matter how you register your custom post types, there are only two arguments that you need to worry about.

In your options, set the following:

$options = [
	'show_ui'      => true,
	'show_in_menu' => 'tvtrax-index'
];

You will notice that the show_in_menu label refers to the tvtrax-index in the previous main panel addition. This is !important.

At this point, you will get a top-level menu for your plugin and an unordered list of submenus in the order of panels then CPTs (or vice-versa). Now we need to list them in the correct order.

Get your hooks in order

I like to have all of my actions and filters in one file. I call it hooks.php and it sits in my \app folder.

Create an apps\hooks.php file. Include it in your herbert.congig.php file with:

/**
 * Auto-load all required files.
 */
'requires' => [
    __DIR__ . '/app/hooks.php'
]

Before we can hook something, we need something to hook it to. In this case, we need an AdminController.

Create a controller in /controllers called AdminController.php. Add the following:

<?php
namespace TVTrax\Controllers;

class AdminController {
	
	public function index() {
		
		echo '<h1>TV Trax Dashboard</h1>';

	}
	
	public function settings() {
	
		echo '<h1>TV Trax Settings</h1>';
	}
	
	/**
	 * Reorders submenu items for TVTrax Admin Toplevel menu
	 * 
	 * While the filter passes a menu order array, we don't use it.
	 * Instead, we alter the global variable $submenu to accomplish
	 * our reording.
	 * 
	 * @uses filter 'custom_menu_order'
	 * 
	 * @param array $menu_order
	 * @return array
	 */
	public static function custom_menu_order( $menu_order ) {
		
		global $submenu;

		$tv_menu = 'tvtrax-index';
		
		// Reorder the submenu array
		$arr = array();
		$arr[] = $submenu[$tv_menu][3];
		$arr[] = $submenu[$tv_menu][0];
		$arr[] = $submenu[$tv_menu][1];
		$arr[] = $submenu[$tv_menu][2];
		$arr[] = $submenu[$tv_menu][4];
		
		// Assign re-ordered array to our top level menu
		$submenu[$tv_menu] = $arr;
		
		return $menu_order;
	}
	
}

Inside the hooks.php file, add the following:

// Adjust the order of TVTrax submenu items
add_filter( 'custom_menu_order', [ '\TVTrax\Controllers\AdminController', 'custom_menu_order' ] );

Remember to change your namespaces and mind your R's. Help me improve on this too!

@webstractions
Copy link
Author

Perhaps this can be added to the Wiki?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant