Как отключить плагины на фронт-энде?

Вопрос: Есть интересный плагин "Plugin Organizer", который позволяет выборочно отключать нужные плагины на сайте. т.е. плагин в админке будет продолжать выполнять свои функции (например, отображать поля или что-то еще, что нужно только в админке), во фронтенде он загружаться не будет.

Есть ли способ обойтись парой строк кода в файле functions.php для этого?

Я посмотрел некоторые плагины через плагин Query Monitor, он выдал, какие события срабатывают при генерации страницы, а затем отключил эти события с помощью remove_action().

Но есть плагины, которые не так просто отключить, и их слишком много. Вот я и интересуюсь, может есть готовый вариант кода.

Ответ (решение):

Это можно сделать прицепившись на хук: option_active_plugins. Вот готовый код для этого. Других хуков, чтобы это сделать я не нашел...

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;
	}

}

Теперь нам нужно использовать класс, в котором необходимо указать плагины, которые мы хотим отключить:

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

Важно: код нужно вставлять до того как плагины начнут подключаться! Это можно сделать только создав MU плагин, т.е. делаешь так:

  1. В папке wp-content, создаешь, если её там нет, папку mu-plugins.
  2. В созданной папке mu-plugins создаешь любой php файл, пусть будет disable-plugins-on-front.php и копируешь этот код в этот файл.
  3. Готово! указанные в коде плагины не будут загружаться во фронте...

П.С. Глянул в код Plugin Organizer - неплохой вроде плаг. Но там чет много настроек, таблицы в БД создает зачем-то, в общем, навороченный он какой-то...