update.php 21 KB
Newer Older
godog's avatar
godog committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?php
/**
 * A simple set of functions to check our version 1.0 update service.
 *
 * @package WordPress
 * @since 2.3.0
 */

/**
 * Check WordPress version against the newest version.
 *
 * The WordPress version, PHP version, and Locale is sent. Checks against the
 * WordPress server at api.wordpress.org server. Will only check if WordPress
 * isn't installing.
 *
 * @package WordPress
 * @since 2.3.0
 * @uses $wp_version Used to check against the newest WordPress version.
 *
lucha's avatar
lucha committed
20
 * @param array $extra_stats Extra statistics to report to the WordPress.org API.
lucha's avatar
lucha committed
21
 * @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.
godog's avatar
godog committed
22 23
 * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
 */
lucha's avatar
lucha committed
24
function wp_version_check( $extra_stats = array(), $force_check = false ) {
godog's avatar
godog committed
25 26 27
	if ( defined('WP_INSTALLING') )
		return;

shammash's avatar
shammash committed
28 29
	global $wpdb, $wp_local_package;
	include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
godog's avatar
godog committed
30 31 32
	$php_version = phpversion();

	$current = get_site_transient( 'update_core' );
lucha's avatar
lucha committed
33 34
	$translations = wp_get_installed_translations( 'core' );

lucha's avatar
lucha committed
35 36 37 38
	// Invalidate the transient when $wp_version changes
	if ( is_object( $current ) && $wp_version != $current->version_checked )
		$current = false;

godog's avatar
godog committed
39 40 41 42 43 44
	if ( ! is_object($current) ) {
		$current = new stdClass;
		$current->updates = array();
		$current->version_checked = $wp_version;
	}

lucha's avatar
lucha committed
45 46 47
	if ( ! empty( $extra_stats ) )
		$force_check = true;

lechuck's avatar
lechuck committed
48 49 50
	// Wait 60 seconds between multiple version check requests
	$timeout = 60;
	$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
lucha's avatar
lucha committed
51
	if ( ! $force_check && $time_not_changed )
lechuck's avatar
lechuck committed
52 53
		return false;

lucha's avatar
lucha committed
54 55 56 57 58 59 60 61 62
	$locale = get_locale();
	/**
	 * Filter the locale requested for WordPress core translations.
	 *
	 * @since 2.8.0
	 *
	 * @param string $locale Current locale.
	 */
	$locale = apply_filters( 'core_version_check_locale', $locale );
godog's avatar
godog committed
63 64 65 66 67 68 69 70 71 72

	// Update last_checked for current to prevent multiple blocking requests if request hangs
	$current->last_checked = time();
	set_site_transient( 'update_core', $current );

	if ( method_exists( $wpdb, 'db_version' ) )
		$mysql_version = preg_replace('/[^0-9.].*/', '', $wpdb->db_version());
	else
		$mysql_version = 'N/A';

lechuck's avatar
lechuck committed
73 74 75 76
	if ( is_multisite() ) {
		$user_count = get_user_count();
		$num_blogs = get_blog_count();
		$wp_install = network_site_url();
godog's avatar
godog committed
77
		$multisite_enabled = 1;
root's avatar
root committed
78
	} else {
lechuck's avatar
lechuck committed
79
		$user_count = count_users();
lechuck's avatar
lechuck committed
80
		$user_count = $user_count['total_users'];
root's avatar
root committed
81 82 83
		$multisite_enabled = 0;
		$num_blogs = 1;
		$wp_install = home_url( '/' );
godog's avatar
godog committed
84 85
	}

root's avatar
root committed
86 87 88 89 90 91 92
	$query = array(
		'version'           => $wp_version,
		'php'               => $php_version,
		'locale'            => $locale,
		'mysql'             => $mysql_version,
		'local_package'     => isset( $wp_local_package ) ? $wp_local_package : '',
		'blogs'             => $num_blogs,
lechuck's avatar
lechuck committed
93
		'users'             => $user_count,
lucha's avatar
lucha committed
94 95 96 97 98
		'multisite_enabled' => $multisite_enabled,
	);

	$post_body = array(
		'translations' => json_encode( $translations ),
root's avatar
root committed
99 100
	);

lucha's avatar
lucha committed
101
	if ( is_array( $extra_stats ) )
lucha's avatar
lucha committed
102 103 104 105 106
		$post_body = array_merge( $post_body, $extra_stats );

	$url = $http_url = 'http://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, null, '&' );
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
		$url = set_url_scheme( $url, 'https' );
godog's avatar
godog committed
107 108 109 110 111 112 113

	$options = array(
		'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3 ),
		'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
		'headers' => array(
			'wp_install' => $wp_install,
			'wp_blog' => home_url( '/' )
lucha's avatar
lucha committed
114 115
		),
		'body' => $post_body,
godog's avatar
godog committed
116 117
	);

lucha's avatar
lucha committed
118 119 120 121 122
	$response = wp_remote_post( $url, $options );
	if ( $ssl && is_wp_error( $response ) ) {
		trigger_error( __( '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="http://wordpress.org/support/">support forums</a>.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
		$response = wp_remote_post( $http_url, $options );
	}
godog's avatar
godog committed
123

shammash's avatar
shammash committed
124
	if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) )
godog's avatar
godog committed
125 126
		return false;

shammash's avatar
shammash committed
127
	$body = trim( wp_remote_retrieve_body( $response ) );
lucha's avatar
lucha committed
128
	$body = json_decode( $body, true );
lechuck's avatar
lechuck committed
129 130

	if ( ! is_array( $body ) || ! isset( $body['offers'] ) )
shammash's avatar
shammash committed
131
		return false;
lechuck's avatar
lechuck committed
132

shammash's avatar
shammash committed
133 134 135 136 137 138
	$offers = $body['offers'];

	foreach ( $offers as &$offer ) {
		foreach ( $offer as $offer_key => $value ) {
			if ( 'packages' == $offer_key )
				$offer['packages'] = (object) array_intersect_key( array_map( 'esc_url', $offer['packages'] ),
lucha's avatar
lucha committed
139
					array_fill_keys( array( 'full', 'no_content', 'new_bundled', 'partial', 'rollback' ), '' ) );
shammash's avatar
shammash committed
140 141 142 143 144 145
			elseif ( 'download' == $offer_key )
				$offer['download'] = esc_url( $value );
			else
				$offer[ $offer_key ] = esc_html( $value );
		}
		$offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
lucha's avatar
lucha committed
146
			'packages', 'current', 'version', 'php_version', 'mysql_version', 'new_bundled', 'partial_version', 'notify_email' ), '' ) );
