Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions src/js/_enqueues/wp/updates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2715,7 +2715,13 @@
var $pluginRow = $( event.target ).parents( 'tr' ),
confirmMessage;

if ( $pluginRow.hasClass( 'is-uninstallable' ) ) {
if ( $pluginRow.hasClass( 'active' ) ) {
confirmMessage = sprintf(
/* translators: %s: Plugin name. */
__( 'You are about to delete %s.\n\nThis plugin is active and will be deactivated before deletion.\n\nAre you sure you want to proceed?' ),
$pluginRow.find( '.plugin-title strong' ).text()
);
} else if ( $pluginRow.hasClass( 'is-uninstallable' ) ) {
confirmMessage = sprintf(
/* translators: %s: Plugin name. */
__( 'Are you sure you want to delete %s and its data?' ),
Expand Down Expand Up @@ -2842,9 +2848,22 @@
break;

case 'delete-selected':
var confirmMessage = 'plugin' === type ?
__( 'Are you sure you want to delete the selected plugins and their data?' ) :
__( 'Caution: These themes may be active on other sites in the network. Are you sure you want to proceed?' );
var confirmMessage;
if ( 'plugin' === type ) {
var hasActivePlugins = false;
$bulkActionForm.find( 'input[name="checked[]"]:checked' ).each( function() {
if ( $( this ).parents( 'tr' ).hasClass( 'active' ) ) {
hasActivePlugins = true;
}
} );

confirmMessage = __( 'Are you sure you want to delete the selected plugins and their data?' );
if ( hasActivePlugins ) {
confirmMessage += '\n\n' + __( 'Note: Active plugins will be deactivated before deletion.' );
}
} else {
confirmMessage = __( 'Caution: These themes may be active on other sites in the network. Are you sure you want to proceed?' );
}

if ( ! window.confirm( confirmMessage ) ) {
event.preventDefault();
Expand Down
5 changes: 2 additions & 3 deletions src/wp-admin/includes/ajax-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4752,9 +4752,8 @@ function wp_ajax_delete_plugin() {
$status['plugin'] = $plugin;
$status['pluginName'] = $plugin_data['Name'];

if ( is_plugin_active( $plugin ) ) {
$status['errorMessage'] = __( 'You cannot delete a plugin while it is active on the main site.' );
wp_send_json_error( $status );
if ( is_network_admin() ? is_plugin_active_for_network( $plugin ) : is_plugin_active( $plugin ) ) {
deactivate_plugins( $plugin, false, is_network_admin() );
}

// Check filesystem credentials. `delete_plugins()` will bail otherwise.
Expand Down
88 changes: 44 additions & 44 deletions src/wp-admin/includes/class-wp-plugins-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ protected function get_bulk_actions() {
$actions['update-selected'] = __( 'Update' );
}

if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
if ( current_user_can( 'delete_plugins' ) ) {
$actions['delete-selected'] = __( 'Delete' );
}

Expand Down Expand Up @@ -942,29 +942,29 @@ public function single_row( $item ) {
);
}
}
}

if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) {
if ( $has_dependents && ! $has_circular_dependency ) {
$actions['delete'] = __( 'Delete' ) .
'<span class="screen-reader-text">' .
__( 'You cannot delete this plugin as other plugins require it.' ) .
'</span>';
} else {
$delete_url = 'plugins.php?action=delete-selected' .
'&amp;checked[]=' . urlencode( $plugin_file ) .
'&amp;plugin_status=' . $context .
'&amp;paged=' . $page .
'&amp;s=' . $s;
if ( current_user_can( 'delete_plugins' ) ) {
if ( $has_dependents && ! $has_circular_dependency ) {
$actions['delete'] = __( 'Delete' ) .
'<span class="screen-reader-text">' .
__( 'You cannot delete this plugin as other plugins require it.' ) .
'</span>';
} else {
$delete_url = 'plugins.php?action=delete-selected' .
'&amp;checked[]=' . urlencode( $plugin_file ) .
'&amp;plugin_status=' . $context .
'&amp;paged=' . $page .
'&amp;s=' . $s;

$actions['delete'] = sprintf(
'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
wp_nonce_url( $delete_url, 'bulk-plugins' ),
esc_attr( $plugin_id_attr ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
__( 'Delete' )
);
}
$actions['delete'] = sprintf(
'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
wp_nonce_url( $delete_url, 'bulk-plugins' ),
esc_attr( $plugin_id_attr ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
__( 'Delete' )
);
}
}
} else {
Expand Down Expand Up @@ -1048,31 +1048,31 @@ public function single_row( $item ) {
);
}
}
} // End if $is_active.

if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
if ( $has_dependents && ! $has_circular_dependency ) {
$actions['delete'] = __( 'Delete' ) .
'<span class="screen-reader-text">' .
__( 'You cannot delete this plugin as other plugins require it.' ) .
'</span>';
} else {
$delete_url = 'plugins.php?action=delete-selected' .
'&amp;checked[]=' . urlencode( $plugin_file ) .
'&amp;plugin_status=' . $context .
'&amp;paged=' . $page .
'&amp;s=' . $s;
if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
if ( $has_dependents && ! $has_circular_dependency ) {
$actions['delete'] = __( 'Delete' ) .
'<span class="screen-reader-text">' .
__( 'You cannot delete this plugin as other plugins require it.' ) .
'</span>';
} else {
$delete_url = 'plugins.php?action=delete-selected' .
'&amp;checked[]=' . urlencode( $plugin_file ) .
'&amp;plugin_status=' . $context .
'&amp;paged=' . $page .
'&amp;s=' . $s;

$actions['delete'] = sprintf(
'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
wp_nonce_url( $delete_url, 'bulk-plugins' ),
esc_attr( $plugin_id_attr ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
__( 'Delete' )
);
}
$actions['delete'] = sprintf(
'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
wp_nonce_url( $delete_url, 'bulk-plugins' ),
esc_attr( $plugin_id_attr ),
/* translators: %s: Plugin name. */
esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
__( 'Delete' )
);
}
} // End if $is_active.
}
} // End if $screen->in_admin( 'network' ).
} // End if $context.

