In my quest to bring an object oriented separation of concerns to my WordPress plugins, I tend to separate the administration of each custom post type into its own class. I do this by looking at the global variable $typenow
after the admin_init action is fired. But $typenow
isn’t always set after admin_init, so I have to improvise a little.
$typenow
is supposed to hold the post type of the current post being actioned. When listing posts, creating a new post, or trashing / deleting a post, I can access $typenow
to find out whether to handle the action. Of course, it won’t have a value when the WordPress admin isn’t dealing with a post, but I’ve found two circumstances when it doesn’t have a value when I think it should:
- editing a post
- saving a quick edit to a post
In both those situations, admin_init is called without $typenow
being set. Luckily, the ID of the post being edited can be used to find out the post’s type. I have to give credit for this idea to WooCommerce, who showed me the way (reading other people’s source code can be very insightful!)
Here’s an excerpt for the class that manages the admin side of a winery data plugin I’ve co-written with Michael Major Media. The full class is about 720 lines long at present, so I’ve clipped it to just the bits about getting $typenow
in the admin_init hook.
class WpWinePagesAdmin { public function __construct() { // handle admin init action add_action('admin_init', array($this, 'actionAdminInit')); // and the rest... } /** * handle admin init action */ public function actionAdminInit() { global $typenow; // when editing pages, $typenow isn't set until later! if (empty($typenow)) { // try to pick it up from the query string if (!empty($_GET['post'])) { $post = get_post($_GET['post']); $typenow = $post->post_type; } // try to pick it up from the quick edit AJAX post elseif (!empty($_POST['post_ID'])) { $post = get_post($_POST['post_ID']); $typenow = $post->post_type; } } // check for one of our custom post types, // and start admin handling for that type switch ($typenow) { case WP_WINE_PAGES_TYPE_DIST: new WpWinePagesDistributorAdmin(); break; case WP_WINE_PAGES_TYPE_RANGE: new WpWinePagesProductRangeAdmin(); break; case WP_WINE_PAGES_TYPE_PRODUCT: new WpWinePagesProductAdmin(); break; case WP_WINE_PAGES_TYPE_AWARD: new WpWinePagesAwardAdmin(); break; case WP_WINE_PAGES_TYPE_REVIEW: new WpWinePagesReviewAdmin(); break; } } // and the rest ... }
And job is done, even when WordPress’ job isn’t quite done.