WP_Automatic_Updater::send_plugin_theme_email()protectedWP 5.5.0

Sends an email upon the completion or failure of a plugin or theme background update.

Method of the class: WP_Automatic_Updater{}

Hooks from the method

Return

null. Nothing (null).

Usage

// protected - for code of main (parent) or child class
$result = $this->send_plugin_theme_email( $type, $successful_updates, $failed_updates );
$type(string) (required)
The type of email to send. Can be one of 'success', 'fail', 'mixed'.
$successful_updates(array) (required)
A list of updates that succeeded.
$failed_updates(array) (required)
A list of updates that failed.

Changelog

Since 5.5.0 Introduced.

WP_Automatic_Updater::send_plugin_theme_email() code WP 6.6.2

protected function send_plugin_theme_email( $type, $successful_updates, $failed_updates ) {
	// No updates were attempted.
	if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
		return;
	}

	$unique_failures     = false;
	$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

	/*
	 * When only failures have occurred, an email should only be sent if there are unique failures.
	 * A failure is considered unique if an email has not been sent for an update attempt failure
	 * to a plugin or theme with the same new_version.
	 */
	if ( 'fail' === $type ) {
		foreach ( $failed_updates as $update_type => $failures ) {
			foreach ( $failures as $failed_update ) {
				if ( ! isset( $past_failure_emails[ $failed_update->item->{$update_type} ] ) ) {
					$unique_failures = true;
					continue;
				}

				// Check that the failure represents a new failure based on the new_version.
				if ( version_compare( $past_failure_emails[ $failed_update->item->{$update_type} ], $failed_update->item->new_version, '<' ) ) {
					$unique_failures = true;
				}
			}
		}

		if ( ! $unique_failures ) {
			return;
		}
	}

	$body               = array();
	$successful_plugins = ( ! empty( $successful_updates['plugin'] ) );
	$successful_themes  = ( ! empty( $successful_updates['theme'] ) );
	$failed_plugins     = ( ! empty( $failed_updates['plugin'] ) );
	$failed_themes      = ( ! empty( $failed_updates['theme'] ) );

	switch ( $type ) {
		case 'success':
			if ( $successful_plugins && $successful_themes ) {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some plugins and themes have automatically updated' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Some plugins and themes have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
					home_url()
				);
			} elseif ( $successful_plugins ) {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some plugins were automatically updated' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Some plugins have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
					home_url()
				);
			} else {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some themes were automatically updated' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Some themes have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
					home_url()
				);
			}

			break;
		case 'fail':
		case 'mixed':
			if ( $failed_plugins && $failed_themes ) {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some plugins and themes have failed to update' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Plugins and themes failed to update on your site at %s.' ),
					home_url()
				);
			} elseif ( $failed_plugins ) {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some plugins have failed to update' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Plugins failed to update on your site at %s.' ),
					home_url()
				);
			} else {
				/* translators: %s: Site title. */
				$subject = __( '[%s] Some themes have failed to update' );
				$body[]  = sprintf(
					/* translators: %s: Home URL. */
					__( 'Howdy! Themes failed to update on your site at %s.' ),
					home_url()
				);
			}

			break;
	}

	if ( in_array( $type, array( 'fail', 'mixed' ), true ) ) {
		$body[] = "\n";
		$body[] = __( 'Please check your site now. It’s possible that everything is working. If there are updates available, you should update.' );
		$body[] = "\n";

		// List failed plugin updates.
		if ( ! empty( $failed_updates['plugin'] ) ) {
			$body[] = __( 'The following plugins failed to update. If there was a fatal error in the update, the previously installed version has been restored.' );

			foreach ( $failed_updates['plugin'] as $item ) {
				$body_message = '';
				$item_url     = '';

				if ( ! empty( $item->item->url ) ) {
					$item_url = ' : ' . esc_url( $item->item->url );
				}

				if ( $item->item->current_version ) {
					$body_message .= sprintf(
						/* translators: 1: Plugin name, 2: Current version number, 3: New version number, 4: Plugin URL. */
						__( '- %1$s (from version %2$s to %3$s)%4$s' ),
						html_entity_decode( $item->name ),
						$item->item->current_version,
						$item->item->new_version,
						$item_url
					);
				} else {
					$body_message .= sprintf(
						/* translators: 1: Plugin name, 2: Version number, 3: Plugin URL. */
						__( '- %1$s version %2$s%3$s' ),
						html_entity_decode( $item->name ),
						$item->item->new_version,
						$item_url
					);
				}

				$body[] = $body_message;

				$past_failure_emails[ $item->item->plugin ] = $item->item->new_version;
			}

			$body[] = "\n";
		}

		// List failed theme updates.
		if ( ! empty( $failed_updates['theme'] ) ) {
			$body[] = __( 'These themes failed to update:' );

			foreach ( $failed_updates['theme'] as $item ) {
				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)' ),
						html_entity_decode( $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' ),
						html_entity_decode( $item->name ),
						$item->item->new_version
					);
				}

				$past_failure_emails[ $item->item->theme ] = $item->item->new_version;
			}

			$body[] = "\n";
		}
	}

	// List successful updates.
	if ( in_array( $type, array( 'success', 'mixed' ), true ) ) {
		$body[] = "\n";

		// List successful plugin updates.
		if ( ! empty( $successful_updates['plugin'] ) ) {
			$body[] = __( 'These plugins are now up to date:' );

			foreach ( $successful_updates['plugin'] as $item ) {
				$body_message = '';
				$item_url     = '';

				if ( ! empty( $item->item->url ) ) {
					$item_url = ' : ' . esc_url( $item->item->url );
				}

				if ( $item->item->current_version ) {
					$body_message .= sprintf(
						/* translators: 1: Plugin name, 2: Current version number, 3: New version number, 4: Plugin URL. */
						__( '- %1$s (from version %2$s to %3$s)%4$s' ),
						html_entity_decode( $item->name ),
						$item->item->current_version,
						$item->item->new_version,
						$item_url
					);
				} else {
					$body_message .= sprintf(
						/* translators: 1: Plugin name, 2: Version number, 3: Plugin URL. */
						__( '- %1$s version %2$s%3$s' ),
						html_entity_decode( $item->name ),
						$item->item->new_version,
						$item_url
					);
				}
				$body[] = $body_message;

				unset( $past_failure_emails[ $item->item->plugin ] );
			}

			$body[] = "\n";
		}

		// List successful theme updates.
		if ( ! empty( $successful_updates['theme'] ) ) {
			$body[] = __( 'These themes are now up to date:' );

			foreach ( $successful_updates['theme'] as $item ) {
				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)' ),
						html_entity_decode( $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' ),
						html_entity_decode( $item->name ),
						$item->item->new_version
					);
				}

				unset( $past_failure_emails[ $item->item->theme ] );
			}

			$body[] = "\n";
		}
	}

	if ( $failed_plugins ) {
		$body[] = sprintf(
			/* translators: %s: Plugins screen URL. */
			__( 'To manage plugins on your site, visit the Plugins page: %s' ),
			admin_url( 'plugins.php' )
		);
		$body[] = "\n";
	}

	if ( $failed_themes ) {
		$body[] = sprintf(
			/* translators: %s: Themes screen URL. */
			__( 'To manage themes on your site, visit the Themes page: %s' ),
			admin_url( 'themes.php' )
		);
		$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' );

	if ( '' !== get_option( 'blogname' ) ) {
		$site_title = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
	} else {
		$site_title = parse_url( home_url(), PHP_URL_HOST );
	}

	$body    = implode( "\n", $body );
	$to      = get_site_option( 'admin_email' );
	$subject = sprintf( $subject, $site_title );
	$headers = '';

	$email = compact( 'to', 'subject', 'body', 'headers' );

	/**
	 * Filters the email sent following an automatic background update for plugins and themes.
	 *
	 * @since 5.5.0
	 *
	 * @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 array  $successful_updates A list of updates that succeeded.
	 * @param array  $failed_updates     A list of updates that failed.
	 */
	$email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );

	$result = wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );

	if ( $result ) {
		update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
	}
}