godog's avatar
godog committed
147 148 149
	}

	$updates = new stdClass();
shammash's avatar
shammash committed
150
	$updates->updates = $offers;
godog's avatar
godog committed
151 152
	$updates->last_checked = time();
	$updates->version_checked = $wp_version;
lucha's avatar
lucha committed
153 154 155 156

	if ( isset( $body['translations'] ) )
		$updates->translations = $body['translations'];

godog's avatar
godog committed
157 158 159 160 161 162 163 164 165 166 167 168
	set_site_transient( 'update_core',  $updates);
}

/**
 * Check plugin versions against the latest versions hosted on WordPress.org.
 *
 * The WordPress version, PHP version, and Locale is sent along with a list of
 * all plugins installed. Checks against the WordPress server at
 * api.wordpress.org. Will only check if WordPress isn't installing.
 *
 * @package WordPress
 * @since 2.3.0
root's avatar
root committed
169
 * @uses $wp_version Used to notify the WordPress version.
godog's avatar
godog committed
170 171 172 173
 *
 * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
 */
function wp_update_plugins() {
shammash's avatar
shammash committed
174
	include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
godog's avatar
godog committed
175 176 177 178 179 180 181 182 183

	if ( defined('WP_INSTALLING') )
		return false;

	// If running blog-side, bail unless we've not checked in the last 12 hours
	if ( !function_exists( 'get_plugins' ) )
		require_once( ABSPATH . 'wp-admin/includes/plugin.php' );

	$plugins = get_plugins();
lucha's avatar
lucha committed
184 185
	$translations = wp_get_installed_translations( 'plugins' );

godog's avatar
godog committed
186 187 188 189 190 191 192 193
	$active  = get_option( 'active_plugins', array() );
	$current = get_site_transient( 'update_plugins' );
	if ( ! is_object($current) )
		$current = new stdClass;

	$new_option = new stdClass;
	$new_option->last_checked = time();

lechuck's avatar
lechuck committed
194 195
	// Check for update on a different schedule, depending on the page.
	switch ( current_filter() ) {
lucha's avatar
lucha committed
196 197 198
		case 'upgrader_process_complete' :
			$timeout = 0;
			break;
lechuck's avatar
lechuck committed
199
		case 'load-update-core.php' :
lechuck's avatar
lechuck committed
200
			$timeout = MINUTE_IN_SECONDS;
lechuck's avatar
lechuck committed
201 202 203
			break;
		case 'load-plugins.php' :
		case 'load-update.php' :
lechuck's avatar
lechuck committed
204
			$timeout = HOUR_IN_SECONDS;
lechuck's avatar
lechuck committed
205 206
			break;
		default :
lechuck's avatar
lechuck committed
207
			$timeout = 12 * HOUR_IN_SECONDS;
godog's avatar
godog committed
208 209
	}

lechuck's avatar
lechuck committed
210 211 212 213 214 215 216 217
	$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );

	if ( $time_not_changed ) {
		$plugin_changed = false;
		foreach ( $plugins as $file => $p ) {
			$new_option->checked[ $file ] = $p['Version'];

			if ( !isset( $current->checked[ $file ] ) || strval($current->checked[ $file ]) !== strval($p['Version']) )
godog's avatar
godog committed
218
				$plugin_changed = true;
lechuck's avatar
lechuck committed
219 220 221 222 223 224 225 226
		}

		if ( isset ( $current->response ) && is_array( $current->response ) ) {
			foreach ( $current->response as $plugin_file => $update_details ) {
				if ( ! isset($plugins[ $plugin_file ]) ) {
					$plugin_changed = true;
					break;
				}
godog's avatar
godog committed
227 228 229
			}
		}

lechuck's avatar
lechuck committed
230 231 232 233
		// Bail if we've checked recently and if nothing has changed
		if ( ! $plugin_changed )
			return false;
	}
