<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[47835] trunk/src: Security: Add user interface to auto-update themes and plugins.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/47835">47835</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/47835","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>whyisjake</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2020-05-20 18:47:24 +0000 (Wed, 20 May 2020)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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: <a href="https://core.trac.wordpress.org/ticket/50052">#50052</a>.
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.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcjs_enqueueswpupdatesjs">trunk/src/js/_enqueues/wp/updates.js</a></li>
<li><a href="#trunksrcwpadminadminajaxphp">trunk/src/wp-admin/admin-ajax.php</a></li>
<li><a href="#trunksrcwpadmincsscommoncss">trunk/src/wp-admin/css/common.css</a></li>
<li><a href="#trunksrcwpadmincsslisttablescss">trunk/src/wp-admin/css/list-tables.css</a></li>
<li><a href="#trunksrcwpadmincssthemescss">trunk/src/wp-admin/css/themes.css</a></li>
<li><a href="#trunksrcwpadminincludesajaxactionsphp">trunk/src/wp-admin/includes/ajax-actions.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpautomaticupdaterphp">trunk/src/wp-admin/includes/class-wp-automatic-updater.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpdebugdataphp">trunk/src/wp-admin/includes/class-wp-debug-data.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpmsthemeslisttablephp">trunk/src/wp-admin/includes/class-wp-ms-themes-list-table.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswppluginslisttablephp">trunk/src/wp-admin/includes/class-wp-plugins-list-table.php</a></li>
<li><a href="#trunksrcwpadminincludesthemephp">trunk/src/wp-admin/includes/theme.php</a></li>
<li><a href="#trunksrcwpadminincludesupdatephp">trunk/src/wp-admin/includes/update.php</a></li>
<li><a href="#trunksrcwpadminnetworkthemesphp">trunk/src/wp-admin/network/themes.php</a></li>
<li><a href="#trunksrcwpadminpluginsphp">trunk/src/wp-admin/plugins.php</a></li>
<li><a href="#trunksrcwpadminthemesphp">trunk/src/wp-admin/themes.php</a></li>
<li><a href="#trunksrcwpadminupdatecorephp">trunk/src/wp-admin/update-core.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcjs_enqueueswpupdatesjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/js/_enqueues/wp/updates.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/js/_enqueues/wp/updates.js 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/js/_enqueues/wp/updates.js 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -409,6 +409,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.2.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.6.0 More accurately named `updatePluginSuccess`.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.5.0 Auto-update "time to next update" text cleared.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param {object} response Response from the server.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param {string} response.slug Slug of the plugin to be updated.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -431,6 +432,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Update the version number in the row.
</span><span class="cx" style="display: block; padding: 0 10px"> newText = $pluginRow.find( '.plugin-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
</span><span class="cx" style="display: block; padding: 0 10px"> $pluginRow.find( '.plugin-version-author-uri' ).html( newText );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // Clear the "time to next auto-update" text.
+ $pluginRow.find( '.auto-update-time' ).empty();
</ins><span class="cx" style="display: block; padding: 0 10px"> } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' )
</span><span class="cx" style="display: block; padding: 0 10px"> .removeClass( 'updating-message' )
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -969,6 +973,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Updates the UI appropriately after a successful theme update.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.6.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.5.0 Auto-update "time to next update" text cleared.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param {object} response
</span><span class="cx" style="display: block; padding: 0 10px"> * @param {string} response.slug Slug of the theme to be updated.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1002,6 +1007,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Update the version number in the row.
</span><span class="cx" style="display: block; padding: 0 10px"> newText = $theme.find( '.theme-version-author-uri' ).html().replace( response.oldVersion, response.newVersion );
</span><span class="cx" style="display: block; padding: 0 10px"> $theme.find( '.theme-version-author-uri' ).html( newText );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ // Clear the "time to next auto-update" text.
+ $theme.find( '.auto-update-time' ).empty();
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $notice = $( '.theme-info .notice' ).add( $theme.find( '.update-message' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1008,6 +1016,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Focus on Customize button after updating.
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isModalOpen ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $( '.load-customize:visible' ).focus();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $( '.theme-info .theme-autoupdate' ).find( '.auto-update-time' ).empty();
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme.find( '.load-customize' ).focus();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2461,5 +2470,144 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.2.0
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> $( window ).on( 'beforeunload', wp.updates.beforeunload );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * 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' );
+ } );
+ }
+ );
</ins><span class="cx" style="display: block; padding: 0 10px"> } );
</span><span class="cx" style="display: block; padding: 0 10px"> })( jQuery, window.wp, window._wpUpdatesSettings );
</span></span></pre></div>
<a id="trunksrcwpadminadminajaxphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/admin-ajax.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/admin-ajax.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/admin-ajax.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -139,6 +139,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'health-check-background-updates',
</span><span class="cx" style="display: block; padding: 0 10px"> 'health-check-loopback-requests',
</span><span class="cx" style="display: block; padding: 0 10px"> 'health-check-get-sizes',
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'toggle-auto-updates',
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Deprecated.
</span></span></pre></div>
<a id="trunksrcwpadmincsscommoncss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/common.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/common.css 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/css/common.css 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1524,7 +1524,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> .updating-message p:before,
</span><span class="cx" style="display: block; padding: 0 10px"> .import-php .updating-message:before,
</span><span class="cx" style="display: block; padding: 0 10px"> .button.updating-message:before,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.button.installing:before {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.button.installing:before,
+.plugins .column-auto-updates .dashicons-update.spin,
+.theme-overlay .theme-autoupdate .dashicons-update.spin {
</ins><span class="cx" style="display: block; padding: 0 10px"> animation: rotation 2s infinite linear;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpadmincsslisttablescss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/list-tables.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/list-tables.css 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/css/list-tables.css 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1236,6 +1236,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> width: 85px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.plugins .column-auto-updates {
+ width: 14.2em;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> .plugins .inactive .plugin-title strong {
</span><span class="cx" style="display: block; padding: 0 10px"> font-weight: 400;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpadmincssthemescss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/themes.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/themes.css 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/css/themes.css 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -679,7 +679,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> line-height: inherit;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.theme-overlay .theme-author a {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.theme-overlay .theme-author a,
+.theme-overlay .theme-autoupdate a {
</ins><span class="cx" style="display: block; padding: 0 10px"> text-decoration: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpadminincludesajaxactionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/ajax-actions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/ajax-actions.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/ajax-actions.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4567,6 +4567,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_ajax_search_plugins() {
</span><span class="cx" style="display: block; padding: 0 10px"> check_ajax_referer( 'updates' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Ensure after_plugin_row_{$plugin_file} gets hooked.
+ wp_plugin_update_rows();
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'plugins-network' === $pagenow || 'plugins' === $pagenow ) {
</span><span class="cx" style="display: block; padding: 0 10px"> set_current_screen( $pagenow );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5267,3 +5270,73 @@
</span><span class="cx" style="display: block; padding: 0 10px"> function wp_ajax_rest_nonce() {
</span><span class="cx" style="display: block; padding: 0 10px"> exit( wp_create_nonce( 'wp_rest' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * 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();
+}
</ins></span></pre></div>
<a id="trunksrcwpadminincludesclasswpautomaticupdaterphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-automatic-updater.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-automatic-updater.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/class-wp-automatic-updater.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -158,6 +158,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Next up, is this an item we can update?
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'core' === $type ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $update = Core_Upgrader::should_update_to_version( $item->current );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } 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 );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $update = ! empty( $item->autoupdate );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -501,6 +509,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! empty( $this->update_results['core'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->after_core_update( $this->update_results['core'][0] );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } elseif ( ! empty( $this->update_results['plugin'] ) || ! empty( $this->update_results['theme'] ) ) {
+ $this->after_plugin_theme_update( $this->update_results );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -854,7 +864,187 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 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'] );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 3.7.0
</span></span></pre></div>
<a id="trunksrcwpadminincludesclasswpdebugdataphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-debug-data.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-debug-data.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/class-wp-debug-data.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -858,7 +858,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // List all available plugins.
</span><span class="cx" style="display: block; padding: 0 10px"> $plugins = get_plugins();
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_updates = get_plugin_updates();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $auto_updates = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $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() );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $plugins as $plugin_path => $plugin ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -892,6 +901,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_version_string_debug .= sprintf( ' (latest version: %s)', $plugin_updates[ $plugin_path ]->update->new_version );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $info[ $plugin_part ]['fields'][ sanitize_text_field( $plugin['Name'] ) ] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'label' => $plugin['Name'],
</span><span class="cx" style="display: block; padding: 0 10px"> 'value' => $plugin_version_string,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -915,6 +934,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $active_theme_version = $active_theme->version;
</span><span class="cx" style="display: block; padding: 0 10px"> $active_theme_version_debug = $active_theme_version;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $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() );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_update_new_version = $theme_updates[ $active_theme->stylesheet ]->update['new_version'];
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -980,7 +1005,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'value' => get_stylesheet_directory(),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $auto_updates_enabled ) {
+ if ( in_array( $active_theme->stylesheet, $auto_updates ) ) {
+ $theme_auto_update_string = __( 'Enabled' );
+ } else {
+ $theme_auto_update_string = __( 'Disabled' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $info['wp-active-theme']['fields']['auto_update'] = array(
+ 'label' => __( 'Auto-update' ),
+ 'value' => $theme_auto_update_string,
+ 'debug' => $theme_auto_update_string,
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $parent_theme = $active_theme->parent();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $parent_theme ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1026,6 +1063,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'value' => get_template_directory(),
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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,
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Populate a list of all themes available in the install.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1075,6 +1125,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $theme_version_string_debug .= sprintf( ' (latest version: %s)', $theme_updates[ $theme_slug ]->update['new_version'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $info['wp-themes-inactive']['fields'][ sanitize_text_field( $theme->name ) ] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'label' => sprintf(
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: 1: Theme name. 2: Theme slug. */
</span></span></pre></div>
<a id="trunksrcwpadminincludesclasswpmsthemeslisttablephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-ms-themes-list-table.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-ms-themes-list-table.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/class-wp-ms-themes-list-table.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,6 +23,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> private $has_items;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 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;
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Constructor.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 3.1.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45,7 +54,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ), true ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $status = 'all';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,6 +65,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $this->is_site_themes ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) &&
+ ! $this->is_site_themes && current_user_can( 'update_themes' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -107,6 +119,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $this->show_autoupdates ) {
+ $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
+
+ $themes['auto-update-enabled'] = array();
+ $themes['auto-update-disabled'] = array();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( $this->is_site_themes ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
</span><span class="cx" style="display: block; padding: 0 10px"> $allowed_where = 'site';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -131,6 +150,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
</span><span class="cx" style="display: block; padding: 0 10px"> $themes[ $filter ][ $key ] = $themes['all'][ $key ];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ 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 ];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $s ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -257,11 +284,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_columns() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $columns = array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'cb' => '<input type="checkbox" />',
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => __( 'Theme' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'description' => __( 'Description' ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ if ( $this->show_autoupdates ) {
+ $columns['auto-updates'] = __( 'Automatic Updates' );
+ }
+
+ return $columns;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -344,6 +377,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'themes'
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $this->is_site_themes ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -388,6 +437,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $actions['delete-selected'] = __( 'Delete' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ 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' );
+ }
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> return $actions;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -640,6 +700,70 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 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>';
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Handles default column output.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.3.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -721,6 +845,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> echo '</td>';
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ case 'auto-updates':
+ echo "<td class='column-auto-updates{$extra_classes}'>";
+
+ $this->column_autoupdates( $item );
+
+ echo '</td>';
+ break;
</ins><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> echo "<td class='$column_name column-$column_name{$extra_classes}'>";
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpadminincludesclasswppluginslisttablephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-plugins-list-table.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-plugins-list-table.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/class-wp-plugins-list-table.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16,6 +16,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @see WP_List_Table
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_Plugins_List_Table extends WP_List_Table {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * 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;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Constructor.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -39,7 +47,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $status_whitelist = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $status = 'all';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], $status_whitelist, true ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -51,6 +59,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $page = $this->get_pagenum();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' ) &&
+ current_user_can( 'update_plugins' ) &&
+ ( ! is_multisite() || $this->screen->in_admin( 'network' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -103,7 +115,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'dropins' => array(),
</span><span class="cx" style="display: block; padding: 0 10px"> 'paused' => array(),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $this->show_autoupdates ) {
+ $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $plugins['auto-update-enabled'] = array();
+ $plugins['auto-update-disabled'] = array();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $screen = $this->screen;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -233,6 +251,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Populate the inactive list with plugins that aren't activated.
</span><span class="cx" style="display: block; padding: 0 10px"> $plugins['inactive'][ $plugin_file ] = $plugin_data;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ 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 ];
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( strlen( $s ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -399,11 +425,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_columns() {
</span><span class="cx" style="display: block; padding: 0 10px"> global $status;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- return array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $columns = array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'cb' => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '',
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => __( 'Plugin' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'description' => __( 'Description' ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ if ( $this->show_autoupdates ) {
+ $columns['auto-updates'] = __( 'Automatic Updates' );
+ }
+
+ return $columns;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -493,6 +525,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $count
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( 'search' !== $type ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -533,6 +581,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $actions['delete-selected'] = __( 'Delete' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ 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' );
+ }
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> return $actions;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -882,6 +939,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
+ $available_updates = get_site_transient( 'update_plugins' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $columns as $column_name => $column_display_name ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $extra_classes = '';
</span><span class="cx" style="display: block; padding: 0 10px"> if ( in_array( $column_name, $hidden, true ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -974,6 +1034,56 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> echo '</td>';
</span><span class="cx" style="display: block; padding: 0 10px"> break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> $classes = "$column_name column-$column_name $class";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1000,12 +1110,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Fires after each row in the Plugins list table.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.3.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $plugin_file Path to the plugin file relative to the plugins directory.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $plugin_data An array of plugin data.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $status Status of the plugin. Defaults are 'All', 'Active',
</span><span class="cx" style="display: block; padding: 0 10px"> * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * 'Drop-ins', 'Search', 'Paused'.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
+ * 'Auto-updates Disabled'.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1016,12 +1128,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * to the plugin file, relative to the plugins directory.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.7.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.5.0 Added 'Auto-updates Enabled' and 'Auto-updates Disabled' `$status`.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $plugin_file Path to the plugin file relative to the plugins directory.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param array $plugin_data An array of plugin data.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $status Status of the plugin. Defaults are 'All', 'Active',
</span><span class="cx" style="display: block; padding: 0 10px"> * 'Inactive', 'Recently Activated', 'Upgrade', 'Must-Use',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * 'Drop-ins', 'Search', 'Paused'.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 'Drop-ins', 'Search', 'Paused', 'Auto-updates Enabled',
+ * 'Auto-updates Disabled'.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpadminincludesthemephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/theme.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/theme.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/theme.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -660,6 +660,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $parents = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $themes as $theme ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $slug = $theme->get_stylesheet();
</span><span class="cx" style="display: block; padding: 0 10px"> $encoded_slug = urlencode( $slug );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -683,6 +685,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $auto_update = in_array( $slug, $auto_updates, true );
+ $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $prepared_themes[ $slug ] = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'id' => $slug,
</span><span class="cx" style="display: block; padding: 0 10px"> 'name' => $theme->display( 'Name' ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -699,10 +704,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'hasUpdate' => isset( $updates[ $slug ] ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'update' => get_theme_update_available( $theme ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'autoupdate' => $auto_update,
</ins><span class="cx" style="display: block; padding: 0 10px"> 'actions' => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- '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,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ '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,
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpadminincludesupdatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/update.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/update.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/includes/update.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -435,7 +435,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '§ion=changelog&TB_iframe=true&width=600&height=800' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /** @var WP_Plugins_List_Table $wp_list_table */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_list_table = _get_list_table(
+ 'WP_Plugins_List_Table',
+ array(
+ 'screen' => get_current_screen(),
+ )
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_network_admin() || ! is_multisite() ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_network_admin() ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -933,3 +938,76 @@
</span><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * 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
+ );
+ }
+}
</ins></span></pre></div>
<a id="trunksrcwpadminnetworkthemesphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/network/themes.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/network/themes.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/network/themes.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,7 +22,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $s = isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : '';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$temp_args = array( 'enabled', 'disabled', 'deleted', 'error' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$temp_args = array(
+ 'enabled',
+ 'disabled',
+ 'deleted',
+ 'error',
+ 'enabled-auto-update',
+ 'disabled-auto-update',
+);
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $_SERVER['REQUEST_URI'] = remove_query_arg( $temp_args, $_SERVER['REQUEST_URI'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $referer = remove_query_arg( $temp_args, wp_get_referer() );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -123,8 +131,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> require_once ABSPATH . 'wp-admin/admin-header.php';
</span><span class="cx" style="display: block; padding: 0 10px"> $themes_to_delete = count( $themes );
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <div class="wrap">
- <?php if ( 1 == $themes_to_delete ) : ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <div class="wrap">
+ <?php if ( 1 === $themes_to_delete ) : ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <h1><?php _e( 'Delete Theme' ); ?></h1>
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This theme may be active on other sites in the network.' ); ?></p></div>
</span><span class="cx" style="display: block; padding: 0 10px"> <p><?php _e( 'You are about to remove the following theme:' ); ?></p>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,7 +153,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </ul>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php if ( 1 == $themes_to_delete ) : ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <?php if ( 1 === $themes_to_delete ) : ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <p><?php _e( 'Are you sure you want to delete this theme?' ); ?></p>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php else : ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <p><?php _e( 'Are you sure you want to delete these themes?' ); ?></p>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -154,27 +162,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="verify-delete" value="1" />
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="action" value="delete-selected" />
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( (array) $themes as $theme ) {
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<input type="hidden" name="checked[]" value="' . esc_attr( $theme ) . '" />';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_nonce_field( 'bulk-themes' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_nonce_field( 'bulk-themes' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 1 == $themes_to_delete ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 1 === $themes_to_delete ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> submit_button( __( 'Yes, delete this theme' ), '', 'submit', false );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> submit_button( __( 'Yes, delete these themes' ), '', 'submit', false );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </form>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php
- $referer = wp_get_referer();
- ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <?php $referer = wp_get_referer(); ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php submit_button( __( 'No, return me to the theme list' ), '', 'submit', false ); ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </form>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- </div>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> require_once ABSPATH . 'wp-admin/admin-footer.php';
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><span class="cx" style="display: block; padding: 0 10px"> } // End if verify-delete.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -208,6 +217,58 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> $themes = isset( $_POST['checked'] ) ? (array) $_POST['checked'] : array();
</span><span class="cx" style="display: block; padding: 0 10px"> if ( empty( $themes ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -284,7 +345,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $_GET['enabled'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $enabled = absint( $_GET['enabled'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 1 == $enabled ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 1 === $enabled ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $message = __( 'Theme enabled.' );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: %s: Number of themes. */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -293,7 +354,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $enabled ) ) . '</p></div>';
</span><span class="cx" style="display: block; padding: 0 10px"> } elseif ( isset( $_GET['disabled'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $disabled = absint( $_GET['disabled'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 1 == $disabled ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 1 === $disabled ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $message = __( 'Theme disabled.' );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: %s: Number of themes. */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -302,7 +363,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $disabled ) ) . '</p></div>';
</span><span class="cx" style="display: block; padding: 0 10px"> } elseif ( isset( $_GET['deleted'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $deleted = absint( $_GET['deleted'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 1 == $deleted ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 1 === $deleted ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $message = __( 'Theme deleted.' );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: %s: Number of themes. */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -309,9 +370,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $message = _n( '%s theme deleted.', '%s themes deleted.', $deleted );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<div id="message" class="updated notice is-dismissible"><p>' . sprintf( $message, number_format_i18n( $deleted ) ) . '</p></div>';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-} elseif ( isset( $_GET['error'] ) && 'none' == $_GET['error'] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+} 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'] ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> echo '<div id="message" class="error notice is-dismissible"><p>' . __( 'No theme selected.' ) . '</p></div>';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-} elseif ( isset( $_GET['error'] ) && 'main' == $_GET['error'] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+} elseif ( isset( $_GET['error'] ) && 'main' === $_GET['error'] ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> echo '<div class="error notice is-dismissible"><p>' . __( 'You cannot delete a theme while it is active on the main site.' ) . '</p></div>';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -324,7 +403,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_list_table->views();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-if ( 'broken' == $status ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+if ( 'broken' === $status ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> echo '<p class="clear">' . __( 'The following themes are installed but incomplete.' ) . '</p>';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span></span></pre></div>
<a id="trunksrcwpadminpluginsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/plugins.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/plugins.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/plugins.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -22,8 +22,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $s = isset( $_REQUEST['s'] ) ? urlencode( wp_unslash( $_REQUEST['s'] ) ) : '';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$_SERVER['REQUEST_URI'] = remove_query_arg( array( 'error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce' ), $_SERVER['REQUEST_URI'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$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',
+);
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQUEST_URI'] );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'updates' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $action ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -284,11 +298,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! isset( $_REQUEST['verify-delete'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'jquery' );
</span><span class="cx" style="display: block; padding: 0 10px"> require_once ABSPATH . 'wp-admin/admin-header.php';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <div class="wrap">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <div class="wrap">
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $plugin_info = array();
- $have_non_network_plugins = false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $plugin_info = array();
+ $have_non_network_plugins = false;
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( (array) $plugins as $plugin ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_slug = dirname( $plugin );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -315,9 +332,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $plugins_to_delete = count( $plugin_info );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $plugins_to_delete = count( $plugin_info );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php if ( 1 == $plugins_to_delete ) : ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <?php if ( 1 === $plugins_to_delete ) : ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <h1><?php _e( 'Delete Plugin' ); ?></h1>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php if ( $have_non_network_plugins && is_network_admin() ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="error"><p><strong><?php _e( 'Caution:' ); ?></strong> <?php _e( 'This plugin may be active on other sites in the network.' ); ?></p></div>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -332,7 +351,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php endif; ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <ul class="ul-disc">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> $data_to_delete = false;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $plugin_info as $plugin ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $plugin['is_uninstallable'] ) {
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: 1: Plugin name, 2: Plugin author. */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -343,15 +364,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<li>', sprintf( _x( '%1$s by %2$s', 'plugin' ), '<strong>' . $plugin['Name'] . '</strong>', '<em>' . $plugin['AuthorName'] ) . '</em>', '</li>';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </ul>
</span><span class="cx" style="display: block; padding: 0 10px"> <p>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( $data_to_delete ) {
</span><span class="cx" style="display: block; padding: 0 10px"> _e( 'Are you sure you want to delete these files and data?' );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> _e( 'Are you sure you want to delete these files?' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </p>
</span><span class="cx" style="display: block; padding: 0 10px"> <form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -358,21 +382,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="verify-delete" value="1" />
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="action" value="delete-selected" />
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( (array) $plugins as $plugin ) {
</span><span class="cx" style="display: block; padding: 0 10px"> echo '<input type="hidden" name="checked[]" value="' . esc_attr( $plugin ) . '" />';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php wp_nonce_field( 'bulk-plugins' ); ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php submit_button( $data_to_delete ? __( 'Yes, delete these files and data' ) : __( 'Yes, delete these files' ), '', 'submit', false ); ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </form>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> $referer = wp_get_referer();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <form method="post" action="<?php echo $referer ? esc_url( $referer ) : ''; ?>" style="display:inline;">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php submit_button( __( 'No, return me to the plugin list' ), '', 'submit', false ); ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </form>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- </div>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ </div>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> require_once ABSPATH . 'wp-admin/admin-footer.php';
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -385,7 +414,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> set_transient( 'plugins_delete_result_' . $user_ID, $delete_result );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_redirect( self_admin_url( "plugins.php?deleted=$plugins_to_delete&plugin_status=$status&paged=$page&s=$s" ) );
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> case 'clear-recent-list':
</span><span class="cx" style="display: block; padding: 0 10px"> if ( ! is_network_admin() ) {
</span><span class="cx" style="display: block; padding: 0 10px"> update_option( 'recently_activated', array() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -392,8 +420,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> update_site_option( 'recently_activated', array() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> break;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> case 'resume':
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_multisite() ) {
</span><span class="cx" style="display: block; padding: 0 10px"> return;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -413,7 +441,78 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_redirect( self_admin_url( "plugins.php?resume=true&plugin_status=$status&paged=$page&s=$s" ) );
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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.' ) );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $_POST['checked'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> check_admin_referer( 'bulk-plugins' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -498,9 +597,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> echo '</p></div>';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-?>
</del><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php
</del><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $_GET['error'] ) ) :
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $_GET['main'] ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -521,9 +618,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $errmsg = __( 'Plugin could not be activated because it triggered a <strong>fatal error</strong>.' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message" class="error"><p><?php echo $errmsg; ?></p>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( ! isset( $_GET['main'] ) && ! isset( $_GET['charsout'] ) && wp_verify_nonce( $_GET['_error_nonce'], 'plugin-activation-error_' . $plugin ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $iframe_url = add_query_arg(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -533,17 +632,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> admin_url( 'plugins.php' )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <iframe style="border:0" width="100%" height="70px" src="<?php echo esc_url( $iframe_url ); ?>"></iframe>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> elseif ( isset( $_GET['deleted'] ) ) :
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
- // Delete it once we're done.
- delete_transient( 'plugins_delete_result_' . $user_ID );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $delete_result = get_transient( 'plugins_delete_result_' . $user_ID );
+ // Delete it once we're done.
+ delete_transient( 'plugins_delete_result_' . $user_ID );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_wp_error( $delete_result ) ) :
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -562,7 +663,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message" class="updated notice is-dismissible">
</span><span class="cx" style="display: block; padding: 0 10px"> <p>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( 1 == (int) $_GET['deleted'] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 1 === (int) $_GET['deleted'] ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> _e( 'The selected plugin has been deleted.' );
</span><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> _e( 'The selected plugins have been deleted.' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -570,7 +671,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </p>
</span><span class="cx" style="display: block; padding: 0 10px"> </div>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- <?php endif; ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <?php endif; ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php elseif ( isset( $_GET['activate'] ) ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin activated.' ); ?></p></div>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php elseif ( isset( $_GET['activate-multi'] ) ) : ?>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -583,6 +684,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message" class="updated notice is-dismissible"><p><?php _e( 'All selected plugins are up to date.' ); ?></p></div>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php elseif ( isset( $_GET['resume'] ) ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message" class="updated notice is-dismissible"><p><?php _e( 'Plugin resumed.' ); ?></p></div>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?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>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php endif; ?>
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="wrap">
</span></span></pre></div>
<a id="trunksrcwpadminthemesphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/themes.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/themes.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/themes.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,6 +81,45 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_redirect( admin_url( 'themes.php?deleted=true' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> exit;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } 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;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -228,6 +267,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div id="message6" class="error"><p><?php _e( 'Theme could not be resumed because it triggered a <strong>fatal error</strong>.' ); ?></p></div>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+} 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
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $ct = wp_get_theme();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -581,7 +628,31 @@
</span><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </p>
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <# 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>
+ <# } #>
</ins><span class="cx" style="display: block; padding: 0 10px"> <# if ( data.hasUpdate ) { #>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <# 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 ) { #>
</ins><span class="cx" style="display: block; padding: 0 10px"> <div class="notice notice-warning notice-alt notice-large">
</span><span class="cx" style="display: block; padding: 0 10px"> <h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
</span><span class="cx" style="display: block; padding: 0 10px"> {{{ data.update }}}
</span></span></pre></div>
<a id="trunksrcwpadminupdatecorephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/update-core.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/update-core.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-admin/update-core.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -328,6 +328,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <tbody class="plugins">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $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();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( (array) $plugins as $plugin_file => $plugin_data ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_data = (object) _get_plugin_data_markup_translate( $plugin_file, (array) $plugin_data, false, true );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -419,6 +426,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $plugin_data->update->new_version
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> echo ' ' . $details . $compat . $upgrade_notice;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( in_array( $plugin_file, $auto_updates, true ) ) {
+ echo $auto_update_notice;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </p></td>
</span><span class="cx" style="display: block; padding: 0 10px"> </tr>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -478,8 +488,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <tbody class="plugins">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $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();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $themes as $stylesheet => $theme ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <tr>
</span><span class="cx" style="display: block; padding: 0 10px"> <td class="check-column">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -501,6 +518,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $theme->display( 'Version' ),
</span><span class="cx" style="display: block; padding: 0 10px"> $theme->update['new_version']
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( in_array( $stylesheet, $auto_updates, true ) ) {
+ echo $auto_update_notice;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </p></td>
</span><span class="cx" style="display: block; padding: 0 10px"> </tr>
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php 2020-05-20 13:31:32 UTC (rev 47834)
+++ trunk/src/wp-includes/script-loader.php 2020-05-20 18:47:24 UTC (rev 47835)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1520,6 +1520,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /* translators: %s: Number of plugins. */
</span><span class="cx" style="display: block; padding: 0 10px"> 'pluginsFound' => __( 'Number of plugins found: %d' ),
</span><span class="cx" style="display: block; padding: 0 10px"> 'noPluginsFound' => __( 'No plugins found. Try a different search.' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ '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.' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span></span></pre>
</div>
</div>
</body>
</html>