Remove a WordPress menu page added through a static method (inside a class)

Removing annoying and unnecessary WordPress menu pages added by 3rd party plugins that clutter your dashboard is one of those things that seem like they’re not worth the trouble, but when you do them, you realize just how nice it is to have a clutter-free work environment. It’s kind of like rearranging and cleaning up your work desk once in a while.

And, while removing some WordPress menu pages is easy as pie, there are those that are incredibly stubborn and won’t go away no matter which filter or action hook you use. I’m sure you’ve been there. Normally, removing a menu page involves tracking down the name of the action hook a plugin or theme author used when hooking into the standard WordPress function ‘add_menu_page‘ which is usually initialized through ‘admin_init‘ action hook. Here’s an example from WordPress Codex so it’s easier to follow along:


    add_action( 'admin_menu', 'register_my_custom_menu_page' );
function register_my_custom_menu_page() {
  // add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position );
  add_menu_page( 'Custom Menu Page Title', 'Custom Menu Page', 'manage_options', 'custom.php', '', 'dashicons-welcome-widgets-menus', 90 );
}

Seems simple enough, right? Removing this page would be as simple as tracking down slug of the page and using the function ‘remove_menu_page‘ initialized through ‘admin_init‘ hook. So, a little bit like this:


    add_action( 'admin_init', 'remove_my_custom_menu_page' );
function remove_my_custom_menu_page(){
  remove_menu_page( 'custom.php' );
}

This would be an ideal scenario. But, things can get much more complicated than this. There are a lot of plugins out there that add menu pages through static PHP methods inside classes. It makes sense to use the object oriented approach to build your plugins, but it makes it that much more difficult to track down and remove a page initialized through a static method. So, I’ll show you a real world example of a popular plugin that does this, and then I’ll show you how to remove a page added this way to the WordPress dashboard.

The plugin I’ll use in this example is YITH WooCommerce Wishlist, a very popular WooCommerce wishlist plugin. Let’s dive right in, here’s how this plugin adds its dashboard items. I’ll copy a block of code and explain things below the block.


    class YITH_WCWL_Admin {

		/**
		 * Single instance of the class
		 *
		 * @var \YITH_WCWL_Admin
		 * @since 2.0.0
		 */
		protected static $instance;
		
		public static function get_instance() {
			if ( is_null( self::$instance ) ) {
				self::$instance = new self();
			}

			return self::$instance;
		}
		
		/**
		 * Constructor of the class
		 *
		 * @return \YITH_WCWL_Admin
		 * @since 2.0.0
		 */
		public function __construct() {
			// install plugin, or update from older versions.
			add_action( 'init', array( $this, 'install' ) );

			// init admin processing.
			add_action( 'init', array( $this, 'init' ) );

			// enqueue scripts.
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 20 );

			// plugin panel options.
			add_filter( 'yith_plugin_fw_panel_wc_extra_row_classes', array( $this, 'mark_options_disabled' ), 10, 23 );

			// add plugin links.
			add_filter( 'plugin_action_links_' . plugin_basename( YITH_WCWL_DIR . 'init.php' ), array( $this, 'action_links' ) );
			add_filter( 'yith_show_plugin_row_meta', array( $this, 'add_plugin_meta' ), 10, 5 );

			// register wishlist panel.
			add_action( 'admin_menu', array( $this, 'register_panel' ), 5 );
			add_action( 'yith_wcwl_premium_tab', array( $this, 'print_premium_tab' ) );

			// add a post display state for special WC pages.
			add_filter( 'display_post_states', array( $this, 'add_display_post_states' ), 10, 2 );
		}
		
		/**
 * Unique access to instance of YITH_WCWL_Admin class
 *
 * @return \YITH_WCWL_Admin
 * @since 2.0.0
 */
function YITH_WCWL_Admin() {
	return defined( 'YITH_WCWL_PREMIUM' ) ? YITH_WCWL_Admin_Premium::get_instance() : YITH_WCWL_Admin::get_instance();
}

I removed a few lines from the file, because we don’t need to see all the code. Anyway, as you’ll see, the plugin author is using YITH_WCWL_ADMIN class to add menu pages (and a lot of other things the plugin needs). What we’re most interested here in, are the lines 43 and 44, because these are the pages we want to remove. The page ‘register_panel‘ is added via ‘admin_menu‘ action hook, and the ‘print_premium_tab‘ page is added via ‘yith_wcwl_premium_tab‘ action hook. We need this information to be able to remove these pages. Also, as you can see, we have an additional parameter in the action hook, the $this object, which is a reference to the class in which the hook is defined in. This information is also of vital importance if we wish to remove these pages.

Also, it’s important to notice that the class is instantiated through a static get_instance() function.

Knowing all this, we can now write our removal code. I’ll just paste the code block and explain things below:


    add_action('init', __NAMESPACE__ . '\\codeart_remove_yith_pages', 999);
  function codeart_remove_yith_pages() {
  if( class_exists( 'YWRR_Review_Reminder' ) ){
  //review reminder
  $class = \YWRR_Review_Reminder::get_instance();
  remove_action( 'admin_menu', array( $class, 'add_menu_page' ), 5 );
  remove_action( 'yith_review_reminder_premium', array( $class, 'premium_tab' ) );
}

So, a couple of things are going on here:

  1. on line 1, we’re initializing our code with the action hook ‘init‘ with the priority of 999. We want to use a large number here, just to be able to execute our hook as late as possible, to make sure we’re not removing something that’s not yet added.
  2. on line 3 we’re checking whether the class we’re about the instantiate actually exists. We absolutely must do this, not just because it’s common sense when instantiating a class, but also if you ever deactivate a plugin whose class you’re instantiating, and don’t remove this code, your site is going to crash and burn.
  3. on line 5 we’re instantiating our class with the static get_instance() function
  4. on lines 6 & 7 we’re removing the pages with our instantiated class in the form of the $class parameter

And that’s it. Now you have a real world example of how to remove a WordPress menu page added through a class instantiated through a static method.

Hire your codeartist

looking for a development of your own project?

is your agency looking for a partner?