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