Expand Down
31 changes: 22 additions & 9 deletions src/wp-admin/plugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,6 @@
exit;
}

$plugins = array_filter( $plugins, 'is_plugin_inactive' ); // Do not allow to delete activated plugins.
if ( empty( $plugins ) ) {
wp_redirect( self_admin_url( "plugins.php?error=true&main=true&plugin_status=$status&paged=$page&s=$s" ) );
exit;
}

// Bail on all if any paths are invalid.
// validate_file() returns truthy for invalid files.
$invalid_plugin_files = array_filter( $plugins, 'validate_file' );
Expand Down Expand Up @@ -373,14 +367,21 @@

$data_to_delete = false;

foreach ( $plugin_info as $plugin ) {
foreach ( $plugin_info as $plugin_file => $plugin ) {
$is_active = is_network_admin() ? is_plugin_active_for_network( $plugin_file ) : is_plugin_active( $plugin_file );

$active_notice = '';
if ( $is_active ) {
$active_notice = ' <strong>' . __( '(is active and will be deactivated)' ) . '</strong>';
}

if ( $plugin['is_uninstallable'] ) {
/* translators: 1: Plugin name, 2: Plugin author. */
echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), '</li>';
echo '<li>', sprintf( __( '%1$s by %2$s (will also <strong>delete its data</strong>)' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] . '</em>' ), $active_notice, '</li>';
$data_to_delete = true;
} else {
/* translators: 1: Plugin name, 2: Plugin author. */
echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', $active_notice, '</li>';
}
}

Expand Down Expand Up @@ -427,6 +428,18 @@
$plugins_to_delete = count( $plugins );
} // End if verify-delete.

// Deactivate active plugins before deleting them.
$active_plugins = array();
foreach ( $plugins as $plugin ) {
if ( is_network_admin() ? is_plugin_active_for_network( $plugin ) : is_plugin_active( $plugin ) ) {
$active_plugins[] = $plugin;
}
}

if ( ! empty( $active_plugins ) ) {
deactivate_plugins( $active_plugins, false, is_network_admin() );
}

$delete_result = delete_plugins( $plugins );

// Store the result in an option rather than a URL param due to object type & length.
Expand Down
Loading