mirror of
https://github.com/WordPress/WordPress.git
synced 2024-12-22 09:07:59 +01:00
Security: Add user interface to auto-update themes and plugins.
Building on core update mechanisms, this adds the ability to enable automatic updates for themes and plugins to the WordPress admin. Fixes: #50052. Props: afercia, afragen, audrasjb, azaozz, bookdude13, davidperonne, desrosj, gmays, gmays, javiercasares, karmatosed, knutsp, mapk, mukesh27, netweb, nicolaskulka, nielsdeblaauw, paaljoachim, passoniate, pbiron, pedromendonca, whodunitagency, whyisjake, wpamitkumar, and xkon. Built from https://develop.svn.wordpress.org/trunk@47835 git-svn-id: http://core.svn.wordpress.org/trunk@47611 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
2a86d8d534
commit
661b929e1e
@ -139,6 +139,7 @@ $core_actions_post = array(
|
||||
'health-check-background-updates',
|
||||
'health-check-loopback-requests',
|
||||
'health-check-get-sizes',
|
||||
'toggle-auto-updates',
|
||||
);
|
||||
|
||||
// Deprecated.
|
||||
|
@ -1525,7 +1525,9 @@ div.error {
|
||||
.updating-message p:before,
|
||||
.import-php .updating-message:before,
|
||||
.button.updating-message:before,
|
||||
.button.installing:before {
|
||||
.button.installing:before,
|
||||
.plugins .column-auto-updates .dashicons-update.spin,
|
||||
.theme-overlay .theme-autoupdate .dashicons-update.spin {
|
||||
animation: rotation 2s infinite linear;
|
||||
}
|
||||
|
||||
|
2
wp-admin/css/common-rtl.min.css
vendored
2
wp-admin/css/common-rtl.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1524,7 +1524,9 @@ div.error {
|
||||
.updating-message p:before,
|
||||
.import-php .updating-message:before,
|
||||
.button.updating-message:before,
|
||||
.button.installing:before {
|
||||
.button.installing:before,
|
||||
.plugins .column-auto-updates .dashicons-update.spin,
|
||||
.theme-overlay .theme-autoupdate .dashicons-update.spin {
|
||||
animation: rotation 2s infinite linear;
|
||||
}
|
||||
|
||||
|
2
wp-admin/css/common.min.css
vendored
2
wp-admin/css/common.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1237,6 +1237,10 @@ ul.cat-checklist {
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.plugins .column-auto-updates {
|
||||
width: 14.2em;
|
||||
}
|
||||
|
||||
.plugins .inactive .plugin-title strong {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
2
wp-admin/css/list-tables-rtl.min.css
vendored
2
wp-admin/css/list-tables-rtl.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1236,6 +1236,10 @@ ul.cat-checklist {
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.plugins .column-auto-updates {
|
||||
width: 14.2em;
|
||||
}
|
||||
|
||||
.plugins .inactive .plugin-title strong {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
2
wp-admin/css/list-tables.min.css
vendored
2
wp-admin/css/list-tables.min.css
vendored
File diff suppressed because one or more lines are too long
@ -680,7 +680,8 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.theme-overlay .theme-author a {
|
||||
.theme-overlay .theme-author a,
|
||||
.theme-overlay .theme-autoupdate a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
2
wp-admin/css/themes-rtl.min.css
vendored
2
wp-admin/css/themes-rtl.min.css
vendored
File diff suppressed because one or more lines are too long
@ -679,7 +679,8 @@ body.folded .theme-browser ~ .theme-overlay .theme-wrap {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.theme-overlay .theme-author a {
|
||||
.theme-overlay .theme-author a,
|
||||
.theme-overlay .theme-autoupdate a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
2
wp-admin/css/themes.min.css
vendored
2
wp-admin/css/themes.min.css
vendored
File diff suppressed because one or more lines are too long
@ -4567,6 +4567,9 @@ function wp_ajax_delete_plugin() {
|
||||
function wp_ajax_search_plugins() {
|
||||
check_ajax_referer( 'updates' );
|
||||
|
||||
// Ensure after_plugin_row_{$plugin_file} gets hooked.
|
||||
wp_plugin_update_rows();
|
||||
|
||||
$pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
|
||||
if ( 'plugins-network' === $pagenow || 'plugins' === $pagenow ) {
|
||||
set_current_screen( $pagenow );
|
||||
@ -5267,3 +5270,73 @@ function wp_ajax_health_check_get_sizes() {
|
||||
function wp_ajax_rest_nonce() {
|
||||
exit( wp_create_nonce( 'wp_rest' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax handler to enable or disable plugin and theme auto-updates.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*/
|
||||
function wp_ajax_toggle_auto_updates() {
|
||||
check_ajax_referer( 'updates' );
|
||||
|
||||
if ( empty( $_POST['type'] ) || empty( $_POST['asset'] ) || empty( $_POST['state'] ) ) {
|
||||
wp_send_json_error( array( 'error' => __( 'Invalid data. No selected item.' ) ) );
|
||||
}
|
||||
|
||||
$asset = sanitize_text_field( urldecode( $_POST['asset'] ) );
|
||||
|
||||
if ( 'enable' !== $_POST['state'] && 'disable' !== $_POST['state'] ) {
|
||||
wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown state.' ) ) );
|
||||
}
|
||||
$state = $_POST['state'];
|
||||
|
||||
if ( 'plugin' !== $_POST['type'] && 'theme' !== $_POST['type'] ) {
|
||||
wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
|
||||
}
|
||||
$type = $_POST['type'];
|
||||
|
||||
switch ( $type ) {
|
||||
case 'plugin':
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
$error_message = __( 'You do not have permission to modify plugins.' );
|
||||
wp_send_json_error( array( 'error' => $error_message ) );
|
||||
}
|
||||
|
||||
$option = 'auto_update_plugins';
|
||||
/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
|
||||
$all_items = apply_filters( 'all_plugins', get_plugins() );
|
||||
break;
|
||||
case 'theme':
|
||||
if ( ! current_user_can( 'update_themes' ) ) {
|
||||
$error_message = __( 'You do not have permission to modify themes.' );
|
||||
wp_send_json_error( array( 'error' => $error_message ) );
|
||||
}
|
||||
|
||||
$option = 'auto_update_themes';
|
||||
$all_items = wp_get_themes();
|
||||
break;
|
||||
default:
|
||||
wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
|
||||
}
|
||||
|
||||
if ( ! array_key_exists( $asset, $all_items ) ) {
|
||||
$error_message = __( 'Invalid data. The item does not exist.' );
|
||||
wp_send_json_error( array( 'error' => $error_message ) );
|
||||
}
|
||||
|
||||
$auto_updates = (array) get_site_option( $option, array() );
|
||||
|
||||
if ( 'disable' === $state ) {
|
||||
$auto_updates = array_diff( $auto_updates, array( $asset ) );
|
||||
} else {
|
||||
$auto_updates[] = $asset;
|
||||
$auto_updates = array_unique( $auto_updates );
|
||||
}
|
||||
|
||||
// Remove items that have been deleted since the site option was last updated.
|
||||
$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
|
||||
|
||||
update_site_option( $option, $auto_updates );
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
@ -158,6 +158,14 @@ class WP_Automatic_Updater {
|
||||
// Next up, is this an item we can update?
|
||||
if ( 'core' === $type ) {
|
||||
$update = Core_Upgrader::should_update_to_version( $item->current );
|
||||
} elseif ( 'plugin' === $type || 'theme' === $type ) {
|
||||
$update = ! empty( $item->autoupdate );
|
||||
|
||||
if ( ! $update && wp_is_auto_update_enabled_for_type( $type ) ) {
|
||||
// Check if the site admin has enabled auto-updates by default for the specific item.
|
||||
$auto_updates = (array) get_site_option( "auto_update_{$type}s", array() );
|
||||
$update = in_array( $item->{$type}, $auto_updates, true );
|
||||
}
|
||||
} else {
|
||||
$update = ! empty( $item->autoupdate );
|
||||
}
|
||||
@ -501,6 +509,8 @@ class WP_Automatic_Updater {
|
||||
|
||||
if ( ! empty( $this->update_results['core'] ) ) {
|
||||
$this->after_core_update( $this->update_results['core'][0] );
|
||||
} elseif ( ! empty( $this->update_results['plugin'] ) || ! empty( $this->update_results['theme'] ) ) {
|
||||
$this->after_plugin_theme_update( $this->update_results );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -854,6 +864,186 @@ class WP_Automatic_Updater {
|
||||
wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If we tried to perform plugin or theme updates, check if we should send an email.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param object $results The result of updates tasks.
|
||||
*/
|
||||
protected function after_plugin_theme_update( $update_results ) {
|
||||
$successful_updates = array();
|
||||
$failed_updates = array();
|
||||
|
||||
/**
|
||||
* Filters whether to send an email following an automatic background plugin update.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param bool $enabled True if plugins notifications are enabled, false otherwise.
|
||||
*/
|
||||
$notifications_enabled = apply_filters( 'auto_plugin_update_send_email', true );
|
||||
|
||||
if ( ! empty( $update_results['plugin'] ) && $notifications_enabled ) {
|
||||
foreach ( $update_results['plugin'] as $update_result ) {
|
||||
if ( true === $update_result->result ) {
|
||||
$successful_updates['plugin'][] = $update_result;
|
||||
} else {
|
||||
$failed_updates['plugin'][] = $update_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters whether to send an email following an automatic background theme update.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param bool $enabled True if notifications are enabled, false otherwise.
|
||||
*/
|
||||
$notifications_enabled = apply_filters( 'send_theme_auto_update_email', true );
|
||||
|
||||
if ( ! empty( $update_results['theme'] ) && $notifications_enabled ) {
|
||||
foreach ( $update_results['theme'] as $update_result ) {
|
||||
if ( true === $update_result->result ) {
|
||||
$successful_updates['theme'][] = $update_result;
|
||||
} else {
|
||||
$failed_updates['theme'][] = $update_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $failed_updates ) ) {
|
||||
$this->send_plugin_theme_email( 'success', $successful_updates, $failed_updates );
|
||||
} elseif ( empty( $successful_updates ) ) {
|
||||
$this->send_plugin_theme_email( 'fail', $successful_updates, $failed_updates );
|
||||
} else {
|
||||
$this->send_plugin_theme_email( 'mixed', $successful_updates, $failed_updates );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email upon the completion or failure of a plugin or theme background update.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param string $type The type of email to send. Can be one of 'success', 'failure', 'mixed'.
|
||||
* @param array $successful_updates A list of updates that succeeded.
|
||||
* @param array $failed_updates A list of updates that failed.
|
||||
*/
|
||||
protected function send_plugin_theme_email( $type, $successful_updates, $failed_updates ) {
|
||||
// No updates were attempted.
|
||||
if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
|
||||
return;
|
||||
}
|
||||
$body = array();
|
||||
|
||||
switch ( $type ) {
|
||||
case 'success':
|
||||
/* translators: %s: Site title. */
|
||||
$subject = __( '[%s] Some plugins or themes were automatically updated' );
|
||||
break;
|
||||
case 'fail':
|
||||
/* translators: %s: Site title. */
|
||||
$subject = __( '[%s] Some plugins or themes have failed to update' );
|
||||
$body[] = sprintf(
|
||||
/* translators: %s: Home URL. */
|
||||
__( 'Howdy! Failures occurred when attempting to update plugins/themes on your site at %s.' ),
|
||||
home_url()
|
||||
);
|
||||
$body[] = "\n";
|
||||
$body[] = __( 'Please check out your site now. It’s possible that everything is working. If it says you need to update, you should do so.' );
|
||||
break;
|
||||
case 'mixed':
|
||||
/* translators: %s: Site title. */
|
||||
$subject = __( '[%s] Some plugins or themes were automatically updated' );
|
||||
$body[] = sprintf(
|
||||
/* translators: %s: Home URL. */
|
||||
__( 'Howdy! Failures occurred when attempting to update plugins/themes on your site at %s.' ),
|
||||
home_url()
|
||||
);
|
||||
$body[] = "\n";
|
||||
$body[] = __( 'Please check out your site now. It’s possible that everything is working. If it says you need to update, you should do so.' );
|
||||
$body[] = "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// Get failed plugin updates.
|
||||
if ( in_array( $type, array( 'fail', 'mixed' ), true ) && ! empty( $failed_updates['plugin'] ) ) {
|
||||
$body[] = __( 'The following plugins failed to update:' );
|
||||
// List failed updates.
|
||||
foreach ( $failed_updates['plugin'] as $item ) {
|
||||
$body[] = "- {$item->name}";
|
||||
}
|
||||
$body[] = "\n";
|
||||
}
|
||||
// Get failed theme updates.
|
||||
if ( in_array( $type, array( 'fail', 'mixed' ), true ) && ! empty( $failed_updates['theme'] ) ) {
|
||||
$body[] = __( 'The following themes failed to update:' );
|
||||
// List failed updates.
|
||||
foreach ( $failed_updates['theme'] as $item ) {
|
||||
$body[] = "- {$item->name}";
|
||||
}
|
||||
$body[] = "\n";
|
||||
}
|
||||
// Get successful plugin updates.
|
||||
if ( in_array( $type, array( 'success', 'mixed' ), true ) && ! empty( $successful_updates['plugin'] ) ) {
|
||||
$body[] = __( 'The following plugins were successfully updated:' );
|
||||
// List successful updates.
|
||||
foreach ( $successful_updates['plugin'] as $item ) {
|
||||
$body[] = "- {$item->name}";
|
||||
}
|
||||
$body[] = "\n";
|
||||
}
|
||||
// Get successful theme updates.
|
||||
if ( in_array( $type, array( 'success', 'mixed' ), true ) && ! empty( $successful_updates['theme'] ) ) {
|
||||
$body[] = __( 'The following themes were successfully updated:' );
|
||||
// List successful updates.
|
||||
foreach ( $successful_updates['theme'] as $item ) {
|
||||
$body[] = "- {$item->name}";
|
||||
}
|
||||
$body[] = "\n";
|
||||
}
|
||||
$body[] = "\n";
|
||||
|
||||
// Add a note about the support forums.
|
||||
$body[] = __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
|
||||
$body[] = __( 'https://wordpress.org/support/forums/' );
|
||||
$body[] = "\n" . __( 'The WordPress Team' );
|
||||
|
||||
$body = implode( "\n", $body );
|
||||
$to = get_site_option( 'admin_email' );
|
||||
$subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) );
|
||||
$headers = '';
|
||||
|
||||
$email = compact( 'to', 'subject', 'body', 'headers' );
|
||||
|
||||
/**
|
||||
* Filters the email sent following an automatic background plugin update.
|
||||
*
|
||||
* @param array $email {
|
||||
* Array of email arguments that will be passed to wp_mail().
|
||||
*
|
||||
* @type string $to The email recipient. An array of emails
|
||||
* can be returned, as handled by wp_mail().
|
||||
* @type string $subject The email's subject.
|
||||
* @type string $body The email message body.
|
||||
* @type string $headers Any email headers, defaults to no headers.
|
||||
* }
|
||||
* @param string $type The type of email being sent. Can be one of
|
||||
* 'success', 'fail', 'mixed'.
|
||||
* @param object $successful_updates The updates that succeeded.
|
||||
* @param object $failed_updates The updates that failed.
|
||||
*/
|
||||
$email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );
|
||||
wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
|
||||
*
|
||||
|
@ -858,6 +858,15 @@ class WP_Debug_Data {
|
||||
// List all available plugins.
|
||||
$plugins = get_plugins();
|
||||
$plugin_updates = get_plugin_updates();
|
||||
$auto_updates = array();
|
||||
|
||||
$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'plugin' );
|
||||
$auto_updates_enabled_str = __( 'Auto-updates enabled' );
|
||||
$auto_updates_disabled_str = __( 'Auto-updates disabled' );
|
||||
|
||||
if ( $auto_updates_enabled ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
|
||||
}
|
||||
|
||||
foreach ( $plugins as $plugin_path => $plugin ) {
|
||||
$plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';
|
||||
@ -892,6 +901,16 @@ class WP_Debug_Data {
|
||||
$plugin_version_string_debug .= sprintf( ' (latest version: %s)', $plugin_updates[ $plugin_path ]->update->new_version );
|
||||
}
|
||||
|
||||
if ( $auto_updates_enabled ) {
|
||||
if ( in_array( $plugin_path, $auto_updates, true ) ) {
|
||||
$plugin_version_string .= ' | ' . $auto_updates_enabled_str;
|
||||
$plugin_version_string_debug .= ', ' . $auto_updates_enabled_str;
|
||||
} else {
|
||||
$plugin_version_string .= ' | ' . $auto_updates_disabled_str;
|
||||
$plugin_version_string_debug .= ', ' . $auto_updates_disabled_str;
|
||||
}
|
||||
}
|
||||
|
||||
$info[ $plugin_part ]['fields'][ sanitize_text_field( $plugin['Name'] ) ] = array(
|
||||
'label' => $plugin['Name'],
|
||||
'value' => $plugin_version_string,
|
||||
@ -915,6 +934,12 @@ class WP_Debug_Data {
|
||||
$active_theme_version = $active_theme->version;
|
||||
$active_theme_version_debug = $active_theme_version;
|
||||
|
||||
$auto_updates = array();
|
||||
$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' );
|
||||
if ( $auto_updates_enabled ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
}
|
||||
|
||||
if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) {
|
||||
$theme_update_new_version = $theme_updates[ $active_theme->stylesheet ]->update['new_version'];
|
||||
|
||||
@ -980,7 +1005,19 @@ class WP_Debug_Data {
|
||||
'value' => get_stylesheet_directory(),
|
||||
),
|
||||
);
|
||||
if ( $auto_updates_enabled ) {
|
||||
if ( in_array( $active_theme->stylesheet, $auto_updates ) ) {
|
||||
$theme_auto_update_string = __( 'Enabled' );
|
||||
} else {
|
||||
$theme_auto_update_string = __( 'Disabled' );
|
||||
}
|
||||
|
||||
$info['wp-active-theme']['fields']['auto_update'] = array(
|
||||
'label' => __( 'Auto-update' ),
|
||||
'value' => $theme_auto_update_string,
|
||||
'debug' => $theme_auto_update_string,
|
||||
);
|
||||
}
|
||||
$parent_theme = $active_theme->parent();
|
||||
|
||||
if ( $parent_theme ) {
|
||||
@ -1026,6 +1063,19 @@ class WP_Debug_Data {
|
||||
'value' => get_template_directory(),
|
||||
),
|
||||
);
|
||||
if ( $auto_updates_enabled ) {
|
||||
if ( in_array( $parent_theme->stylesheet, $auto_updates ) ) {
|
||||
$parent_theme_auto_update_string = __( 'Enabled' );
|
||||
} else {
|
||||
$parent_theme_auto_update_string = __( 'Disabled' );
|
||||
}
|
||||
|
||||
$info['wp-parent-theme']['fields']['auto_update'] = array(
|
||||
'label' => __( 'Auto-update' ),
|
||||
'value' => $parent_theme_auto_update_string,
|
||||
'debug' => $parent_theme_auto_update_string,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate a list of all themes available in the install.
|
||||
@ -1075,6 +1125,16 @@ class WP_Debug_Data {
|
||||
$theme_version_string_debug .= sprintf( ' (latest version: %s)', $theme_updates[ $theme_slug ]->update['new_version'] );
|
||||
}
|
||||
|
||||
if ( $auto_updates_enabled ) {
|
||||
if ( in_array( $theme_slug, $auto_updates ) ) {
|
||||
$theme_version_string .= ' | ' . $auto_updates_enabled_str;
|
||||
$theme_version_string_debug .= ',' . $auto_updates_enabled_str;
|
||||
} else {
|
||||
$theme_version_string .= ' | ' . $auto_updates_disabled_str;
|
||||
$theme_version_string_debug .= ', ' . $auto_updates_disabled_str;
|
||||
}
|
||||
}
|
||||
|
||||
$info['wp-themes-inactive']['fields'][ sanitize_text_field( $theme->name ) ] = array(
|
||||
'label' => sprintf(
|
||||
/* translators: 1: Theme name. 2: Theme slug. */
|
||||
|
@ -22,6 +22,15 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
|
||||
private $has_items;
|
||||
|
||||
/**
|
||||
* Whether to show the auto-updates UI.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @var bool True if auto-updates UI is to be shown, false otherwise.
|
||||
*/
|
||||
protected $show_autoupdates = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -45,7 +54,7 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
);
|
||||
|
||||
$status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
|
||||
if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ), true ) ) {
|
||||
if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) {
|
||||
$status = 'all';
|
||||
}
|
||||
|
||||
@ -56,6 +65,9 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
if ( $this->is_site_themes ) {
|
||||
$this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
|
||||
}
|
||||
|
||||
$this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) &&
|
||||
! $this->is_site_themes && current_user_can( 'update_themes' );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,6 +119,13 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
|
||||
);
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
|
||||
$themes['auto-update-enabled'] = array();
|
||||
$themes['auto-update-disabled'] = array();
|
||||
}
|
||||
|
||||
if ( $this->is_site_themes ) {
|
||||
$themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
|
||||
$allowed_where = 'site';
|
||||
@ -131,6 +150,14 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
|
||||
$filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
|
||||
$themes[ $filter ][ $key ] = $themes['all'][ $key ];
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
if ( in_array( $key, $auto_updates, true ) ) {
|
||||
$themes['auto-update-enabled'][ $key ] = $themes['all'][ $key ];
|
||||
} else {
|
||||
$themes['auto-update-disabled'][ $key ] = $themes['all'][ $key ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $s ) {
|
||||
@ -257,11 +284,17 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
$columns = array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'name' => __( 'Theme' ),
|
||||
'description' => __( 'Description' ),
|
||||
);
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
$columns['auto-updates'] = __( 'Automatic Updates' );
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,6 +377,22 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
'themes'
|
||||
);
|
||||
break;
|
||||
case 'auto-update-enabled':
|
||||
/* translators: %s: Number of themes. */
|
||||
$text = _n(
|
||||
'Auto-updates Enabled <span class="count">(%s)</span>',
|
||||
'Auto-updates Enabled <span class="count">(%s)</span>',
|
||||
$count
|
||||
);
|
||||
break;
|
||||
case 'auto-update-disabled':
|
||||
/* translators: %s: Number of themes. */
|
||||
$text = _n(
|
||||
'Auto-updates Disabled <span class="count">(%s)</span>',
|
||||
'Auto-updates Disabled <span class="count">(%s)</span>',
|
||||
$count
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( $this->is_site_themes ) {
|
||||
@ -388,6 +437,17 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
$actions['delete-selected'] = __( 'Delete' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
if ( 'auto-update-enabled' !== $status ) {
|
||||
$actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
|
||||
}
|
||||
|
||||
if ( 'auto-update-disabled' !== $status ) {
|
||||
$actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
|
||||
}
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
@ -639,6 +699,70 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the auto-updates column output.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @global string $status
|
||||
* @global int $page
|
||||
*
|
||||
* @param WP_Theme $theme The current WP_Theme object.
|
||||
*/
|
||||
public function column_autoupdates( $theme ) {
|
||||
global $status, $page;
|
||||
|
||||
static $auto_updates, $available_updates;
|
||||
|
||||
if ( ! $auto_updates ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
}
|
||||
if ( ! $available_updates ) {
|
||||
$available_updates = get_site_transient( 'update_themes' );
|
||||
}
|
||||
|
||||
$stylesheet = $theme->get_stylesheet();
|
||||
|
||||
if ( in_array( $stylesheet, $auto_updates, true ) ) {
|
||||
$text = __( 'Disable auto-updates' );
|
||||
$action = 'disable';
|
||||
$time_class = '';
|
||||
} else {
|
||||
$text = __( 'Enable auto-updates' );
|
||||
$action = 'enable';
|
||||
$time_class = ' hidden';
|
||||
}
|
||||
|
||||
$query_args = array(
|
||||
'action' => "{$action}-auto-update",
|
||||
'theme' => $stylesheet,
|
||||
'paged' => $page,
|
||||
'theme_status' => $status,
|
||||
);
|
||||
|
||||
$url = add_query_arg( $query_args, 'themes.php' );
|
||||
|
||||
printf(
|
||||
'<a href="%s" class="toggle-auto-update" data-wp-action="%s">',
|
||||
wp_nonce_url( $url, 'updates' ),
|
||||
$action
|
||||
);
|
||||
|
||||
echo '<span class="dashicons dashicons-update spin hidden"></span>';
|
||||
echo '<span class="label">' . $text . '</span>';
|
||||
echo '</a>';
|
||||
|
||||
$available_updates = get_site_transient( 'update_themes' );
|
||||
if ( isset( $available_updates->response[ $stylesheet ] ) ) {
|
||||
printf(
|
||||
'<div class="auto-update-time%s">%s</div>',
|
||||
$time_class,
|
||||
wp_get_auto_update_message()
|
||||
);
|
||||
}
|
||||
echo '<div class="auto-updates-error inline notice error hidden"><p></p></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles default column output.
|
||||
*
|
||||
@ -721,6 +845,13 @@ class WP_MS_Themes_List_Table extends WP_List_Table {
|
||||
echo '</td>';
|
||||
break;
|
||||
|
||||
case 'auto-updates':
|
||||
echo "<td class='column-auto-updates{$extra_classes}'>";
|
||||
|
||||
$this->column_autoupdates( $item );
|
||||
|
||||
echo '</td>';
|
||||
break;
|
||||
default:
|
||||
echo "<td class='$column_name column-$column_name{$extra_classes}'>";
|
||||
|
||||
|
@ -16,6 +16,14 @@
|
||||
* @see WP_List_Table
|
||||
*/
|
||||
class WP_Plugins_List_Table extends WP_List_Table {
|
||||
/**
|
||||
* Whether to show the auto-updates UI.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @var bool True if auto-updates UI is to be shown, false otherwise.
|
||||
*/
|
||||
protected $show_autoupdates = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -39,7 +47,7 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
)
|
||||
);
|
||||
|
||||
$status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused' );
|
||||
$status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled' );
|
||||
|
||||
$status = 'all';
|
||||
if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], $status_whitelist, true ) ) {
|
||||
@ -51,6 +59,10 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
}
|
||||
|
||||
$page = $this->get_pagenum();
|
||||
|
||||
$this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' ) &&
|
||||
current_user_can( 'update_plugins' ) &&
|
||||
( ! is_multisite() || $this->screen->in_admin( 'network' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,6 +115,12 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
'dropins' => array(),
|
||||
'paused' => array(),
|
||||
);
|
||||
if ( $this->show_autoupdates ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
|
||||
|
||||
$plugins['auto-update-enabled'] = array();
|
||||
$plugins['auto-update-disabled'] = array();
|
||||
}
|
||||
|
||||
$screen = $this->screen;
|
||||
|
||||
@ -233,6 +251,14 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
// Populate the inactive list with plugins that aren't activated.
|
||||
$plugins['inactive'][ $plugin_file ] = $plugin_data;
|
||||
}
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
if ( in_array( $plugin_file, $auto_updates, true ) ) {
|
||||
$plugins['auto-update-enabled'][ $plugin_file ] = $plugins['all'][ $plugin_file ];
|
||||
} else {
|
||||
$plugins['auto-update-disabled'][ $plugin_file ] = $plugins['all'][ $plugin_file ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( strlen( $s ) ) {
|
||||
@ -399,11 +425,17 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
public function get_columns() {
|
||||
global $status;
|
||||
|
||||
return array(
|
||||
$columns = array(
|
||||
'cb' => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '',
|
||||
'name' => __( 'Plugin' ),
|
||||
'description' => __( 'Description' ),
|
||||
);
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
$columns['auto-updates'] = __( 'Automatic Updates' );
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -493,6 +525,22 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
$count
|
||||
);
|
||||
break;
|
||||
case 'auto-update-enabled':
|
||||
/* translators: %s: Number of plugins. */
|
||||
$text = _n(
|
||||
'Auto-updates Enabled <span class="count">(%s)</span>',
|
||||
'Auto-updates Enabled <span class="count">(%s)</span>',
|
||||
$count
|
||||
);
|
||||
break;
|
||||
case 'auto-update-disabled':
|
||||
/* translators: %s: Number of plugins. */
|
||||
$text = _n(
|
||||
'Auto-updates Disabled <span class="count">(%s)</span>',
|
||||
'Auto-updates Disabled <span class="count">(%s)</span>',
|
||||
$count
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( 'search' !== $type ) {
|
||||
@ -533,6 +581,15 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
|
||||
$actions['delete-selected'] = __( 'Delete' );
|
||||
}
|
||||
|
||||
if ( $this->show_autoupdates ) {
|
||||
if ( 'auto-update-enabled' !== $status ) {
|
||||
$actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
|
||||
}
|
||||
if ( 'auto-update-disabled' !== $status ) {
|
||||
$actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $actions;
|
||||
@ -882,6 +939,9 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
|
||||
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
|
||||
|
||||
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
|
||||
$available_updates = get_site_transient( 'update_plugins' );
|
||||
|
||||
foreach ( $columns as $column_name => $column_display_name ) {
|
||||
$extra_classes = '';
|
||||
if ( in_array( $column_name, $hidden, true ) ) {
|
||||
@ -973,6 +1033,56 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
}
|
||||
|
||||
echo '</td>';
|
||||
break;
|
||||
case 'auto-updates':
|
||||
if ( ! $this->show_autoupdates ) {
|
||||
break;
|
||||
}
|
||||
|
||||
echo "<td class='column-auto-updates{$extra_classes}'>";
|
||||
|
||||
if ( in_array( $plugin_file, $auto_updates, true ) ) {
|
||||
$text = __( 'Disable auto-updates' );
|
||||
$action = 'disable';
|
||||
$time_class = '';
|
||||
} else {
|
||||
$text = __( 'Enable auto-updates' );
|
||||
$action = 'enable';
|
||||
$time_class = ' hidden';
|
||||
}
|
||||
|
||||
$query_args = array(
|
||||
'action' => "{$action}-auto-update",
|
||||
'plugin' => $plugin_file,
|
||||
'paged' => $page,
|
||||
'plugin_status' => $status,
|
||||
);
|
||||
|
||||
$url = add_query_arg( $query_args, 'plugins.php' );
|
||||
|
||||
printf(
|
||||
'<a href="%s" class="toggle-auto-update" data-wp-action="%s">',
|
||||
wp_nonce_url( $url, 'updates' ),
|
||||
$action
|
||||
);
|
||||
|
||||
echo '<span class="dashicons dashicons-update spin hidden"></span>';
|
||||
echo '<span class="label">' . $text . '</span>';
|
||||
echo '</a>';
|
||||
|
||||
$available_updates = get_site_transient( 'update_plugins' );
|
||||
|
||||
if ( isset( $available_updates->response[ $plugin_file ] ) ) {
|
||||
printf(
|
||||
'<div class="auto-update-time%s">%s</div>',
|
||||
$time_class,
|
||||
wp_get_auto_update_message()
|
||||
);
|
||||
}
|
||||
|
||||
echo '<div class="inline notice error hidden"><p></p></div>';
|
||||
echo '</td>';
|
||||
|
||||
break;
|
||||
default:
|
||||
$classes = "$column_name column-$column_name $class";
|
||||
@ -1000,12 +1110,14 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
* Fires after each row in the Plugins list table.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
|
||||
*
|
||||
* @param string $plugin_file Path to the plugin file relative to the plugins directory.
|
||||
* @param array $plugin_data An array of plugin data.
|
||||
* @param string $status Status of the plugin. Defaults are 'All', 'Active',
|
||||
* 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
|
||||
* 'Drop-ins', 'Search', 'Paused'.
|
||||
* 'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
|
||||
* 'Auto-updates Disabled'.
|
||||
*/
|
||||
do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
|
||||
|
||||
@ -1016,12 +1128,14 @@ class WP_Plugins_List_Table extends WP_List_Table {
|
||||
* to the plugin file, relative to the plugins directory.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
|
||||
*
|
||||
* @param string $plugin_file Path to the plugin file relative to the plugins directory.
|
||||
* @param array $plugin_data An array of plugin data.
|
||||
* @param string $status Status of the plugin. Defaults are 'All', 'Active',
|
||||
* 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
|
||||
* 'Drop-ins', 'Search', 'Paused'.
|
||||
* 'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
|
||||
* 'Auto-updates Disabled'.
|
||||
*/
|
||||
do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
|
||||
}
|
||||
|
@ -660,6 +660,8 @@ function wp_prepare_themes_for_js( $themes = null ) {
|
||||
|
||||
$parents = array();
|
||||
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
|
||||
foreach ( $themes as $theme ) {
|
||||
$slug = $theme->get_stylesheet();
|
||||
$encoded_slug = urlencode( $slug );
|
||||
@ -683,6 +685,9 @@ function wp_prepare_themes_for_js( $themes = null ) {
|
||||
);
|
||||
}
|
||||
|
||||
$auto_update = in_array( $slug, $auto_updates, true );
|
||||
$auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
|
||||
|
||||
$prepared_themes[ $slug ] = array(
|
||||
'id' => $slug,
|
||||
'name' => $theme->display( 'Name' ),
|
||||
@ -699,10 +704,14 @@ function wp_prepare_themes_for_js( $themes = null ) {
|
||||
'hasUpdate' => isset( $updates[ $slug ] ),
|
||||
'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
|
||||
'update' => get_theme_update_available( $theme ),
|
||||
'autoupdate' => $auto_update,
|
||||
'actions' => array(
|
||||
'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
|
||||
'customize' => $customize_action,
|
||||
'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
|
||||
'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
|
||||
'customize' => $customize_action,
|
||||
'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
|
||||
'autoupdate' => wp_is_auto_update_enabled_for_type( 'theme' ) && ! is_multisite() && current_user_can( 'update_themes' )
|
||||
? wp_nonce_url( admin_url( 'themes.php?action=' . $auto_update_action . '&stylesheet=' . $encoded_slug ), 'updates' )
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -435,7 +435,12 @@ function wp_plugin_update_row( $file, $plugin_data ) {
|
||||
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '§ion=changelog&TB_iframe=true&width=600&height=800' );
|
||||
|
||||
/** @var WP_Plugins_List_Table $wp_list_table */
|
||||
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
|
||||
$wp_list_table = _get_list_table(
|
||||
'WP_Plugins_List_Table',
|
||||
array(
|
||||
'screen' => get_current_screen(),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_network_admin() || ! is_multisite() ) {
|
||||
if ( is_network_admin() ) {
|
||||
@ -933,3 +938,76 @@ function wp_recovery_mode_nag() {
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether auto-updates are enabled.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param string $type The type of update being checked: 'theme' or 'plugin'.
|
||||
* @return bool True if auto-updates are enabled for `$type`, false otherwise.
|
||||
*/
|
||||
function wp_is_auto_update_enabled_for_type( $type ) {
|
||||
switch ( $type ) {
|
||||
case 'plugin':
|
||||
/**
|
||||
* Filters whether plugins manual auto-update is enabled.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param bool $enabled True if plugins auto-update is enabled, false otherwise.
|
||||
*/
|
||||
return apply_filters( 'wp_plugins_auto_update_enabled', true );
|
||||
case 'theme':
|
||||
/**
|
||||
* Filters whether plugins manual auto-update is enabled.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @param bool True if themes auto-update is enabled, false otherwise.
|
||||
*/
|
||||
return apply_filters( 'wp_themes_auto_update_enabled', true );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the appropriate update message to be displayed.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*
|
||||
* @return string The update message to be shown.
|
||||
*/
|
||||
function wp_get_auto_update_message() {
|
||||
$next_update_time = wp_next_scheduled( 'wp_version_check' );
|
||||
|
||||
// Check if event exists.
|
||||
if ( false === $next_update_time ) {
|
||||
return __( 'There may be a problem with WP-Cron. Automatic update not scheduled.' );
|
||||
}
|
||||
|
||||
// See if cron is disabled
|
||||
$cron_disabled = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON;
|
||||
if ( $cron_disabled ) {
|
||||
return __( 'WP-Cron is disabled. Automatic updates not available.' );
|
||||
}
|
||||
|
||||
$time_to_next_update = human_time_diff( intval( $next_update_time ) );
|
||||
|
||||
// See if cron is overdue.
|
||||
$overdue = ( time() - $next_update_time ) > 0;
|
||||
if ( $overdue ) {
|
||||
return sprintf(
|
||||
/* translators: Duration that WP-Cron has been overdue. */
|
||||
__( 'There may be a problem with WP-Cron. Automatic update overdue by %s.' ),
|
||||
$time_to_next_update
|
||||
);
|
||||
} else {
|
||||
return sprintf(
|
||||
/* translators: Time until the next update. */
|
||||
__( 'Auto-update scheduled in %s.' ),
|
||||
$time_to_next_update
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -409,6 +409,7 @@
|
||||
*
|
||||
* @since 4.2.0
|
||||
* @since 4.6.0 More accurately named `updatePluginSuccess`.
|
||||
* @since 5.5.0 Auto-update "time to next update" text cleared.
|
||||
*
|
||||
* @param {object} response Response from the server.
|
||||
* @param {string} response.slug Slug of the plugin to be updated.
|
||||
@ -431,6 +432,9 @@
|
||||
// Update the version number in the row.
|
||||
newText = $pluginRow.find( '.plugin-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
|
||||
$pluginRow.find( '.plugin-version-author-uri' ).html( newText );
|
||||
|
||||
// Clear the "time to next auto-update" text.
|
||||
$pluginRow.find( '.auto-update-time' ).empty();
|
||||
} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
|
||||
$updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' )
|
||||
.removeClass( 'updating-message' )
|
||||
@ -969,6 +973,7 @@
|
||||
* Updates the UI appropriately after a successful theme update.
|
||||
*
|
||||
* @since 4.6.0
|
||||
* @since 5.5.0 Auto-update "time to next update" text cleared.
|
||||
*
|
||||
* @param {object} response
|
||||
* @param {string} response.slug Slug of the theme to be updated.
|
||||
@ -1002,12 +1007,16 @@
|
||||
// Update the version number in the row.
|
||||
newText = $theme.find( '.theme-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
|
||||
$theme.find( '.theme-version-author-uri' ).html( newText );
|
||||
|
||||
// Clear the "time to next auto-update" text.
|
||||
$theme.find( '.auto-update-time' ).empty();
|
||||
} else {
|
||||
$notice = $( '.theme-info .notice' ).add( $theme.find( '.update-message' ) );
|
||||
|
||||
// Focus on Customize button after updating.
|
||||
if ( isModalOpen ) {
|
||||
$( '.load-customize:visible' ).focus();
|
||||
$( '.theme-info .theme-autoupdate' ).find( '.auto-update-time' ).empty();
|
||||
} else {
|
||||
$theme.find( '.load-customize' ).focus();
|
||||
}
|
||||
@ -2461,5 +2470,144 @@
|
||||
* @since 4.2.0
|
||||
*/
|
||||
$( window ).on( 'beforeunload', wp.updates.beforeunload );
|
||||
|
||||
/**
|
||||
* Click handler for enabling and disabling plugin and theme auto-updates.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*/
|
||||
$document.on( 'click', '.column-auto-updates a.toggle-auto-update, .theme-overlay a.toggle-auto-update', function( event ) {
|
||||
var data, asset, type, $parent;
|
||||
var $anchor = $( this ),
|
||||
action = $anchor.attr( 'data-wp-action' ),
|
||||
$label = $anchor.find( '.label' );
|
||||
|
||||
if ( 'themes' !== pagenow ) {
|
||||
$parent = $anchor.closest( '.column-auto-updates' );
|
||||
} else {
|
||||
$parent = $anchor.closest( '.theme-autoupdate' );
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// Prevent multiple simultaneous requests.
|
||||
if ( $anchor.attr( 'data-doing-ajax' ) === 'yes' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$anchor.attr( 'data-doing-ajax', 'yes' );
|
||||
|
||||
switch ( pagenow ) {
|
||||
case 'plugins':
|
||||
case 'plugins-network':
|
||||
type = 'plugin';
|
||||
asset = $anchor.closest( 'tr' ).attr( 'data-plugin' );
|
||||
break;
|
||||
case 'themes-network':
|
||||
type = 'theme';
|
||||
asset = $anchor.closest( 'tr' ).attr( 'data-slug' );
|
||||
break;
|
||||
case 'themes':
|
||||
type = 'theme';
|
||||
asset = $anchor.attr( 'data-slug' );
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear any previous errors.
|
||||
$parent.find( '.notice.error' ).addClass( 'hidden' );
|
||||
|
||||
// Show loading status.
|
||||
if ( 'enable' === action ) {
|
||||
$label.text( wp.updates.l10n.autoUpdatesEnabling );
|
||||
} else {
|
||||
$label.text( wp.updates.l10n.autoUpdatesDisabling );
|
||||
}
|
||||
|
||||
$anchor.find( '.dashicons-update' ).removeClass( 'hidden' );
|
||||
|
||||
data = {
|
||||
action: 'toggle-auto-updates',
|
||||
_ajax_nonce: settings.ajax_nonce,
|
||||
state: action,
|
||||
type: type,
|
||||
asset: asset
|
||||
};
|
||||
|
||||
$.post( window.ajaxurl, data )
|
||||
.done( function( response ) {
|
||||
var $enabled, $disabled, enabledNumber, disabledNumber, errorMessage;
|
||||
var href = $anchor.attr( 'href' );
|
||||
|
||||
if ( ! response.success ) {
|
||||
// if WP returns 0 for response (which can happen in a few cases),
|
||||
// output the general error message since we won't have response.data.error.
|
||||
if ( response.data && response.data.error ) {
|
||||
errorMessage = response.data.error;
|
||||
} else {
|
||||
errorMessage = wp.updates.l10n.autoUpdatesError;
|
||||
}
|
||||
|
||||
$parent.find( '.notice.error' ).removeClass( 'hidden' ).find( 'p' ).text( errorMessage );
|
||||
wp.a11y.speak( errorMessage, 'polite' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the counts in the enabled/disabled views if on a screen
|
||||
// with a list table.
|
||||
if ( 'themes' !== pagenow ) {
|
||||
$enabled = $( '.auto-update-enabled span' );
|
||||
$disabled = $( '.auto-update-disabled span' );
|
||||
enabledNumber = parseInt( $enabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0;
|
||||
disabledNumber = parseInt( $disabled.text().replace( /[^\d]+/g, '' ), 10 ) || 0;
|
||||
|
||||
switch ( action ) {
|
||||
case 'enable':
|
||||
++enabledNumber;
|
||||
--disabledNumber;
|
||||
break;
|
||||
case 'disable':
|
||||
--enabledNumber;
|
||||
++disabledNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
enabledNumber = Math.max( 0, enabledNumber );
|
||||
disabledNumber = Math.max( 0, disabledNumber );
|
||||
|
||||
$enabled.text( '(' + enabledNumber + ')' );
|
||||
$disabled.text( '(' + disabledNumber + ')' );
|
||||
}
|
||||
|
||||
if ( 'enable' === action ) {
|
||||
href = href.replace( 'action=enable-auto-update', 'action=disable-auto-update' );
|
||||
$anchor.attr( {
|
||||
'data-wp-action': 'disable',
|
||||
href: href
|
||||
} );
|
||||
|
||||
$label.text( wp.updates.l10n.autoUpdatesDisable );
|
||||
$parent.find( '.auto-update-time' ).removeClass( 'hidden' );
|
||||
wp.a11y.speak( wp.updates.l10n.autoUpdatesEnabled, 'polite' );
|
||||
} else {
|
||||
href = href.replace( 'action=disable-auto-update', 'action=enable-auto-update' );
|
||||
$anchor.attr( {
|
||||
'data-wp-action': 'enable',
|
||||
href: href
|
||||
} );
|
||||
|
||||
$label.text( wp.updates.l10n.autoUpdatesEnable );
|
||||
$parent.find( '.auto-update-time' ).addClass( 'hidden' );
|
||||
wp.a11y.speak( wp.updates.l10n.autoUpdatesDisabled, 'polite' );
|
||||
}
|
||||
} )
|
||||
.fail( function() {
|
||||
$parent.find( '.notice.error' ).removeClass( 'hidden' ).find( 'p' ).text( wp.updates.l10n.autoUpdatesError );
|
||||
wp.a11y.speak( wp.updates.l10n.autoUpdatesError, 'polite' );
|
||||
} )
|
||||
.always( function() {
|
||||
$anchor.removeAttr( 'data-doing-ajax' ).find( '.dashicons-update' ).addClass( 'hidden' );
|
||||
} );
|
||||
}
|
||||
);
|
||||
} );
|
||||
})( jQuery, window.wp, window._wpUpdatesSettings );
|
||||
|
2
wp-admin/js/updates.min.js
vendored
2
wp-admin/js/updates.min.js
vendored
File diff suppressed because one or more lines are too long
@ -22,7 +22,15 @@ $action = $wp_list_table->current_action();
|
||||
$s = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : '';
|
||||
|
||||
// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
|
||||
$temp_args = array( 'enabled', 'disabled', 'deleted', 'error' );
|
||||
$temp_args = array(
|
||||
'enabled',
|
||||
'disabled',
|
||||
'deleted',
|
||||
'error',
|
||||
'enabled-auto-update',
|
||||
'disabled-auto-update',
|
||||
);
|
||||
|
||||
$_SERVER['REQUEST_URI'] = remove_query_arg( $temp_args, $_SERVER['REQUEST_URI'] );
|
||||
$referer = remove_query_arg( $temp_args, wp_get_referer() );
|
||||
|
||||
@ -123,8 +131,8 @@ if ( $action ) {
|
||||
require_once ABSPATH . 'wp-admin/admin-header.php';
|
||||
$themes_to_delete = count( $themes );
|
||||
?>
|
||||
<div class="wrap">
|
||||
<?php if ( 1 == $themes_to_delete ) : ?>
|
||||
<div class="wrap">
|
||||
<?php if ( 1 === $themes_to_delete ) : ?>
|
||||
<h1><?php _e( 'Delete Theme' ); ?></h1>
|
||||
<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This theme may be active on other sites in the network.' ); ?></p></div>
|
||||
<p><?php _e( 'You are about to remove the following theme:' ); ?></p>
|
||||
@ -145,7 +153,7 @@ if ( $action ) {
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<?php if ( 1 == $themes_to_delete ) : ?>
|
||||
<?php if ( 1 === $themes_to_delete ) : ?>
|
||||
<p><?php _e( 'Are you sure you want to delete this theme?' ); ?></p>
|
||||
<?php else : ?>
|
||||
<p><?php _e( 'Are you sure you want to delete these themes?' ); ?></p>
|
||||
@ -154,27 +162,28 @@ if ( $action ) {
|
||||
<input type="hidden" name="verify-delete" value="1" />
|
||||
<input type="hidden" name="action" value="delete-selected" />
|
||||
<?php
|
||||
|
||||
foreach ( (array) $themes as $theme ) {
|
||||
echo '<input type="hidden" name="checked[]" value="' . esc_attr( $theme ) . '" />';
|
||||
}
|
||||
|
||||
wp_nonce_field( 'bulk-themes' );
|
||||
wp_nonce_field( 'bulk-themes' );
|
||||
|
||||
if ( 1 == $themes_to_delete ) {
|
||||
if ( 1 === $themes_to_delete ) {
|
||||
submit_button( __( 'Yes, delete this theme' ), '', 'submit', false );
|
||||
} else {
|
||||
submit_button( __( 'Yes, delete these themes' ), '', 'submit', false );
|
||||
}
|
||||
|
||||
?>
|
||||
</form>
|
||||
<?php
|
||||
$referer = wp_get_referer();
|
||||
?>
|
||||
<?php $referer = wp_get_referer(); ?>
|
||||
<form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
|
||||
<?php submit_button( __( 'No, return me to the theme list' ), '', 'submit', false ); ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
require_once ABSPATH . 'wp-admin/admin-footer.php';
|
||||
exit;
|
||||
} // End if verify-delete.
|
||||
@ -208,6 +217,58 @@ if ( $action ) {
|
||||
)
|
||||
);
|
||||
exit;
|
||||
case 'enable-auto-update':
|
||||
case 'disable-auto-update':
|
||||
case 'enable-auto-update-selected':
|
||||
case 'disable-auto-update-selected':
|
||||
if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
|
||||
wp_die( __( 'Sorry, you are not allowed to change themes automatic update settings.' ) );
|
||||
}
|
||||
|
||||
if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
|
||||
check_admin_referer( 'updates' );
|
||||
} else {
|
||||
if ( empty( $_POST['checked'] ) ) {
|
||||
// Nothing to do.
|
||||
wp_safe_redirect( add_query_arg( 'error', 'none', $referer ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
check_admin_referer( 'bulk-themes' );
|
||||
}
|
||||
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
|
||||
if ( 'enable-auto-update' === $action ) {
|
||||
$auto_updates[] = $_GET['theme'];
|
||||
$auto_updates = array_unique( $auto_updates );
|
||||
$referer = add_query_arg( 'enabled-auto-update', 1, $referer );
|
||||
} elseif ( 'disable-auto-update' === $action ) {
|
||||
$auto_updates = array_diff( $auto_updates, array( $_GET['theme'] ) );
|
||||
$referer = add_query_arg( 'disabled-auto-update', 1, $referer );
|
||||
} else {
|
||||
// Bulk enable/disable.
|
||||
$themes = (array) wp_unslash( $_POST['checked'] );
|
||||
|
||||
if ( 'enable-auto-update-selected' === $action ) {
|
||||
$auto_updates = array_merge( $auto_updates, $themes );
|
||||
$auto_updates = array_unique( $auto_updates );
|
||||
$referer = add_query_arg( 'enabled-auto-update', count( $themes ), $referer );
|
||||
} else {
|
||||
$auto_updates = array_diff( $auto_updates, $themes );
|
||||
$referer = add_query_arg( 'disabled-auto-update', count( $themes ), $referer );
|
||||
}
|
||||
}
|
||||
|
||||
$all_items = wp_get_themes();
|
||||
|
||||
// Remove themes that don't exist or have been deleted since the option was last updated.
|
||||
$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
|
||||
|
||||
update_site_option( 'auto_update_themes', $auto_updates );
|
||||
|
||||
wp_safe_redirect( $referer );
|
||||
exit;
|
||||
default:
|
||||
$themes = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
|
||||
if ( empty( $themes ) ) {
|
||||
@ -284,7 +345,7 @@ if ( isset( $_REQUEST['s'] ) && strlen( $_REQUEST['s'] ) ) {
|
||||
<?php
|
||||
if ( isset( $_GET['enabled'] ) ) {
|
||||
$enabled = absint( $_GET['enabled'] );
|
||||
if ( 1 == $enabled ) {
|
||||
if ( 1 === $enabled ) {
|
||||
$message = __( 'Theme enabled.' );
|
||||
} else {
|
||||
/* translators: %s: Number of themes. */
|
||||
@ -293,7 +354,7 @@ if ( isset( $_GET['enabled'] ) ) {
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $enabled ) ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['disabled'] ) ) {
|
||||
$disabled = absint( $_GET['disabled'] );
|
||||
if ( 1 == $disabled ) {
|
||||
if ( 1 === $disabled ) {
|
||||
$message = __( 'Theme disabled.' );
|
||||
} else {
|
||||
/* translators: %s: Number of themes. */
|
||||
@ -302,16 +363,34 @@ if ( isset( $_GET['enabled'] ) ) {
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $disabled ) ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['deleted'] ) ) {
|
||||
$deleted = absint( $_GET['deleted'] );
|
||||
if ( 1 == $deleted ) {
|
||||
if ( 1 === $deleted ) {
|
||||
$message = __( 'Theme deleted.' );
|
||||
} else {
|
||||
/* translators: %s: Number of themes. */
|
||||
$message = _n( '%s theme deleted.', '%s themes deleted.', $deleted );
|
||||
}
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $deleted ) ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['error'] ) && 'none' == $_GET['error'] ) {
|
||||
} elseif ( isset( $_GET['enabled-auto-update'] ) ) {
|
||||
$enabled = absint( $_GET['enabled-auto-update'] );
|
||||
if ( 1 === $enabled ) {
|
||||
$message = __( 'Theme will be auto-updated.' );
|
||||
} else {
|
||||
/* translators: %s: Number of themes. */
|
||||
$message = _n( '%s theme will be auto-updated.', '%s themes will be auto-updated.', $enabled );
|
||||
}
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $enabled ) ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['disabled-auto-update'] ) ) {
|
||||
$disabled = absint( $_GET['disabled-auto-update'] );
|
||||
if ( 1 === $disabled ) {
|
||||
$message = __( 'Theme will no longer be auto-updated.' );
|
||||
} else {
|
||||
/* translators: %s: Number of themes. */
|
||||
$message = _n( '%s theme will no longer be auto-updated.', '%s themes will no longer be auto-updated.', $disabled );
|
||||
}
|
||||
echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $disabled ) ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['error'] ) && 'none' === $_GET['error'] ) {
|
||||
echo '<div id="message" class="error notice is-dismissible"><p>' . __( 'No theme selected.' ) . '</p></div>';
|
||||
} elseif ( isset( $_GET['error'] ) && 'main' == $_GET['error'] ) {
|
||||
} elseif ( isset( $_GET['error'] ) && 'main' === $_GET['error'] ) {
|
||||
echo '<div class="error notice is-dismissible"><p>' . __( 'You cannot delete a theme while it is active on the main site.' ) . '</p></div>';
|
||||
}
|
||||
|
||||
@ -324,7 +403,7 @@ if ( isset( $_GET['enabled'] ) ) {
|
||||
<?php
|
||||
$wp_list_table->views();
|
||||
|
||||
if ( 'broken' == $status ) {
|
||||
if ( 'broken' === $status ) {
|
||||
echo '<p class="clear">' . __( 'The following themes are installed but incomplete.' ) . '</p>';
|
||||
}
|
||||
?>
|
||||
|
@ -22,7 +22,21 @@ $plugin = isset( $_REQUEST['plugin'] ) ? wp_unslash( $_REQUEST['plugin'] ) : '';
|
||||
$s = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
|
||||
|
||||
// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
|
||||
$_SERVER['REQUEST_URI'] = remove_query_arg( array( 'error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce' ), $_SERVER['REQUEST_URI'] );
|
||||
$query_args_to_remove = array(
|
||||
'error',
|
||||
'deleted',
|
||||
'activate',
|
||||
'activate-multi',
|
||||
'deactivate',
|
||||
'deactivate-multi',
|
||||
'enabled-auto-update',
|
||||
'disabled-auto-update',
|
||||
'enabled-auto-update-multi',
|
||||
'disabled-auto-update-multi',
|
||||
'_error_nonce',
|
||||
);
|
||||
|
||||
$_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQUEST_URI'] );
|
||||
|
||||
wp_enqueue_script( 'updates' );
|
||||
|
||||
@ -284,11 +298,14 @@ if ( $action ) {
|
||||
if ( ! isset( $_REQUEST['verify-delete'] ) ) {
|
||||
wp_enqueue_script( 'jquery' );
|
||||
require_once ABSPATH . 'wp-admin/admin-header.php';
|
||||
|
||||
?>
|
||||
<div class="wrap">
|
||||
<div class="wrap">
|
||||
<?php
|
||||
$plugin_info = array();
|
||||
$have_non_network_plugins = false;
|
||||
|
||||
$plugin_info = array();
|
||||
$have_non_network_plugins = false;
|
||||
|
||||
foreach ( (array) $plugins as $plugin ) {
|
||||
$plugin_slug = dirname( $plugin );
|
||||
|
||||
@ -315,9 +332,11 @@ if ( $action ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
$plugins_to_delete = count( $plugin_info );
|
||||
|
||||
$plugins_to_delete = count( $plugin_info );
|
||||
|
||||
?>
|
||||
<?php if ( 1 == $plugins_to_delete ) : ?>
|
||||
<?php if ( 1 === $plugins_to_delete ) : ?>
|
||||
<h1><?php _e( 'Delete Plugin' ); ?></h1>
|
||||
<?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
|
||||
<div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
|
||||
@ -332,7 +351,9 @@ if ( $action ) {
|
||||
<?php endif; ?>
|
||||
<ul class="ul-disc">
|
||||
<?php
|
||||
|
||||
$data_to_delete = false;
|
||||
|
||||
foreach ( $plugin_info as $plugin ) {
|
||||
if ( $plugin['is_uninstallable'] ) {
|
||||
/* translators: 1: Plugin name, 2: Plugin author. */
|
||||
@ -343,36 +364,44 @@ if ( $action ) {
|
||||
echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
</ul>
|
||||
<p>
|
||||
<?php
|
||||
|
||||
if ( $data_to_delete ) {
|
||||
_e( 'Are you sure you want to delete these files and data?' );
|
||||
} else {
|
||||
_e( 'Are you sure you want to delete these files?' );
|
||||
}
|
||||
|
||||
?>
|
||||
</p>
|
||||
<form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
|
||||
<input type="hidden" name="verify-delete" value="1" />
|
||||
<input type="hidden" name="action" value="delete-selected" />
|
||||
<?php
|
||||
|
||||
foreach ( (array) $plugins as $plugin ) {
|
||||
echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
|
||||
}
|
||||
|
||||
?>
|
||||
<?php wp_nonce_field( 'bulk-plugins' ); ?>
|
||||
<?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
|
||||
</form>
|
||||
<?php
|
||||
|
||||
$referer = wp_get_referer();
|
||||
|
||||
?>
|
||||
<form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
|
||||
<?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
require_once ABSPATH . 'wp-admin/admin-footer.php';
|
||||
exit;
|
||||
} else {
|
||||
@ -385,15 +414,14 @@ if ( $action ) {
|
||||
set_transient( 'plugins_delete_result_' . $user_ID, $delete_result );
|
||||
wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
|
||||
exit;
|
||||
|
||||
case 'clear-recent-list':
|
||||
if ( ! is_network_admin() ) {
|
||||
update_option( 'recently_activated', array() );
|
||||
} else {
|
||||
update_site_option( 'recently_activated', array() );
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
case 'resume':
|
||||
if ( is_multisite() ) {
|
||||
return;
|
||||
@ -413,7 +441,78 @@ if ( $action ) {
|
||||
|
||||
wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
|
||||
exit;
|
||||
case 'enable-auto-update':
|
||||
case 'disable-auto-update':
|
||||
case 'enable-auto-update-selected':
|
||||
case 'disable-auto-update-selected':
|
||||
if ( ! current_user_can( 'update_plugins' ) || ! wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
|
||||
wp_die( __( 'Sorry, you are not allowed to manage plugins automatic updates.' ) );
|
||||
}
|
||||
|
||||
if ( is_multisite() && ! is_network_admin() ) {
|
||||
wp_die( __( 'Please connect to your network admin to manage plugins automatic updates.' ) );
|
||||
}
|
||||
|
||||
$redirect = self_admin_url( "plugins.php?plugin_status={$status}&paged={$page}&s={$s}" );
|
||||
|
||||
if ( 'enable-auto-update' === $action || 'disable-auto-update' === $action ) {
|
||||
if ( empty( $plugin ) ) {
|
||||
wp_redirect( $redirect );
|
||||
exit;
|
||||
}
|
||||
|
||||
check_admin_referer( 'updates' );
|
||||
} else {
|
||||
if ( empty( $_POST['checked'] ) ) {
|
||||
wp_redirect( $redirect );
|
||||
exit;
|
||||
}
|
||||
|
||||
check_admin_referer( 'bulk-plugins' );
|
||||
}
|
||||
|
||||
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
|
||||
|
||||
if ( 'enable-auto-update' === $action ) {
|
||||
$auto_updates[] = $plugin;
|
||||
$auto_updates = array_unique( $auto_updates );
|
||||
$redirect = add_query_arg( array( 'enabled-auto-update' => 'true' ), $redirect );
|
||||
} elseif ( 'disable-auto-update' === $action ) {
|
||||
$auto_updates = array_diff( $auto_updates, array( $plugin ) );
|
||||
$redirect = add_query_arg( array( 'disabled-auto-update' => 'true' ), $redirect );
|
||||
} else {
|
||||
$plugins = (array) wp_unslash( $_POST['checked'] );
|
||||
|
||||
if ( 'enable-auto-update-selected' === $action ) {
|
||||
$new_auto_updates = array_merge( $auto_updates, $plugins );
|
||||
$new_auto_updates = array_unique( $new_auto_updates );
|
||||
$query_args = array( 'enabled-auto-update-multi' => 'true' );
|
||||
} else {
|
||||
$new_auto_updates = array_diff( $auto_updates, $plugins );
|
||||
$query_args = array( 'disabled-auto-update-multi' => 'true' );
|
||||
}
|
||||
|
||||
// Return early if all selected plugins already have auto-updates enabled or disabled.
|
||||
// Must use non-strict comparison, so that array order is not treated as significant.
|
||||
if ( $new_auto_updates == $auto_updates ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
||||
wp_redirect( $redirect );
|
||||
exit;
|
||||
}
|
||||
|
||||
$auto_updates = $new_auto_updates;
|
||||
$redirect = add_query_arg( $query_args, $redirect );
|
||||
}
|
||||
|
||||
/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
|
||||
$all_items = apply_filters( 'all_plugins', get_plugins() );
|
||||
|
||||
// Remove plugins that don't exist or have been deleted since the option was last updated.
|
||||
$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
|
||||
|
||||
update_site_option( 'auto_update_plugins', $auto_updates );
|
||||
|
||||
wp_redirect( $redirect );
|
||||
exit;
|
||||
default:
|
||||
if ( isset( $_POST['checked'] ) ) {
|
||||
check_admin_referer( 'bulk-plugins' );
|
||||
@ -498,9 +597,7 @@ if ( ! empty( $invalid ) ) {
|
||||
echo '</p></div>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
if ( isset( $_GET['error'] ) ) :
|
||||
|
||||
if ( isset( $_GET['main'] ) ) {
|
||||
@ -521,9 +618,11 @@ if ( isset( $_GET['error'] ) ) :
|
||||
} else {
|
||||
$errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="message" class="error"><p><?php echo $errmsg; ?></p>
|
||||
<?php
|
||||
|
||||
if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
|
||||
$iframe_url = add_query_arg(
|
||||
array(
|
||||
@ -533,17 +632,19 @@ if ( isset( $_GET['error'] ) ) :
|
||||
),
|
||||
admin_url( 'plugins.php' )
|
||||
);
|
||||
|
||||
?>
|
||||
<iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
|
||||
<iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
elseif ( isset( $_GET['deleted'] ) ) :
|
||||
$delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
|
||||
// Delete it once we're done.
|
||||
delete_transient( 'plugins_delete_result_' . $user_ID );
|
||||
$delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
|
||||
// Delete it once we're done.
|
||||
delete_transient( 'plugins_delete_result_' . $user_ID );
|
||||
|
||||
if ( is_wp_error( $delete_result ) ) :
|
||||
?>
|
||||
@ -562,7 +663,7 @@ elseif ( isset( $_GET['deleted'] ) ) :
|
||||
<div id="message" class="updated notice is-dismissible">
|
||||
<p>
|
||||
<?php
|
||||
if ( 1 == (int) $_GET['deleted'] ) {
|
||||
if ( 1 === (int) $_GET['deleted'] ) {
|
||||
_e( 'The selected plugin has been deleted.' );
|
||||
} else {
|
||||
_e( 'The selected plugins have been deleted.' );
|
||||
@ -570,7 +671,7 @@ elseif ( isset( $_GET['deleted'] ) ) :
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php elseif ( isset( $_GET['activate'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin activated.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['activate-multi'] ) ) : ?>
|
||||
@ -583,6 +684,14 @@ elseif ( isset( $_GET['deleted'] ) ) :
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['resume'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin resumed.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['enabled-auto-update'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will be auto-updated.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['disabled-auto-update'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin will no longer be auto-updated.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['enabled-auto-update-multi'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will be auto-updated.' ); ?></p></div>
|
||||
<?php elseif ( isset( $_GET['disabled-auto-update-multi'] ) ) : ?>
|
||||
<div id="message" class="updated notice is-dismissible"><p><?php _e( 'Selected plugins will no longer be auto-updated.' ); ?></p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="wrap">
|
||||
|
@ -80,6 +80,45 @@ if ( current_user_can( 'switch_themes' ) && isset( $_GET['action'] ) ) {
|
||||
delete_theme( $_GET['stylesheet'] );
|
||||
wp_redirect( admin_url( 'themes.php?deleted=true' ) );
|
||||
}
|
||||
exit;
|
||||
} elseif ( 'enable-auto-update' === $_GET['action'] ) {
|
||||
if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
|
||||
wp_die( __( 'Sorry, you are not allowed to enable themes automatic updates.' ) );
|
||||
}
|
||||
|
||||
check_admin_referer( 'updates' );
|
||||
|
||||
$all_items = wp_get_themes();
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
|
||||
$auto_updates[] = $_GET['stylesheet'];
|
||||
$auto_updates = array_unique( $auto_updates );
|
||||
// Remove themes that have been deleted since the site option was last updated.
|
||||
$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
|
||||
|
||||
update_site_option( 'auto_update_themes', $auto_updates );
|
||||
|
||||
wp_redirect( admin_url( 'themes.php?enabled-auto-update=true' ) );
|
||||
|
||||
exit;
|
||||
} elseif ( 'disable-auto-update' === $_GET['action'] ) {
|
||||
if ( ! ( current_user_can( 'update_themes' ) && wp_is_auto_update_enabled_for_type( 'theme' ) ) ) {
|
||||
wp_die( __( 'Sorry, you are not allowed to disable themes automatic updates.' ) );
|
||||
}
|
||||
|
||||
check_admin_referer( 'updates' );
|
||||
|
||||
$all_items = wp_get_themes();
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
|
||||
$auto_updates = array_diff( $auto_updates, array( $_GET['stylesheet'] ) );
|
||||
// Remove themes that have been deleted since the site option was last updated.
|
||||
$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );
|
||||
|
||||
update_site_option( 'auto_update_themes', $auto_updates );
|
||||
|
||||
wp_redirect( admin_url( 'themes.php?disabled-auto-update=true' ) );
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@ -228,6 +267,14 @@ if ( ! validate_current_theme() || isset( $_GET['broken'] ) ) {
|
||||
?>
|
||||
<div id="message6" class="error"><p><?php _e( 'Theme could not be resumed because it triggered a <strong>fatal error</strong>.' ); ?></p></div>
|
||||
<?php
|
||||
} elseif ( isset( $_GET['enabled-auto-update'] ) ) {
|
||||
?>
|
||||
<div id="message7" class="updated notice is-dismissible"><p><?php _e( 'Theme will be auto-updated.' ); ?></p></div>
|
||||
<?php
|
||||
} elseif ( isset( $_GET['disabled-auto-update'] ) ) {
|
||||
?>
|
||||
<div id="message8" class="updated notice is-dismissible"><p><?php _e( 'Theme will no longer be auto-updated.' ); ?></p></div>
|
||||
<?php
|
||||
}
|
||||
|
||||
$ct = wp_get_theme();
|
||||
@ -581,6 +628,30 @@ if ( ! is_multisite() && $broken_themes ) {
|
||||
?>
|
||||
</p>
|
||||
|
||||
<# if ( data.actions.autoupdate ) { #>
|
||||
<p class="theme-autoupdate">
|
||||
<# if ( data.autoupdate ) { #>
|
||||
<a href="{{{ data.actions.autoupdate }}}" class="toggle-auto-update" data-slug="{{ data.id }}" data-wp-action="disable">
|
||||
<span class="dashicons dashicons-update spin hidden"></span>
|
||||
<span class="label"><?php _e( 'Disable auto-updates' ); ?></span>
|
||||
</a>
|
||||
<# } else { #>
|
||||
<a href="{{{ data.actions.autoupdate }}}" class="toggle-auto-update" data-slug="{{ data.id }}" data-wp-action="enable">
|
||||
<span class="dashicons dashicons-update spin hidden"></span>
|
||||
<span class="label"><?php _e( 'Enable auto-updates' ); ?></span>
|
||||
</a>
|
||||
<# } #>
|
||||
<# if ( data.hasUpdate ) { #>
|
||||
<# if ( data.autoupdate) { #>
|
||||
<span class="auto-update-time"><br /><?php echo wp_get_auto_update_message(); ?></span>
|
||||
<# } else { #>
|
||||
<span class="auto-update-time hidden"><br /><?php echo wp_get_auto_update_message(); ?></span>
|
||||
<# } #>
|
||||
<# } #>
|
||||
<span class="auto-updates-error hidden"><p></p></span>
|
||||
</p>
|
||||
<# } #>
|
||||
|
||||
<# if ( data.hasUpdate ) { #>
|
||||
<div class="notice notice-warning notice-alt notice-large">
|
||||
<h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
|
||||
|
@ -328,6 +328,13 @@ function list_plugin_updates() {
|
||||
|
||||
<tbody class="plugins">
|
||||
<?php
|
||||
|
||||
$auto_updates = array();
|
||||
if ( wp_is_auto_update_enabled_for_type( 'plugin' ) ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
|
||||
$auto_update_notice = ' | ' . wp_get_auto_update_message();
|
||||
}
|
||||
|
||||
foreach ( (array) $plugins as $plugin_file => $plugin_data ) {
|
||||
$plugin_data = (object) _get_plugin_data_markup_translate( $plugin_file, (array) $plugin_data, false, true );
|
||||
|
||||
@ -419,6 +426,9 @@ function list_plugin_updates() {
|
||||
$plugin_data->update->new_version
|
||||
);
|
||||
echo ' ' . $details . $compat . $upgrade_notice;
|
||||
if ( in_array( $plugin_file, $auto_updates, true ) ) {
|
||||
echo $auto_update_notice;
|
||||
}
|
||||
?>
|
||||
</p></td>
|
||||
</tr>
|
||||
@ -478,8 +488,15 @@ function list_theme_updates() {
|
||||
|
||||
<tbody class="plugins">
|
||||
<?php
|
||||
$auto_updates = array();
|
||||
if ( wp_is_auto_update_enabled_for_type( 'theme' ) ) {
|
||||
$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
|
||||
$auto_update_notice = ' | ' . wp_get_auto_update_message();
|
||||
}
|
||||
|
||||
foreach ( $themes as $stylesheet => $theme ) {
|
||||
$checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td class="check-column">
|
||||
@ -501,6 +518,9 @@ function list_theme_updates() {
|
||||
$theme->display( 'Version' ),
|
||||
$theme->update['new_version']
|
||||
);
|
||||
if ( in_array( $stylesheet, $auto_updates, true ) ) {
|
||||
echo $auto_update_notice;
|
||||
}
|
||||
?>
|
||||
</p></td>
|
||||
</tr>
|
||||
|
@ -1520,6 +1520,13 @@ function wp_default_scripts( $scripts ) {
|
||||
/* translators: %s: Number of plugins. */
|
||||
'pluginsFound' => __( 'Number of plugins found: %d' ),
|
||||
'noPluginsFound' => __( 'No plugins found. Try a different search.' ),
|
||||
'autoUpdatesEnable' => __( 'Enable auto-updates' ),
|
||||
'autoUpdatesEnabling' => __( 'Enabling...' ),
|
||||
'autoUpdatesEnabled' => __( 'Auto-updates enabled' ),
|
||||
'autoUpdatesDisable' => __( 'Disable auto-updates' ),
|
||||
'autoUpdatesDisabling' => __( 'Disabling...' ),
|
||||
'autoUpdatesDisabled' => __( 'Auto-updates disabled' ),
|
||||
'autoUpdatesError' => __( 'The request could not be completed.' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '5.5-alpha-47834';
|
||||
$wp_version = '5.5-alpha-47835';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
Loading…
Reference in New Issue
Block a user