godog's avatar
godog committed
234 235 236 237 238

	// Update last_checked for current to prevent multiple blocking requests if request hangs
	$current->last_checked = time();
	set_site_transient( 'update_plugins', $current );

lucha's avatar
lucha committed
239 240 241 242 243 244 245 246 247 248 249
	$to_send = compact( 'plugins', 'active' );

	$locales = array( get_locale() );
	/**
	 * Filter the locales requested for plugin translations.
	 *
	 * @since 3.7.0
	 *
	 * @param array $locales Plugin locale. Default is current locale of the site.
	 */
	$locales = apply_filters( 'plugins_update_check_locales', $locales );
godog's avatar
godog committed
250 251 252

	$options = array(
		'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3),
lucha's avatar
lucha committed
253 254 255 256 257
		'body' => array(
			'plugins'      => json_encode( $to_send ),
			'translations' => json_encode( $translations ),
			'locale'       => json_encode( $locales ),
		),
godog's avatar
godog committed
258 259 260
		'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
	);

lucha's avatar
lucha committed
261 262 263 264 265 266 267 268 269
	$url = $http_url = 'http://api.wordpress.org/plugins/update-check/1.1/';
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
		$url = set_url_scheme( $url, 'https' );

	$raw_response = wp_remote_post( $url, $options );
	if ( $ssl && is_wp_error( $raw_response ) ) {
		trigger_error( __( '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="http://wordpress.org/support/">support forums</a>.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
		$raw_response = wp_remote_post( $http_url, $options );
	}
godog's avatar
godog committed
270

shammash's avatar
shammash committed
271
	if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) )
godog's avatar
godog committed
272 273
		return false;

lucha's avatar
lucha committed
274 275 276 277 278
	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );
	foreach ( $response['plugins'] as &$plugin ) {
		$plugin = (object) $plugin;
	}
	unset( $plugin );
