wp/wp-admin/includes/class-wp-automatic-updater.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
--- a/wp/wp-admin/includes/class-wp-automatic-updater.php	Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-admin/includes/class-wp-automatic-updater.php	Wed Sep 21 18:19:35 2022 +0200
@@ -62,7 +62,7 @@
 	 * filesystem to the top of the drive, erring on the side of detecting a VCS
 	 * checkout somewhere.
 	 *
-	 * ABSPATH is always checked in addition to whatever $context is (which may be the
+	 * ABSPATH is always checked in addition to whatever `$context` is (which may be the
 	 * wp-content directory, for example). The underlying assumption is that if you are
 	 * using version control *anywhere*, then you should be making decisions for
 	 * how things get updated.
@@ -70,6 +70,8 @@
 	 * @since 3.7.0
 	 *
 	 * @param string $context The filesystem path to check, in addition to ABSPATH.
+	 * @return bool True if a VCS checkout was discovered at `$context` or ABSPATH,
+	 *              or anywhere higher. False otherwise.
 	 */
 	public function is_vcs_checkout( $context ) {
 		$context_dirs = array( untrailingslashit( $context ) );
@@ -112,7 +114,7 @@
 		 *
 		 * @since 3.7.0
 		 *
-		 * @param bool $checkout  Whether a VCS checkout was discovered at $context
+		 * @param bool $checkout  Whether a VCS checkout was discovered at `$context`
 		 *                        or ABSPATH, or anywhere higher.
 		 * @param string $context The filesystem context (a path) against which
 		 *                        filesystem status should be checked.
@@ -132,6 +134,7 @@
 	 * @param object $item    The update offer.
 	 * @param string $context The filesystem context (a path) against which filesystem
 	 *                        access and status should be checked.
+	 * @return bool True if the item should be updated, false otherwise.
 	 */
 	public function should_update( $type, $item, $context ) {
 		// Used to see if WP_Filesystem is set up to allow unattended updates.
@@ -148,7 +151,9 @@
 		}
 
 		// If we can't do an auto core update, we may still be able to email the user.
-		if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership ) || $this->is_vcs_checkout( $context ) ) {
+		if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership )
+			|| $this->is_vcs_checkout( $context )
+		) {
 			if ( 'core' === $type ) {
 				$this->send_core_update_notification_email( $item );
 			}
@@ -179,7 +184,9 @@
 		 * Filters whether to automatically update core, a plugin, a theme, or a language.
 		 *
 		 * The dynamic portion of the hook name, `$type`, refers to the type of update
-		 * being checked. Potential hook names include:
+		 * being checked.
+		 *
+		 * Possible hook names include:
 		 *
 		 *  - `auto_update_core`
 		 *  - `auto_update_plugin`
@@ -242,12 +249,17 @@
 	 * @since 3.7.0
 	 *
 	 * @param object $item The update offer.
+	 * @return bool True if the site administrator is notified of a core update,
+	 *              false otherwise.
 	 */
 	protected function send_core_update_notification_email( $item ) {
 		$notified = get_site_option( 'auto_core_update_notified' );
 
 		// Don't notify if we've already notified the same email address of the same version.
-		if ( $notified && get_site_option( 'admin_email' ) === $notified['email'] && $notified['version'] == $item->current ) {
+		if ( $notified
+			&& get_site_option( 'admin_email' ) === $notified['email']
+			&& $notified['version'] === $item->current
+		) {
 			return false;
 		}
 
@@ -343,6 +355,11 @@
 				$upgrader_item = $item->theme;
 				$theme         = wp_get_theme( $upgrader_item );
 				$item_name     = $theme->Get( 'Name' );
+				// Add the current version so that it can be reported in the notification email.
+				$item->current_version = $theme->get( 'Version' );
+				if ( empty( $item->current_version ) ) {
+					$item->current_version = false;
+				}
 				/* translators: %s: Theme name. */
 				$skin->feedback( __( 'Updating theme: %s' ), $item_name );
 				break;
@@ -350,6 +367,11 @@
 				$upgrader_item = $item->plugin;
 				$plugin_data   = get_plugin_data( $context . '/' . $upgrader_item );
 				$item_name     = $plugin_data['Name'];
+				// Add the current version so that it can be reported in the notification email.
+				$item->current_version = $plugin_data['Version'];
+				if ( empty( $item->current_version ) ) {
+					$item->current_version = false;
+				}
 				/* translators: %s: Plugin name. */
 				$skin->feedback( __( 'Updating plugin: %s' ), $item_name );
 				break;
@@ -607,9 +629,14 @@
 			$send = false;
 		}
 
-		$n = get_site_option( 'auto_core_update_notified' );
+		$notified = get_site_option( 'auto_core_update_notified' );
+
 		// Don't notify if we've already notified the same email address of the same version of the same notification type.
-		if ( $n && 'fail' === $n['type'] && get_site_option( 'admin_email' ) === $n['email'] && $n['version'] == $core_update->current ) {
+		if ( $notified
+			&& 'fail' === $notified['type']
+			&& get_site_option( 'admin_email' ) === $notified['email']
+			&& $notified['version'] === $core_update->current
+		) {
 			$send = false;
 		}
 
@@ -657,7 +684,13 @@
 			$next_user_core_update = $core_update;
 		}
 
-		$newer_version_available = ( 'upgrade' === $next_user_core_update->response && version_compare( $next_user_core_update->version, $core_update->version, '>' ) );
+		if ( 'upgrade' === $next_user_core_update->response
+			&& version_compare( $next_user_core_update->version, $core_update->version, '>' )
+		) {
+			$newer_version_available = true;
+		} else {
+			$newer_version_available = false;
+		}
 
 		/**
 		 * Filters whether to send an email following an automatic background core update.
@@ -887,44 +920,48 @@
 		$successful_updates = array();
 		$failed_updates     = array();
 
-		/**
-		 * Filters whether to send an email following an automatic background plugin update.
-		 *
-		 * @since 5.5.0
-		 * @since 5.5.1 Added the $update_results parameter.
-		 *
-		 * @param bool  $enabled        True if plugins notifications are enabled, false otherwise.
-		 * @param array $update_results The results of plugins update tasks.
-		 */
-		$notifications_enabled = apply_filters( 'auto_plugin_update_send_email', true, $update_results['plugin'] );
+		if ( ! empty( $update_results['plugin'] ) ) {
+			/**
+			 * Filters whether to send an email following an automatic background plugin update.
+			 *
+			 * @since 5.5.0
+			 * @since 5.5.1 Added the `$update_results` parameter.
+			 *
+			 * @param bool  $enabled        True if plugin update notifications are enabled, false otherwise.
+			 * @param array $update_results The results of plugins update tasks.
+			 */
+			$notifications_enabled = apply_filters( 'auto_plugin_update_send_email', true, $update_results['plugin'] );
 
-		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;
+			if ( $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
-		 * @since 5.5.1 Added the $update_results parameter.
-		 *
-		 * @param bool  $enabled True if notifications are enabled, false otherwise.
-		 * @param array $update_results The results of theme update tasks.
-		 */
-		$notifications_enabled = apply_filters( 'auto_theme_update_send_email', true, $update_results['theme'] );
+		if ( ! empty( $update_results['theme'] ) ) {
+			/**
+			 * Filters whether to send an email following an automatic background theme update.
+			 *
+			 * @since 5.5.0
+			 * @since 5.5.1 Added the `$update_results` parameter.
+			 *
+			 * @param bool  $enabled        True if theme update notifications are enabled, false otherwise.
+			 * @param array $update_results The results of theme update tasks.
+			 */
+			$notifications_enabled = apply_filters( 'auto_theme_update_send_email', true, $update_results['theme'] );
 
-		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 ( $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;
+					}
 				}
 			}
 		}
@@ -1061,12 +1098,22 @@
 				$body[] = __( 'These plugins failed to update:' );
 
 				foreach ( $failed_updates['plugin'] as $item ) {
-					$body[] = sprintf(
-						/* translators: 1: Plugin name, 2: Version number. */
-						__( '- %1$s version %2$s' ),
-						$item->name,
-						$item->item->new_version
-					);
+					if ( $item->item->current_version ) {
+						$body[] = sprintf(
+							/* translators: 1: Plugin name, 2: Current version number, 3: New version number. */
+							__( '- %1$s (from version %2$s to %3$s)' ),
+							$item->name,
+							$item->item->current_version,
+							$item->item->new_version
+						);
+					} else {
+						$body[] = sprintf(
+							/* translators: 1: Plugin name, 2: Version number. */
+							__( '- %1$s version %2$s' ),
+							$item->name,
+							$item->item->new_version
+						);
+					}
 
 					$past_failure_emails[ $item->item->plugin ] = $item->item->new_version;
 				}
@@ -1079,12 +1126,22 @@
 				$body[] = __( 'These themes failed to update:' );
 
 				foreach ( $failed_updates['theme'] as $item ) {
-					$body[] = sprintf(
-						/* translators: 1: Theme name, 2: Version number. */
-						__( '- %1$s version %2$s' ),
-						$item->name,
-						$item->item->new_version
-					);
+					if ( $item->item->current_version ) {
+						$body[] = sprintf(
+							/* translators: 1: Theme name, 2: Current version number, 3: New version number. */
+							__( '- %1$s (from version %2$s to %3$s)' ),
+							$item->name,
+							$item->item->current_version,
+							$item->item->new_version
+						);
+					} else {
+						$body[] = sprintf(
+							/* translators: 1: Theme name, 2: Version number. */
+							__( '- %1$s version %2$s' ),
+							$item->name,
+							$item->item->new_version
+						);
+					}
 
 					$past_failure_emails[ $item->item->theme ] = $item->item->new_version;
 				}
@@ -1102,12 +1159,22 @@
 				$body[] = __( 'These plugins are now up to date:' );
 
 				foreach ( $successful_updates['plugin'] as $item ) {
-					$body[] = sprintf(
-						/* translators: 1: Plugin name, 2: Version number. */
-						__( '- %1$s version %2$s' ),
-						$item->name,
-						$item->item->new_version
-					);
+					if ( $item->item->current_version ) {
+						$body[] = sprintf(
+							/* translators: 1: Plugin name, 2: Current version number, 3: New version number. */
+							__( '- %1$s (from version %2$s to %3$s)' ),
+							$item->name,
+							$item->item->current_version,
+							$item->item->new_version
+						);
+					} else {
+						$body[] = sprintf(
+							/* translators: 1: Plugin name, 2: Version number. */
+							__( '- %1$s version %2$s' ),
+							$item->name,
+							$item->item->new_version
+						);
+					}
 
 					unset( $past_failure_emails[ $item->item->plugin ] );
 				}
@@ -1120,12 +1187,22 @@
 				$body[] = __( 'These themes are now up to date:' );
 
 				foreach ( $successful_updates['theme'] as $item ) {
-					$body[] = sprintf(
-						/* translators: 1: Theme name, 2: Version number. */
-						__( '- %1$s version %2$s' ),
-						$item->name,
-						$item->item->new_version
-					);
+					if ( $item->item->current_version ) {
+						$body[] = sprintf(
+							/* translators: 1: Theme name, 2: Current version number, 3: New version number. */
+							__( '- %1$s (from version %2$s to %3$s)' ),
+							$item->name,
+							$item->item->current_version,
+							$item->item->new_version
+						);
+					} else {
+						$body[] = sprintf(
+							/* translators: 1: Theme name, 2: Version number. */
+							__( '- %1$s version %2$s' ),
+							$item->name,
+							$item->item->new_version
+						);
+					}
 
 					unset( $past_failure_emails[ $item->item->theme ] );
 				}
@@ -1211,6 +1288,7 @@
 		// Core.
 		if ( isset( $this->update_results['core'] ) ) {
 			$result = $this->update_results['core'][0];
+
 			if ( $result->result && ! is_wp_error( $result->result ) ) {
 				/* translators: %s: WordPress version. */
 				$body[] = sprintf( __( 'SUCCESS: WordPress was successfully updated to %s' ), $result->name );
@@ -1219,6 +1297,7 @@
 				$body[] = sprintf( __( 'FAILED: WordPress failed to update to %s' ), $result->name );
 				$failures++;
 			}
+
 			$body[] = '';
 		}
 
@@ -1227,7 +1306,9 @@
 			if ( ! isset( $this->update_results[ $type ] ) ) {
 				continue;
 			}
+
 			$success_items = wp_list_filter( $this->update_results[ $type ], array( 'result' => true ) );
+
 			if ( $success_items ) {
 				$messages = array(
 					'plugin'      => __( 'The following plugins were successfully updated:' ),
@@ -1241,7 +1322,8 @@
 					$body[] = ' * ' . sprintf( __( 'SUCCESS: %s' ), $name );
 				}
 			}
-			if ( $success_items != $this->update_results[ $type ] ) {
+
+			if ( $success_items !== $this->update_results[ $type ] ) {
 				// Failed updates.
 				$messages = array(
 					'plugin'      => __( 'The following plugins failed to update:' ),
@@ -1250,6 +1332,7 @@
 				);
 
 				$body[] = $messages[ $type ];
+
 				foreach ( $this->update_results[ $type ] as $item ) {
 					if ( ! $item->result || is_wp_error( $item->result ) ) {
 						/* translators: %s: Name of plugin / theme / translation. */
@@ -1258,10 +1341,12 @@
 					}
 				}
 			}
+
 			$body[] = '';
 		}
 
 		$site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
+
 		if ( $failures ) {
 			$body[] = trim(
 				__(
@@ -1298,18 +1383,23 @@
 			if ( ! isset( $this->update_results[ $type ] ) ) {
 				continue;
 			}
+
 			foreach ( $this->update_results[ $type ] as $update ) {
 				$body[] = $update->name;
 				$body[] = str_repeat( '-', strlen( $update->name ) );
+
 				foreach ( $update->messages as $message ) {
 					$body[] = '  ' . html_entity_decode( str_replace( '…', '...', $message ) );
 				}
+
 				if ( is_wp_error( $update->result ) ) {
 					$results = array( 'update' => $update->result );
+
 					// If we rolled back, we want to know an error that occurred then too.
 					if ( 'rollback_was_required' === $update->result->get_error_code() ) {
 						$results = (array) $update->result->get_error_data();
 					}
+
 					foreach ( $results as $result_type => $result ) {
 						if ( ! is_wp_error( $result ) ) {
 							continue;
@@ -1328,6 +1418,7 @@
 						}
 					}
 				}
+
 				$body[] = '';
 			}
 		}