How Disable Plugins on Front-end?

Question: There is an interesting plugin "Plugin Organizer", which allows you to selectively disable the necessary plugins on the site. ie plugin in the admin will continue to perform its functions (eg, display fields or anything else that is needed only in the admin), in front-end it will not be loaded.

Is there any way to get by with a couple lines of code in the functions.php file for this?

I monitored some plugins through the Query Monitor plugin, it gave out what events are triggered during page generation, and then disabled these events using remove_action().

But there are plugins that are not so easy to disable events and there are too many of them. So I am interested, maybe there is a ready-made code version.

Answer (solution):

This can be done by hooking on option_active_plugins. Here's the ready-made code to do it. I couldn't find any other hooks to do it...

GitHub
<?php

/**
 * Disables the connection of the specified plugins at the front and ajax requests.
 *
 * @version 2.0
 * @author  Kama (wp-kama.ru)
 */
class Kama_Hard_Disable_Plugins_On_Front {

	/**
	 * To be deactivated plugins folder names.
	 * The names placed in array index. The array value means nothing.
	 */
	protected array $disable_foldernames = [];

	public static function instance(): self {
		static $instance;

		$instance || $instance = new self();

		return $instance;
	}

	/**
	 * @param array $plugins_names List of plugins you want to deactivate on front.
	 *                             Specify plugin`s folder name.
	 */
	public function set_disabled( array $plugins_names = [] ): self {
		/**
		 * Allows you to filter plugins slugs (folder names) that will be disabled.
		 *
		 * @param string[] $plugins_names Array of folder names.
		 */
		$plugins_names = apply_filters( 'hard_disable_plugins__filter_names', $plugins_names );

		$this->disable_foldernames = array_flip( $plugins_names );

		return $this;
	}

	/**
	 * Gets currently disabled plugins slugs (folder names) list.
	 */
	public function get_disabled(): array {
		return $this->disable_foldernames;
	}

	public function init(): void {

		if( ! $this->get_disabled() ){
			return;
		}

		// for multisite
		add_filter( 'site_option_active_sitewide_plugins', [ $this, 'disable' ] );

		// for regular activated
		add_filter( 'option_active_plugins', [ $this, 'disable' ] );
	}

	protected function skip_deactivation(): bool {
		return (
			defined( 'WP_CLI' )
			// admin (but not ajax)
			|| ( ! defined( 'DOING_AJAX' ) && is_admin()  )
			// ajax request from admin-panel
			|| ( defined( 'DOING_AJAX' ) && str_contains( $_SERVER['HTTP_REFERER'], '/wp-admin/' ) )
		);
	}

	/**
	 * The function is used on the hook `option_active_plugins` or `site_option_active_sitewide_plugins`.
	 */
	public function disable( array $active_plugins ): array {

		if( $this->skip_deactivation() ){
			return $active_plugins;
		}

		$is_sitewide_option = ( current_filter() === 'site_option_active_sitewide_plugins' );

		/**
		 * Sitewide plugins stored as flipped array compared with regular plugins.
		 */
		if( $is_sitewide_option ){
			$active = $this->remove_deactivated( array_keys( $active_plugins ) );
			$active = array_flip( $active );
			$active_plugins = array_intersect_key( $active_plugins, $active );
		}
		else {
			$active = $this->remove_deactivated( $active_plugins );
			$active_plugins = array_intersect( $active_plugins, $active );
		}

		return $active_plugins;
	}

	/**
	 * Deletes the disabled plug-ins from the array.
	 *
	 * You must specify an array with the names of the folders of the plugins,
	 * which you want to remove from the array of active plugins.
	 *
	 * @param array $plugins  Array of active plugins basenames.
	 *                        Example: [ 0 => redis-cache/redis-cache.php, 1 => wp-crontrol/wp-crontrol.php ]
	 *
	 * @return array array of active plugins without deactivated.
	 */
	protected function remove_deactivated( array $plugins ): array {

		foreach( $plugins as $index => $basename ){
			$folder_name = dirname( $basename );

			if( isset( $this->disable_foldernames[ $folder_name ] ) ){
				unset( $plugins[ $index ] );
			}
		}

		return $plugins;
	}

}

Usage

Now we need use the class, where we need to specify the plugins we want to disable:

Kama_Hard_Disable_Plugins_On_Front::instance()->set_disabled( [
	'advanced-custom-fields-pro',
	'wp-crontrol',
	'tiny-compress-images',
] )->init();

Important: The code must be inserted before the plugins start plugging! This can only be done by creating an MU plugin, i.e. you do the following:

  1. In the wp-content folder, create, if it is not there, the folder mu-plugins.

  2. In the created mu-plugins folder create any php file, let it be disable-plugins-on-front.php and copy this code to that file.

  3. Done! The plugins specified in the code will not load on the front area.

--

P.S. I Looked inside the Plugin Organizer - not a bad plugin. But it has a lot of settings, creates tables in the database for some reason, and in general, it is tricky somehow...