godog's avatar
godog committed
279

lucha's avatar
lucha committed
280 281 282 283
	if ( is_array( $response ) ) {
		$new_option->response = $response['plugins'];
		$new_option->translations = $response['translations'];
	} else {
godog's avatar
godog committed
284
		$new_option->response = array();
lucha's avatar
lucha committed
285 286
		$new_option->translations = array();
	}
godog's avatar
godog committed
287 288 289 290 291 292 293 294 295 296 297 298 299

	set_site_transient( 'update_plugins', $new_option );
}

/**
 * Check theme versions against the latest versions hosted on WordPress.org.
 *
 * A list of all themes installed in sent to WP. Checks against the
 * WordPress server at api.wordpress.org. Will only check if WordPress isn't
 * installing.
 *
 * @package WordPress
 * @since 2.7.0
root's avatar
root committed
300
 * @uses $wp_version Used to notify the WordPress version.
godog's avatar
godog committed
301 302 303
 *
 * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
 */
shammash's avatar
shammash committed
304 305
function wp_update_themes() {
	include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
godog's avatar
godog committed
306 307 308 309

	if ( defined( 'WP_INSTALLING' ) )
		return false;

lechuck's avatar
lechuck committed
310
	$installed_themes = wp_get_themes();
lucha's avatar
lucha committed
311 312
	$translations = wp_get_installed_translations( 'themes' );

godog's avatar
godog committed
313 314 315 316
	$last_update = get_site_transient( 'update_themes' );
	if ( ! is_object($last_update) )
		$last_update = new stdClass;

lucha's avatar
lucha committed
317
	$themes = $checked = $request = array();
godog's avatar
godog committed
318 319

	// Put slug of current theme into request.
lucha's avatar
lucha committed
320
	$request['active'] = get_option( 'stylesheet' );
godog's avatar
godog committed
321

lechuck's avatar
lechuck committed
322 323 324 325 326 327 328 329 330 331 332 333 334
	foreach ( $installed_themes as $theme ) {
		$checked[ $theme->get_stylesheet() ] = $theme->get('Version');

		$themes[ $theme->get_stylesheet() ] = array(
			'Name'       => $theme->get('Name'),
			'Title'      => $theme->get('Name'),
			'Version'    => $theme->get('Version'),
			'Author'     => $theme->get('Author'),
			'Author URI' => $theme->get('AuthorURI'),
			'Template'   => $theme->get_template(),
			'Stylesheet' => $theme->get_stylesheet(),
		);
	}
godog's avatar
godog committed
335

lechuck's avatar
lechuck committed
336 337
	// Check for update on a different schedule, depending on the page.
	switch ( current_filter() ) {
lucha's avatar
lucha committed
338 339 340
		case 'upgrader_process_complete' :
			$timeout = 0;
			break;
lechuck's avatar
lechuck committed
341
		case 'load-update-core.php' :
lechuck's avatar
lechuck committed
342
			$timeout = MINUTE_IN_SECONDS;
lechuck's avatar
lechuck committed
343 344 345
			break;
		case 'load-themes.php' :
		case 'load-update.php' :
lechuck's avatar
lechuck committed
346
			$timeout = HOUR_IN_SECONDS;
lechuck's avatar
lechuck committed
347 348
			break;
		default :
lechuck's avatar
lechuck committed
349
			$timeout = 12 * HOUR_IN_SECONDS;
godog's avatar
godog committed
350 351
	}

lechuck's avatar
lechuck committed
352
	$time_not_changed = isset( $last_update->last_checked ) && $timeout > ( time() - $last_update->last_checked );
godog's avatar
godog committed
353

lechuck's avatar
lechuck committed
354 355 356 357
	if ( $time_not_changed ) {
		$theme_changed = false;
		foreach ( $checked as $slug => $v ) {
			if ( !isset( $last_update->checked[ $slug ] ) || strval($last_update->checked[ $slug ]) !== strval($v) )
godog's avatar
godog committed
358
				$theme_changed = true;
lechuck's avatar
lechuck committed
359 360 361 362 363 364 365 366
		}

		if ( isset ( $last_update->response ) && is_array( $last_update->response ) ) {
			foreach ( $last_update->response as $slug => $update_details ) {
				if ( ! isset($checked[ $slug ]) ) {
					$theme_changed = true;
					break;
				}
godog's avatar
godog committed
367 368 369
			}
		}

lechuck's avatar
lechuck committed
370 371 372 373
		// Bail if we've checked recently and if nothing has changed
		if ( ! $theme_changed )
			return false;
	}
godog's avatar
godog committed
374 375 376 377 378

	// Update last_checked for current to prevent multiple blocking requests if request hangs
	$last_update->last_checked = time();
	set_site_transient( 'update_themes', $last_update );

lucha's avatar
lucha committed
379 380 381 382 383 384 385 386 387 388 389 390
	$request['themes'] = $themes;

	$locales = array( get_locale() );
	/**
	 * Filter the locales requested for theme translations.
	 *
	 * @since 3.7.0
	 *
	 * @param array $locales Theme locale. Default is current locale of the site.
	 */
	$locales = apply_filters( 'themes_update_check_locales', $locales );

godog's avatar
godog committed
391 392
	$options = array(
		'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3),
lucha's avatar
lucha committed
393 394 395 396 397
		'body' => array(
			'themes'       => json_encode( $request ),
			'translations' => json_encode( $translations ),
			'locale'       => json_encode( $locales ),
		),
godog's avatar
godog committed
398 399 400
		'user-agent'	=> 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
	);

lucha's avatar
lucha committed
401 402 403 404 405 406 407 408 409
	$url = $http_url = 'http://api.wordpress.org/themes/update-check/1.1/';
	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
		$url = set_url_scheme( $url, 'https' );

	$raw_response = wp_remote_post( $url, $options );
	if ( $ssl && is_wp_error( $raw_response ) ) {
		trigger_error( __( '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="http://wordpress.org/support/">support forums</a>.' ) . ' ' . '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)', headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
		$raw_response = wp_remote_post( $http_url, $options );
	}
godog's avatar
godog committed
410

shammash's avatar
shammash committed
411
	if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) )
