WordPress Version: 5.5
/**
* Attempts activation of plugin in a "sandbox" and redirects on success.
*
* A plugin that is already activated will not attempt to be activated again.
*
* The way it works is by setting the redirection to the error before trying to
* include the plugin file. If the plugin fails, then the redirection will not
* be overwritten with the success message. Also, the options will not be
* updated and the activation hook will not be called on plugin error.
*
* It should be noted that in no way the below code will actually prevent errors
* within the file. The code should not be used elsewhere to replicate the
* "sandbox", which uses redirection to work.
* {@source 13 1}
*
* If any errors are found or text is outputted, then it will be captured to
* ensure that the success redirection will update the error redirection.
*
* @since 2.5.0
* @since 5.2.0 Test for WordPress version and PHP version compatibility.
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
* @param string $redirect Optional. URL to redirect to.
* @param bool $network_wide Optional. Whether to enable the plugin for all sites in the network
* or just the current site. Multisite only. Default false.
* @param bool $silent Optional. Whether to prevent calling activation hooks. Default false.
* @return null|WP_Error Null on success, WP_Error on invalid file.
*/
function activate_plugin($plugin, $redirect = '', $network_wide = false, $silent = false)
{
$plugin = plugin_basename(trim($plugin));
if (is_multisite() && ($network_wide || is_network_only_plugin($plugin))) {
$network_wide = true;
$current = get_site_option('active_sitewide_plugins', array());
$_GET['networkwide'] = 1;
// Back compat for plugins looking for this value.
} else {
$current = get_option('active_plugins', array());
}
$valid = validate_plugin($plugin);
if (is_wp_error($valid)) {
return $valid;
}
$requirements = validate_plugin_requirements($plugin);
if (is_wp_error($requirements)) {
return $requirements;
}
if ($network_wide && !isset($current[$plugin]) || !$network_wide && !in_array($plugin, $current, true)) {
if (!empty($redirect)) {
// We'll override this later if the plugin can be included without fatal error.
wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect));
}
ob_start();
if (!defined('WP_SANDBOX_SCRAPING')) {
define('WP_SANDBOX_SCRAPING', true);
}
wp_register_plugin_realpath(WP_PLUGIN_DIR . '/' . $plugin);
$_wp_plugin_file = $plugin;
include_once WP_PLUGIN_DIR . '/' . $plugin;
$plugin = $_wp_plugin_file;
// Avoid stomping of the $plugin variable in a plugin.
if (!$silent) {
/**
* Fires before a plugin is activated.
*
* If a plugin is silently activated (such as during an update),
* this hook does not fire.
*
* @since 2.9.0
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
* @param bool $network_wide Whether to enable the plugin for all sites in the network
* or just the current site. Multisite only. Default false.
*/
do_action('activate_plugin', $plugin, $network_wide);
/**
* Fires as a specific plugin is being activated.
*
* This hook is the "activation" hook used internally by register_activation_hook().
* The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
*
* If a plugin is silently activated (such as during an update), this hook does not fire.
*
* @since 2.0.0
*
* @param bool $network_wide Whether to enable the plugin for all sites in the network
* or just the current site. Multisite only. Default false.
*/
do_action("activate_{$plugin}", $network_wide);
}
if ($network_wide) {
$current = get_site_option('active_sitewide_plugins', array());
$current[$plugin] = time();
update_site_option('active_sitewide_plugins', $current);
} else {
$current = get_option('active_plugins', array());
$current[] = $plugin;
sort($current);
update_option('active_plugins', $current);
}
if (!$silent) {
/**
* Fires after a plugin has been activated.
*
* If a plugin is silently activated (such as during an update),
* this hook does not fire.
*
* @since 2.9.0
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
* @param bool $network_wide Whether to enable the plugin for all sites in the network
* or just the current site. Multisite only. Default false.
*/
do_action('activated_plugin', $plugin, $network_wide);
}
if (ob_get_length() > 0) {
$output = ob_get_clean();
return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output);
}
ob_end_clean();
}
return null;
}