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