godog's avatar
godog committed
412 413 414
		return false;

	$new_update = new stdClass;
lechuck's avatar
lechuck committed
415
	$new_update->last_checked = time();
shammash's avatar
shammash committed
416 417
	$new_update->checked = $checked;

lucha's avatar
lucha committed
418 419 420 421 422 423
	$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );

	if ( is_array( $response ) ) {
		$new_update->response     = $response['themes'];
		$new_update->translations = $response['translations'];
	}
godog's avatar
godog committed
424 425 426 427

	set_site_transient( 'update_themes', $new_update );
}

lucha's avatar
lucha committed
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
/**
 * Performs WordPress automatic background updates.
 *
 * @since 3.7.0
 */
function wp_maybe_auto_update() {
	include_once ABSPATH . '/wp-admin/includes/admin.php';
	include_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';

	$upgrader = new WP_Automatic_Updater;
	$upgrader->run();
}

/**
 * Retrieves a list of all language updates available.
 *
 * @since 3.7.0
 */
function wp_get_translation_updates() {
	$updates = array();
	$transients = array( 'update_core' => 'core', 'update_plugins' => 'plugin', 'update_themes' => 'theme' );
	foreach ( $transients as $transient => $type ) {

		$transient = get_site_transient( $transient );
		if ( empty( $transient->translations ) )
			continue;

		foreach ( $transient->translations as $translation ) {
			$updates[] = (object) $translation;
		}
	}

	return $updates;
}

lucha's avatar
lucha committed
463
/**
root's avatar
root committed
464 465 466 467 468 469 470
 * Collect counts and UI strings for available updates
 *
 * @since 3.3.0
 *
 * @return array
 */
