wp/wp-includes/update.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     1 <?php
     1 <?php
     2 /**
     2 /**
     3  * A simple set of functions to check our version 1.0 update service.
     3  * A simple set of functions to check the WordPress.org Version Update service.
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @since 2.3.0
     6  * @since 2.3.0
     7  */
     7  */
     8 
     8 
     9 /**
     9 /**
    10  * Check WordPress version against the newest version.
    10  * Checks WordPress version against the newest version.
    11  *
    11  *
    12  * The WordPress version, PHP version, and locale is sent.
    12  * The WordPress version, PHP version, and locale is sent.
    13  *
    13  *
    14  * Checks against the WordPress server at api.wordpress.org. Will only check
    14  * Checks against the WordPress server at api.wordpress.org. Will only check
    15  * if WordPress isn't installing.
    15  * if WordPress isn't installing.
    19  * @global string $wp_version       Used to check against the newest WordPress version.
    19  * @global string $wp_version       Used to check against the newest WordPress version.
    20  * @global wpdb   $wpdb             WordPress database abstraction object.
    20  * @global wpdb   $wpdb             WordPress database abstraction object.
    21  * @global string $wp_local_package Locale code of the package.
    21  * @global string $wp_local_package Locale code of the package.
    22  *
    22  *
    23  * @param array $extra_stats Extra statistics to report to the WordPress.org API.
    23  * @param array $extra_stats Extra statistics to report to the WordPress.org API.
    24  * @param bool  $force_check Whether to bypass the transient cache and force a fresh update check. Defaults to false, true if $extra_stats is set.
    24  * @param bool  $force_check Whether to bypass the transient cache and force a fresh update check.
       
    25  *                           Defaults to false, true if $extra_stats is set.
    25  */
    26  */
    26 function wp_version_check( $extra_stats = array(), $force_check = false ) {
    27 function wp_version_check( $extra_stats = array(), $force_check = false ) {
    27 	global $wpdb, $wp_local_package;
    28 	global $wpdb, $wp_local_package;
    28 
    29 
    29 	if ( wp_installing() ) {
    30 	if ( wp_installing() ) {
    30 		return;
    31 		return;
    31 	}
    32 	}
    32 
    33 
    33 	// Include an unmodified $wp_version.
    34 	// Include an unmodified $wp_version.
    34 	require ABSPATH . WPINC . '/version.php';
    35 	require ABSPATH . WPINC . '/version.php';
    35 	$php_version = phpversion();
    36 	$php_version = PHP_VERSION;
    36 
    37 
    37 	$current      = get_site_transient( 'update_core' );
    38 	$current      = get_site_transient( 'update_core' );
    38 	$translations = wp_get_installed_translations( 'core' );
    39 	$translations = wp_get_installed_translations( 'core' );
    39 
    40 
    40 	// Invalidate the transient when $wp_version changes.
    41 	// Invalidate the transient when $wp_version changes.
    41 	if ( is_object( $current ) && $wp_version !== $current->version_checked ) {
    42 	if ( is_object( $current ) && $wp_version !== $current->version_checked ) {
    42 		$current = false;
    43 		$current = false;
    43 	}
    44 	}
    44 
    45 
    45 	if ( ! is_object( $current ) ) {
    46 	if ( ! is_object( $current ) ) {
    46 		$current                  = new stdClass;
    47 		$current                  = new stdClass();
    47 		$current->updates         = array();
    48 		$current->updates         = array();
    48 		$current->version_checked = $wp_version;
    49 		$current->version_checked = $wp_version;
    49 	}
    50 	}
    50 
    51 
    51 	if ( ! empty( $extra_stats ) ) {
    52 	if ( ! empty( $extra_stats ) ) {
    71 
    72 
    72 	// Update last_checked for current to prevent multiple blocking requests if request hangs.
    73 	// Update last_checked for current to prevent multiple blocking requests if request hangs.
    73 	$current->last_checked = time();
    74 	$current->last_checked = time();
    74 	set_site_transient( 'update_core', $current );
    75 	set_site_transient( 'update_core', $current );
    75 
    76 
    76 	if ( method_exists( $wpdb, 'db_version' ) ) {
    77 	if ( method_exists( $wpdb, 'db_server_info' ) ) {
       
    78 		$mysql_version = $wpdb->db_server_info();
       
    79 	} elseif ( method_exists( $wpdb, 'db_version' ) ) {
    77 		$mysql_version = preg_replace( '/[^0-9.].*/', '', $wpdb->db_version() );
    80 		$mysql_version = preg_replace( '/[^0-9.].*/', '', $wpdb->db_version() );
    78 	} else {
    81 	} else {
    79 		$mysql_version = 'N/A';
    82 		$mysql_version = 'N/A';
    80 	}
    83 	}
    81 
    84 
    87 		$multisite_enabled = 0;
    90 		$multisite_enabled = 0;
    88 		$num_blogs         = 1;
    91 		$num_blogs         = 1;
    89 		$wp_install        = home_url( '/' );
    92 		$wp_install        = home_url( '/' );
    90 	}
    93 	}
    91 
    94 
       
    95 	$extensions = get_loaded_extensions();
       
    96 	sort( $extensions, SORT_STRING | SORT_FLAG_CASE );
    92 	$query = array(
    97 	$query = array(
    93 		'version'            => $wp_version,
    98 		'version'            => $wp_version,
    94 		'php'                => $php_version,
    99 		'php'                => $php_version,
    95 		'locale'             => $locale,
   100 		'locale'             => $locale,
    96 		'mysql'              => $mysql_version,
   101 		'mysql'              => $mysql_version,
    97 		'local_package'      => isset( $wp_local_package ) ? $wp_local_package : '',
   102 		'local_package'      => isset( $wp_local_package ) ? $wp_local_package : '',
    98 		'blogs'              => $num_blogs,
   103 		'blogs'              => $num_blogs,
    99 		'users'              => get_user_count(),
   104 		'users'              => get_user_count(),
   100 		'multisite_enabled'  => $multisite_enabled,
   105 		'multisite_enabled'  => $multisite_enabled,
   101 		'initial_db_version' => get_site_option( 'initial_db_version' ),
   106 		'initial_db_version' => get_site_option( 'initial_db_version' ),
       
   107 		'extensions'         => array_combine( $extensions, array_map( 'phpversion', $extensions ) ),
       
   108 		'platform_flags'     => array(
       
   109 			'os'   => PHP_OS,
       
   110 			'bits' => PHP_INT_SIZE === 4 ? 32 : 64,
       
   111 		),
       
   112 		'image_support'      => array(),
   102 	);
   113 	);
       
   114 
       
   115 	if ( function_exists( 'gd_info' ) ) {
       
   116 		$gd_info = gd_info();
       
   117 		// Filter to supported values.
       
   118 		$gd_info = array_filter( $gd_info );
       
   119 
       
   120 		// Add data for GD WebP and AVIF support.
       
   121 		$query['image_support']['gd'] = array_keys(
       
   122 			array_filter(
       
   123 				array(
       
   124 					'webp' => isset( $gd_info['WebP Support'] ),
       
   125 					'avif' => isset( $gd_info['AVIF Support'] ),
       
   126 				)
       
   127 			)
       
   128 		);
       
   129 	}
       
   130 
       
   131 	if ( class_exists( 'Imagick' ) ) {
       
   132 		// Add data for Imagick WebP and AVIF support.
       
   133 		$query['image_support']['imagick'] = array_keys(
       
   134 			array_filter(
       
   135 				array(
       
   136 					'webp' => ! empty( Imagick::queryFormats( 'WEBP' ) ),
       
   137 					'avif' => ! empty( Imagick::queryFormats( 'AVIF' ) ),
       
   138 				)
       
   139 			)
       
   140 		);
       
   141 	}
   103 
   142 
   104 	/**
   143 	/**
   105 	 * Filters the query arguments sent as part of the core version check.
   144 	 * Filters the query arguments sent as part of the core version check.
   106 	 *
   145 	 *
   107 	 * WARNING: Changing this data may result in your site not receiving security updates.
   146 	 * WARNING: Changing this data may result in your site not receiving security updates.
   161 	);
   200 	);
   162 
   201 
   163 	$response = wp_remote_post( $url, $options );
   202 	$response = wp_remote_post( $url, $options );
   164 
   203 
   165 	if ( $ssl && is_wp_error( $response ) ) {
   204 	if ( $ssl && is_wp_error( $response ) ) {
   166 		trigger_error(
   205 		wp_trigger_error(
       
   206 			__FUNCTION__,
   167 			sprintf(
   207 			sprintf(
   168 				/* translators: %s: Support forums URL. */
   208 				/* translators: %s: Support forums URL. */
   169 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   209 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   170 				__( 'https://wordpress.org/support/forums/' )
   210 				__( 'https://wordpress.org/support/forums/' )
   171 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   211 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   288 
   328 
   289 	$active  = get_option( 'active_plugins', array() );
   329 	$active  = get_option( 'active_plugins', array() );
   290 	$current = get_site_transient( 'update_plugins' );
   330 	$current = get_site_transient( 'update_plugins' );
   291 
   331 
   292 	if ( ! is_object( $current ) ) {
   332 	if ( ! is_object( $current ) ) {
   293 		$current = new stdClass;
   333 		$current = new stdClass();
   294 	}
   334 	}
   295 
   335 
   296 	$updates               = new stdClass;
   336 	$updates               = new stdClass();
   297 	$updates->last_checked = time();
   337 	$updates->last_checked = time();
   298 	$updates->response     = array();
   338 	$updates->response     = array();
   299 	$updates->translations = array();
   339 	$updates->translations = array();
   300 	$updates->no_update    = array();
   340 	$updates->no_update    = array();
   301 
   341 
   361 	 * Filters the locales requested for plugin translations.
   401 	 * Filters the locales requested for plugin translations.
   362 	 *
   402 	 *
   363 	 * @since 3.7.0
   403 	 * @since 3.7.0
   364 	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
   404 	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
   365 	 *
   405 	 *
   366 	 * @param array $locales Plugin locales. Default is all available locales of the site.
   406 	 * @param string[] $locales Plugin locales. Default is all available locales of the site.
   367 	 */
   407 	 */
   368 	$locales = apply_filters( 'plugins_update_check_locales', $locales );
   408 	$locales = apply_filters( 'plugins_update_check_locales', $locales );
   369 	$locales = array_unique( $locales );
   409 	$locales = array_unique( $locales );
   370 
   410 
   371 	if ( $doing_cron ) {
   411 	if ( $doing_cron ) {
   372 		$timeout = 30;
   412 		$timeout = 30; // 30 seconds.
   373 	} else {
   413 	} else {
   374 		// Three seconds, plus one extra second for every 10 plugins.
   414 		// Three seconds, plus one extra second for every 10 plugins.
   375 		$timeout = 3 + (int) ( count( $plugins ) / 10 );
   415 		$timeout = 3 + (int) ( count( $plugins ) / 10 );
   376 	}
   416 	}
   377 
   417 
   399 	}
   439 	}
   400 
   440 
   401 	$raw_response = wp_remote_post( $url, $options );
   441 	$raw_response = wp_remote_post( $url, $options );
   402 
   442 
   403 	if ( $ssl && is_wp_error( $raw_response ) ) {
   443 	if ( $ssl && is_wp_error( $raw_response ) ) {
   404 		trigger_error(
   444 		wp_trigger_error(
       
   445 			__FUNCTION__,
   405 			sprintf(
   446 			sprintf(
   406 				/* translators: %s: Support forums URL. */
   447 				/* translators: %s: Support forums URL. */
   407 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   448 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   408 				__( 'https://wordpress.org/support/forums/' )
   449 				__( 'https://wordpress.org/support/forums/' )
   409 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   450 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   428 	foreach ( $plugins as $plugin_file => $plugin_data ) {
   469 	foreach ( $plugins as $plugin_file => $plugin_data ) {
   429 		if ( ! $plugin_data['UpdateURI'] || isset( $updates->response[ $plugin_file ] ) ) {
   470 		if ( ! $plugin_data['UpdateURI'] || isset( $updates->response[ $plugin_file ] ) ) {
   430 			continue;
   471 			continue;
   431 		}
   472 		}
   432 
   473 
   433 		$hostname = wp_parse_url( esc_url_raw( $plugin_data['UpdateURI'] ), PHP_URL_HOST );
   474 		$hostname = wp_parse_url( sanitize_url( $plugin_data['UpdateURI'] ), PHP_URL_HOST );
   434 
   475 
   435 		/**
   476 		/**
   436 		 * Filters the update response for a given plugin hostname.
   477 		 * Filters the update response for a given plugin hostname.
   437 		 *
   478 		 *
   438 		 * The dynamic portion of the hook name, `$hostname`, refers to the hostname
   479 		 * The dynamic portion of the hook name, `$hostname`, refers to the hostname
   467 		 *         @type string $autoupdate Whether the translation should be automatically installed.
   508 		 *         @type string $autoupdate Whether the translation should be automatically installed.
   468 		 *     }
   509 		 *     }
   469 		 * }
   510 		 * }
   470 		 * @param array       $plugin_data      Plugin headers.
   511 		 * @param array       $plugin_data      Plugin headers.
   471 		 * @param string      $plugin_file      Plugin filename.
   512 		 * @param string      $plugin_file      Plugin filename.
   472 		 * @param array       $locales          Installed locales to look translations for.
   513 		 * @param string[]    $locales          Installed locales to look up translations for.
   473 		 */
   514 		 */
   474 		$update = apply_filters( "update_plugins_{$hostname}", false, $plugin_data, $plugin_file, $locales );
   515 		$update = apply_filters( "update_plugins_{$hostname}", false, $plugin_data, $plugin_file, $locales );
   475 
   516 
   476 		if ( ! $update ) {
   517 		if ( ! $update ) {
   477 			continue;
   518 			continue;
   512 		} else {
   553 		} else {
   513 			$updates->no_update[ $plugin_file ] = $update;
   554 			$updates->no_update[ $plugin_file ] = $update;
   514 		}
   555 		}
   515 	}
   556 	}
   516 
   557 
   517 	$sanitize_plugin_update_payload = static function( &$item ) {
   558 	$sanitize_plugin_update_payload = static function ( &$item ) {
   518 		$item = (object) $item;
   559 		$item = (object) $item;
   519 
   560 
   520 		unset( $item->translations, $item->compatibility );
   561 		unset( $item->translations, $item->compatibility );
   521 
   562 
   522 		return $item;
   563 		return $item;
   556 	$translations     = wp_get_installed_translations( 'themes' );
   597 	$translations     = wp_get_installed_translations( 'themes' );
   557 
   598 
   558 	$last_update = get_site_transient( 'update_themes' );
   599 	$last_update = get_site_transient( 'update_themes' );
   559 
   600 
   560 	if ( ! is_object( $last_update ) ) {
   601 	if ( ! is_object( $last_update ) ) {
   561 		$last_update = new stdClass;
   602 		$last_update = new stdClass();
   562 	}
   603 	}
   563 
   604 
   564 	$themes  = array();
   605 	$themes  = array();
   565 	$checked = array();
   606 	$checked = array();
   566 	$request = array();
   607 	$request = array();
   575 			'Name'       => $theme->get( 'Name' ),
   616 			'Name'       => $theme->get( 'Name' ),
   576 			'Title'      => $theme->get( 'Name' ),
   617 			'Title'      => $theme->get( 'Name' ),
   577 			'Version'    => $theme->get( 'Version' ),
   618 			'Version'    => $theme->get( 'Version' ),
   578 			'Author'     => $theme->get( 'Author' ),
   619 			'Author'     => $theme->get( 'Author' ),
   579 			'Author URI' => $theme->get( 'AuthorURI' ),
   620 			'Author URI' => $theme->get( 'AuthorURI' ),
       
   621 			'UpdateURI'  => $theme->get( 'UpdateURI' ),
   580 			'Template'   => $theme->get_template(),
   622 			'Template'   => $theme->get_template(),
   581 			'Stylesheet' => $theme->get_stylesheet(),
   623 			'Stylesheet' => $theme->get_stylesheet(),
   582 		);
   624 		);
   583 	}
   625 	}
   584 
   626 
   642 	 * Filters the locales requested for theme translations.
   684 	 * Filters the locales requested for theme translations.
   643 	 *
   685 	 *
   644 	 * @since 3.7.0
   686 	 * @since 3.7.0
   645 	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
   687 	 * @since 4.5.0 The default value of the `$locales` parameter changed to include all locales.
   646 	 *
   688 	 *
   647 	 * @param array $locales Theme locales. Default is all available locales of the site.
   689 	 * @param string[] $locales Theme locales. Default is all available locales of the site.
   648 	 */
   690 	 */
   649 	$locales = apply_filters( 'themes_update_check_locales', $locales );
   691 	$locales = apply_filters( 'themes_update_check_locales', $locales );
   650 	$locales = array_unique( $locales );
   692 	$locales = array_unique( $locales );
   651 
   693 
   652 	if ( $doing_cron ) {
   694 	if ( $doing_cron ) {
   653 		$timeout = 30;
   695 		$timeout = 30; // 30 seconds.
   654 	} else {
   696 	} else {
   655 		// Three seconds, plus one extra second for every 10 themes.
   697 		// Three seconds, plus one extra second for every 10 themes.
   656 		$timeout = 3 + (int) ( count( $themes ) / 10 );
   698 		$timeout = 3 + (int) ( count( $themes ) / 10 );
   657 	}
   699 	}
   658 
   700 
   679 	}
   721 	}
   680 
   722 
   681 	$raw_response = wp_remote_post( $url, $options );
   723 	$raw_response = wp_remote_post( $url, $options );
   682 
   724 
   683 	if ( $ssl && is_wp_error( $raw_response ) ) {
   725 	if ( $ssl && is_wp_error( $raw_response ) ) {
   684 		trigger_error(
   726 		wp_trigger_error(
       
   727 			__FUNCTION__,
   685 			sprintf(
   728 			sprintf(
   686 				/* translators: %s: Support forums URL. */
   729 				/* translators: %s: Support forums URL. */
   687 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   730 				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
   688 				__( 'https://wordpress.org/support/forums/' )
   731 				__( 'https://wordpress.org/support/forums/' )
   689 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   732 			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
   694 
   737 
   695 	if ( is_wp_error( $raw_response ) || 200 !== wp_remote_retrieve_response_code( $raw_response ) ) {
   738 	if ( is_wp_error( $raw_response ) || 200 !== wp_remote_retrieve_response_code( $raw_response ) ) {
   696 		return;
   739 		return;
   697 	}
   740 	}
   698 
   741 
   699 	$new_update               = new stdClass;
   742 	$new_update               = new stdClass();
   700 	$new_update->last_checked = time();
   743 	$new_update->last_checked = time();
   701 	$new_update->checked      = $checked;
   744 	$new_update->checked      = $checked;
   702 
   745 
   703 	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
   746 	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
   704 
   747 
   706 		$new_update->response     = $response['themes'];
   749 		$new_update->response     = $response['themes'];
   707 		$new_update->no_update    = $response['no_update'];
   750 		$new_update->no_update    = $response['no_update'];
   708 		$new_update->translations = $response['translations'];
   751 		$new_update->translations = $response['translations'];
   709 	}
   752 	}
   710 
   753 
       
   754 	// Support updates for any themes using the `Update URI` header field.
       
   755 	foreach ( $themes as $theme_stylesheet => $theme_data ) {
       
   756 		if ( ! $theme_data['UpdateURI'] || isset( $new_update->response[ $theme_stylesheet ] ) ) {
       
   757 			continue;
       
   758 		}
       
   759 
       
   760 		$hostname = wp_parse_url( sanitize_url( $theme_data['UpdateURI'] ), PHP_URL_HOST );
       
   761 
       
   762 		/**
       
   763 		 * Filters the update response for a given theme hostname.
       
   764 		 *
       
   765 		 * The dynamic portion of the hook name, `$hostname`, refers to the hostname
       
   766 		 * of the URI specified in the `Update URI` header field.
       
   767 		 *
       
   768 		 * @since 6.1.0
       
   769 		 *
       
   770 		 * @param array|false $update {
       
   771 		 *     The theme update data with the latest details. Default false.
       
   772 		 *
       
   773 		 *     @type string $id           Optional. ID of the theme for update purposes, should be a URI
       
   774 		 *                                specified in the `Update URI` header field.
       
   775 		 *     @type string $theme        Directory name of the theme.
       
   776 		 *     @type string $version      The version of the theme.
       
   777 		 *     @type string $url          The URL for details of the theme.
       
   778 		 *     @type string $package      Optional. The update ZIP for the theme.
       
   779 		 *     @type string $tested       Optional. The version of WordPress the theme is tested against.
       
   780 		 *     @type string $requires_php Optional. The version of PHP which the theme requires.
       
   781 		 *     @type bool   $autoupdate   Optional. Whether the theme should automatically update.
       
   782 		 *     @type array  $translations {
       
   783 		 *         Optional. List of translation updates for the theme.
       
   784 		 *
       
   785 		 *         @type string $language   The language the translation update is for.
       
   786 		 *         @type string $version    The version of the theme this translation is for.
       
   787 		 *                                  This is not the version of the language file.
       
   788 		 *         @type string $updated    The update timestamp of the translation file.
       
   789 		 *                                  Should be a date in the `YYYY-MM-DD HH:MM:SS` format.
       
   790 		 *         @type string $package    The ZIP location containing the translation update.
       
   791 		 *         @type string $autoupdate Whether the translation should be automatically installed.
       
   792 		 *     }
       
   793 		 * }
       
   794 		 * @param array       $theme_data       Theme headers.
       
   795 		 * @param string      $theme_stylesheet Theme stylesheet.
       
   796 		 * @param string[]    $locales          Installed locales to look up translations for.
       
   797 		 */
       
   798 		$update = apply_filters( "update_themes_{$hostname}", false, $theme_data, $theme_stylesheet, $locales );
       
   799 
       
   800 		if ( ! $update ) {
       
   801 			continue;
       
   802 		}
       
   803 
       
   804 		$update = (object) $update;
       
   805 
       
   806 		// Is it valid? We require at least a version.
       
   807 		if ( ! isset( $update->version ) ) {
       
   808 			continue;
       
   809 		}
       
   810 
       
   811 		// This should remain constant.
       
   812 		$update->id = $theme_data['UpdateURI'];
       
   813 
       
   814 		// WordPress needs the version field specified as 'new_version'.
       
   815 		if ( ! isset( $update->new_version ) ) {
       
   816 			$update->new_version = $update->version;
       
   817 		}
       
   818 
       
   819 		// Handle any translation updates.
       
   820 		if ( ! empty( $update->translations ) ) {
       
   821 			foreach ( $update->translations as $translation ) {
       
   822 				if ( isset( $translation['language'], $translation['package'] ) ) {
       
   823 					$translation['type'] = 'theme';
       
   824 					$translation['slug'] = isset( $update->theme ) ? $update->theme : $update->id;
       
   825 
       
   826 					$new_update->translations[] = $translation;
       
   827 				}
       
   828 			}
       
   829 		}
       
   830 
       
   831 		unset( $new_update->no_update[ $theme_stylesheet ], $new_update->response[ $theme_stylesheet ] );
       
   832 
       
   833 		if ( version_compare( $update->new_version, $theme_data['Version'], '>' ) ) {
       
   834 			$new_update->response[ $theme_stylesheet ] = (array) $update;
       
   835 		} else {
       
   836 			$new_update->no_update[ $theme_stylesheet ] = (array) $update;
       
   837 		}
       
   838 	}
       
   839 
   711 	set_site_transient( 'update_themes', $new_update );
   840 	set_site_transient( 'update_themes', $new_update );
   712 }
   841 }
   713 
   842 
   714 /**
   843 /**
   715  * Performs WordPress automatic background updates.
   844  * Performs WordPress automatic background updates.
   717  * Updates WordPress core plus any plugins and themes that have automatic updates enabled.
   846  * Updates WordPress core plus any plugins and themes that have automatic updates enabled.
   718  *
   847  *
   719  * @since 3.7.0
   848  * @since 3.7.0
   720  */
   849  */
   721 function wp_maybe_auto_update() {
   850 function wp_maybe_auto_update() {
   722 	include_once ABSPATH . 'wp-admin/includes/admin.php';
   851 	require_once ABSPATH . 'wp-admin/includes/admin.php';
   723 	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
   852 	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
   724 
   853 
   725 	$upgrader = new WP_Automatic_Updater;
   854 	$upgrader = new WP_Automatic_Updater();
   726 	$upgrader->run();
   855 	$upgrader->run();
   727 }
   856 }
   728 
   857 
   729 /**
   858 /**
   730  * Retrieves a list of all language updates available.
   859  * Retrieves a list of all language updates available.
   755 
   884 
   756 	return $updates;
   885 	return $updates;
   757 }
   886 }
   758 
   887 
   759 /**
   888 /**
   760  * Collect counts and UI strings for available updates
   889  * Collects counts and UI strings for available updates.
   761  *
   890  *
   762  * @since 3.3.0
   891  * @since 3.3.0
   763  *
   892  *
   764  * @return array
   893  * @return array
   765  */
   894  */
   873 	}
  1002 	}
   874 
  1003 
   875 	wp_version_check();
  1004 	wp_version_check();
   876 }
  1005 }
   877 /**
  1006 /**
   878  * Check the last time plugins were run before checking plugin versions.
  1007  * Checks the last time plugins were run before checking plugin versions.
   879  *
  1008  *
   880  * This might have been backported to WordPress 2.6.1 for performance reasons.
  1009  * This might have been backported to WordPress 2.6.1 for performance reasons.
   881  * This is used for the wp-admin to check only so often instead of every page
  1010  * This is used for the wp-admin to check only so often instead of every page
   882  * load.
  1011  * load.
   883  *
  1012  *
   895 
  1024 
   896 	wp_update_plugins();
  1025 	wp_update_plugins();
   897 }
  1026 }
   898 
  1027 
   899 /**
  1028 /**
   900  * Check themes versions only after a duration of time.
  1029  * Checks themes versions only after a duration of time.
   901  *
  1030  *
   902  * This is for performance reasons to make sure that on the theme version
  1031  * This is for performance reasons to make sure that on the theme version
   903  * checker is not run on every page load.
  1032  * checker is not run on every page load.
   904  *
  1033  *
   905  * @since 2.7.0
  1034  * @since 2.7.0
   916 
  1045 
   917 	wp_update_themes();
  1046 	wp_update_themes();
   918 }
  1047 }
   919 
  1048 
   920 /**
  1049 /**
   921  * Schedule core, theme, and plugin update checks.
  1050  * Schedules core, theme, and plugin update checks.
   922  *
  1051  *
   923  * @since 3.1.0
  1052  * @since 3.1.0
   924  */
  1053  */
   925 function wp_schedule_update_checks() {
  1054 function wp_schedule_update_checks() {
   926 	if ( ! wp_next_scheduled( 'wp_version_check' ) && ! wp_installing() ) {
  1055 	if ( ! wp_next_scheduled( 'wp_version_check' ) && ! wp_installing() ) {
   935 		wp_schedule_event( time(), 'twicedaily', 'wp_update_themes' );
  1064 		wp_schedule_event( time(), 'twicedaily', 'wp_update_themes' );
   936 	}
  1065 	}
   937 }
  1066 }
   938 
  1067 
   939 /**
  1068 /**
   940  * Clear existing update caches for plugins, themes, and core.
  1069  * Clears existing update caches for plugins, themes, and core.
   941  *
  1070  *
   942  * @since 4.1.0
  1071  * @since 4.1.0
   943  */
  1072  */
   944 function wp_clean_update_cache() {
  1073 function wp_clean_update_cache() {
   945 	if ( function_exists( 'wp_clean_plugins_cache' ) ) {
  1074 	if ( function_exists( 'wp_clean_plugins_cache' ) ) {
   951 	wp_clean_themes_cache();
  1080 	wp_clean_themes_cache();
   952 
  1081 
   953 	delete_site_transient( 'update_core' );
  1082 	delete_site_transient( 'update_core' );
   954 }
  1083 }
   955 
  1084 
       
  1085 /**
       
  1086  * Schedules the removal of all contents in the temporary backup directory.
       
  1087  *
       
  1088  * @since 6.3.0
       
  1089  */
       
  1090 function wp_delete_all_temp_backups() {
       
  1091 	/*
       
  1092 	 * Check if there is a lock, or if currently performing an Ajax request,
       
  1093 	 * in which case there is a chance an update is running.
       
  1094 	 * Reschedule for an hour from now and exit early.
       
  1095 	 */
       
  1096 	if ( get_option( 'core_updater.lock' ) || get_option( 'auto_updater.lock' ) || wp_doing_ajax() ) {
       
  1097 		wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_delete_temp_updater_backups' );
       
  1098 		return;
       
  1099 	}
       
  1100 
       
  1101 	// This action runs on shutdown to make sure there are no plugin updates currently running.
       
  1102 	add_action( 'shutdown', '_wp_delete_all_temp_backups' );
       
  1103 }
       
  1104 
       
  1105 /**
       
  1106  * Deletes all contents in the temporary backup directory.
       
  1107  *
       
  1108  * @since 6.3.0
       
  1109  *
       
  1110  * @access private
       
  1111  *
       
  1112  * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
       
  1113  *
       
  1114  * @return void|WP_Error Void on success, or a WP_Error object on failure.
       
  1115  */
       
  1116 function _wp_delete_all_temp_backups() {
       
  1117 	global $wp_filesystem;
       
  1118 
       
  1119 	if ( ! function_exists( 'WP_Filesystem' ) ) {
       
  1120 		require_once ABSPATH . '/wp-admin/includes/file.php';
       
  1121 	}
       
  1122 
       
  1123 	ob_start();
       
  1124 	$credentials = request_filesystem_credentials( '' );
       
  1125 	ob_end_clean();
       
  1126 
       
  1127 	if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
       
  1128 		return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
       
  1129 	}
       
  1130 
       
  1131 	if ( ! $wp_filesystem->wp_content_dir() ) {
       
  1132 		return new WP_Error(
       
  1133 			'fs_no_content_dir',
       
  1134 			/* translators: %s: Directory name. */
       
  1135 			sprintf( __( 'Unable to locate WordPress content directory (%s).' ), 'wp-content' )
       
  1136 		);
       
  1137 	}
       
  1138 
       
  1139 	$temp_backup_dir = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/';
       
  1140 	$dirlist         = $wp_filesystem->dirlist( $temp_backup_dir );
       
  1141 	$dirlist         = $dirlist ? $dirlist : array();
       
  1142 
       
  1143 	foreach ( array_keys( $dirlist ) as $dir ) {
       
  1144 		if ( '.' === $dir || '..' === $dir ) {
       
  1145 			continue;
       
  1146 		}
       
  1147 
       
  1148 		$wp_filesystem->delete( $temp_backup_dir . $dir, true );
       
  1149 	}
       
  1150 }
       
  1151 
   956 if ( ( ! is_main_site() && ! is_network_admin() ) || wp_doing_ajax() ) {
  1152 if ( ( ! is_main_site() && ! is_network_admin() ) || wp_doing_ajax() ) {
   957 	return;
  1153 	return;
   958 }
  1154 }
   959 
  1155 
   960 add_action( 'admin_init', '_maybe_update_core' );
  1156 add_action( 'admin_init', '_maybe_update_core' );
   975 add_action( 'update_option_WPLANG', 'wp_clean_update_cache', 10, 0 );
  1171 add_action( 'update_option_WPLANG', 'wp_clean_update_cache', 10, 0 );
   976 
  1172 
   977 add_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
  1173 add_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
   978 
  1174 
   979 add_action( 'init', 'wp_schedule_update_checks' );
  1175 add_action( 'init', 'wp_schedule_update_checks' );
       
  1176 
       
  1177 add_action( 'wp_delete_temp_updater_backups', 'wp_delete_all_temp_backups' );