WPTip.me

WordPress Development Tutorials & Tips

How to Modify Active Plugins

 

Active WordPress Plugins

Let’s say you have a site that depends on a single plugin functioning. Maybe you have a really nice core utilities plugin that needs to be on or your entire site will go down. That would be a good use case for modifying which plugins WordPress sees as active.

How Plugins Get Loaded

After WordPress loads it’s main environment, must use plugins, and — if you’re on multisite — network activated plugins, it registers a few initial post types, sets up the theme directory, and finally loads the currently active plugins. The relative lines of wp-settings.php:

<?php
// Load active plugins.
foreach ( wp_get_active_and_valid_plugins() as $plugin )
    include_once( $plugin );
unset( $plugin );

wp_get_active_and_valid_plugins is what really does the work. It fetchs all the currently active plugins. So let's take a look at that.

/**
 * Returns array of plugin files to be included in global scope.
 *
 * The default directory is wp-content/plugins. To change the default directory
 * manually, define <code>WP_PLUGIN_DIR</code> and <code>WP_PLUGIN_URL</code>
 * in wp-config.php.
 *
 * @access private
 * @since 3.0.0
 * @return array Files to include
 */
function wp_get_active_and_valid_plugins() {
	$plugins = array();
	$active_plugins = (array) get_option( 'active_plugins', array() );

	// Check for hacks file if the option is enabled
	if ( get_option( 'hack_file' ) && file_exists( ABSPATH . 'my-hacks.php' ) ) {
		_deprecated_file( 'my-hacks.php', '1.5' );
		array_unshift( $plugins, ABSPATH . 'my-hacks.php' );
	}

	if ( empty( $active_plugins ) || defined( 'WP_INSTALLING' ) )
		return $plugins;

	$network_plugins = is_multisite() ? wp_get_active_network_plugins() : false;

	foreach ( $active_plugins as $plugin ) {
		if ( ! validate_file( $plugin ) // $plugin must validate as file
			&& '.php' == substr( $plugin, -4 ) // $plugin must end with '.php'
			&& file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist
			// not already included as a network plugin
			&& ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins ) )
			)
		$plugins[] = WP_PLUGIN_DIR . '/' . $plugin;
	}
	return $plugins;
}

The line we're most interested in is get_option( 'active_plugins', array() );. Active plugins are stored in the database.

How Plugins are Stored

Plugins are stored in the {$wpdb->prefix}_options table as an array. Each item in the array is the plugin_basename of the plugin. If your main plugin file is called my-plugin.php and it's stored in the folder my-awesome-plugin, the plugin_basename version of that plugin would be my-awesome-plugin/my-plugin.php. basename(dirname(__FILE__)) . '/' . basename(__FILE__) to put it another way.

wp_get_active_and_valid_plugins takes each plugin basename, validates the file, and combines it with WP_PLUGIN_DIR then returns the array for the includes.

Programmatically Adding Plugins

Because plugins are stored in the database and fetched with get_option, we can use the option_{$option_name} hook to modify the results.

So if want my-plugin/my-plugin.php to always be active:

<?php
add_filter('option_active_plugins', 'wpt100_filter_plugins');
function wpt100_filter_plugins($p)
{
    // make sure it's not already there.
    if(array_search('my-plugin/my-plugin.php', (array)$p) === false) {
        $p[] = 'my-plugin/my-plugin.php';
    }

    return $p;
};

You can, of course, turn off plugins like this as well. Maybe you want to deactivate a plugin if WP_DEBUG is turned on.

<?php
add_filter('option_active_plugins', 'wpt100_filter_plugins');
function wpt100_filter_plugins($p)
{
    // snip snip

    // remove a plugin
    if(
        ($i = array_search('my-plugin/my-plugin.php', (array)$p)) !== false &&
        WP_DEBUG
    ) {
        unset($p[$i]);
    }

    return $p;
}

The above code would need to loaded sometime before WordPress loads plugins. Your only option, short of hacking into the core (don't do that, by the way, bad idea) is a must use plugin.