Wordpress 3.2-scripts
[autoinstalls/wordpress.git] / wp-includes / update.php
1 <?php
2 /**
3  * A simple set of functions to check our version 1.0 update service.
4  *
5  * @package WordPress
6  * @since 2.3.0
7  */
8
9 /**
10  * Check WordPress version against the newest version.
11  *
12  * The WordPress version, PHP version, and Locale is sent. Checks against the
13  * WordPress server at api.wordpress.org server. Will only check if WordPress
14  * isn't installing.
15  *
16  * @package WordPress
17  * @since 2.3.0
18  * @uses $wp_version Used to check against the newest WordPress version.
19  *
20  * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
21  */
22 function wp_version_check() {
23         if ( defined('WP_INSTALLING') )
24                 return;
25
26         global $wpdb, $wp_local_package;
27         include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
28         $php_version = phpversion();
29
30         $current = get_site_transient( 'update_core' );
31         if ( ! is_object($current) ) {
32                 $current = new stdClass;
33                 $current->updates = array();
34                 $current->version_checked = $wp_version;
35         }
36
37         $locale = apply_filters( 'core_version_check_locale', get_locale() );
38
39         // Update last_checked for current to prevent multiple blocking requests if request hangs
40         $current->last_checked = time();
41         set_site_transient( 'update_core', $current );
42
43         if ( method_exists( $wpdb, 'db_version' ) )
44                 $mysql_version = preg_replace('/[^0-9.].*/', '', $wpdb->db_version());
45         else
46                 $mysql_version = 'N/A';
47
48         if ( is_multisite( ) ) {
49                 $user_count = get_user_count( );
50                 $num_blogs = get_blog_count( );
51                 $wp_install = network_site_url( );
52                 $multisite_enabled = 1;
53         } else {
54                 $user_count = count_users( );
55                 $multisite_enabled = 0;
56                 $num_blogs = 1;
57                 $wp_install = home_url( '/' );
58         }
59
60         $local_package = isset( $wp_local_package )? $wp_local_package : '';
61         $url = "http://api.wordpress.org/core/version-check/1.6/?version=$wp_version&php=$php_version&locale=$locale&mysql=$mysql_version&local_package=$local_package&blogs=$num_blogs&users={$user_count['total_users']}&multisite_enabled=$multisite_enabled";
62
63         $options = array(
64                 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3 ),
65                 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ),
66                 'headers' => array(
67                         'wp_install' => $wp_install,
68                         'wp_blog' => home_url( '/' )
69                 )
70         );
71
72         $response = wp_remote_get($url, $options);
73
74         if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) )
75                 return false;
76
77         $body = trim( wp_remote_retrieve_body( $response ) );
78         if ( ! $body = maybe_unserialize( $body ) )
79                 return false;
80         if ( ! isset( $body['offers'] ) )
81                 return false;
82         $offers = $body['offers'];
83
84         foreach ( $offers as &$offer ) {
85                 foreach ( $offer as $offer_key => $value ) {
86                         if ( 'packages' == $offer_key )
87                                 $offer['packages'] = (object) array_intersect_key( array_map( 'esc_url', $offer['packages'] ),
88                                         array_fill_keys( array( 'full', 'no_content', 'new_bundled', 'partial' ), '' ) );
89                         elseif ( 'download' == $offer_key )
90                                 $offer['download'] = esc_url( $value );
91                         else
92                                 $offer[ $offer_key ] = esc_html( $value );
93                 }
94                 $offer = (object) array_intersect_key( $offer, array_fill_keys( array( 'response', 'download', 'locale',
95                         'packages', 'current', 'php_version', 'mysql_version', 'new_bundled', 'partial_version' ), '' ) );
96         }
97
98         $updates = new stdClass();
99         $updates->updates = $offers;
100         $updates->last_checked = time();
101         $updates->version_checked = $wp_version;
102         set_site_transient( 'update_core',  $updates);
103 }
104
105 /**
106  * Check plugin versions against the latest versions hosted on WordPress.org.
107  *
108  * The WordPress version, PHP version, and Locale is sent along with a list of
109  * all plugins installed. Checks against the WordPress server at
110  * api.wordpress.org. Will only check if WordPress isn't installing.
111  *
112  * @package WordPress
113  * @since 2.3.0
114  * @uses $wp_version Used to notify the WordPress version.
115  *
116  * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
117  */
118 function wp_update_plugins() {
119         include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
120
121         if ( defined('WP_INSTALLING') )
122                 return false;
123
124         // If running blog-side, bail unless we've not checked in the last 12 hours
125         if ( !function_exists( 'get_plugins' ) )
126                 require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
127
128         $plugins = get_plugins();
129         $active  = get_option( 'active_plugins', array() );
130         $current = get_site_transient( 'update_plugins' );
131         if ( ! is_object($current) )
132                 $current = new stdClass;
133
134         $new_option = new stdClass;
135         $new_option->last_checked = time();
136         $timeout = 'load-plugins.php' == current_filter() ? 3600 : 43200; //Check for updated every 60 minutes if hitting the themes page, Else, check every 12 hours
137         $time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
138
139         $plugin_changed = false;
140         foreach ( $plugins as $file => $p ) {
141                 $new_option->checked[ $file ] = $p['Version'];
142
143                 if ( !isset( $current->checked[ $file ] ) || strval($current->checked[ $file ]) !== strval($p['Version']) )
144                         $plugin_changed = true;
145         }
146
147         if ( isset ( $current->response ) && is_array( $current->response ) ) {
148                 foreach ( $current->response as $plugin_file => $update_details ) {
149                         if ( ! isset($plugins[ $plugin_file ]) ) {
150                                 $plugin_changed = true;
151                                 break;
152                         }
153                 }
154         }
155
156         // Bail if we've checked in the last 12 hours and if nothing has changed
157         if ( $time_not_changed && !$plugin_changed )
158                 return false;
159
160         // Update last_checked for current to prevent multiple blocking requests if request hangs
161         $current->last_checked = time();
162         set_site_transient( 'update_plugins', $current );
163
164         $to_send = (object) compact('plugins', 'active');
165
166         $options = array(
167                 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3),
168                 'body' => array( 'plugins' => serialize( $to_send ) ),
169                 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
170         );
171
172         $raw_response = wp_remote_post('http://api.wordpress.org/plugins/update-check/1.0/', $options);
173
174         if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) )
175                 return false;
176
177         $response = unserialize( wp_remote_retrieve_body( $raw_response ) );
178
179         if ( false !== $response )
180                 $new_option->response = $response;
181         else
182                 $new_option->response = array();
183
184         set_site_transient( 'update_plugins', $new_option );
185 }
186
187 /**
188  * Check theme versions against the latest versions hosted on WordPress.org.
189  *
190  * A list of all themes installed in sent to WP. Checks against the
191  * WordPress server at api.wordpress.org. Will only check if WordPress isn't
192  * installing.
193  *
194  * @package WordPress
195  * @since 2.7.0
196  * @uses $wp_version Used to notify the WordPress version.
197  *
198  * @return mixed Returns null if update is unsupported. Returns false if check is too soon.
199  */
200 function wp_update_themes() {
201         include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
202
203         if ( defined( 'WP_INSTALLING' ) )
204                 return false;
205
206         if ( !function_exists( 'get_themes' ) )
207                 require_once( ABSPATH . 'wp-includes/theme.php' );
208
209         $installed_themes = get_themes( );
210         $last_update = get_site_transient( 'update_themes' );
211         if ( ! is_object($last_update) )
212                 $last_update = new stdClass;
213
214         $timeout = 'load-themes.php' == current_filter() ? 3600 : 43200; //Check for updated every 60 minutes if hitting the themes page, Else, check every 12 hours
215         $time_not_changed = isset( $last_update->last_checked ) && $timeout > ( time( ) - $last_update->last_checked );
216
217         $themes = array();
218         $checked = array();
219         $exclude_fields = array('Template Files', 'Stylesheet Files', 'Status', 'Theme Root', 'Theme Root URI', 'Template Dir', 'Stylesheet Dir', 'Description', 'Tags', 'Screenshot');
220
221         // Put slug of current theme into request.
222         $themes['current_theme'] = get_option( 'stylesheet' );
223
224         foreach ( (array) $installed_themes as $theme_title => $theme ) {
225                 $themes[$theme['Stylesheet']] = array();
226                 $checked[$theme['Stylesheet']] = $theme['Version'];
227
228                 $themes[$theme['Stylesheet']]['Name'] = $theme['Name'];
229                 $themes[$theme['Stylesheet']]['Version'] = $theme['Version'];
230
231                 foreach ( (array) $theme as $key => $value ) {
232                         if ( !in_array($key, $exclude_fields) )
233                                 $themes[$theme['Stylesheet']][$key] = $value;
234                 }
235         }
236
237         $theme_changed = false;
238         foreach ( $checked as $slug => $v ) {
239                 $update_request->checked[ $slug ] = $v;
240
241                 if ( !isset( $last_update->checked[ $slug ] ) || strval($last_update->checked[ $slug ]) !== strval($v) )
242                         $theme_changed = true;
243         }
244
245         if ( isset ( $last_update->response ) && is_array( $last_update->response ) ) {
246                 foreach ( $last_update->response as $slug => $update_details ) {
247                         if ( ! isset($checked[ $slug ]) ) {
248                                 $theme_changed = true;
249                                 break;
250                         }
251                 }
252         }
253
254         if ( $time_not_changed && !$theme_changed )
255                 return false;
256
257         // Update last_checked for current to prevent multiple blocking requests if request hangs
258         $last_update->last_checked = time();
259         set_site_transient( 'update_themes', $last_update );
260
261         $options = array(
262                 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3),
263                 'body'                  => array( 'themes' => serialize( $themes ) ),
264                 'user-agent'    => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
265         );
266
267         $raw_response = wp_remote_post( 'http://api.wordpress.org/themes/update-check/1.0/', $options );
268
269         if ( is_wp_error( $raw_response ) || 200 != wp_remote_retrieve_response_code( $raw_response ) )
270                 return false;
271
272         $new_update = new stdClass;
273         $new_update->last_checked = time( );
274         $new_update->checked = $checked;
275
276         $response = unserialize( wp_remote_retrieve_body( $raw_response ) );
277         if ( false !== $response )
278                 $new_update->response = $response;
279
280         set_site_transient( 'update_themes', $new_update );
281 }
282
283 function _maybe_update_core() {
284         include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
285
286         $current = get_site_transient( 'update_core' );
287
288         if ( isset( $current->last_checked ) &&
289                 43200 > ( time() - $current->last_checked ) &&
290                 isset( $current->version_checked ) &&
291                 $current->version_checked == $wp_version )
292                 return;
293
294         wp_version_check();
295 }
296 /**
297  * Check the last time plugins were run before checking plugin versions.
298  *
299  * This might have been backported to WordPress 2.6.1 for performance reasons.
300  * This is used for the wp-admin to check only so often instead of every page
301  * load.
302  *
303  * @since 2.7.0
304  * @access private
305  */
306 function _maybe_update_plugins() {
307         $current = get_site_transient( 'update_plugins' );
308         if ( isset( $current->last_checked ) && 43200 > ( time() - $current->last_checked ) )
309                 return;
310         wp_update_plugins();
311 }
312
313 /**
314  * Check themes versions only after a duration of time.
315  *
316  * This is for performance reasons to make sure that on the theme version
317  * checker is not run on every page load.
318  *
319  * @since 2.7.0
320  * @access private
321  */
322 function _maybe_update_themes( ) {
323         $current = get_site_transient( 'update_themes' );
324         if ( isset( $current->last_checked ) && 43200 > ( time( ) - $current->last_checked ) )
325                 return;
326
327         wp_update_themes();
328 }
329
330 /**
331  * Schedule core, theme, and plugin update checks.
332  *
333  * @since 3.1.0
334  */
335 function wp_schedule_update_checks() {
336         if ( !wp_next_scheduled('wp_version_check') && !defined('WP_INSTALLING') )
337                 wp_schedule_event(time(), 'twicedaily', 'wp_version_check');
338
339         if ( !wp_next_scheduled('wp_update_plugins') && !defined('WP_INSTALLING') )
340                 wp_schedule_event(time(), 'twicedaily', 'wp_update_plugins');
341
342         if ( !wp_next_scheduled('wp_update_themes') && !defined('WP_INSTALLING') )
343                 wp_schedule_event(time(), 'twicedaily', 'wp_update_themes');
344 }
345
346 if ( ! is_main_site() )
347         return;
348
349 add_action( 'admin_init', '_maybe_update_core' );
350 add_action( 'wp_version_check', 'wp_version_check' );
351
352 add_action( 'load-plugins.php', 'wp_update_plugins' );
353 add_action( 'load-update.php', 'wp_update_plugins' );
354 add_action( 'load-update-core.php', 'wp_update_plugins' );
355 add_action( 'admin_init', '_maybe_update_plugins' );
356 add_action( 'wp_update_plugins', 'wp_update_plugins' );
357
358 add_action( 'load-themes.php', 'wp_update_themes' );
359 add_action( 'load-update.php', 'wp_update_themes' );
360 add_action( 'load-update-core.php', 'wp_update_themes' );
361 add_action( 'admin_init', '_maybe_update_themes' );
362 add_action( 'wp_update_themes', 'wp_update_themes' );
363
364 add_action('init', 'wp_schedule_update_checks');
365
366 ?>