: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
__( 'The PHP version on your server is %1$s, however the uploaded plugin requires %2$s.' ),
return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error );
if ( ! is_wp_version_compatible( $requires_wp ) ) {
/* translators: 1: Current WordPress version, 2: Version required by the uploaded plugin. */
__( 'Your WordPress version is %1$s, however the uploaded plugin requires %2$s.' ),
return new WP_Error( 'incompatible_wp_required_version', $this->strings['incompatible_archive'], $error );
* Retrieves the path to the file that contains the plugin info.
* This isn't used internally in the class, but is called by the skins.
* @return string|false The full path to the main plugin file, or false.
public function plugin_info() {
if ( ! is_array( $this->result ) ) {
if ( empty( $this->result['destination_name'] ) ) {
// Ensure to pass with leading slash.
$plugin = get_plugins( '/' . $this->result['destination_name'] );
if ( empty( $plugin ) ) {
// Assume the requested plugin is the first in the list.
$pluginfiles = array_keys( $plugin );
return $this->result['destination_name'] . '/' . $pluginfiles[0];
* Deactivates a plugin before it is upgraded.
* Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade().
* @since 4.1.0 Added a return value.
* @param bool|WP_Error $response The installation response before the installation has started.
* @param array $plugin Plugin package arguments.
* @return bool|WP_Error The original `$response` parameter or WP_Error.
public function deactivate_plugin_before_upgrade( $response, $plugin ) {
if ( is_wp_error( $response ) ) { // Bypass.
// When in cron (background updates) don't deactivate the plugin, as we require a browser to reactivate it.
$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
if ( empty( $plugin ) ) {
return new WP_Error( 'bad_request', $this->strings['bad_request'] );
if ( is_plugin_active( $plugin ) ) {
// Deactivate the plugin silently, Prevent deactivation hooks from running.
deactivate_plugins( $plugin, true );
* Turns on maintenance mode before attempting to background update an active plugin.
* Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade().
* @param bool|WP_Error $response The installation response before the installation has started.
* @param array $plugin Plugin package arguments.
* @return bool|WP_Error The original `$response` parameter or WP_Error.
public function active_before( $response, $plugin ) {
if ( is_wp_error( $response ) ) {
// Only enable maintenance mode when in cron (background update).
if ( ! wp_doing_cron() ) {
$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
// Only run if plugin is active.
if ( ! is_plugin_active( $plugin ) ) {
// Change to maintenance mode. Bulk edit handles this separately.
$this->maintenance_mode( true );
* Turns off maintenance mode after upgrading an active plugin.
* Hooked to the {@see 'upgrader_post_install'} filter by Plugin_Upgrader::upgrade().
* @param bool|WP_Error $response The installation response after the installation has finished.
* @param array $plugin Plugin package arguments.
* @return bool|WP_Error The original `$response` parameter or WP_Error.
public function active_after( $response, $plugin ) {
if ( is_wp_error( $response ) ) {
// Only disable maintenance mode when in cron (background update).
if ( ! wp_doing_cron() ) {
$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
// Only run if plugin is active.
if ( ! is_plugin_active( $plugin ) ) {
// Time to remove maintenance mode. Bulk edit handles this separately.
$this->maintenance_mode( false );
* Deletes the old plugin during an upgrade.
* Hooked to the {@see 'upgrader_clear_destination'} filter by
* Plugin_Upgrader::upgrade() and Plugin_Upgrader::bulk_upgrade().
* @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
* @param bool|WP_Error $removed Whether the destination was cleared.
* True on success, WP_Error on failure.
* @param string $local_destination The local package destination.
* @param string $remote_destination The remote package destination.
* @param array $plugin Extra arguments passed to hooked filters.
public function delete_old_plugin( $removed, $local_destination, $remote_destination, $plugin ) {
if ( is_wp_error( $removed ) ) {
return $removed; // Pass errors through.
$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
if ( empty( $plugin ) ) {
return new WP_Error( 'bad_request', $this->strings['bad_request'] );
$plugins_dir = $wp_filesystem->wp_plugins_dir();
$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin ) );
if ( ! $wp_filesystem->exists( $this_plugin_dir ) ) { // If it's already vanished.
* If plugin is in its own directory, recursively delete the directory.
* Base check on if plugin includes directory separator AND that it's not the root plugin folder.
if ( strpos( $plugin, '/' ) && $this_plugin_dir !== $plugins_dir ) {
$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
$deleted = $wp_filesystem->delete( $plugins_dir . $plugin );
return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );