[wp-trac] [WordPress Trac] #50850: When the deactivate_plugins() function is called in the ABSPATH/wp-admin/includes/plugin.php file, the is_plugin_active_for_network() conditional tag always returns true when the active_sitewide_plugins sitemeta option is set to 1
WordPress Trac
noreply at wordpress.org
Wed Aug 5 01:28:10 UTC 2020
#50850: When the deactivate_plugins() function is called in the ABSPATH/wp-
admin/includes/plugin.php file, the is_plugin_active_for_network()
conditional tag always returns true when the active_sitewide_plugins
sitemeta option is set to 1
--------------------------------+-----------------------------
Reporter: zenithcity | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Options, Meta APIs | Version: 5.4.2
Severity: critical | Keywords: needs-patch
Focuses: |
--------------------------------+-----------------------------
On multisite during the process of activating a plugin across the network
(sitewide plugin activation), I noticed that if the activation process is
not successful or if errors are triggered, the `active_sitewide_plugins'
sitemeta option will be set to 1 and this causes the
**is_plugin_active_for_network()** conditional tag to return true when
called within the **deactivate_plugins** function, which is so untrue.
Also, when on the admin or network `plugins.php` screen, the
**deactivate_plugins()** function triggers the following error becuase the
**$plugins = get_site_option( 'active_sitewide_plugins' )** code doesn't
return the correct type (array):
{{{
Fatal error: Uncaught Error: Cannot unset string offsets in ABSPATH\wp-
admin\includes\plugin.php on line 779
}}}
Futhermore, after exploring the error, I found that since the
**active_sitewide_plugins** sitemeta option is set to 1 and the
**array_keys()** function is used to extract the plugin basenames into a
new array and merged with non-sitewide activated plugins, then when used
in the **foreach()** loop, this will always return true.
{{{#!php
<?php
/**
* @see ABSPATH/wp-admin/includes/plugin.php#L1047
*/
function validate_active_plugins() {
$plugins = get_option( 'active_plugins', array() );
// Validate vartype: array.
if ( ! is_array( $plugins ) ) {
update_option( 'active_plugins', array() );
$plugins = array();
}
if ( is_multisite() && current_user_can( 'manage_network_plugins' ) )
{
$network_plugins = (array) get_site_option(
'active_sitewide_plugins', array() );
// If the 'active_sitewide_plugins' option is set to 1,
// then the $network_plugins var will contain 0 as the only
elements
$plugins = array_merge( $plugins, array_keys(
$network_plugins ) );
}
if ( empty( $plugins ) ) {
return array();
}
$invalid = array();
// Invalid plugins get deactivated.
foreach ( $plugins as $plugin ) {
$result = validate_plugin( $plugin );
if ( is_wp_error( $result ) ) {
$invalid[ $plugin ] = $result;
deactivate_plugins( $plugin, true );
}
}
return $invalid;
}
}}}
I also ran a test with the **is_plugin_active_for_network()** conditional
tag using the **in_array()** function to replace the **isset()** function
in other to see if things would work as normal, and the test was passed:
{{{#!php
<?php
function is_plugin_active_for_network( $plugin ) {
if ( ! is_multisite() ) {
return false;
}
// Need fix: the $plugins var need to be type-cast into an array
$plugins = get_site_option( 'active_sitewide_plugins' );
//if ( isset( $plugins[ $plugin ] ) ) {
// Note: If the $plugins var is not an array then we have to
// type-cast it into an array
if ( in_array( $plugin, (array) $plugins, true ) ) {
return true;
}
return false;
}
}}}
**File:**
{{{
ABSPATH/wp-admin/includes/plugin.php
}}}
--
Ticket URL: <https://core.trac.wordpress.org/ticket/50850>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list