function wp_get_update_data() {
lucha's avatar
lucha committed
471
	$counts = array( 'plugins' => 0, 'themes' => 0, 'wordpress' => 0, 'translations' => 0 );
root's avatar
root committed
472

lucha's avatar
lucha committed
473
	if ( $plugins = current_user_can( 'update_plugins' ) ) {
root's avatar
root committed
474 475 476 477 478
		$update_plugins = get_site_transient( 'update_plugins' );
		if ( ! empty( $update_plugins->response ) )
			$counts['plugins'] = count( $update_plugins->response );
	}

lucha's avatar
lucha committed
479
	if ( $themes = current_user_can( 'update_themes' ) ) {
root's avatar
root committed
480 481 482 483 484
		$update_themes = get_site_transient( 'update_themes' );
		if ( ! empty( $update_themes->response ) )
			$counts['themes'] = count( $update_themes->response );
	}

lucha's avatar
lucha committed
485
	if ( ( $core = current_user_can( 'update_core' ) ) && function_exists( 'get_core_updates' ) ) {
root's avatar
root committed
486 487 488 489 490
		$update_wordpress = get_core_updates( array('dismissed' => false) );
		if ( ! empty( $update_wordpress ) && ! in_array( $update_wordpress[0]->response, array('development', 'latest') ) && current_user_can('update_core') )
			$counts['wordpress'] = 1;
	}

lucha's avatar
lucha committed
491 492 493 494
	if ( ( $core || $plugins || $themes ) && wp_get_translation_updates() )
		$counts['translations'] = 1;

	$counts['total'] = $counts['plugins'] + $counts['themes'] + $counts['wordpress'] + $counts['translations'];
lechuck's avatar
lechuck committed
495
	$titles = array();
root's avatar
root committed
496
	if ( $counts['wordpress'] )
lechuck's avatar
lechuck committed
497
		$titles['wordpress'] = sprintf( __( '%d WordPress Update'), $counts['wordpress'] );
root's avatar
root committed
498
	if ( $counts['plugins'] )
lechuck's avatar
lechuck committed
499
		$titles['plugins'] = sprintf( _n( '%d Plugin Update', '%d Plugin Updates', $counts['plugins'] ), $counts['plugins'] );
root's avatar
root committed
500
	if ( $counts['themes'] )
lechuck's avatar
lechuck committed
501
		$titles['themes'] = sprintf( _n( '%d Theme Update', '%d Theme Updates', $counts['themes'] ), $counts['themes'] );
lucha's avatar
lucha committed
502 503
	if ( $counts['translations'] )
		$titles['translations'] = __( 'Translation Updates' );
root's avatar
root committed
504

lechuck's avatar
lechuck committed
505
	$update_title = $titles ? esc_attr( implode( ', ', $titles ) ) : '';
root's avatar
root committed
506

lucha's avatar
lucha committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
	$update_data = array( 'counts' => $counts, 'title' => $update_title );
	/**
	 * Filter the returned array of update data for plugins, themes, and WordPress core.
	 *
	 * @since 3.5.0
	 *
	 * @param array $update_data {
	 *     Fetched update data.
	 *
	 *     @type array   $counts       An array of counts for available plugin, theme, and WordPress updates.
	 *     @type string  $update_title Titles of available updates.
	 * }
	 * @param array $titles An array of update counts and UI strings for available updates.
	 */
	return apply_filters( 'wp_get_update_data', $update_data, $titles );
root's avatar
root committed
522 523
}

godog's avatar
godog committed
524
function _maybe_update_core() {
shammash's avatar
shammash committed
525
	include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
godog's avatar
godog committed
526 527 528 529

	$current = get_site_transient( 'update_core' );

	if ( isset( $current->last_checked ) &&
lechuck's avatar
lechuck committed
530
		12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) &&
godog's avatar
godog committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
		isset( $current->version_checked ) &&
		$current->version_checked == $wp_version )
		return;

	wp_version_check();
}
/**
 * Check the last time plugins were run before checking plugin versions.
 *
 * This might have been backported to WordPress 2.6.1 for performance reasons.
 * This is used for the wp-admin to check only so often instead of every page
 * load.
 *
 * @since 2.7.0
 * @access private
 */
function _maybe_update_plugins() {
	$current = get_site_transient( 'update_plugins' );
lechuck's avatar
lechuck committed
549
	if ( isset( $current->last_checked ) && 12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) )
