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