Wordpress 4.6
[autoinstalls/wordpress.git] / wp-admin / includes / upgrade.php
1 <?php
2 /**
3  * WordPress Upgrade API
4  *
5  * Most of the functions are pluggable and can be overwritten.
6  *
7  * @package WordPress
8  * @subpackage Administration
9  */
10
11 /** Include user install customize script. */
12 if ( file_exists(WP_CONTENT_DIR . '/install.php') )
13         require (WP_CONTENT_DIR . '/install.php');
14
15 /** WordPress Administration API */
16 require_once(ABSPATH . 'wp-admin/includes/admin.php');
17
18 /** WordPress Schema API */
19 require_once(ABSPATH . 'wp-admin/includes/schema.php');
20
21 if ( !function_exists('wp_install') ) :
22 /**
23  * Installs the site.
24  *
25  * Runs the required functions to set up and populate the database,
26  * including primary admin user and initial options.
27  *
28  * @since 2.1.0
29  *
30  * @param string $blog_title    Site title.
31  * @param string $user_name     User's username.
32  * @param string $user_email    User's email.
33  * @param bool   $public        Whether site is public.
34  * @param string $deprecated    Optional. Not used.
35  * @param string $user_password Optional. User's chosen password. Default empty (random password).
36  * @param string $language      Optional. Language chosen. Default empty.
37  * @return array Array keys 'url', 'user_id', 'password', and 'password_message'.
38  */
39 function wp_install( $blog_title, $user_name, $user_email, $public, $deprecated = '', $user_password = '', $language = '' ) {
40         if ( !empty( $deprecated ) )
41                 _deprecated_argument( __FUNCTION__, '2.6.0' );
42
43         wp_check_mysql_version();
44         wp_cache_flush();
45         make_db_current_silent();
46         populate_options();
47         populate_roles();
48
49         update_option('blogname', $blog_title);
50         update_option('admin_email', $user_email);
51         update_option('blog_public', $public);
52
53         if ( $language ) {
54                 update_option( 'WPLANG', $language );
55         }
56
57         $guessurl = wp_guess_url();
58
59         update_option('siteurl', $guessurl);
60
61         // If not a public blog, don't ping.
62         if ( ! $public )
63                 update_option('default_pingback_flag', 0);
64
65         /*
66          * Create default user. If the user already exists, the user tables are
67          * being shared among sites. Just set the role in that case.
68          */
69         $user_id = username_exists($user_name);
70         $user_password = trim($user_password);
71         $email_password = false;
72         if ( !$user_id && empty($user_password) ) {
73                 $user_password = wp_generate_password( 12, false );
74                 $message = __('<strong><em>Note that password</em></strong> carefully! It is a <em>random</em> password that was generated just for you.');
75                 $user_id = wp_create_user($user_name, $user_password, $user_email);
76                 update_user_option($user_id, 'default_password_nag', true, true);
77                 $email_password = true;
78         } elseif ( ! $user_id ) {
79                 // Password has been provided
80                 $message = '<em>'.__('Your chosen password.').'</em>';
81                 $user_id = wp_create_user($user_name, $user_password, $user_email);
82         } else {
83                 $message = __('User already exists. Password inherited.');
84         }
85
86         $user = new WP_User($user_id);
87         $user->set_role('administrator');
88
89         wp_install_defaults($user_id);
90
91         wp_install_maybe_enable_pretty_permalinks();
92
93         flush_rewrite_rules();
94
95         wp_new_blog_notification($blog_title, $guessurl, $user_id, ($email_password ? $user_password : __('The password you chose during the install.') ) );
96
97         wp_cache_flush();
98
99         /**
100          * Fires after a site is fully installed.
101          *
102          * @since 3.9.0
103          *
104          * @param WP_User $user The site owner.
105          */
106         do_action( 'wp_install', $user );
107
108         return array('url' => $guessurl, 'user_id' => $user_id, 'password' => $user_password, 'password_message' => $message);
109 }
110 endif;
111
112 if ( !function_exists('wp_install_defaults') ) :
113 /**
114  * Creates the initial content for a newly-installed site.
115  *
116  * Adds the default "Uncategorized" category, the first post (with comment),
117  * first page, and default widgets for default theme for the current version.
118  *
119  * @since 2.1.0
120  *
121  * @global wpdb       $wpdb
122  * @global WP_Rewrite $wp_rewrite
123  * @global string     $table_prefix
124  *
125  * @param int $user_id User ID.
126  */
127 function wp_install_defaults( $user_id ) {
128         global $wpdb, $wp_rewrite, $table_prefix;
129
130         // Default category
131         $cat_name = __('Uncategorized');
132         /* translators: Default category slug */
133         $cat_slug = sanitize_title(_x('Uncategorized', 'Default category slug'));
134
135         if ( global_terms_enabled() ) {
136                 $cat_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = %s", $cat_slug ) );
137                 if ( $cat_id == null ) {
138                         $wpdb->insert( $wpdb->sitecategories, array('cat_ID' => 0, 'cat_name' => $cat_name, 'category_nicename' => $cat_slug, 'last_updated' => current_time('mysql', true)) );
139                         $cat_id = $wpdb->insert_id;
140                 }
141                 update_option('default_category', $cat_id);
142         } else {
143                 $cat_id = 1;
144         }
145
146         $wpdb->insert( $wpdb->terms, array('term_id' => $cat_id, 'name' => $cat_name, 'slug' => $cat_slug, 'term_group' => 0) );
147         $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $cat_id, 'taxonomy' => 'category', 'description' => '', 'parent' => 0, 'count' => 1));
148         $cat_tt_id = $wpdb->insert_id;
149
150         // First post
151         $now = current_time( 'mysql' );
152         $now_gmt = current_time( 'mysql', 1 );
153         $first_post_guid = get_option( 'home' ) . '/?p=1';
154
155         if ( is_multisite() ) {
156                 $first_post = get_site_option( 'first_post' );
157
158                 if ( ! $first_post ) {
159                         /* translators: %s: site link */
160                         $first_post = __( 'Welcome to %s. This is your first post. Edit or delete it, then start blogging!' );
161                 }
162
163                 $first_post = sprintf( $first_post,
164                         sprintf( '<a href="%s">%s</a>', esc_url( network_home_url() ), get_current_site()->site_name )
165                 );
166
167                 // Back-compat for pre-4.4
168                 $first_post = str_replace( 'SITE_URL', esc_url( network_home_url() ), $first_post );
169                 $first_post = str_replace( 'SITE_NAME', get_current_site()->site_name, $first_post );
170         } else {
171                 $first_post = __( 'Welcome to WordPress. This is your first post. Edit or delete it, then start writing!' );
172         }
173
174         $wpdb->insert( $wpdb->posts, array(
175                 'post_author' => $user_id,
176                 'post_date' => $now,
177                 'post_date_gmt' => $now_gmt,
178                 'post_content' => $first_post,
179                 'post_excerpt' => '',
180                 'post_title' => __('Hello world!'),
181                 /* translators: Default post slug */
182                 'post_name' => sanitize_title( _x('hello-world', 'Default post slug') ),
183                 'post_modified' => $now,
184                 'post_modified_gmt' => $now_gmt,
185                 'guid' => $first_post_guid,
186                 'comment_count' => 1,
187                 'to_ping' => '',
188                 'pinged' => '',
189                 'post_content_filtered' => ''
190         ));
191         $wpdb->insert( $wpdb->term_relationships, array('term_taxonomy_id' => $cat_tt_id, 'object_id' => 1) );
192
193         // Default comment
194         $first_comment_author = __( 'A WordPress Commenter' );
195         $first_comment_email = 'wapuu@wordpress.example';
196         $first_comment_url = 'https://wordpress.org/';
197         $first_comment = __( 'Hi, this is a comment.
198 To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
199 Commenter avatars come from <a href="https://gravatar.com">Gravatar</a>.' );
200         if ( is_multisite() ) {
201                 $first_comment_author = get_site_option( 'first_comment_author', $first_comment_author );
202                 $first_comment_email = get_site_option( 'first_comment_email', $first_comment_email );
203                 $first_comment_url = get_site_option( 'first_comment_url', network_home_url() );
204                 $first_comment = get_site_option( 'first_comment', $first_comment );
205         }
206         $wpdb->insert( $wpdb->comments, array(
207                 'comment_post_ID' => 1,
208                 'comment_author' => $first_comment_author,
209                 'comment_author_email' => $first_comment_email,
210                 'comment_author_url' => $first_comment_url,
211                 'comment_date' => $now,
212                 'comment_date_gmt' => $now_gmt,
213                 'comment_content' => $first_comment
214         ));
215
216         // First Page
217         $first_page = sprintf( __( "This is an example page. It's different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this:
218
219 <blockquote>Hi there! I'm a bike messenger by day, aspiring actor by night, and this is my website. I live in Los Angeles, have a great dog named Jack, and I like pi&#241;a coladas. (And gettin' caught in the rain.)</blockquote>
220
221 ...or something like this:
222
223 <blockquote>The XYZ Doohickey Company was founded in 1971, and has been providing quality doohickeys to the public ever since. Located in Gotham City, XYZ employs over 2,000 people and does all kinds of awesome things for the Gotham community.</blockquote>
224
225 As a new WordPress user, you should go to <a href=\"%s\">your dashboard</a> to delete this page and create new pages for your content. Have fun!" ), admin_url() );
226         if ( is_multisite() )
227                 $first_page = get_site_option( 'first_page', $first_page );
228         $first_post_guid = get_option('home') . '/?page_id=2';
229         $wpdb->insert( $wpdb->posts, array(
230                 'post_author' => $user_id,
231                 'post_date' => $now,
232                 'post_date_gmt' => $now_gmt,
233                 'post_content' => $first_page,
234                 'post_excerpt' => '',
235                 'comment_status' => 'closed',
236                 'post_title' => __( 'Sample Page' ),
237                 /* translators: Default page slug */
238                 'post_name' => __( 'sample-page' ),
239                 'post_modified' => $now,
240                 'post_modified_gmt' => $now_gmt,
241                 'guid' => $first_post_guid,
242                 'post_type' => 'page',
243                 'to_ping' => '',
244                 'pinged' => '',
245                 'post_content_filtered' => ''
246         ));
247         $wpdb->insert( $wpdb->postmeta, array( 'post_id' => 2, 'meta_key' => '_wp_page_template', 'meta_value' => 'default' ) );
248
249         // Set up default widgets for default theme.
250         update_option( 'widget_search', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) );
251         update_option( 'widget_recent-posts', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) );
252         update_option( 'widget_recent-comments', array ( 2 => array ( 'title' => '', 'number' => 5 ), '_multiwidget' => 1 ) );
253         update_option( 'widget_archives', array ( 2 => array ( 'title' => '', 'count' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) );
254         update_option( 'widget_categories', array ( 2 => array ( 'title' => '', 'count' => 0, 'hierarchical' => 0, 'dropdown' => 0 ), '_multiwidget' => 1 ) );
255         update_option( 'widget_meta', array ( 2 => array ( 'title' => '' ), '_multiwidget' => 1 ) );
256         update_option( 'sidebars_widgets', array ( 'wp_inactive_widgets' => array (), 'sidebar-1' => array ( 0 => 'search-2', 1 => 'recent-posts-2', 2 => 'recent-comments-2', 3 => 'archives-2', 4 => 'categories-2', 5 => 'meta-2', ), 'array_version' => 3 ) );
257
258         if ( ! is_multisite() )
259                 update_user_meta( $user_id, 'show_welcome_panel', 1 );
260         elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) )
261                 update_user_meta( $user_id, 'show_welcome_panel', 2 );
262
263         if ( is_multisite() ) {
264                 // Flush rules to pick up the new page.
265                 $wp_rewrite->init();
266                 $wp_rewrite->flush_rules();
267
268                 $user = new WP_User($user_id);
269                 $wpdb->update( $wpdb->options, array('option_value' => $user->user_email), array('option_name' => 'admin_email') );
270
271                 // Remove all perms except for the login user.
272                 $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'user_level') );
273                 $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix.'capabilities') );
274
275                 // Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.) TODO: Get previous_blog_id.
276                 if ( !is_super_admin( $user_id ) && $user_id != 1 )
277                         $wpdb->delete( $wpdb->usermeta, array( 'user_id' => $user_id , 'meta_key' => $wpdb->base_prefix.'1_capabilities' ) );
278         }
279 }
280 endif;
281
282 /**
283  * Maybe enable pretty permalinks on install.
284  *
285  * If after enabling pretty permalinks don't work, fallback to query-string permalinks.
286  *
287  * @since 4.2.0
288  *
289  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
290  *
291  * @return bool Whether pretty permalinks are enabled. False otherwise.
292  */
293 function wp_install_maybe_enable_pretty_permalinks() {
294         global $wp_rewrite;
295
296         // Bail if a permalink structure is already enabled.
297         if ( get_option( 'permalink_structure' ) ) {
298                 return true;
299         }
300
301         /*
302          * The Permalink structures to attempt.
303          *
304          * The first is designed for mod_rewrite or nginx rewriting.
305          *
306          * The second is PATHINFO-based permalinks for web server configurations
307          * without a true rewrite module enabled.
308          */
309         $permalink_structures = array(
310                 '/%year%/%monthnum%/%day%/%postname%/',
311                 '/index.php/%year%/%monthnum%/%day%/%postname%/'
312         );
313
314         foreach ( (array) $permalink_structures as $permalink_structure ) {
315                 $wp_rewrite->set_permalink_structure( $permalink_structure );
316
317                 /*
318                  * Flush rules with the hard option to force refresh of the web-server's
319                  * rewrite config file (e.g. .htaccess or web.config).
320                  */
321                 $wp_rewrite->flush_rules( true );
322
323                 $test_url = '';
324
325                 // Test against a real WordPress Post
326                 $first_post = get_page_by_path( sanitize_title( _x( 'hello-world', 'Default post slug' ) ), OBJECT, 'post' );
327                 if ( $first_post ) {
328                         $test_url = get_permalink( $first_post->ID );
329                 }
330
331                 /*
332                  * Send a request to the site, and check whether
333                  * the 'x-pingback' header is returned as expected.
334                  *
335                  * Uses wp_remote_get() instead of wp_remote_head() because web servers
336                  * can block head requests.
337                  */
338                 $response          = wp_remote_get( $test_url, array( 'timeout' => 5 ) );
339                 $x_pingback_header = wp_remote_retrieve_header( $response, 'x-pingback' );
340                 $pretty_permalinks = $x_pingback_header && $x_pingback_header === get_bloginfo( 'pingback_url' );
341
342                 if ( $pretty_permalinks ) {
343                         return true;
344                 }
345         }
346
347         /*
348          * If it makes it this far, pretty permalinks failed.
349          * Fallback to query-string permalinks.
350          */
351         $wp_rewrite->set_permalink_structure( '' );
352         $wp_rewrite->flush_rules( true );
353
354         return false;
355 }
356
357 if ( !function_exists('wp_new_blog_notification') ) :
358 /**
359  * Notifies the site admin that the setup is complete.
360  *
361  * Sends an email with wp_mail to the new administrator that the site setup is complete,
362  * and provides them with a record of their login credentials.
363  *
364  * @since 2.1.0
365  *
366  * @param string $blog_title Site title.
367  * @param string $blog_url   Site url.
368  * @param int    $user_id    User ID.
369  * @param string $password   User's Password.
370  */
371 function wp_new_blog_notification($blog_title, $blog_url, $user_id, $password) {
372         $user = new WP_User( $user_id );
373         $email = $user->user_email;
374         $name = $user->user_login;
375         $login_url = wp_login_url();
376         $message = sprintf( __( "Your new WordPress site has been successfully set up at:
377
378 %1\$s
379
380 You can log in to the administrator account with the following information:
381
382 Username: %2\$s
383 Password: %3\$s
384 Log in here: %4\$s
385
386 We hope you enjoy your new site. Thanks!
387
388 --The WordPress Team
389 https://wordpress.org/
390 "), $blog_url, $name, $password, $login_url );
391
392         @wp_mail($email, __('New WordPress Site'), $message);
393 }
394 endif;
395
396 if ( !function_exists('wp_upgrade') ) :
397 /**
398  * Runs WordPress Upgrade functions.
399  *
400  * Upgrades the database if needed during a site update.
401  *
402  * @since 2.1.0
403  *
404  * @global int  $wp_current_db_version
405  * @global int  $wp_db_version
406  * @global wpdb $wpdb WordPress database abstraction object.
407  */
408 function wp_upgrade() {
409         global $wp_current_db_version, $wp_db_version, $wpdb;
410
411         $wp_current_db_version = __get_option('db_version');
412
413         // We are up-to-date. Nothing to do.
414         if ( $wp_db_version == $wp_current_db_version )
415                 return;
416
417         if ( ! is_blog_installed() )
418                 return;
419
420         wp_check_mysql_version();
421         wp_cache_flush();
422         pre_schema_upgrade();
423         make_db_current_silent();
424         upgrade_all();
425         if ( is_multisite() && is_main_site() )
426                 upgrade_network();
427         wp_cache_flush();
428
429         if ( is_multisite() ) {
430                 if ( $wpdb->get_row( "SELECT blog_id FROM {$wpdb->blog_versions} WHERE blog_id = '{$wpdb->blogid}'" ) )
431                         $wpdb->query( "UPDATE {$wpdb->blog_versions} SET db_version = '{$wp_db_version}' WHERE blog_id = '{$wpdb->blogid}'" );
432                 else
433                         $wpdb->query( "INSERT INTO {$wpdb->blog_versions} ( `blog_id` , `db_version` , `last_updated` ) VALUES ( '{$wpdb->blogid}', '{$wp_db_version}', NOW());" );
434         }
435
436         /**
437          * Fires after a site is fully upgraded.
438          *
439          * @since 3.9.0
440          *
441          * @param int $wp_db_version         The new $wp_db_version.
442          * @param int $wp_current_db_version The old (current) $wp_db_version.
443          */
444         do_action( 'wp_upgrade', $wp_db_version, $wp_current_db_version );
445 }
446 endif;
447
448 /**
449  * Functions to be called in install and upgrade scripts.
450  *
451  * Contains conditional checks to determine which upgrade scripts to run,
452  * based on database version and WP version being updated-to.
453  *
454  * @ignore
455  * @since 1.0.1
456  *
457  * @global int $wp_current_db_version
458  * @global int $wp_db_version
459  */
460 function upgrade_all() {
461         global $wp_current_db_version, $wp_db_version;
462         $wp_current_db_version = __get_option('db_version');
463
464         // We are up-to-date. Nothing to do.
465         if ( $wp_db_version == $wp_current_db_version )
466                 return;
467
468         // If the version is not set in the DB, try to guess the version.
469         if ( empty($wp_current_db_version) ) {
470                 $wp_current_db_version = 0;
471
472                 // If the template option exists, we have 1.5.
473                 $template = __get_option('template');
474                 if ( !empty($template) )
475                         $wp_current_db_version = 2541;
476         }
477
478         if ( $wp_current_db_version < 6039 )
479                 upgrade_230_options_table();
480
481         populate_options();
482
483         if ( $wp_current_db_version < 2541 ) {
484                 upgrade_100();
485                 upgrade_101();
486                 upgrade_110();
487                 upgrade_130();
488         }
489
490         if ( $wp_current_db_version < 3308 )
491                 upgrade_160();
492
493         if ( $wp_current_db_version < 4772 )
494                 upgrade_210();
495
496         if ( $wp_current_db_version < 4351 )
497                 upgrade_old_slugs();
498
499         if ( $wp_current_db_version < 5539 )
500                 upgrade_230();
501
502         if ( $wp_current_db_version < 6124 )
503                 upgrade_230_old_tables();
504
505         if ( $wp_current_db_version < 7499 )
506                 upgrade_250();
507
508         if ( $wp_current_db_version < 7935 )
509                 upgrade_252();
510
511         if ( $wp_current_db_version < 8201 )
512                 upgrade_260();
513
514         if ( $wp_current_db_version < 8989 )
515                 upgrade_270();
516
517         if ( $wp_current_db_version < 10360 )
518                 upgrade_280();
519
520         if ( $wp_current_db_version < 11958 )
521                 upgrade_290();
522
523         if ( $wp_current_db_version < 15260 )
524                 upgrade_300();
525
526         if ( $wp_current_db_version < 19389 )
527                 upgrade_330();
528
529         if ( $wp_current_db_version < 20080 )
530                 upgrade_340();
531
532         if ( $wp_current_db_version < 22422 )
533                 upgrade_350();
534
535         if ( $wp_current_db_version < 25824 )
536                 upgrade_370();
537
538         if ( $wp_current_db_version < 26148 )
539                 upgrade_372();
540
541         if ( $wp_current_db_version < 26691 )
542                 upgrade_380();
543
544         if ( $wp_current_db_version < 29630 )
545                 upgrade_400();
546
547         if ( $wp_current_db_version < 33055 )
548                 upgrade_430();
549
550         if ( $wp_current_db_version < 33056 )
551                 upgrade_431();
552
553         if ( $wp_current_db_version < 35700 )
554                 upgrade_440();
555
556         if ( $wp_current_db_version < 36686 )
557                 upgrade_450();
558
559         if ( $wp_current_db_version < 37965 )
560                 upgrade_460();
561
562         maybe_disable_link_manager();
563
564         maybe_disable_automattic_widgets();
565
566         update_option( 'db_version', $wp_db_version );
567         update_option( 'db_upgraded', true );
568 }
569
570 /**
571  * Execute changes made in WordPress 1.0.
572  *
573  * @ignore
574  * @since 1.0.0
575  *
576  * @global wpdb $wpdb WordPress database abstraction object.
577  */
578 function upgrade_100() {
579         global $wpdb;
580
581         // Get the title and ID of every post, post_name to check if it already has a value
582         $posts = $wpdb->get_results("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE post_name = ''");
583         if ($posts) {
584                 foreach ($posts as $post) {
585                         if ('' == $post->post_name) {
586                                 $newtitle = sanitize_title($post->post_title);
587                                 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_name = %s WHERE ID = %d", $newtitle, $post->ID) );
588                         }
589                 }
590         }
591
592         $categories = $wpdb->get_results("SELECT cat_ID, cat_name, category_nicename FROM $wpdb->categories");
593         foreach ($categories as $category) {
594                 if ('' == $category->category_nicename) {
595                         $newtitle = sanitize_title($category->cat_name);
596                         $wpdb->update( $wpdb->categories, array('category_nicename' => $newtitle), array('cat_ID' => $category->cat_ID) );
597                 }
598         }
599
600         $sql = "UPDATE $wpdb->options
601                 SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/')
602                 WHERE option_name LIKE %s
603                 AND option_value LIKE %s";
604         $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( 'links_rating_image' ) . '%', $wpdb->esc_like( 'wp-links/links-images/' ) . '%' ) );
605
606         $done_ids = $wpdb->get_results("SELECT DISTINCT post_id FROM $wpdb->post2cat");
607         if ($done_ids) :
608                 $done_posts = array();
609                 foreach ($done_ids as $done_id) :
610                         $done_posts[] = $done_id->post_id;
611                 endforeach;
612                 $catwhere = ' AND ID NOT IN (' . implode(',', $done_posts) . ')';
613         else:
614                 $catwhere = '';
615         endif;
616
617         $allposts = $wpdb->get_results("SELECT ID, post_category FROM $wpdb->posts WHERE post_category != '0' $catwhere");
618         if ($allposts) :
619                 foreach ($allposts as $post) {
620                         // Check to see if it's already been imported
621                         $cat = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->post2cat WHERE post_id = %d AND category_id = %d", $post->ID, $post->post_category) );
622                         if (!$cat && 0 != $post->post_category) { // If there's no result
623                                 $wpdb->insert( $wpdb->post2cat, array('post_id' => $post->ID, 'category_id' => $post->post_category) );
624                         }
625                 }
626         endif;
627 }
628
629 /**
630  * Execute changes made in WordPress 1.0.1.
631  *
632  * @ignore
633  * @since 1.0.1
634  *
635  * @global wpdb $wpdb WordPress database abstraction object.
636  */
637 function upgrade_101() {
638         global $wpdb;
639
640         // Clean up indices, add a few
641         add_clean_index($wpdb->posts, 'post_name');
642         add_clean_index($wpdb->posts, 'post_status');
643         add_clean_index($wpdb->categories, 'category_nicename');
644         add_clean_index($wpdb->comments, 'comment_approved');
645         add_clean_index($wpdb->comments, 'comment_post_ID');
646         add_clean_index($wpdb->links , 'link_category');
647         add_clean_index($wpdb->links , 'link_visible');
648 }
649
650 /**
651  * Execute changes made in WordPress 1.2.
652  *
653  * @ignore
654  * @since 1.2.0
655  *
656  * @global wpdb $wpdb WordPress database abstraction object.
657  */
658 function upgrade_110() {
659         global $wpdb;
660
661         // Set user_nicename.
662         $users = $wpdb->get_results("SELECT ID, user_nickname, user_nicename FROM $wpdb->users");
663         foreach ($users as $user) {
664                 if ('' == $user->user_nicename) {
665                         $newname = sanitize_title($user->user_nickname);
666                         $wpdb->update( $wpdb->users, array('user_nicename' => $newname), array('ID' => $user->ID) );
667                 }
668         }
669
670         $users = $wpdb->get_results("SELECT ID, user_pass from $wpdb->users");
671         foreach ($users as $row) {
672                 if (!preg_match('/^[A-Fa-f0-9]{32}$/', $row->user_pass)) {
673                         $wpdb->update( $wpdb->users, array('user_pass' => md5($row->user_pass)), array('ID' => $row->ID) );
674                 }
675         }
676
677         // Get the GMT offset, we'll use that later on
678         $all_options = get_alloptions_110();
679
680         $time_difference = $all_options->time_difference;
681
682                 $server_time = time()+date('Z');
683         $weblogger_time = $server_time + $time_difference * HOUR_IN_SECONDS;
684         $gmt_time = time();
685
686         $diff_gmt_server = ($gmt_time - $server_time) / HOUR_IN_SECONDS;
687         $diff_weblogger_server = ($weblogger_time - $server_time) / HOUR_IN_SECONDS;
688         $diff_gmt_weblogger = $diff_gmt_server - $diff_weblogger_server;
689         $gmt_offset = -$diff_gmt_weblogger;
690
691         // Add a gmt_offset option, with value $gmt_offset
692         add_option('gmt_offset', $gmt_offset);
693
694         // Check if we already set the GMT fields (if we did, then
695         // MAX(post_date_gmt) can't be '0000-00-00 00:00:00'
696         // <michel_v> I just slapped myself silly for not thinking about it earlier
697         $got_gmt_fields = ! ($wpdb->get_var("SELECT MAX(post_date_gmt) FROM $wpdb->posts") == '0000-00-00 00:00:00');
698
699         if (!$got_gmt_fields) {
700
701                 // Add or subtract time to all dates, to get GMT dates
702                 $add_hours = intval($diff_gmt_weblogger);
703                 $add_minutes = intval(60 * ($diff_gmt_weblogger - $add_hours));
704                 $wpdb->query("UPDATE $wpdb->posts SET post_date_gmt = DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)");
705                 $wpdb->query("UPDATE $wpdb->posts SET post_modified = post_date");
706                 $wpdb->query("UPDATE $wpdb->posts SET post_modified_gmt = DATE_ADD(post_modified, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE) WHERE post_modified != '0000-00-00 00:00:00'");
707                 $wpdb->query("UPDATE $wpdb->comments SET comment_date_gmt = DATE_ADD(comment_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)");
708                 $wpdb->query("UPDATE $wpdb->users SET user_registered = DATE_ADD(user_registered, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)");
709         }
710
711 }
712
713 /**
714  * Execute changes made in WordPress 1.5.
715  *
716  * @ignore
717  * @since 1.5.0
718  *
719  * @global wpdb $wpdb WordPress database abstraction object.
720  */
721 function upgrade_130() {
722         global $wpdb;
723
724         // Remove extraneous backslashes.
725         $posts = $wpdb->get_results("SELECT ID, post_title, post_content, post_excerpt, guid, post_date, post_name, post_status, post_author FROM $wpdb->posts");
726         if ($posts) {
727                 foreach ($posts as $post) {
728                         $post_content = addslashes(deslash($post->post_content));
729                         $post_title = addslashes(deslash($post->post_title));
730                         $post_excerpt = addslashes(deslash($post->post_excerpt));
731                         if ( empty($post->guid) )
732                                 $guid = get_permalink($post->ID);
733                         else
734                                 $guid = $post->guid;
735
736                         $wpdb->update( $wpdb->posts, compact('post_title', 'post_content', 'post_excerpt', 'guid'), array('ID' => $post->ID) );
737
738                 }
739         }
740
741         // Remove extraneous backslashes.
742         $comments = $wpdb->get_results("SELECT comment_ID, comment_author, comment_content FROM $wpdb->comments");
743         if ($comments) {
744                 foreach ($comments as $comment) {
745                         $comment_content = deslash($comment->comment_content);
746                         $comment_author = deslash($comment->comment_author);
747
748                         $wpdb->update($wpdb->comments, compact('comment_content', 'comment_author'), array('comment_ID' => $comment->comment_ID) );
749                 }
750         }
751
752         // Remove extraneous backslashes.
753         $links = $wpdb->get_results("SELECT link_id, link_name, link_description FROM $wpdb->links");
754         if ($links) {
755                 foreach ($links as $link) {
756                         $link_name = deslash($link->link_name);
757                         $link_description = deslash($link->link_description);
758
759                         $wpdb->update( $wpdb->links, compact('link_name', 'link_description'), array('link_id' => $link->link_id) );
760                 }
761         }
762
763         $active_plugins = __get_option('active_plugins');
764
765         /*
766          * If plugins are not stored in an array, they're stored in the old
767          * newline separated format. Convert to new format.
768          */
769         if ( !is_array( $active_plugins ) ) {
770                 $active_plugins = explode("\n", trim($active_plugins));
771                 update_option('active_plugins', $active_plugins);
772         }
773
774         // Obsolete tables
775         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optionvalues');
776         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiontypes');
777         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroups');
778         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroup_options');
779
780         // Update comments table to use comment_type
781         $wpdb->query("UPDATE $wpdb->comments SET comment_type='trackback', comment_content = REPLACE(comment_content, '<trackback />', '') WHERE comment_content LIKE '<trackback />%'");
782         $wpdb->query("UPDATE $wpdb->comments SET comment_type='pingback', comment_content = REPLACE(comment_content, '<pingback />', '') WHERE comment_content LIKE '<pingback />%'");
783
784         // Some versions have multiple duplicate option_name rows with the same values
785         $options = $wpdb->get_results("SELECT option_name, COUNT(option_name) AS dupes FROM `$wpdb->options` GROUP BY option_name");
786         foreach ( $options as $option ) {
787                 if ( 1 != $option->dupes ) { // Could this be done in the query?
788                         $limit = $option->dupes - 1;
789                         $dupe_ids = $wpdb->get_col( $wpdb->prepare("SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT %d", $option->option_name, $limit) );
790                         if ( $dupe_ids ) {
791                                 $dupe_ids = join($dupe_ids, ',');
792                                 $wpdb->query("DELETE FROM $wpdb->options WHERE option_id IN ($dupe_ids)");
793                         }
794                 }
795         }
796
797         make_site_theme();
798 }
799
800 /**
801  * Execute changes made in WordPress 2.0.
802  *
803  * @ignore
804  * @since 2.0.0
805  *
806  * @global wpdb $wpdb WordPress database abstraction object.
807  * @global int  $wp_current_db_version
808  */
809 function upgrade_160() {
810         global $wpdb, $wp_current_db_version;
811
812         populate_roles_160();
813
814         $users = $wpdb->get_results("SELECT * FROM $wpdb->users");
815         foreach ( $users as $user ) :
816                 if ( !empty( $user->user_firstname ) )
817                         update_user_meta( $user->ID, 'first_name', wp_slash($user->user_firstname) );
818                 if ( !empty( $user->user_lastname ) )
819                         update_user_meta( $user->ID, 'last_name', wp_slash($user->user_lastname) );
820                 if ( !empty( $user->user_nickname ) )
821                         update_user_meta( $user->ID, 'nickname', wp_slash($user->user_nickname) );
822                 if ( !empty( $user->user_level ) )
823                         update_user_meta( $user->ID, $wpdb->prefix . 'user_level', $user->user_level );
824                 if ( !empty( $user->user_icq ) )
825                         update_user_meta( $user->ID, 'icq', wp_slash($user->user_icq) );
826                 if ( !empty( $user->user_aim ) )
827                         update_user_meta( $user->ID, 'aim', wp_slash($user->user_aim) );
828                 if ( !empty( $user->user_msn ) )
829                         update_user_meta( $user->ID, 'msn', wp_slash($user->user_msn) );
830                 if ( !empty( $user->user_yim ) )
831                         update_user_meta( $user->ID, 'yim', wp_slash($user->user_icq) );
832                 if ( !empty( $user->user_description ) )
833                         update_user_meta( $user->ID, 'description', wp_slash($user->user_description) );
834
835                 if ( isset( $user->user_idmode ) ):
836                         $idmode = $user->user_idmode;
837                         if ($idmode == 'nickname') $id = $user->user_nickname;
838                         if ($idmode == 'login') $id = $user->user_login;
839                         if ($idmode == 'firstname') $id = $user->user_firstname;
840                         if ($idmode == 'lastname') $id = $user->user_lastname;
841                         if ($idmode == 'namefl') $id = $user->user_firstname.' '.$user->user_lastname;
842                         if ($idmode == 'namelf') $id = $user->user_lastname.' '.$user->user_firstname;
843                         if (!$idmode) $id = $user->user_nickname;
844                         $wpdb->update( $wpdb->users, array('display_name' => $id), array('ID' => $user->ID) );
845                 endif;
846
847                 // FIXME: RESET_CAPS is temporary code to reset roles and caps if flag is set.
848                 $caps = get_user_meta( $user->ID, $wpdb->prefix . 'capabilities');
849                 if ( empty($caps) || defined('RESET_CAPS') ) {
850                         $level = get_user_meta($user->ID, $wpdb->prefix . 'user_level', true);
851                         $role = translate_level_to_role($level);
852                         update_user_meta( $user->ID, $wpdb->prefix . 'capabilities', array($role => true) );
853                 }
854
855         endforeach;
856         $old_user_fields = array( 'user_firstname', 'user_lastname', 'user_icq', 'user_aim', 'user_msn', 'user_yim', 'user_idmode', 'user_ip', 'user_domain', 'user_browser', 'user_description', 'user_nickname', 'user_level' );
857         $wpdb->hide_errors();
858         foreach ( $old_user_fields as $old )
859                 $wpdb->query("ALTER TABLE $wpdb->users DROP $old");
860         $wpdb->show_errors();
861
862         // Populate comment_count field of posts table.
863         $comments = $wpdb->get_results( "SELECT comment_post_ID, COUNT(*) as c FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID" );
864         if ( is_array( $comments ) )
865                 foreach ($comments as $comment)
866                         $wpdb->update( $wpdb->posts, array('comment_count' => $comment->c), array('ID' => $comment->comment_post_ID) );
867
868         /*
869          * Some alpha versions used a post status of object instead of attachment
870          * and put the mime type in post_type instead of post_mime_type.
871          */
872         if ( $wp_current_db_version > 2541 && $wp_current_db_version <= 3091 ) {
873                 $objects = $wpdb->get_results("SELECT ID, post_type FROM $wpdb->posts WHERE post_status = 'object'");
874                 foreach ($objects as $object) {
875                         $wpdb->update( $wpdb->posts, array(     'post_status' => 'attachment',
876                                                                                                 'post_mime_type' => $object->post_type,
877                                                                                                 'post_type' => ''),
878                                                                                  array( 'ID' => $object->ID ) );
879
880                         $meta = get_post_meta($object->ID, 'imagedata', true);
881                         if ( ! empty($meta['file']) )
882                                 update_attached_file( $object->ID, $meta['file'] );
883                 }
884         }
885 }
886
887 /**
888  * Execute changes made in WordPress 2.1.
889  *
890  * @ignore
891  * @since 2.1.0
892  *
893  * @global wpdb $wpdb WordPress database abstraction object.
894  * @global int  $wp_current_db_version
895  */
896 function upgrade_210() {
897         global $wpdb, $wp_current_db_version;
898
899         if ( $wp_current_db_version < 3506 ) {
900                 // Update status and type.
901                 $posts = $wpdb->get_results("SELECT ID, post_status FROM $wpdb->posts");
902
903                 if ( ! empty($posts) ) foreach ($posts as $post) {
904                         $status = $post->post_status;
905                         $type = 'post';
906
907                         if ( 'static' == $status ) {
908                                 $status = 'publish';
909                                 $type = 'page';
910                         } elseif ( 'attachment' == $status ) {
911                                 $status = 'inherit';
912                                 $type = 'attachment';
913                         }
914
915                         $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_status = %s, post_type = %s WHERE ID = %d", $status, $type, $post->ID) );
916                 }
917         }
918
919         if ( $wp_current_db_version < 3845 ) {
920                 populate_roles_210();
921         }
922
923         if ( $wp_current_db_version < 3531 ) {
924                 // Give future posts a post_status of future.
925                 $now = gmdate('Y-m-d H:i:59');
926                 $wpdb->query ("UPDATE $wpdb->posts SET post_status = 'future' WHERE post_status = 'publish' AND post_date_gmt > '$now'");
927
928                 $posts = $wpdb->get_results("SELECT ID, post_date FROM $wpdb->posts WHERE post_status ='future'");
929                 if ( !empty($posts) )
930                         foreach ( $posts as $post )
931                                 wp_schedule_single_event(mysql2date('U', $post->post_date, false), 'publish_future_post', array($post->ID));
932         }
933 }
934
935 /**
936  * Execute changes made in WordPress 2.3.
937  *
938  * @ignore
939  * @since 2.3.0
940  *
941  * @global wpdb $wpdb WordPress database abstraction object.
942  * @global int  $wp_current_db_version
943  */
944 function upgrade_230() {
945         global $wp_current_db_version, $wpdb;
946
947         if ( $wp_current_db_version < 5200 ) {
948                 populate_roles_230();
949         }
950
951         // Convert categories to terms.
952         $tt_ids = array();
953         $have_tags = false;
954         $categories = $wpdb->get_results("SELECT * FROM $wpdb->categories ORDER BY cat_ID");
955         foreach ($categories as $category) {
956                 $term_id = (int) $category->cat_ID;
957                 $name = $category->cat_name;
958                 $description = $category->category_description;
959                 $slug = $category->category_nicename;
960                 $parent = $category->category_parent;
961                 $term_group = 0;
962
963                 // Associate terms with the same slug in a term group and make slugs unique.
964                 if ( $exists = $wpdb->get_results( $wpdb->prepare("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug) ) ) {
965                         $term_group = $exists[0]->term_group;
966                         $id = $exists[0]->term_id;
967                         $num = 2;
968                         do {
969                                 $alt_slug = $slug . "-$num";
970                                 $num++;
971                                 $slug_check = $wpdb->get_var( $wpdb->prepare("SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug) );
972                         } while ( $slug_check );
973
974                         $slug = $alt_slug;
975
976                         if ( empty( $term_group ) ) {
977                                 $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group") + 1;
978                                 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->terms SET term_group = %d WHERE term_id = %d", $term_group, $id) );
979                         }
980                 }
981
982                 $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES
983                 (%d, %s, %s, %d)", $term_id, $name, $slug, $term_group) );
984
985                 $count = 0;
986                 if ( !empty($category->category_count) ) {
987                         $count = (int) $category->category_count;
988                         $taxonomy = 'category';
989                         $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count) );
990                         $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id;
991                 }
992
993                 if ( !empty($category->link_count) ) {
994                         $count = (int) $category->link_count;
995                         $taxonomy = 'link_category';
996                         $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count) );
997                         $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id;
998                 }
999
1000                 if ( !empty($category->tag_count) ) {
1001                         $have_tags = true;
1002                         $count = (int) $category->tag_count;
1003                         $taxonomy = 'post_tag';
1004                         $wpdb->insert( $wpdb->term_taxonomy, compact('term_id', 'taxonomy', 'description', 'parent', 'count') );
1005                         $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id;
1006                 }
1007
1008                 if ( empty($count) ) {
1009                         $count = 0;
1010                         $taxonomy = 'category';
1011                         $wpdb->insert( $wpdb->term_taxonomy, compact('term_id', 'taxonomy', 'description', 'parent', 'count') );
1012                         $tt_ids[$term_id][$taxonomy] = (int) $wpdb->insert_id;
1013                 }
1014         }
1015
1016         $select = 'post_id, category_id';
1017         if ( $have_tags )
1018                 $select .= ', rel_type';
1019
1020         $posts = $wpdb->get_results("SELECT $select FROM $wpdb->post2cat GROUP BY post_id, category_id");
1021         foreach ( $posts as $post ) {
1022                 $post_id = (int) $post->post_id;
1023                 $term_id = (int) $post->category_id;
1024                 $taxonomy = 'category';
1025                 if ( !empty($post->rel_type) && 'tag' == $post->rel_type)
1026                         $taxonomy = 'tag';
1027                 $tt_id = $tt_ids[$term_id][$taxonomy];
1028                 if ( empty($tt_id) )
1029                         continue;
1030
1031                 $wpdb->insert( $wpdb->term_relationships, array('object_id' => $post_id, 'term_taxonomy_id' => $tt_id) );
1032         }
1033
1034         // < 3570 we used linkcategories. >= 3570 we used categories and link2cat.
1035         if ( $wp_current_db_version < 3570 ) {
1036                 /*
1037                  * Create link_category terms for link categories. Create a map of link
1038                  * cat IDs to link_category terms.
1039                  */
1040                 $link_cat_id_map = array();
1041                 $default_link_cat = 0;
1042                 $tt_ids = array();
1043                 $link_cats = $wpdb->get_results("SELECT cat_id, cat_name FROM " . $wpdb->prefix . 'linkcategories');
1044                 foreach ( $link_cats as $category) {
1045                         $cat_id = (int) $category->cat_id;
1046                         $term_id = 0;
1047                         $name = wp_slash($category->cat_name);
1048                         $slug = sanitize_title($name);
1049                         $term_group = 0;
1050
1051                         // Associate terms with the same slug in a term group and make slugs unique.
1052                         if ( $exists = $wpdb->get_results( $wpdb->prepare("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug) ) ) {
1053                                 $term_group = $exists[0]->term_group;
1054                                 $term_id = $exists[0]->term_id;
1055                         }
1056
1057                         if ( empty($term_id) ) {
1058                                 $wpdb->insert( $wpdb->terms, compact('name', 'slug', 'term_group') );
1059                                 $term_id = (int) $wpdb->insert_id;
1060                         }
1061
1062                         $link_cat_id_map[$cat_id] = $term_id;
1063                         $default_link_cat = $term_id;
1064
1065                         $wpdb->insert( $wpdb->term_taxonomy, array('term_id' => $term_id, 'taxonomy' => 'link_category', 'description' => '', 'parent' => 0, 'count' => 0) );
1066                         $tt_ids[$term_id] = (int) $wpdb->insert_id;
1067                 }
1068
1069                 // Associate links to cats.
1070                 $links = $wpdb->get_results("SELECT link_id, link_category FROM $wpdb->links");
1071                 if ( !empty($links) ) foreach ( $links as $link ) {
1072                         if ( 0 == $link->link_category )
1073                                 continue;
1074                         if ( ! isset($link_cat_id_map[$link->link_category]) )
1075                                 continue;
1076                         $term_id = $link_cat_id_map[$link->link_category];
1077                         $tt_id = $tt_ids[$term_id];
1078                         if ( empty($tt_id) )
1079                                 continue;
1080
1081                         $wpdb->insert( $wpdb->term_relationships, array('object_id' => $link->link_id, 'term_taxonomy_id' => $tt_id) );
1082                 }
1083
1084                 // Set default to the last category we grabbed during the upgrade loop.
1085                 update_option('default_link_category', $default_link_cat);
1086         } else {
1087                 $links = $wpdb->get_results("SELECT link_id, category_id FROM $wpdb->link2cat GROUP BY link_id, category_id");
1088                 foreach ( $links as $link ) {
1089                         $link_id = (int) $link->link_id;
1090                         $term_id = (int) $link->category_id;
1091                         $taxonomy = 'link_category';
1092                         $tt_id = $tt_ids[$term_id][$taxonomy];
1093                         if ( empty($tt_id) )
1094                                 continue;
1095                         $wpdb->insert( $wpdb->term_relationships, array('object_id' => $link_id, 'term_taxonomy_id' => $tt_id) );
1096                 }
1097         }
1098
1099         if ( $wp_current_db_version < 4772 ) {
1100                 // Obsolete linkcategories table
1101                 $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'linkcategories');
1102         }
1103
1104         // Recalculate all counts
1105         $terms = $wpdb->get_results("SELECT term_taxonomy_id, taxonomy FROM $wpdb->term_taxonomy");
1106         foreach ( (array) $terms as $term ) {
1107                 if ( ('post_tag' == $term->taxonomy) || ('category' == $term->taxonomy) )
1108                         $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type = 'post' AND term_taxonomy_id = %d", $term->term_taxonomy_id) );
1109                 else
1110                         $count = $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term->term_taxonomy_id) );
1111                 $wpdb->update( $wpdb->term_taxonomy, array('count' => $count), array('term_taxonomy_id' => $term->term_taxonomy_id) );
1112         }
1113 }
1114
1115 /**
1116  * Remove old options from the database.
1117  *
1118  * @ignore
1119  * @since 2.3.0
1120  *
1121  * @global wpdb $wpdb WordPress database abstraction object.
1122  */
1123 function upgrade_230_options_table() {
1124         global $wpdb;
1125         $old_options_fields = array( 'option_can_override', 'option_type', 'option_width', 'option_height', 'option_description', 'option_admin_level' );
1126         $wpdb->hide_errors();
1127         foreach ( $old_options_fields as $old )
1128                 $wpdb->query("ALTER TABLE $wpdb->options DROP $old");
1129         $wpdb->show_errors();
1130 }
1131
1132 /**
1133  * Remove old categories, link2cat, and post2cat database tables.
1134  *
1135  * @ignore
1136  * @since 2.3.0
1137  *
1138  * @global wpdb $wpdb WordPress database abstraction object.
1139  */
1140 function upgrade_230_old_tables() {
1141         global $wpdb;
1142         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'categories');
1143         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'link2cat');
1144         $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post2cat');
1145 }
1146
1147 /**
1148  * Upgrade old slugs made in version 2.2.
1149  *
1150  * @ignore
1151  * @since 2.2.0
1152  *
1153  * @global wpdb $wpdb WordPress database abstraction object.
1154  */
1155 function upgrade_old_slugs() {
1156         // Upgrade people who were using the Redirect Old Slugs plugin.
1157         global $wpdb;
1158         $wpdb->query("UPDATE $wpdb->postmeta SET meta_key = '_wp_old_slug' WHERE meta_key = 'old_slug'");
1159 }
1160
1161 /**
1162  * Execute changes made in WordPress 2.5.0.
1163  *
1164  * @ignore
1165  * @since 2.5.0
1166  *
1167  * @global int $wp_current_db_version
1168  */
1169 function upgrade_250() {
1170         global $wp_current_db_version;
1171
1172         if ( $wp_current_db_version < 6689 ) {
1173                 populate_roles_250();
1174         }
1175
1176 }
1177
1178 /**
1179  * Execute changes made in WordPress 2.5.2.
1180  *
1181  * @ignore
1182  * @since 2.5.2
1183  *
1184  * @global wpdb $wpdb WordPress database abstraction object.
1185  */
1186 function upgrade_252() {
1187         global $wpdb;
1188
1189         $wpdb->query("UPDATE $wpdb->users SET user_activation_key = ''");
1190 }
1191
1192 /**
1193  * Execute changes made in WordPress 2.6.
1194  *
1195  * @ignore
1196  * @since 2.6.0
1197  *
1198  * @global int $wp_current_db_version
1199  */
1200 function upgrade_260() {
1201         global $wp_current_db_version;
1202
1203         if ( $wp_current_db_version < 8000 )
1204                 populate_roles_260();
1205 }
1206
1207 /**
1208  * Execute changes made in WordPress 2.7.
1209  *
1210  * @ignore
1211  * @since 2.7.0
1212  *
1213  * @global wpdb $wpdb WordPress database abstraction object.
1214  * @global int  $wp_current_db_version
1215  */
1216 function upgrade_270() {
1217         global $wpdb, $wp_current_db_version;
1218
1219         if ( $wp_current_db_version < 8980 )
1220                 populate_roles_270();
1221
1222         // Update post_date for unpublished posts with empty timestamp
1223         if ( $wp_current_db_version < 8921 )
1224                 $wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" );
1225 }
1226
1227 /**
1228  * Execute changes made in WordPress 2.8.
1229  *
1230  * @ignore
1231  * @since 2.8.0
1232  *
1233  * @global int  $wp_current_db_version
1234  * @global wpdb $wpdb WordPress database abstraction object.
1235  */
1236 function upgrade_280() {
1237         global $wp_current_db_version, $wpdb;
1238
1239         if ( $wp_current_db_version < 10360 )
1240                 populate_roles_280();
1241         if ( is_multisite() ) {
1242                 $start = 0;
1243                 while( $rows = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options ORDER BY option_id LIMIT $start, 20" ) ) {
1244                         foreach ( $rows as $row ) {
1245                                 $value = $row->option_value;
1246                                 if ( !@unserialize( $value ) )
1247                                         $value = stripslashes( $value );
1248                                 if ( $value !== $row->option_value ) {
1249                                         update_option( $row->option_name, $value );
1250                                 }
1251                         }
1252                         $start += 20;
1253                 }
1254                 refresh_blog_details( $wpdb->blogid );
1255         }
1256 }
1257
1258 /**
1259  * Execute changes made in WordPress 2.9.
1260  *
1261  * @ignore
1262  * @since 2.9.0
1263  *
1264  * @global int $wp_current_db_version
1265  */
1266 function upgrade_290() {
1267         global $wp_current_db_version;
1268
1269         if ( $wp_current_db_version < 11958 ) {
1270                 // Previously, setting depth to 1 would redundantly disable threading, but now 2 is the minimum depth to avoid confusion
1271                 if ( get_option( 'thread_comments_depth' ) == '1' ) {
1272                         update_option( 'thread_comments_depth', 2 );
1273                         update_option( 'thread_comments', 0 );
1274                 }
1275         }
1276 }
1277
1278 /**
1279  * Execute changes made in WordPress 3.0.
1280  *
1281  * @ignore
1282  * @since 3.0.0
1283  *
1284  * @global int  $wp_current_db_version
1285  * @global wpdb $wpdb WordPress database abstraction object.
1286  */
1287 function upgrade_300() {
1288         global $wp_current_db_version, $wpdb;
1289
1290         if ( $wp_current_db_version < 15093 )
1291                 populate_roles_300();
1292
1293         if ( $wp_current_db_version < 14139 && is_multisite() && is_main_site() && ! defined( 'MULTISITE' ) && get_site_option( 'siteurl' ) === false )
1294                 add_site_option( 'siteurl', '' );
1295
1296         // 3.0 screen options key name changes.
1297         if ( wp_should_upgrade_global_tables() ) {
1298                 $sql = "DELETE FROM $wpdb->usermeta
1299                         WHERE meta_key LIKE %s
1300                         OR meta_key LIKE %s
1301                         OR meta_key LIKE %s
1302                         OR meta_key LIKE %s
1303                         OR meta_key LIKE %s
1304                         OR meta_key LIKE %s
1305                         OR meta_key = 'manageedittagscolumnshidden'
1306                         OR meta_key = 'managecategoriescolumnshidden'
1307                         OR meta_key = 'manageedit-tagscolumnshidden'
1308                         OR meta_key = 'manageeditcolumnshidden'
1309                         OR meta_key = 'categories_per_page'
1310                         OR meta_key = 'edit_tags_per_page'";
1311                 $prefix = $wpdb->esc_like( $wpdb->base_prefix );
1312                 $wpdb->query( $wpdb->prepare( $sql,
1313                         $prefix . '%' . $wpdb->esc_like( 'meta-box-hidden' ) . '%',
1314                         $prefix . '%' . $wpdb->esc_like( 'closedpostboxes' ) . '%',
1315                         $prefix . '%' . $wpdb->esc_like( 'manage-'         ) . '%' . $wpdb->esc_like( '-columns-hidden' ) . '%',
1316                         $prefix . '%' . $wpdb->esc_like( 'meta-box-order'  ) . '%',
1317                         $prefix . '%' . $wpdb->esc_like( 'metaboxorder'    ) . '%',
1318                         $prefix . '%' . $wpdb->esc_like( 'screen_layout'   ) . '%'
1319                 ) );
1320         }
1321
1322 }
1323
1324 /**
1325  * Execute changes made in WordPress 3.3.
1326  *
1327  * @ignore
1328  * @since 3.3.0
1329  *
1330  * @global int   $wp_current_db_version
1331  * @global wpdb  $wpdb
1332  * @global array $wp_registered_widgets
1333  * @global array $sidebars_widgets
1334  */
1335 function upgrade_330() {
1336         global $wp_current_db_version, $wpdb, $wp_registered_widgets, $sidebars_widgets;
1337
1338         if ( $wp_current_db_version < 19061 && wp_should_upgrade_global_tables() ) {
1339                 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" );
1340         }
1341
1342         if ( $wp_current_db_version >= 11548 )
1343                 return;
1344
1345         $sidebars_widgets = get_option( 'sidebars_widgets', array() );
1346         $_sidebars_widgets = array();
1347
1348         if ( isset($sidebars_widgets['wp_inactive_widgets']) || empty($sidebars_widgets) )
1349                 $sidebars_widgets['array_version'] = 3;
1350         elseif ( !isset($sidebars_widgets['array_version']) )
1351                 $sidebars_widgets['array_version'] = 1;
1352
1353         switch ( $sidebars_widgets['array_version'] ) {
1354                 case 1 :
1355                         foreach ( (array) $sidebars_widgets as $index => $sidebar )
1356                         if ( is_array($sidebar) )
1357                         foreach ( (array) $sidebar as $i => $name ) {
1358                                 $id = strtolower($name);
1359                                 if ( isset($wp_registered_widgets[$id]) ) {
1360                                         $_sidebars_widgets[$index][$i] = $id;
1361                                         continue;
1362                                 }
1363                                 $id = sanitize_title($name);
1364                                 if ( isset($wp_registered_widgets[$id]) ) {
1365                                         $_sidebars_widgets[$index][$i] = $id;
1366                                         continue;
1367                                 }
1368
1369                                 $found = false;
1370
1371                                 foreach ( $wp_registered_widgets as $widget_id => $widget ) {
1372                                         if ( strtolower($widget['name']) == strtolower($name) ) {
1373                                                 $_sidebars_widgets[$index][$i] = $widget['id'];
1374                                                 $found = true;
1375                                                 break;
1376                                         } elseif ( sanitize_title($widget['name']) == sanitize_title($name) ) {
1377                                                 $_sidebars_widgets[$index][$i] = $widget['id'];
1378                                                 $found = true;
1379                                                 break;
1380                                         }
1381                                 }
1382
1383                                 if ( $found )
1384                                         continue;
1385
1386                                 unset($_sidebars_widgets[$index][$i]);
1387                         }
1388                         $_sidebars_widgets['array_version'] = 2;
1389                         $sidebars_widgets = $_sidebars_widgets;
1390                         unset($_sidebars_widgets);
1391
1392                 case 2 :
1393                         $sidebars_widgets = retrieve_widgets();
1394                         $sidebars_widgets['array_version'] = 3;
1395                         update_option( 'sidebars_widgets', $sidebars_widgets );
1396         }
1397 }
1398
1399 /**
1400  * Execute changes made in WordPress 3.4.
1401  *
1402  * @ignore
1403  * @since 3.4.0
1404  *
1405  * @global int   $wp_current_db_version
1406  * @global wpdb  $wpdb
1407  */
1408 function upgrade_340() {
1409         global $wp_current_db_version, $wpdb;
1410
1411         if ( $wp_current_db_version < 19798 ) {
1412                 $wpdb->hide_errors();
1413                 $wpdb->query( "ALTER TABLE $wpdb->options DROP COLUMN blog_id" );
1414                 $wpdb->show_errors();
1415         }
1416
1417         if ( $wp_current_db_version < 19799 ) {
1418                 $wpdb->hide_errors();
1419                 $wpdb->query("ALTER TABLE $wpdb->comments DROP INDEX comment_approved");
1420                 $wpdb->show_errors();
1421         }
1422
1423         if ( $wp_current_db_version < 20022 && wp_should_upgrade_global_tables() ) {
1424                 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" );
1425         }
1426
1427         if ( $wp_current_db_version < 20080 ) {
1428                 if ( 'yes' == $wpdb->get_var( "SELECT autoload FROM $wpdb->options WHERE option_name = 'uninstall_plugins'" ) ) {
1429                         $uninstall_plugins = get_option( 'uninstall_plugins' );
1430                         delete_option( 'uninstall_plugins' );
1431                         add_option( 'uninstall_plugins', $uninstall_plugins, null, 'no' );
1432                 }
1433         }
1434 }
1435
1436 /**
1437  * Execute changes made in WordPress 3.5.
1438  *
1439  * @ignore
1440  * @since 3.5.0
1441  *
1442  * @global int   $wp_current_db_version
1443  * @global wpdb  $wpdb
1444  */
1445 function upgrade_350() {
1446         global $wp_current_db_version, $wpdb;
1447
1448         if ( $wp_current_db_version < 22006 && $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) )
1449                 update_option( 'link_manager_enabled', 1 ); // Previously set to 0 by populate_options()
1450
1451         if ( $wp_current_db_version < 21811 && wp_should_upgrade_global_tables() ) {
1452                 $meta_keys = array();
1453                 foreach ( array_merge( get_post_types(), get_taxonomies() ) as $name ) {
1454                         if ( false !== strpos( $name, '-' ) )
1455                         $meta_keys[] = 'edit_' . str_replace( '-', '_', $name ) . '_per_page';
1456                 }
1457                 if ( $meta_keys ) {
1458                         $meta_keys = implode( "', '", $meta_keys );
1459                         $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('$meta_keys')" );
1460                 }
1461         }
1462
1463         if ( $wp_current_db_version < 22422 && $term = get_term_by( 'slug', 'post-format-standard', 'post_format' ) )
1464                 wp_delete_term( $term->term_id, 'post_format' );
1465 }
1466
1467 /**
1468  * Execute changes made in WordPress 3.7.
1469  *
1470  * @ignore
1471  * @since 3.7.0
1472  *
1473  * @global int $wp_current_db_version
1474  */
1475 function upgrade_370() {
1476         global $wp_current_db_version;
1477         if ( $wp_current_db_version < 25824 )
1478                 wp_clear_scheduled_hook( 'wp_auto_updates_maybe_update' );
1479 }
1480
1481 /**
1482  * Execute changes made in WordPress 3.7.2.
1483  *
1484  * @ignore
1485  * @since 3.7.2
1486  * @since 3.8.0
1487  *
1488  * @global int $wp_current_db_version
1489  */
1490 function upgrade_372() {
1491         global $wp_current_db_version;
1492         if ( $wp_current_db_version < 26148 )
1493                 wp_clear_scheduled_hook( 'wp_maybe_auto_update' );
1494 }
1495
1496 /**
1497  * Execute changes made in WordPress 3.8.0.
1498  *
1499  * @ignore
1500  * @since 3.8.0
1501  *
1502  * @global int $wp_current_db_version
1503  */
1504 function upgrade_380() {
1505         global $wp_current_db_version;
1506         if ( $wp_current_db_version < 26691 ) {
1507                 deactivate_plugins( array( 'mp6/mp6.php' ), true );
1508         }
1509 }
1510
1511 /**
1512  * Execute changes made in WordPress 4.0.0.
1513  *
1514  * @ignore
1515  * @since 4.0.0
1516  *
1517  * @global int $wp_current_db_version
1518  */
1519 function upgrade_400() {
1520         global $wp_current_db_version;
1521         if ( $wp_current_db_version < 29630 ) {
1522                 if ( ! is_multisite() && false === get_option( 'WPLANG' ) ) {
1523                         if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) && in_array( WPLANG, get_available_languages() ) ) {
1524                                 update_option( 'WPLANG', WPLANG );
1525                         } else {
1526                                 update_option( 'WPLANG', '' );
1527                         }
1528                 }
1529         }
1530 }
1531
1532 /**
1533  * Execute changes made in WordPress 4.2.0.
1534  *
1535  * @ignore
1536  * @since 4.2.0
1537  *
1538  * @global int   $wp_current_db_version
1539  * @global wpdb  $wpdb
1540  */
1541 function upgrade_420() {}
1542
1543 /**
1544  * Executes changes made in WordPress 4.3.0.
1545  *
1546  * @ignore
1547  * @since 4.3.0
1548  *
1549  * @global int  $wp_current_db_version Current version.
1550  * @global wpdb $wpdb                  WordPress database abstraction object.
1551  */
1552 function upgrade_430() {
1553         global $wp_current_db_version, $wpdb;
1554
1555         if ( $wp_current_db_version < 32364 ) {
1556                 upgrade_430_fix_comments();
1557         }
1558
1559         // Shared terms are split in a separate process.
1560         if ( $wp_current_db_version < 32814 ) {
1561                 update_option( 'finished_splitting_shared_terms', 0 );
1562                 wp_schedule_single_event( time() + ( 1 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
1563         }
1564
1565         if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) {
1566                 if ( is_multisite() ) {
1567                         $tables = $wpdb->tables( 'blog' );
1568                 } else {
1569                         $tables = $wpdb->tables( 'all' );
1570                         if ( ! wp_should_upgrade_global_tables() ) {
1571                                 $global_tables = $wpdb->tables( 'global' );
1572                                 $tables = array_diff_assoc( $tables, $global_tables );
1573                         }
1574                 }
1575
1576                 foreach ( $tables as $table ) {
1577                         maybe_convert_table_to_utf8mb4( $table );
1578                 }
1579         }
1580 }
1581
1582 /**
1583  * Executes comments changes made in WordPress 4.3.0.
1584  *
1585  * @ignore
1586  * @since 4.3.0
1587  *
1588  * @global int  $wp_current_db_version Current version.
1589  * @global wpdb $wpdb                  WordPress database abstraction object.
1590  */
1591 function upgrade_430_fix_comments() {
1592         global $wp_current_db_version, $wpdb;
1593
1594         $content_length = $wpdb->get_col_length( $wpdb->comments, 'comment_content' );
1595
1596         if ( is_wp_error( $content_length ) ) {
1597                 return;
1598         }
1599
1600         if ( false === $content_length ) {
1601                 $content_length = array(
1602                         'type'   => 'byte',
1603                         'length' => 65535,
1604                 );
1605         } elseif ( ! is_array( $content_length ) ) {
1606                 $length = (int) $content_length > 0 ? (int) $content_length : 65535;
1607                 $content_length = array(
1608                         'type'   => 'byte',
1609                         'length' => $length
1610                 );
1611         }
1612
1613         if ( 'byte' !== $content_length['type'] || 0 === $content_length['length'] ) {
1614                 // Sites with malformed DB schemas are on their own.
1615                 return;
1616         }
1617
1618         $allowed_length = intval( $content_length['length'] ) - 10;
1619
1620         $comments = $wpdb->get_results(
1621                 "SELECT `comment_ID` FROM `{$wpdb->comments}`
1622                         WHERE `comment_date_gmt` > '2015-04-26'
1623                         AND LENGTH( `comment_content` ) >= {$allowed_length}
1624                         AND ( `comment_content` LIKE '%<%' OR `comment_content` LIKE '%>%' )"
1625         );
1626
1627         foreach ( $comments as $comment ) {
1628                 wp_delete_comment( $comment->comment_ID, true );
1629         }
1630 }
1631
1632 /**
1633  * Executes changes made in WordPress 4.3.1.
1634  *
1635  * @ignore
1636  * @since 4.3.1
1637  */
1638 function upgrade_431() {
1639         // Fix incorrect cron entries for term splitting
1640         $cron_array = _get_cron_array();
1641         if ( isset( $cron_array['wp_batch_split_terms'] ) ) {
1642                 unset( $cron_array['wp_batch_split_terms'] );
1643                 _set_cron_array( $cron_array );
1644         }
1645 }
1646
1647 /**
1648  * Executes changes made in WordPress 4.4.0.
1649  *
1650  * @ignore
1651  * @since 4.4.0
1652  *
1653  * @global int  $wp_current_db_version Current version.
1654  * @global wpdb $wpdb                  WordPress database abstraction object.
1655  */
1656 function upgrade_440() {
1657         global $wp_current_db_version, $wpdb;
1658
1659         if ( $wp_current_db_version < 34030 ) {
1660                 $wpdb->query( "ALTER TABLE {$wpdb->options} MODIFY option_name VARCHAR(191)" );
1661         }
1662
1663         // Remove the unused 'add_users' role.
1664         $roles = wp_roles();
1665         foreach ( $roles->role_objects as $role ) {
1666                 if ( $role->has_cap( 'add_users' ) ) {
1667                         $role->remove_cap( 'add_users' );
1668                 }
1669         }
1670 }
1671
1672 /**
1673  * Executes changes made in WordPress 4.5.0.
1674  *
1675  * @ignore
1676  * @since 4.5.0
1677  *
1678  * @global int  $wp_current_db_version Current database version.
1679  * @global wpdb $wpdb                  WordPress database abstraction object.
1680  */
1681 function upgrade_450() {
1682         global $wp_current_db_version, $wpdb;
1683
1684         if ( $wp_current_db_version < 36180 ) {
1685                 wp_clear_scheduled_hook( 'wp_maybe_auto_update' );
1686         }
1687
1688         // Remove unused email confirmation options, moved to usermeta.
1689         if ( $wp_current_db_version < 36679 && is_multisite() ) {
1690                 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^[0-9]+_new_email$'" );
1691         }
1692
1693         // Remove unused user setting for wpLink.
1694         delete_user_setting( 'wplink' );
1695 }
1696
1697 /**
1698  * Executes changes made in WordPress 4.6.0.
1699  *
1700  * @ignore
1701  * @since 4.6.0
1702  *
1703  * @global int $wp_current_db_version Current database version.
1704  */
1705 function upgrade_460() {
1706         global $wp_current_db_version;
1707
1708         // Remove unused post meta.
1709         if ( $wp_current_db_version < 37854 ) {
1710                 delete_post_meta_by_key( '_post_restored_from' );
1711         }
1712
1713         // Remove plugins with callback as an array object/method as the uninstall hook, see #13786.
1714         if ( $wp_current_db_version < 37965 ) {
1715                 $uninstall_plugins = get_option( 'uninstall_plugins', array() );
1716
1717                 if ( ! empty( $uninstall_plugins ) ) {
1718                         foreach ( $uninstall_plugins as $basename => $callback ) {
1719                                 if ( is_array( $callback ) && is_object( $callback[0] ) ) {
1720                                         unset( $uninstall_plugins[ $basename ] );
1721                                 }
1722                         }
1723
1724                         update_option( 'uninstall_plugins', $uninstall_plugins );
1725                 }
1726         }
1727 }
1728
1729 /**
1730  * Executes network-level upgrade routines.
1731  *
1732  * @since 3.0.0
1733  *
1734  * @global int   $wp_current_db_version
1735  * @global wpdb  $wpdb
1736  */
1737 function upgrade_network() {
1738         global $wp_current_db_version, $wpdb;
1739
1740         // Always.
1741         if ( is_main_network() ) {
1742                 /*
1743                  * Deletes all expired transients. The multi-table delete syntax is used
1744                  * to delete the transient record from table a, and the corresponding
1745                  * transient_timeout record from table b.
1746                  */
1747                 $time = time();
1748                 $sql = "DELETE a, b FROM $wpdb->sitemeta a, $wpdb->sitemeta b
1749                         WHERE a.meta_key LIKE %s
1750                         AND a.meta_key NOT LIKE %s
1751                         AND b.meta_key = CONCAT( '_site_transient_timeout_', SUBSTRING( a.meta_key, 17 ) )
1752                         AND b.meta_value < %d";
1753                 $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like ( '_site_transient_timeout_' ) . '%', $time ) );
1754         }
1755
1756         // 2.8.
1757         if ( $wp_current_db_version < 11549 ) {
1758                 $wpmu_sitewide_plugins = get_site_option( 'wpmu_sitewide_plugins' );
1759                 $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' );
1760                 if ( $wpmu_sitewide_plugins ) {
1761                         if ( !$active_sitewide_plugins )
1762                                 $sitewide_plugins = (array) $wpmu_sitewide_plugins;
1763                         else
1764                                 $sitewide_plugins = array_merge( (array) $active_sitewide_plugins, (array) $wpmu_sitewide_plugins );
1765
1766                         update_site_option( 'active_sitewide_plugins', $sitewide_plugins );
1767                 }
1768                 delete_site_option( 'wpmu_sitewide_plugins' );
1769                 delete_site_option( 'deactivated_sitewide_plugins' );
1770
1771                 $start = 0;
1772                 while( $rows = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} ORDER BY meta_id LIMIT $start, 20" ) ) {
1773                         foreach ( $rows as $row ) {
1774                                 $value = $row->meta_value;
1775                                 if ( !@unserialize( $value ) )
1776                                         $value = stripslashes( $value );
1777                                 if ( $value !== $row->meta_value ) {
1778                                         update_site_option( $row->meta_key, $value );
1779                                 }
1780                         }
1781                         $start += 20;
1782                 }
1783         }
1784
1785         // 3.0
1786         if ( $wp_current_db_version < 13576 )
1787                 update_site_option( 'global_terms_enabled', '1' );
1788
1789         // 3.3
1790         if ( $wp_current_db_version < 19390 )
1791                 update_site_option( 'initial_db_version', $wp_current_db_version );
1792
1793         if ( $wp_current_db_version < 19470 ) {
1794                 if ( false === get_site_option( 'active_sitewide_plugins' ) )
1795                         update_site_option( 'active_sitewide_plugins', array() );
1796         }
1797
1798         // 3.4
1799         if ( $wp_current_db_version < 20148 ) {
1800                 // 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name.
1801                 $allowedthemes  = get_site_option( 'allowedthemes'  );
1802                 $allowed_themes = get_site_option( 'allowed_themes' );
1803                 if ( false === $allowedthemes && is_array( $allowed_themes ) && $allowed_themes ) {
1804                         $converted = array();
1805                         $themes = wp_get_themes();
1806                         foreach ( $themes as $stylesheet => $theme_data ) {
1807                                 if ( isset( $allowed_themes[ $theme_data->get('Name') ] ) )
1808                                         $converted[ $stylesheet ] = true;
1809                         }
1810                         update_site_option( 'allowedthemes', $converted );
1811                         delete_site_option( 'allowed_themes' );
1812                 }
1813         }
1814
1815         // 3.5
1816         if ( $wp_current_db_version < 21823 )
1817                 update_site_option( 'ms_files_rewriting', '1' );
1818
1819         // 3.5.2
1820         if ( $wp_current_db_version < 24448 ) {
1821                 $illegal_names = get_site_option( 'illegal_names' );
1822                 if ( is_array( $illegal_names ) && count( $illegal_names ) === 1 ) {
1823                         $illegal_name = reset( $illegal_names );
1824                         $illegal_names = explode( ' ', $illegal_name );
1825                         update_site_option( 'illegal_names', $illegal_names );
1826                 }
1827         }
1828
1829         // 4.2
1830         if ( $wp_current_db_version < 31351 && $wpdb->charset === 'utf8mb4' ) {
1831                 if ( wp_should_upgrade_global_tables() ) {
1832                         $wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
1833                         $wpdb->query( "ALTER TABLE $wpdb->site DROP INDEX domain, ADD INDEX domain(domain(140),path(51))" );
1834                         $wpdb->query( "ALTER TABLE $wpdb->sitemeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
1835                         $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" );
1836
1837                         $tables = $wpdb->tables( 'global' );
1838
1839                         // sitecategories may not exist.
1840                         if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) {
1841                                 unset( $tables['sitecategories'] );
1842                         }
1843
1844                         foreach ( $tables as $table ) {
1845                                 maybe_convert_table_to_utf8mb4( $table );
1846                         }
1847                 }
1848         }
1849
1850         // 4.3
1851         if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) {
1852                 if ( wp_should_upgrade_global_tables() ) {
1853                         $upgrade = false;
1854                         $indexes = $wpdb->get_results( "SHOW INDEXES FROM $wpdb->signups" );
1855                         foreach ( $indexes as $index ) {
1856                                 if ( 'domain_path' == $index->Key_name && 'domain' == $index->Column_name && 140 != $index->Sub_part ) {
1857                                         $upgrade = true;
1858                                         break;
1859                                 }
1860                         }
1861
1862                         if ( $upgrade ) {
1863                                 $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" );
1864                         }
1865
1866                         $tables = $wpdb->tables( 'global' );
1867
1868                         // sitecategories may not exist.
1869                         if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) {
1870                                 unset( $tables['sitecategories'] );
1871                         }
1872
1873                         foreach ( $tables as $table ) {
1874                                 maybe_convert_table_to_utf8mb4( $table );
1875                         }
1876                 }
1877         }
1878 }
1879
1880 //
1881 // General functions we use to actually do stuff
1882 //
1883
1884 /**
1885  * Creates a table in the database if it doesn't already exist.
1886  *
1887  * This method checks for an existing database and creates a new one if it's not
1888  * already present. It doesn't rely on MySQL's "IF NOT EXISTS" statement, but chooses
1889  * to query all tables first and then run the SQL statement creating the table.
1890  *
1891  * @since 1.0.0
1892  *
1893  * @global wpdb  $wpdb
1894  *
1895  * @param string $table_name Database table name to create.
1896  * @param string $create_ddl SQL statement to create table.
1897  * @return bool If table already exists or was created by function.
1898  */
1899 function maybe_create_table($table_name, $create_ddl) {
1900         global $wpdb;
1901
1902         $query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $table_name ) );
1903
1904         if ( $wpdb->get_var( $query ) == $table_name ) {
1905                 return true;
1906         }
1907
1908         // Didn't find it try to create it..
1909         $wpdb->query($create_ddl);
1910
1911         // We cannot directly tell that whether this succeeded!
1912         if ( $wpdb->get_var( $query ) == $table_name ) {
1913                 return true;
1914         }
1915         return false;
1916 }
1917
1918 /**
1919  * Drops a specified index from a table.
1920  *
1921  * @since 1.0.1
1922  *
1923  * @global wpdb  $wpdb
1924  *
1925  * @param string $table Database table name.
1926  * @param string $index Index name to drop.
1927  * @return true True, when finished.
1928  */
1929 function drop_index($table, $index) {
1930         global $wpdb;
1931         $wpdb->hide_errors();
1932         $wpdb->query("ALTER TABLE `$table` DROP INDEX `$index`");
1933         // Now we need to take out all the extra ones we may have created
1934         for ($i = 0; $i < 25; $i++) {
1935                 $wpdb->query("ALTER TABLE `$table` DROP INDEX `{$index}_$i`");
1936         }
1937         $wpdb->show_errors();
1938         return true;
1939 }
1940
1941 /**
1942  * Adds an index to a specified table.
1943  *
1944  * @since 1.0.1
1945  *
1946  * @global wpdb  $wpdb
1947  *
1948  * @param string $table Database table name.
1949  * @param string $index Database table index column.
1950  * @return true True, when done with execution.
1951  */
1952 function add_clean_index($table, $index) {
1953         global $wpdb;
1954         drop_index($table, $index);
1955         $wpdb->query("ALTER TABLE `$table` ADD INDEX ( `$index` )");
1956         return true;
1957 }
1958
1959 /**
1960  * Adds column to a database table if it doesn't already exist.
1961  *
1962  * @since 1.3.0
1963  *
1964  * @global wpdb  $wpdb
1965  *
1966  * @param string $table_name  The table name to modify.
1967  * @param string $column_name The column name to add to the table.
1968  * @param string $create_ddl  The SQL statement used to add the column.
1969  * @return bool True if already exists or on successful completion, false on error.
1970  */
1971 function maybe_add_column($table_name, $column_name, $create_ddl) {
1972         global $wpdb;
1973         foreach ($wpdb->get_col("DESC $table_name", 0) as $column ) {
1974                 if ($column == $column_name) {
1975                         return true;
1976                 }
1977         }
1978
1979         // Didn't find it try to create it.
1980         $wpdb->query($create_ddl);
1981
1982         // We cannot directly tell that whether this succeeded!
1983         foreach ($wpdb->get_col("DESC $table_name", 0) as $column ) {
1984                 if ($column == $column_name) {
1985                         return true;
1986                 }
1987         }
1988         return false;
1989 }
1990
1991 /**
1992  * If a table only contains utf8 or utf8mb4 columns, convert it to utf8mb4.
1993  *
1994  * @since 4.2.0
1995  *
1996  * @global wpdb  $wpdb
1997  *
1998  * @param string $table The table to convert.
1999  * @return bool true if the table was converted, false if it wasn't.
2000  */
2001 function maybe_convert_table_to_utf8mb4( $table ) {
2002         global $wpdb;
2003
2004         $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `$table`" );
2005         if ( ! $results ) {
2006                 return false;
2007         }
2008
2009         foreach ( $results as $column ) {
2010                 if ( $column->Collation ) {
2011                         list( $charset ) = explode( '_', $column->Collation );
2012                         $charset = strtolower( $charset );
2013                         if ( 'utf8' !== $charset && 'utf8mb4' !== $charset ) {
2014                                 // Don't upgrade tables that have non-utf8 columns.
2015                                 return false;
2016                         }
2017                 }
2018         }
2019
2020         $table_details = $wpdb->get_row( "SHOW TABLE STATUS LIKE '$table'" );
2021         if ( ! $table_details ) {
2022                 return false;
2023         }
2024
2025         list( $table_charset ) = explode( '_', $table_details->Collation );
2026         $table_charset = strtolower( $table_charset );
2027         if ( 'utf8mb4' === $table_charset ) {
2028                 return true;
2029         }
2030
2031         return $wpdb->query( "ALTER TABLE $table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
2032 }
2033
2034 /**
2035  * Retrieve all options as it was for 1.2.
2036  *
2037  * @since 1.2.0
2038  *
2039  * @global wpdb  $wpdb
2040  *
2041  * @return stdClass List of options.
2042  */
2043 function get_alloptions_110() {
2044         global $wpdb;
2045         $all_options = new stdClass;
2046         if ( $options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" ) ) {
2047                 foreach ( $options as $option ) {
2048                         if ( 'siteurl' == $option->option_name || 'home' == $option->option_name || 'category_base' == $option->option_name )
2049                                 $option->option_value = untrailingslashit( $option->option_value );
2050                         $all_options->{$option->option_name} = stripslashes( $option->option_value );
2051                 }
2052         }
2053         return $all_options;
2054 }
2055
2056 /**
2057  * Utility version of get_option that is private to install/upgrade.
2058  *
2059  * @ignore
2060  * @since 1.5.1
2061  * @access private
2062  *
2063  * @global wpdb  $wpdb
2064  *
2065  * @param string $setting Option name.
2066  * @return mixed
2067  */
2068 function __get_option($setting) {
2069         global $wpdb;
2070
2071         if ( $setting == 'home' && defined( 'WP_HOME' ) )
2072                 return untrailingslashit( WP_HOME );
2073
2074         if ( $setting == 'siteurl' && defined( 'WP_SITEURL' ) )
2075                 return untrailingslashit( WP_SITEURL );
2076
2077         $option = $wpdb->get_var( $wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s", $setting ) );
2078
2079         if ( 'home' == $setting && '' == $option )
2080                 return __get_option( 'siteurl' );
2081
2082         if ( 'siteurl' == $setting || 'home' == $setting || 'category_base' == $setting || 'tag_base' == $setting )
2083                 $option = untrailingslashit( $option );
2084
2085         return maybe_unserialize( $option );
2086 }
2087
2088 /**
2089  * Filters for content to remove unnecessary slashes.
2090  *
2091  * @since 1.5.0
2092  *
2093  * @param string $content The content to modify.
2094  * @return string The de-slashed content.
2095  */
2096 function deslash($content) {
2097         // Note: \\\ inside a regex denotes a single backslash.
2098
2099         /*
2100          * Replace one or more backslashes followed by a single quote with
2101          * a single quote.
2102          */
2103         $content = preg_replace("/\\\+'/", "'", $content);
2104
2105         /*
2106          * Replace one or more backslashes followed by a double quote with
2107          * a double quote.
2108          */
2109         $content = preg_replace('/\\\+"/', '"', $content);
2110
2111         // Replace one or more backslashes with one backslash.
2112         $content = preg_replace("/\\\+/", "\\", $content);
2113
2114         return $content;
2115 }
2116
2117 /**
2118  * Modifies the database based on specified SQL statements.
2119  *
2120  * Useful for creating new tables and updating existing tables to a new structure.
2121  *
2122  * @since 1.5.0
2123  *
2124  * @global wpdb  $wpdb
2125  *
2126  * @param string|array $queries Optional. The query to run. Can be multiple queries
2127  *                              in an array, or a string of queries separated by
2128  *                              semicolons. Default empty.
2129  * @param bool         $execute Optional. Whether or not to execute the query right away.
2130  *                              Default true.
2131  * @return array Strings containing the results of the various update queries.
2132  */
2133 function dbDelta( $queries = '', $execute = true ) {
2134         global $wpdb;
2135
2136         if ( in_array( $queries, array( '', 'all', 'blog', 'global', 'ms_global' ), true ) )
2137             $queries = wp_get_db_schema( $queries );
2138
2139         // Separate individual queries into an array
2140         if ( !is_array($queries) ) {
2141                 $queries = explode( ';', $queries );
2142                 $queries = array_filter( $queries );
2143         }
2144
2145         /**
2146          * Filters the dbDelta SQL queries.
2147          *
2148          * @since 3.3.0
2149          *
2150          * @param array $queries An array of dbDelta SQL queries.
2151          */
2152         $queries = apply_filters( 'dbdelta_queries', $queries );
2153
2154         $cqueries = array(); // Creation Queries
2155         $iqueries = array(); // Insertion Queries
2156         $for_update = array();
2157
2158         // Create a tablename index for an array ($cqueries) of queries
2159         foreach ($queries as $qry) {
2160                 if ( preg_match( "|CREATE TABLE ([^ ]*)|", $qry, $matches ) ) {
2161                         $cqueries[ trim( $matches[1], '`' ) ] = $qry;
2162                         $for_update[$matches[1]] = 'Created table '.$matches[1];
2163                 } elseif ( preg_match( "|CREATE DATABASE ([^ ]*)|", $qry, $matches ) ) {
2164                         array_unshift( $cqueries, $qry );
2165                 } elseif ( preg_match( "|INSERT INTO ([^ ]*)|", $qry, $matches ) ) {
2166                         $iqueries[] = $qry;
2167                 } elseif ( preg_match( "|UPDATE ([^ ]*)|", $qry, $matches ) ) {
2168                         $iqueries[] = $qry;
2169                 } else {
2170                         // Unrecognized query type
2171                 }
2172         }
2173
2174         /**
2175          * Filters the dbDelta SQL queries for creating tables and/or databases.
2176          *
2177          * Queries filterable via this hook contain "CREATE TABLE" or "CREATE DATABASE".
2178          *
2179          * @since 3.3.0
2180          *
2181          * @param array $cqueries An array of dbDelta create SQL queries.
2182          */
2183         $cqueries = apply_filters( 'dbdelta_create_queries', $cqueries );
2184
2185         /**
2186          * Filters the dbDelta SQL queries for inserting or updating.
2187          *
2188          * Queries filterable via this hook contain "INSERT INTO" or "UPDATE".
2189          *
2190          * @since 3.3.0
2191          *
2192          * @param array $iqueries An array of dbDelta insert or update SQL queries.
2193          */
2194         $iqueries = apply_filters( 'dbdelta_insert_queries', $iqueries );
2195
2196         $text_fields = array( 'tinytext', 'text', 'mediumtext', 'longtext' );
2197         $blob_fields = array( 'tinyblob', 'blob', 'mediumblob', 'longblob' );
2198
2199         $global_tables = $wpdb->tables( 'global' );
2200         foreach ( $cqueries as $table => $qry ) {
2201                 // Upgrade global tables only for the main site. Don't upgrade at all if conditions are not optimal.
2202                 if ( in_array( $table, $global_tables ) && ! wp_should_upgrade_global_tables() ) {
2203                         unset( $cqueries[ $table ], $for_update[ $table ] );
2204                         continue;
2205                 }
2206
2207                 // Fetch the table column structure from the database
2208                 $suppress = $wpdb->suppress_errors();
2209                 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
2210                 $wpdb->suppress_errors( $suppress );
2211
2212                 if ( ! $tablefields )
2213                         continue;
2214
2215                 // Clear the field and index arrays.
2216                 $cfields = $indices = array();
2217
2218                 // Get all of the field names in the query from between the parentheses.
2219                 preg_match("|\((.*)\)|ms", $qry, $match2);
2220                 $qryline = trim($match2[1]);
2221
2222                 // Separate field lines into an array.
2223                 $flds = explode("\n", $qryline);
2224
2225                 // For every field line specified in the query.
2226                 foreach ( $flds as $fld ) {
2227                         $fld = trim( $fld, " \t\n\r\0\x0B," ); // Default trim characters, plus ','.
2228
2229                         // Extract the field name.
2230                         preg_match( '|^([^ ]*)|', $fld, $fvals );
2231                         $fieldname = trim( $fvals[1], '`' );
2232                         $fieldname_lowercased = strtolower( $fieldname );
2233
2234                         // Verify the found field name.
2235                         $validfield = true;
2236                         switch ( $fieldname_lowercased ) {
2237                                 case '':
2238                                 case 'primary':
2239                                 case 'index':
2240                                 case 'fulltext':
2241                                 case 'unique':
2242                                 case 'key':
2243                                 case 'spatial':
2244                                         $validfield = false;
2245
2246                                         /*
2247                                          * Normalize the index definition.
2248                                          *
2249                                          * This is done so the definition can be compared against the result of a
2250                                          * `SHOW INDEX FROM $table_name` query which returns the current table
2251                                          * index information.
2252                                          */
2253
2254                                         // Extract type, name and columns from the definition.
2255                                         preg_match(
2256                                                   '/^'
2257                                                 .   '(?P<index_type>'             // 1) Type of the index.
2258                                                 .       'PRIMARY\s+KEY|(?:UNIQUE|FULLTEXT|SPATIAL)\s+(?:KEY|INDEX)|KEY|INDEX'
2259                                                 .   ')'
2260                                                 .   '\s+'                         // Followed by at least one white space character.
2261                                                 .   '(?:'                         // Name of the index. Optional if type is PRIMARY KEY.
2262                                                 .       '`?'                      // Name can be escaped with a backtick.
2263                                                 .           '(?P<index_name>'     // 2) Name of the index.
2264                                                 .               '(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+'
2265                                                 .           ')'
2266                                                 .       '`?'                      // Name can be escaped with a backtick.
2267                                                 .       '\s+'                     // Followed by at least one white space character.
2268                                                 .   ')*'
2269                                                 .   '\('                          // Opening bracket for the columns.
2270                                                 .       '(?P<index_columns>'
2271                                                 .           '.+?'                 // 3) Column names, index prefixes, and orders.
2272                                                 .       ')'
2273                                                 .   '\)'                          // Closing bracket for the columns.
2274                                                 . '$/im',
2275                                                 $fld,
2276                                                 $index_matches
2277                                         );
2278
2279                                         // Uppercase the index type and normalize space characters.
2280                                         $index_type = strtoupper( preg_replace( '/\s+/', ' ', trim( $index_matches['index_type'] ) ) );
2281
2282                                         // 'INDEX' is a synonym for 'KEY', standardize on 'KEY'.
2283                                         $index_type = str_replace( 'INDEX', 'KEY', $index_type );
2284
2285                                         // Escape the index name with backticks. An index for a primary key has no name.
2286                                         $index_name = ( 'PRIMARY KEY' === $index_type ) ? '' : '`' . $index_matches['index_name'] . '`';
2287
2288                                         // Parse the columns. Multiple columns are separated by a comma.
2289                                         $index_columns = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) );
2290
2291                                         // Normalize columns.
2292                                         foreach ( $index_columns as &$index_column ) {
2293                                                 // Extract column name and number of indexed characters (sub_part).
2294                                                 preg_match(
2295                                                           '/'
2296                                                         .   '`?'                      // Name can be escaped with a backtick.
2297                                                         .       '(?P<column_name>'    // 1) Name of the column.
2298                                                         .           '(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+'
2299                                                         .       ')'
2300                                                         .   '`?'                      // Name can be escaped with a backtick.
2301                                                         .   '(?:'                     // Optional sub part.
2302                                                         .       '\s*'                 // Optional white space character between name and opening bracket.
2303                                                         .       '\('                  // Opening bracket for the sub part.
2304                                                         .           '\s*'             // Optional white space character after opening bracket.
2305                                                         .           '(?P<sub_part>'
2306                                                         .               '\d+'         // 2) Number of indexed characters.
2307                                                         .           ')'
2308                                                         .           '\s*'             // Optional white space character before closing bracket.
2309                                                         .        '\)'                 // Closing bracket for the sub part.
2310                                                         .   ')?'
2311                                                         . '/',
2312                                                         $index_column,
2313                                                         $index_column_matches
2314                                                 );
2315
2316                                                 // Escape the column name with backticks.
2317                                                 $index_column = '`' . $index_column_matches['column_name'] . '`';
2318
2319                                                 // Append the optional sup part with the number of indexed characters.
2320                                                 if ( isset( $index_column_matches['sub_part'] ) ) {
2321                                                         $index_column .= '(' . $index_column_matches['sub_part'] . ')';
2322                                                 }
2323                                         }
2324
2325                                         // Build the normalized index definition and add it to the list of indices.
2326                                         $indices[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns ) . ")";
2327
2328                                         // Destroy no longer needed variables.
2329                                         unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns );
2330
2331                                         break;
2332                         }
2333
2334                         // If it's a valid field, add it to the field array.
2335                         if ( $validfield ) {
2336                                 $cfields[ $fieldname_lowercased ] = $fld;
2337                         }
2338                 }
2339
2340                 // For every field in the table.
2341                 foreach ( $tablefields as $tablefield ) {
2342                         $tablefield_field_lowercased = strtolower( $tablefield->Field );
2343                         $tablefield_type_lowercased = strtolower( $tablefield->Type );
2344
2345                         // If the table field exists in the field array ...
2346                         if ( array_key_exists( $tablefield_field_lowercased, $cfields ) ) {
2347
2348                                 // Get the field type from the query.
2349                                 preg_match( '|`?' . $tablefield->Field . '`? ([^ ]*( unsigned)?)|i', $cfields[ $tablefield_field_lowercased ], $matches );
2350                                 $fieldtype = $matches[1];
2351                                 $fieldtype_lowercased = strtolower( $fieldtype );
2352
2353                                 // Is actual field type different from the field type in query?
2354                                 if ($tablefield->Type != $fieldtype) {
2355                                         $do_change = true;
2356                                         if ( in_array( $fieldtype_lowercased, $text_fields ) && in_array( $tablefield_type_lowercased, $text_fields ) ) {
2357                                                 if ( array_search( $fieldtype_lowercased, $text_fields ) < array_search( $tablefield_type_lowercased, $text_fields ) ) {
2358                                                         $do_change = false;
2359                                                 }
2360                                         }
2361
2362                                         if ( in_array( $fieldtype_lowercased, $blob_fields ) && in_array( $tablefield_type_lowercased, $blob_fields ) ) {
2363                                                 if ( array_search( $fieldtype_lowercased, $blob_fields ) < array_search( $tablefield_type_lowercased, $blob_fields ) ) {
2364                                                         $do_change = false;
2365                                                 }
2366                                         }
2367
2368                                         if ( $do_change ) {
2369                                                 // Add a query to change the column type.
2370                                                 $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN `{$tablefield->Field}` " . $cfields[ $tablefield_field_lowercased ];
2371                                                 $for_update[$table.'.'.$tablefield->Field] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}";
2372                                         }
2373                                 }
2374
2375                                 // Get the default value from the array.
2376                                 if ( preg_match( "| DEFAULT '(.*?)'|i", $cfields[ $tablefield_field_lowercased ], $matches ) ) {
2377                                         $default_value = $matches[1];
2378                                         if ($tablefield->Default != $default_value) {
2379                                                 // Add a query to change the column's default value
2380                                                 $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN `{$tablefield->Field}` SET DEFAULT '{$default_value}'";
2381                                                 $for_update[$table.'.'.$tablefield->Field] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}";
2382                                         }
2383                                 }
2384
2385                                 // Remove the field from the array (so it's not added).
2386                                 unset( $cfields[ $tablefield_field_lowercased ] );
2387                         } else {
2388                                 // This field exists in the table, but not in the creation queries?
2389                         }
2390                 }
2391
2392                 // For every remaining field specified for the table.
2393                 foreach ($cfields as $fieldname => $fielddef) {
2394                         // Push a query line into $cqueries that adds the field to that table.
2395                         $cqueries[] = "ALTER TABLE {$table} ADD COLUMN $fielddef";
2396                         $for_update[$table.'.'.$fieldname] = 'Added column '.$table.'.'.$fieldname;
2397                 }
2398
2399                 // Index stuff goes here. Fetch the table index structure from the database.
2400                 $tableindices = $wpdb->get_results("SHOW INDEX FROM {$table};");
2401
2402                 if ($tableindices) {
2403                         // Clear the index array.
2404                         $index_ary = array();
2405
2406                         // For every index in the table.
2407                         foreach ($tableindices as $tableindex) {
2408
2409                                 // Add the index to the index data array.
2410                                 $keyname = $tableindex->Key_name;
2411                                 $index_ary[$keyname]['columns'][] = array('fieldname' => $tableindex->Column_name, 'subpart' => $tableindex->Sub_part);
2412                                 $index_ary[$keyname]['unique'] = ($tableindex->Non_unique == 0)?true:false;
2413                                 $index_ary[$keyname]['index_type'] = $tableindex->Index_type;
2414                         }
2415
2416                         // For each actual index in the index array.
2417                         foreach ($index_ary as $index_name => $index_data) {
2418
2419                                 // Build a create string to compare to the query.
2420                                 $index_string = '';
2421                                 if ($index_name == 'PRIMARY') {
2422                                         $index_string .= 'PRIMARY ';
2423                                 } elseif ( $index_data['unique'] ) {
2424                                         $index_string .= 'UNIQUE ';
2425                                 }
2426                                 if ( 'FULLTEXT' === strtoupper( $index_data['index_type'] ) ) {
2427                                         $index_string .= 'FULLTEXT ';
2428                                 }
2429                                 if ( 'SPATIAL' === strtoupper( $index_data['index_type'] ) ) {
2430                                         $index_string .= 'SPATIAL ';
2431                                 }
2432                                 $index_string .= 'KEY ';
2433                                 if ( 'PRIMARY' !== $index_name  ) {
2434                                         $index_string .= '`' . $index_name . '`';
2435                                 }
2436                                 $index_columns = '';
2437
2438                                 // For each column in the index.
2439                                 foreach ($index_data['columns'] as $column_data) {
2440                                         if ( $index_columns != '' ) {
2441                                                 $index_columns .= ',';
2442                                         }
2443
2444                                         // Add the field to the column list string.
2445                                         $index_columns .= '`' . $column_data['fieldname'] . '`';
2446                                         if ($column_data['subpart'] != '') {
2447                                                 $index_columns .= '('.$column_data['subpart'].')';
2448                                         }
2449                                 }
2450
2451                                 // The alternative index string doesn't care about subparts
2452                                 $alt_index_columns = preg_replace( '/\([^)]*\)/', '', $index_columns );
2453
2454                                 // Add the column list to the index create string.
2455                                 $index_strings = array(
2456                                         "$index_string ($index_columns)",
2457                                         "$index_string ($alt_index_columns)",
2458                                 );
2459
2460                                 foreach ( $index_strings as $index_string ) {
2461                                         if ( ! ( ( $aindex = array_search( $index_string, $indices ) ) === false ) ) {
2462                                                 unset( $indices[ $aindex ] );
2463                                                 break;
2464                                         }
2465                                 }
2466                         }
2467                 }
2468
2469                 // For every remaining index specified for the table.
2470                 foreach ( (array) $indices as $index ) {
2471                         // Push a query line into $cqueries that adds the index to that table.
2472                         $cqueries[] = "ALTER TABLE {$table} ADD $index";
2473                         $for_update[] = 'Added index ' . $table . ' ' . $index;
2474                 }
2475
2476                 // Remove the original table creation query from processing.
2477                 unset( $cqueries[ $table ], $for_update[ $table ] );
2478         }
2479
2480         $allqueries = array_merge($cqueries, $iqueries);
2481         if ($execute) {
2482                 foreach ($allqueries as $query) {
2483                         $wpdb->query($query);
2484                 }
2485         }
2486
2487         return $for_update;
2488 }
2489
2490 /**
2491  * Updates the database tables to a new schema.
2492  *
2493  * By default, updates all the tables to use the latest defined schema, but can also
2494  * be used to update a specific set of tables in wp_get_db_schema().
2495  *
2496  * @since 1.5.0
2497  *
2498  * @uses dbDelta
2499  *
2500  * @param string $tables Optional. Which set of tables to update. Default is 'all'.
2501  */
2502 function make_db_current( $tables = 'all' ) {
2503         $alterations = dbDelta( $tables );
2504         echo "<ol>\n";
2505         foreach ($alterations as $alteration) echo "<li>$alteration</li>\n";
2506         echo "</ol>\n";
2507 }
2508
2509 /**
2510  * Updates the database tables to a new schema, but without displaying results.
2511  *
2512  * By default, updates all the tables to use the latest defined schema, but can
2513  * also be used to update a specific set of tables in wp_get_db_schema().
2514  *
2515  * @since 1.5.0
2516  *
2517  * @see make_db_current()
2518  *
2519  * @param string $tables Optional. Which set of tables to update. Default is 'all'.
2520  */
2521 function make_db_current_silent( $tables = 'all' ) {
2522         dbDelta( $tables );
2523 }
2524
2525 /**
2526  * Creates a site theme from an existing theme.
2527  *
2528  * {@internal Missing Long Description}}
2529  *
2530  * @since 1.5.0
2531  *
2532  * @param string $theme_name The name of the theme.
2533  * @param string $template   The directory name of the theme.
2534  * @return bool
2535  */
2536 function make_site_theme_from_oldschool($theme_name, $template) {
2537         $home_path = get_home_path();
2538         $site_dir = WP_CONTENT_DIR . "/themes/$template";
2539
2540         if (! file_exists("$home_path/index.php"))
2541                 return false;
2542
2543         /*
2544          * Copy files from the old locations to the site theme.
2545          * TODO: This does not copy arbitrary include dependencies. Only the standard WP files are copied.
2546          */
2547         $files = array('index.php' => 'index.php', 'wp-layout.css' => 'style.css', 'wp-comments.php' => 'comments.php', 'wp-comments-popup.php' => 'comments-popup.php');
2548
2549         foreach ($files as $oldfile => $newfile) {
2550                 if ($oldfile == 'index.php')
2551                         $oldpath = $home_path;
2552                 else
2553                         $oldpath = ABSPATH;
2554
2555                 // Check to make sure it's not a new index.
2556                 if ($oldfile == 'index.php') {
2557                         $index = implode('', file("$oldpath/$oldfile"));
2558                         if (strpos($index, 'WP_USE_THEMES') !== false) {
2559                                 if (! @copy(WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME . '/index.php', "$site_dir/$newfile"))
2560                                         return false;
2561
2562                                 // Don't copy anything.
2563                                 continue;
2564                         }
2565                 }
2566
2567                 if (! @copy("$oldpath/$oldfile", "$site_dir/$newfile"))
2568                         return false;
2569
2570                 chmod("$site_dir/$newfile", 0777);
2571
2572                 // Update the blog header include in each file.
2573                 $lines = explode("\n", implode('', file("$site_dir/$newfile")));
2574                 if ($lines) {
2575                         $f = fopen("$site_dir/$newfile", 'w');
2576
2577                         foreach ($lines as $line) {
2578                                 if (preg_match('/require.*wp-blog-header/', $line))
2579                                         $line = '//' . $line;
2580
2581                                 // Update stylesheet references.
2582                                 $line = str_replace("<?php echo __get_option('siteurl'); ?>/wp-layout.css", "<?php bloginfo('stylesheet_url'); ?>", $line);
2583
2584                                 // Update comments template inclusion.
2585                                 $line = str_replace("<?php include(ABSPATH . 'wp-comments.php'); ?>", "<?php comments_template(); ?>", $line);
2586
2587                                 fwrite($f, "{$line}\n");
2588                         }
2589                         fclose($f);
2590                 }
2591         }
2592
2593         // Add a theme header.
2594         $header = "/*\nTheme Name: $theme_name\nTheme URI: " . __get_option('siteurl') . "\nDescription: A theme automatically created by the update.\nVersion: 1.0\nAuthor: Moi\n*/\n";
2595
2596         $stylelines = file_get_contents("$site_dir/style.css");
2597         if ($stylelines) {
2598                 $f = fopen("$site_dir/style.css", 'w');
2599
2600                 fwrite($f, $header);
2601                 fwrite($f, $stylelines);
2602                 fclose($f);
2603         }
2604
2605         return true;
2606 }
2607
2608 /**
2609  * Creates a site theme from the default theme.
2610  *
2611  * {@internal Missing Long Description}}
2612  *
2613  * @since 1.5.0
2614  *
2615  * @param string $theme_name The name of the theme.
2616  * @param string $template   The directory name of the theme.
2617  * @return false|void
2618  */
2619 function make_site_theme_from_default($theme_name, $template) {
2620         $site_dir = WP_CONTENT_DIR . "/themes/$template";
2621         $default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME;
2622
2623         // Copy files from the default theme to the site theme.
2624         //$files = array('index.php', 'comments.php', 'comments-popup.php', 'footer.php', 'header.php', 'sidebar.php', 'style.css');
2625
2626         $theme_dir = @ opendir($default_dir);
2627         if ($theme_dir) {
2628                 while(($theme_file = readdir( $theme_dir )) !== false) {
2629                         if (is_dir("$default_dir/$theme_file"))
2630                                 continue;
2631                         if (! @copy("$default_dir/$theme_file", "$site_dir/$theme_file"))
2632                                 return;
2633                         chmod("$site_dir/$theme_file", 0777);
2634                 }
2635         }
2636         @closedir($theme_dir);
2637
2638         // Rewrite the theme header.
2639         $stylelines = explode("\n", implode('', file("$site_dir/style.css")));
2640         if ($stylelines) {
2641                 $f = fopen("$site_dir/style.css", 'w');
2642
2643                 foreach ($stylelines as $line) {
2644                         if (strpos($line, 'Theme Name:') !== false) $line = 'Theme Name: ' . $theme_name;
2645                         elseif (strpos($line, 'Theme URI:') !== false) $line = 'Theme URI: ' . __get_option('url');
2646                         elseif (strpos($line, 'Description:') !== false) $line = 'Description: Your theme.';
2647                         elseif (strpos($line, 'Version:') !== false) $line = 'Version: 1';
2648                         elseif (strpos($line, 'Author:') !== false) $line = 'Author: You';
2649                         fwrite($f, $line . "\n");
2650                 }
2651                 fclose($f);
2652         }
2653
2654         // Copy the images.
2655         umask(0);
2656         if (! mkdir("$site_dir/images", 0777)) {
2657                 return false;
2658         }
2659
2660         $images_dir = @ opendir("$default_dir/images");
2661         if ($images_dir) {
2662                 while(($image = readdir($images_dir)) !== false) {
2663                         if (is_dir("$default_dir/images/$image"))
2664                                 continue;
2665                         if (! @copy("$default_dir/images/$image", "$site_dir/images/$image"))
2666                                 return;
2667                         chmod("$site_dir/images/$image", 0777);
2668                 }
2669         }
2670         @closedir($images_dir);
2671 }
2672
2673 /**
2674  * Creates a site theme.
2675  *
2676  * {@internal Missing Long Description}}
2677  *
2678  * @since 1.5.0
2679  *
2680  * @return false|string
2681  */
2682 function make_site_theme() {
2683         // Name the theme after the blog.
2684         $theme_name = __get_option('blogname');
2685         $template = sanitize_title($theme_name);
2686         $site_dir = WP_CONTENT_DIR . "/themes/$template";
2687
2688         // If the theme already exists, nothing to do.
2689         if ( is_dir($site_dir)) {
2690                 return false;
2691         }
2692
2693         // We must be able to write to the themes dir.
2694         if (! is_writable(WP_CONTENT_DIR . "/themes")) {
2695                 return false;
2696         }
2697
2698         umask(0);
2699         if (! mkdir($site_dir, 0777)) {
2700                 return false;
2701         }
2702
2703         if (file_exists(ABSPATH . 'wp-layout.css')) {
2704                 if (! make_site_theme_from_oldschool($theme_name, $template)) {
2705                         // TODO: rm -rf the site theme directory.
2706                         return false;
2707                 }
2708         } else {
2709                 if (! make_site_theme_from_default($theme_name, $template))
2710                         // TODO: rm -rf the site theme directory.
2711                         return false;
2712         }
2713
2714         // Make the new site theme active.
2715         $current_template = __get_option('template');
2716         if ($current_template == WP_DEFAULT_THEME) {
2717                 update_option('template', $template);
2718                 update_option('stylesheet', $template);
2719         }
2720         return $template;
2721 }
2722
2723 /**
2724  * Translate user level to user role name.
2725  *
2726  * @since 2.0.0
2727  *
2728  * @param int $level User level.
2729  * @return string User role name.
2730  */
2731 function translate_level_to_role($level) {
2732         switch ($level) {
2733         case 10:
2734         case 9:
2735         case 8:
2736                 return 'administrator';
2737         case 7:
2738         case 6:
2739         case 5:
2740                 return 'editor';
2741         case 4:
2742         case 3:
2743         case 2:
2744                 return 'author';
2745         case 1:
2746                 return 'contributor';
2747         case 0:
2748                 return 'subscriber';
2749         }
2750 }
2751
2752 /**
2753  * Checks the version of the installed MySQL binary.
2754  *
2755  * @since 2.1.0
2756  *
2757  * @global wpdb  $wpdb
2758  */
2759 function wp_check_mysql_version() {
2760         global $wpdb;
2761         $result = $wpdb->check_database_version();
2762         if ( is_wp_error( $result ) )
2763                 die( $result->get_error_message() );
2764 }
2765
2766 /**
2767  * Disables the Automattic widgets plugin, which was merged into core.
2768  *
2769  * @since 2.2.0
2770  */
2771 function maybe_disable_automattic_widgets() {
2772         $plugins = __get_option( 'active_plugins' );
2773
2774         foreach ( (array) $plugins as $plugin ) {
2775                 if ( basename( $plugin ) == 'widgets.php' ) {
2776                         array_splice( $plugins, array_search( $plugin, $plugins ), 1 );
2777                         update_option( 'active_plugins', $plugins );
2778                         break;
2779                 }
2780         }
2781 }
2782
2783 /**
2784  * Disables the Link Manager on upgrade if, at the time of upgrade, no links exist in the DB.
2785  *
2786  * @since 3.5.0
2787  *
2788  * @global int  $wp_current_db_version
2789  * @global wpdb $wpdb WordPress database abstraction object.
2790  */
2791 function maybe_disable_link_manager() {
2792         global $wp_current_db_version, $wpdb;
2793
2794         if ( $wp_current_db_version >= 22006 && get_option( 'link_manager_enabled' ) && ! $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) )
2795                 update_option( 'link_manager_enabled', 0 );
2796 }
2797
2798 /**
2799  * Runs before the schema is upgraded.
2800  *
2801  * @since 2.9.0
2802  *
2803  * @global int  $wp_current_db_version
2804  * @global wpdb $wpdb WordPress database abstraction object.
2805  */
2806 function pre_schema_upgrade() {
2807         global $wp_current_db_version, $wpdb;
2808
2809         // Upgrade versions prior to 2.9
2810         if ( $wp_current_db_version < 11557 ) {
2811                 // Delete duplicate options. Keep the option with the highest option_id.
2812                 $wpdb->query("DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (`option_name`) WHERE o2.option_id > o1.option_id");
2813
2814                 // Drop the old primary key and add the new.
2815                 $wpdb->query("ALTER TABLE $wpdb->options DROP PRIMARY KEY, ADD PRIMARY KEY(option_id)");
2816
2817                 // Drop the old option_name index. dbDelta() doesn't do the drop.
2818                 $wpdb->query("ALTER TABLE $wpdb->options DROP INDEX option_name");
2819         }
2820
2821         // Multisite schema upgrades.
2822         if ( $wp_current_db_version < 25448 && is_multisite() && wp_should_upgrade_global_tables() ) {
2823
2824                 // Upgrade verions prior to 3.7
2825                 if ( $wp_current_db_version < 25179 ) {
2826                         // New primary key for signups.
2827                         $wpdb->query( "ALTER TABLE $wpdb->signups ADD signup_id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST" );
2828                         $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain" );
2829                 }
2830
2831                 if ( $wp_current_db_version < 25448 ) {
2832                         // Convert archived from enum to tinyint.
2833                         $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived varchar(1) NOT NULL default '0'" );
2834                         $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived tinyint(2) NOT NULL default 0" );
2835                 }
2836         }
2837
2838         // Upgrade versions prior to 4.2.
2839         if ( $wp_current_db_version < 31351 ) {
2840                 if ( ! is_multisite() && wp_should_upgrade_global_tables() ) {
2841                         $wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
2842                 }
2843                 $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX slug, ADD INDEX slug(slug(191))" );
2844                 $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX name, ADD INDEX name(name(191))" );
2845                 $wpdb->query( "ALTER TABLE $wpdb->commentmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
2846                 $wpdb->query( "ALTER TABLE $wpdb->postmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
2847                 $wpdb->query( "ALTER TABLE $wpdb->posts DROP INDEX post_name, ADD INDEX post_name(post_name(191))" );
2848         }
2849
2850         // Upgrade versions prior to 4.4.
2851         if ( $wp_current_db_version < 34978 ) {
2852                 // If compatible termmeta table is found, use it, but enforce a proper index and update collation.
2853                 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->termmeta}'" ) && $wpdb->get_results( "SHOW INDEX FROM {$wpdb->termmeta} WHERE Column_name = 'meta_key'" ) ) {
2854                         $wpdb->query( "ALTER TABLE $wpdb->termmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
2855                         maybe_convert_table_to_utf8mb4( $wpdb->termmeta );
2856                 }
2857         }
2858 }
2859
2860 /**
2861  * Install global terms.
2862  *
2863  * @since 3.0.0
2864  *
2865  * @global wpdb   $wpdb
2866  * @global string $charset_collate
2867  */
2868 if ( !function_exists( 'install_global_terms' ) ) :
2869 function install_global_terms() {
2870         global $wpdb, $charset_collate;
2871         $ms_queries = "
2872 CREATE TABLE $wpdb->sitecategories (
2873   cat_ID bigint(20) NOT NULL auto_increment,
2874   cat_name varchar(55) NOT NULL default '',
2875   category_nicename varchar(200) NOT NULL default '',
2876   last_updated timestamp NOT NULL,
2877   PRIMARY KEY  (cat_ID),
2878   KEY category_nicename (category_nicename),
2879   KEY last_updated (last_updated)
2880 ) $charset_collate;
2881 ";
2882 // now create tables
2883         dbDelta( $ms_queries );
2884 }
2885 endif;
2886
2887 /**
2888  * Determine if global tables should be upgraded.
2889  *
2890  * This function performs a series of checks to ensure the environment allows
2891  * for the safe upgrading of global WordPress database tables. It is necessary
2892  * because global tables will commonly grow to millions of rows on large
2893  * installations, and the ability to control their upgrade routines can be
2894  * critical to the operation of large networks.
2895  *
2896  * In a future iteration, this function may use `wp_is_large_network()` to more-
2897  * intelligently prevent global table upgrades. Until then, we make sure
2898  * WordPress is on the main site of the main network, to avoid running queries
2899  * more than once in multi-site or multi-network environments.
2900  *
2901  * @since 4.3.0
2902  *
2903  * @return bool Whether to run the upgrade routines on global tables.
2904  */
2905 function wp_should_upgrade_global_tables() {
2906
2907         // Return false early if explicitly not upgrading
2908         if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
2909                 return false;
2910         }
2911
2912         // Assume global tables should be upgraded
2913         $should_upgrade = true;
2914
2915         // Set to false if not on main network (does not matter if not multi-network)
2916         if ( ! is_main_network() ) {
2917                 $should_upgrade = false;
2918         }
2919
2920         // Set to false if not on main site of current network (does not matter if not multi-site)
2921         if ( ! is_main_site() ) {
2922                 $should_upgrade = false;
2923         }
2924
2925         /**
2926          * Filters if upgrade routines should be run on global tables.
2927          *
2928          * @param bool $should_upgrade Whether to run the upgrade routines on global tables.
2929          */
2930         return apply_filters( 'wp_should_upgrade_global_tables', $should_upgrade );
2931 }