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