Codeable info

Making Plugins Compatible with WordPress Multisite

Posted on by in WordPress Tutorials

WordPress Multisite, introduced in version 3.0.0, gives site owners the ability to easily create and manage several WordPress blogs with a single installation of WordPress. The most famous use of WordPress Multisite is the popular blogging website WordPress.com. There are so many potential uses of such a setup, including departmental websites within a corporation, project management within a group, or a site owner that wants to host several blogs at once while keeping them easy to maintain and expand. However, unless your plugin was specifically built to work with the Multisite feature, your plugin is missing out on potential users. You never know, your plugin could be very helpful to site owners using WordPress Multisite.

What you will need to do is not incredibly simple, but not overly complicated. You will need basic PHP skills and an understanding of how to work with the core functions of WordPress. The most important changes to be made will be finding which functions and hooks will need to be changed, and modifying your plugin’s code to use the correct function or hook in case your plugin is being used in a Multisite environment. Two different types of network-wide functions and hooks include some that are specific to plugins, and others that can be used by all extensions in a similar, communal fashion. Both are likely to be used by plugins, so both will be covered.

Specific for Plugins

There are some functions and hooks that are used in a Multisite environment that are meant to replace the standard functions normally used by plugins. Just swapping the normal functions and hooks for the Multisite equivalents will not work, since your plugin would be useless for everyone not using WordPress Multisite. What needs to be done is your plugin should detect the environment, and apply the correct function or hook based on if Multisite is active or not. The main difference for plugin-specific functions are the functions that are used for activation, deactivation, and uninstallation.

Activation, Deactivation, and Uninstallation

You would normally use register_activation_hook(), register_deactivation_hook(), and register_uninstall_hook() for working with a change in a plugin’s state. These are the same functions that you would encounter within a Multisite environment, but what your functions should accomplish differs.

Normally, your activation function may just add options, register some options pages, and prepare itself to work with WordPress. However, due to the way that WordPress Multisite is set up, you will need your activation function to apply itself to every site operated within the Multisite environment if activate on the entire network. To accomplish this, your plugin will need two separate activation functions. One, which will be called by register_activation_hook(), will determine the environment and run the appropriate function. The other will be your old activation function, and will do what it did before. The first activation function will need to use an “if” clause with is_multisite() and $network_wide.

Your plugin’s activation routine should resemble something like the example below. For the sake of this tutorial, assume that this plugin’s namespace is “wphub.”

<?php
register_activation_hook( __FILE__, 'wphub_activation');
 
function  wphub_activation( $network_wide ) {
	if ( is_multisite() && $network_wide ) { // See if being activated on the entire network or one blog
		global $wpdb;
 
		// Get this so we can switch back to it later
		$current_blog = $wpdb->blogid;
		// For storing the list of activated blogs
		$activated = array();
 
		// Get all blogs in the network and activate plugin on each one
		$sql = “SELECT blog_id FROM $wpdb->blogs;
		$b1og_ids = $wpdb->get_co1($wpdb->prepare($sql));
		foreach ($blog_ids as $blog_id) {
			switch_to_blog($blog_id);
			wphub_activate(); // The normal activation function
			$activated[] = $blog_id;
		}
 
		// Switch back to the current blog
		switch_to_b1og($current_blog);
 
		// Store the array for a later function
		update_site_option('wphub_activated', $activated);
	} else { // Running on a single blog
		wphub_activate(); // The normal activation function
	}
}
?>

The code in the previous example determines if it is running inside a WordPress Multisite environment. If so, the code gets all of the current blogs and activates the plugin on each one before returning to the current blog for further processing. If not within a Multisite environment, the code assumes that this is a single installation, and activates the plugin normally. Similar code may be used upon deactivation and uninstallation.

Communal Functions

There are some functions and hooks that are specific to plugins in a Multisite environment, but there are plenty more to be used by all. They are not relevant to just plugins, meaning that they are considered communal to all software being run within a network.

Data Storage

For working with individual WordPress installations, your plugin would use functions similar to get_option() and get_transient() for retrieving stored information. Those functions would still work in a Multisite environment, but only for individual blogs. If you want to store and retrieve information on a global (network-wide) scale, then you need to use functions similar to get_site_option() and set_site_transient(). Their name may be slightly confusing, since one might assume that the word “site” means that they apply to individual sites, but WordPress has decided to call the entire network a “site” and individual members of the network “blogs.”