godog's avatar
godog committed
550 551 552 553 554 555 556 557 558 559 560 561 562
		return;
	wp_update_plugins();
}

/**
 * Check themes versions only after a duration of time.
 *
 * This is for performance reasons to make sure that on the theme version
 * checker is not run on every page load.
 *
 * @since 2.7.0
 * @access private
 */
lechuck's avatar
lechuck committed
563
function _maybe_update_themes() {
godog's avatar
godog committed
564
	$current = get_site_transient( 'update_themes' );
lechuck's avatar
lechuck committed
565
	if ( isset( $current->last_checked ) && 12 * HOUR_IN_SECONDS > ( time() - $current->last_checked ) )
godog's avatar
godog committed
566 567 568 569 570
		return;

	wp_update_themes();
}

root's avatar
root committed
571 572 573 574 575 576 577 578 579 580 581 582 583 584
/**
 * Schedule core, theme, and plugin update checks.
 *
 * @since 3.1.0
 */
function wp_schedule_update_checks() {
	if ( !wp_next_scheduled('wp_version_check') && !defined('WP_INSTALLING') )
		wp_schedule_event(time(), 'twicedaily', 'wp_version_check');

	if ( !wp_next_scheduled('wp_update_plugins') && !defined('WP_INSTALLING') )
		wp_schedule_event(time(), 'twicedaily', 'wp_update_plugins');

	if ( !wp_next_scheduled('wp_update_themes') && !defined('WP_INSTALLING') )
		wp_schedule_event(time(), 'twicedaily', 'wp_update_themes');
lucha's avatar
lucha committed
585 586 587 588 589 590 591 592 593 594

	if ( ! wp_next_scheduled( 'wp_maybe_auto_update' ) && ! defined( 'WP_INSTALLING' ) ) {
		// Schedule auto updates for 7 a.m. and 7 p.m. in the timezone of the site.
		$next = strtotime( 'today 7am' );
		$now = time();
		// Find the next instance of 7 a.m. or 7 p.m., but skip it if it is within 3 hours from now.
		while ( ( $now + 3 * HOUR_IN_SECONDS ) > $next ) {
			$next += 12 * HOUR_IN_SECONDS;
		}
		$next = $next - get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
lucha's avatar
lucha committed
595 596
		// Add a random number of minutes, so we don't have all sites trying to update exactly on the hour
		$next = $next + rand( 0, 59 ) * MINUTE_IN_SECONDS;
lucha's avatar
lucha committed
597 598
		wp_schedule_event( $next, 'twicedaily', 'wp_maybe_auto_update' );
	}
root's avatar
root committed
599 600
}

lechuck's avatar
lechuck committed
601
if ( ( ! is_main_site() && ! is_network_admin() ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )
root's avatar
root committed
602 603
	return;

godog's avatar
godog committed
604 605
add_action( 'admin_init', '_maybe_update_core' );
add_action( 'wp_version_check', 'wp_version_check' );
lucha's avatar
lucha committed
606
add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
godog's avatar
godog committed
607 608 609 610 611 612

add_action( 'load-plugins.php', 'wp_update_plugins' );
add_action( 'load-update.php', 'wp_update_plugins' );
add_action( 'load-update-core.php', 'wp_update_plugins' );
add_action( 'admin_init', '_maybe_update_plugins' );
add_action( 'wp_update_plugins', 'wp_update_plugins' );
lucha's avatar
lucha committed
613
add_action( 'upgrader_process_complete', 'wp_update_plugins' );
godog's avatar
godog committed
614 615 616 617 618 619

add_action( 'load-themes.php', 'wp_update_themes' );
add_action( 'load-update.php', 'wp_update_themes' );
add_action( 'load-update-core.php', 'wp_update_themes' );
add_action( 'admin_init', '_maybe_update_themes' );
add_action( 'wp_update_themes', 'wp_update_themes' );
lucha's avatar
lucha committed
620 621 622
add_action( 'upgrader_process_complete', 'wp_update_themes' );

add_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
godog's avatar
godog committed
623

root's avatar
root committed
624
add_action('init', 'wp_schedule_update_checks');