Site-wide options may be useful for storing information about the network at certain intervals, such as the blogs IDs that your plugin is currently installed on. With that information, you can check to see if any new blogs have been created, and install your plugin on them. The example below demonstrates how this can be accomplished.

<?php
 
if ( is_multisite()  ) { // Only run if in a Multisite environment
	add_action('admin_init','wphub_check_activated');
}
function wphub_check_activated() {
	// Get this so we can switch back to it later
	$current_blog = $wpdb->blogid;
 
	// If the option does not exist, plugin was not set to be network active
	if(get_site_option('wphub_activated') == 'false') {
		return false;
	}
 
	// Now compare the stored value to the current value
	$activated = get_site_option('wpload_activated'); // An array of blogs with the plugin activated
	$sql = “SELECT blog_id FROM $wpdb->blogs;
	$b1og_ids = $wpdb->get_co1($wpdb->prepare($sql));
	foreach ($blog_ids as $blog_id) {
		if ( !in_array($blog_id, $activated)  ){ // Plugin is not activated on that blog
			switch_to_blog($blog_id);
			wphub_activate();
			$activated[] = $blog_id;
		}
	}
 
	// Switch back to the current blog
	switch_to_b1og($current_blog);
 
	// Save the list for later runs
	update_site_option('wpload_activated', $activated);
}
?>

Site transients can be useful for information relevant to the network, but can be deleted after some time. Some examples of some useful site transients include the last time a Super Admin modified one of your plugin’s settings, when a blog was last added, and the last time a Super Admin logged in to any networked blog. These pieces of information could have an expiration date, so a transient can be used to detect if enough time has passed between user interaction. This enables your plugin to prompt Super Admins on regular intervals that their attention is needed.

Administration Menu Actions

Only one new hook relevant to the administration manu has been added in a Multisite environment, and it only applies to pages for viewing by Super Admins. When making an options page for only Super Admins, you can use the same functions as you would for any other site or blog. All you need to do is hook into the network_admin_menu action. For example, you may need to collect some information from a Super Admin about how your plugin should interact with the network. The following code demonstrates the beginning of how to create an options page for only Super Admins.

<?php
add_action('network_admin_menu', 'function_name');
function wphub_register_options_page() {
	add_options_page('Page title', 'Sidebar Text', 'manage_network', 'wphub-options', 'wphub_options_page');
}
?>

Folder Paths

Three new functions in a WordPress Multisite environment help you to determine the location of certain folders. They are closely related to their non-network counterparts, and work in a similar fashion. They are network_admin_url(), network_home_url(), and network_site_url(). These are needed because WordPress Multisite uses a single installation of WordPress to operate. All plugins reside in one location, and each must know to use the site’s address instead of an individual blog’s address when linking to certain content. The following example demonstrates how to use the new functions. While it is true that you could always use the network functions and let them fallback to their non-network counterparts in case of a single site, the example below guarantees that your code will work if that fallback is removed.

<?php
$home_url = ( is_multisite() ? network_home_url() : home_url() );
?>

Summary

When writing or modifying a plugin to be compatible with WordPress Multisite, there are several functions and hooks that differ from a single site being run by WordPress. There are a few differences for just plugins, but plenty of new common functions can be used by all software running within a Multisite environment. As a developer, you need your plugin to realize when it is confronted with multiple sites, adapt itself to use different methods for this, and still have all of the features it would normally posses. Now that your plugin is ready to work with WordPress Multisite, you can now place “Network: true” into your plugin’s metadata (where the name, description, and version number reside in the main plugin file).

Resources
– Link: Create a Network in the WordPress Codex

)
Codeable info

Comments (4)

Comment by Michael Davis says:

Same question as Sean… I have a utility plugin that I use that just calls up additional php, css and js files without ever writing to database tables and no hooks on activation.

Trying it out on an MU site for the first time and, even though it’s Network Activated, it doesn’t show up on network sites. Any tips?

Comment by Michael Scott says:

Corrected…thank you for pointing that out:)

Comment by Sakib says:

Thanks. Good tip.
There is a typo in your code in this line

$current_blog = Swpdb->blogid;

Change ‘S’ to ‘$’
Correct line should be
$current_blog = $wpdb->blogid;

Comment by Sean says:

Hi I am using a plugin on a wp multisite, I only want to display it in the network admin dashboard or main site dashboard. Is this possible?

Codeable info