[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 installation customization script. */ 12 if ( file_exists( WP_CONTENT_DIR . '/install.php' ) ) { 13 require WP_CONTENT_DIR . '/install.php'; 14 } 15 16 /** WordPress Administration API */ 17 require_once ABSPATH . 'wp-admin/includes/admin.php'; 18 19 /** WordPress Schema API */ 20 require_once ABSPATH . 'wp-admin/includes/schema.php'; 21 22 if ( ! function_exists( 'wp_install' ) ) : 23 /** 24 * Installs the site. 25 * 26 * Runs the required functions to set up and populate the database, 27 * including primary admin user and initial options. 28 * 29 * @since 2.1.0 30 * 31 * @param string $blog_title Site title. 32 * @param string $user_name User's username. 33 * @param string $user_email User's email. 34 * @param bool $is_public Whether the site is public. 35 * @param string $deprecated Optional. Not used. 36 * @param string $user_password Optional. User's chosen password. Default empty (random password). 37 * @param string $language Optional. Language chosen. Default empty. 38 * @return array { 39 * Data for the newly installed site. 40 * 41 * @type string $url The URL of the site. 42 * @type int $user_id The ID of the site owner. 43 * @type string $password The password of the site owner, if their user account didn't already exist. 44 * @type string $password_message The explanatory message regarding the password. 45 * } 46 */ 47 function wp_install( $blog_title, $user_name, $user_email, $is_public, $deprecated = '', $user_password = '', $language = '' ) { 48 if ( ! empty( $deprecated ) ) { 49 _deprecated_argument( __FUNCTION__, '2.6.0' ); 50 } 51 52 wp_check_mysql_version(); 53 wp_cache_flush(); 54 make_db_current_silent(); 55 populate_options(); 56 populate_roles(); 57 58 update_option( 'blogname', $blog_title ); 59 update_option( 'admin_email', $user_email ); 60 update_option( 'blog_public', $is_public ); 61 62 // Freshness of site - in the future, this could get more specific about actions taken, perhaps. 63 update_option( 'fresh_site', 1 ); 64 65 if ( $language ) { 66 update_option( 'WPLANG', $language ); 67 } 68 69 $guessurl = wp_guess_url(); 70 71 update_option( 'siteurl', $guessurl ); 72 73 // If not a public site, don't ping. 74 if ( ! $is_public ) { 75 update_option( 'default_pingback_flag', 0 ); 76 } 77 78 /* 79 * Create default user. If the user already exists, the user tables are 80 * being shared among sites. Just set the role in that case. 81 */ 82 $user_id = username_exists( $user_name ); 83 $user_password = trim( $user_password ); 84 $email_password = false; 85 $user_created = false; 86 87 if ( ! $user_id && empty( $user_password ) ) { 88 $user_password = wp_generate_password( 12, false ); 89 $message = __( '<strong><em>Note that password</em></strong> carefully! It is a <em>random</em> password that was generated just for you.' ); 90 $user_id = wp_create_user( $user_name, $user_password, $user_email ); 91 update_user_meta( $user_id, 'default_password_nag', true ); 92 $email_password = true; 93 $user_created = true; 94 } elseif ( ! $user_id ) { 95 // Password has been provided. 96 $message = '<em>' . __( 'Your chosen password.' ) . '</em>'; 97 $user_id = wp_create_user( $user_name, $user_password, $user_email ); 98 $user_created = true; 99 } else { 100 $message = __( 'User already exists. Password inherited.' ); 101 } 102 103 $user = new WP_User( $user_id ); 104 $user->set_role( 'administrator' ); 105 106 if ( $user_created ) { 107 $user->user_url = $guessurl; 108 wp_update_user( $user ); 109 } 110 111 wp_install_defaults( $user_id ); 112 113 wp_install_maybe_enable_pretty_permalinks(); 114 115 flush_rewrite_rules(); 116 117 wp_new_blog_notification( $blog_title, $guessurl, $user_id, ( $email_password ? $user_password : __( 'The password you chose during installation.' ) ) ); 118 119 wp_cache_flush(); 120 121 /** 122 * Fires after a site is fully installed. 123 * 124 * @since 3.9.0 125 * 126 * @param WP_User $user The site owner. 127 */ 128 do_action( 'wp_install', $user ); 129 130 return array( 131 'url' => $guessurl, 132 'user_id' => $user_id, 133 'password' => $user_password, 134 'password_message' => $message, 135 ); 136 } 137 endif; 138 139 if ( ! function_exists( 'wp_install_defaults' ) ) : 140 /** 141 * Creates the initial content for a newly-installed site. 142 * 143 * Adds the default "Uncategorized" category, the first post (with comment), 144 * first page, and default widgets for default theme for the current version. 145 * 146 * @since 2.1.0 147 * 148 * @global wpdb $wpdb WordPress database abstraction object. 149 * @global WP_Rewrite $wp_rewrite WordPress rewrite component. 150 * @global string $table_prefix The database table prefix. 151 * 152 * @param int $user_id User ID. 153 */ 154 function wp_install_defaults( $user_id ) { 155 global $wpdb, $wp_rewrite, $table_prefix; 156 157 // Default category. 158 $cat_name = __( 'Uncategorized' ); 159 /* translators: Default category slug. */ 160 $cat_slug = sanitize_title( _x( 'Uncategorized', 'Default category slug' ) ); 161 162 $cat_id = 1; 163 164 $wpdb->insert( 165 $wpdb->terms, 166 array( 167 'term_id' => $cat_id, 168 'name' => $cat_name, 169 'slug' => $cat_slug, 170 'term_group' => 0, 171 ) 172 ); 173 $wpdb->insert( 174 $wpdb->term_taxonomy, 175 array( 176 'term_id' => $cat_id, 177 'taxonomy' => 'category', 178 'description' => '', 179 'parent' => 0, 180 'count' => 1, 181 ) 182 ); 183 $cat_tt_id = $wpdb->insert_id; 184 185 // First post. 186 $now = current_time( 'mysql' ); 187 $now_gmt = current_time( 'mysql', 1 ); 188 $first_post_guid = get_option( 'home' ) . '/?p=1'; 189 190 if ( is_multisite() ) { 191 $first_post = get_site_option( 'first_post' ); 192 193 if ( ! $first_post ) { 194 $first_post = "<!-- wp:paragraph -->\n<p>" . 195 /* translators: First post content. %s: Site link. */ 196 __( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ) . 197 "</p>\n<!-- /wp:paragraph -->"; 198 } 199 200 $first_post = sprintf( 201 $first_post, 202 sprintf( '<a href="%s">%s</a>', esc_url( network_home_url() ), get_network()->site_name ) 203 ); 204 205 // Back-compat for pre-4.4. 206 $first_post = str_replace( 'SITE_URL', esc_url( network_home_url() ), $first_post ); 207 $first_post = str_replace( 'SITE_NAME', get_network()->site_name, $first_post ); 208 } else { 209 $first_post = "<!-- wp:paragraph -->\n<p>" . 210 /* translators: First post content. %s: Site link. */ 211 __( 'Welcome to WordPress. This is your first post. Edit or delete it, then start writing!' ) . 212 "</p>\n<!-- /wp:paragraph -->"; 213 } 214 215 $wpdb->insert( 216 $wpdb->posts, 217 array( 218 'post_author' => $user_id, 219 'post_date' => $now, 220 'post_date_gmt' => $now_gmt, 221 'post_content' => $first_post, 222 'post_excerpt' => '', 223 'post_title' => __( 'Hello world!' ), 224 /* translators: Default post slug. */ 225 'post_name' => sanitize_title( _x( 'hello-world', 'Default post slug' ) ), 226 'post_modified' => $now, 227 'post_modified_gmt' => $now_gmt, 228 'guid' => $first_post_guid, 229 'comment_count' => 1, 230 'to_ping' => '', 231 'pinged' => '', 232 'post_content_filtered' => '', 233 ) 234 ); 235 236 if ( is_multisite() ) { 237 update_posts_count(); 238 } 239 240 $wpdb->insert( 241 $wpdb->term_relationships, 242 array( 243 'term_taxonomy_id' => $cat_tt_id, 244 'object_id' => 1, 245 ) 246 ); 247 248 // Default comment. 249 if ( is_multisite() ) { 250 $first_comment_author = get_site_option( 'first_comment_author' ); 251 $first_comment_email = get_site_option( 'first_comment_email' ); 252 $first_comment_url = get_site_option( 'first_comment_url', network_home_url() ); 253 $first_comment = get_site_option( 'first_comment' ); 254 } 255 256 $first_comment_author = ! empty( $first_comment_author ) ? $first_comment_author : __( 'A WordPress Commenter' ); 257 $first_comment_email = ! empty( $first_comment_email ) ? $first_comment_email : 'wapuu@wordpress.example'; 258 $first_comment_url = ! empty( $first_comment_url ) ? $first_comment_url : esc_url( __( 'https://wordpress.org/' ) ); 259 $first_comment = ! empty( $first_comment ) ? $first_comment : sprintf( 260 /* translators: %s: Gravatar URL. */ 261 __( 262 'Hi, this is a comment. 263 To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard. 264 Commenter avatars come from <a href="%s">Gravatar</a>.' 265 ), 266 esc_url( __( 'https://en.gravatar.com/' ) ) 267 ); 268 $wpdb->insert( 269 $wpdb->comments, 270 array( 271 'comment_post_ID' => 1, 272 'comment_author' => $first_comment_author, 273 'comment_author_email' => $first_comment_email, 274 'comment_author_url' => $first_comment_url, 275 'comment_date' => $now, 276 'comment_date_gmt' => $now_gmt, 277 'comment_content' => $first_comment, 278 'comment_type' => 'comment', 279 ) 280 ); 281 282 // First page. 283 if ( is_multisite() ) { 284 $first_page = get_site_option( 'first_page' ); 285 } 286 287 if ( empty( $first_page ) ) { 288 $first_page = "<!-- wp:paragraph -->\n<p>"; 289 /* translators: First page content. */ 290 $first_page .= __( "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:" ); 291 $first_page .= "</p>\n<!-- /wp:paragraph -->\n\n"; 292 293 $first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>"; 294 /* translators: First page content. */ 295 $first_page .= __( "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ña coladas. (And gettin' caught in the rain.)" ); 296 $first_page .= "</p></blockquote>\n<!-- /wp:quote -->\n\n"; 297 298 $first_page .= "<!-- wp:paragraph -->\n<p>"; 299 /* translators: First page content. */ 300 $first_page .= __( '...or something like this:' ); 301 $first_page .= "</p>\n<!-- /wp:paragraph -->\n\n"; 302 303 $first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>"; 304 /* translators: First page content. */ 305 $first_page .= __( '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.' ); 306 $first_page .= "</p></blockquote>\n<!-- /wp:quote -->\n\n"; 307 308 $first_page .= "<!-- wp:paragraph -->\n<p>"; 309 $first_page .= sprintf( 310 /* translators: First page content. %s: Site admin URL. */ 311 __( '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!' ), 312 admin_url() 313 ); 314 $first_page .= "</p>\n<!-- /wp:paragraph -->"; 315 } 316 317 $first_post_guid = get_option( 'home' ) . '/?page_id=2'; 318 $wpdb->insert( 319 $wpdb->posts, 320 array( 321 'post_author' => $user_id, 322 'post_date' => $now, 323 'post_date_gmt' => $now_gmt, 324 'post_content' => $first_page, 325 'post_excerpt' => '', 326 'comment_status' => 'closed', 327 'post_title' => __( 'Sample Page' ), 328 /* translators: Default page slug. */ 329 'post_name' => __( 'sample-page' ), 330 'post_modified' => $now, 331 'post_modified_gmt' => $now_gmt, 332 'guid' => $first_post_guid, 333 'post_type' => 'page', 334 'to_ping' => '', 335 'pinged' => '', 336 'post_content_filtered' => '', 337 ) 338 ); 339 $wpdb->insert( 340 $wpdb->postmeta, 341 array( 342 'post_id' => 2, 343 'meta_key' => '_wp_page_template', 344 'meta_value' => 'default', 345 ) 346 ); 347 348 // Privacy Policy page. 349 if ( is_multisite() ) { 350 // Disable by default unless the suggested content is provided. 351 $privacy_policy_content = get_site_option( 'default_privacy_policy_content' ); 352 } else { 353 if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) { 354 require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php'; 355 } 356 357 $privacy_policy_content = WP_Privacy_Policy_Content::get_default_content(); 358 } 359 360 if ( ! empty( $privacy_policy_content ) ) { 361 $privacy_policy_guid = get_option( 'home' ) . '/?page_id=3'; 362 363 $wpdb->insert( 364 $wpdb->posts, 365 array( 366 'post_author' => $user_id, 367 'post_date' => $now, 368 'post_date_gmt' => $now_gmt, 369 'post_content' => $privacy_policy_content, 370 'post_excerpt' => '', 371 'comment_status' => 'closed', 372 'post_title' => __( 'Privacy Policy' ), 373 /* translators: Privacy Policy page slug. */ 374 'post_name' => __( 'privacy-policy' ), 375 'post_modified' => $now, 376 'post_modified_gmt' => $now_gmt, 377 'guid' => $privacy_policy_guid, 378 'post_type' => 'page', 379 'post_status' => 'draft', 380 'to_ping' => '', 381 'pinged' => '', 382 'post_content_filtered' => '', 383 ) 384 ); 385 $wpdb->insert( 386 $wpdb->postmeta, 387 array( 388 'post_id' => 3, 389 'meta_key' => '_wp_page_template', 390 'meta_value' => 'default', 391 ) 392 ); 393 update_option( 'wp_page_for_privacy_policy', 3 ); 394 } 395 396 // Set up default widgets for default theme. 397 update_option( 398 'widget_block', 399 array( 400 2 => array( 'content' => '<!-- wp:search /-->' ), 401 3 => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Recent Posts' ) . '</h2><!-- /wp:heading --><!-- wp:latest-posts /--></div><!-- /wp:group -->' ), 402 4 => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Recent Comments' ) . '</h2><!-- /wp:heading --><!-- wp:latest-comments {"displayAvatar":false,"displayDate":false,"displayExcerpt":false} /--></div><!-- /wp:group -->' ), 403 5 => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Archives' ) . '</h2><!-- /wp:heading --><!-- wp:archives /--></div><!-- /wp:group -->' ), 404 6 => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Categories' ) . '</h2><!-- /wp:heading --><!-- wp:categories /--></div><!-- /wp:group -->' ), 405 '_multiwidget' => 1, 406 ) 407 ); 408 update_option( 409 'sidebars_widgets', 410 array( 411 'wp_inactive_widgets' => array(), 412 'sidebar-1' => array( 413 0 => 'block-2', 414 1 => 'block-3', 415 2 => 'block-4', 416 ), 417 'sidebar-2' => array( 418 0 => 'block-5', 419 1 => 'block-6', 420 ), 421 'array_version' => 3, 422 ) 423 ); 424 425 if ( ! is_multisite() ) { 426 update_user_meta( $user_id, 'show_welcome_panel', 1 ); 427 } elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) ) { 428 update_user_meta( $user_id, 'show_welcome_panel', 2 ); 429 } 430 431 if ( is_multisite() ) { 432 // Flush rules to pick up the new page. 433 $wp_rewrite->init(); 434 $wp_rewrite->flush_rules(); 435 436 $user = new WP_User( $user_id ); 437 $wpdb->update( $wpdb->options, array( 'option_value' => $user->user_email ), array( 'option_name' => 'admin_email' ) ); 438 439 // Remove all perms except for the login user. 440 $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'user_level' ) ); 441 $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'capabilities' ) ); 442 443 /* 444 * Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.) 445 * TODO: Get previous_blog_id. 446 */ 447 if ( ! is_super_admin( $user_id ) && 1 != $user_id ) { 448 $wpdb->delete( 449 $wpdb->usermeta, 450 array( 451 'user_id' => $user_id, 452 'meta_key' => $wpdb->base_prefix . '1_capabilities', 453 ) 454 ); 455 } 456 } 457 } 458 endif; 459 460 /** 461 * Maybe enable pretty permalinks on installation. 462 * 463 * If after enabling pretty permalinks don't work, fallback to query-string permalinks. 464 * 465 * @since 4.2.0 466 * 467 * @global WP_Rewrite $wp_rewrite WordPress rewrite component. 468 * 469 * @return bool Whether pretty permalinks are enabled. False otherwise. 470 */ 471 function wp_install_maybe_enable_pretty_permalinks() { 472 global $wp_rewrite; 473 474 // Bail if a permalink structure is already enabled. 475 if ( get_option( 'permalink_structure' ) ) { 476 return true; 477 } 478 479 /* 480 * The Permalink structures to attempt. 481 * 482 * The first is designed for mod_rewrite or nginx rewriting. 483 * 484 * The second is PATHINFO-based permalinks for web server configurations 485 * without a true rewrite module enabled. 486 */ 487 $permalink_structures = array( 488 '/%year%/%monthnum%/%day%/%postname%/', 489 '/index.php/%year%/%monthnum%/%day%/%postname%/', 490 ); 491 492 foreach ( (array) $permalink_structures as $permalink_structure ) { 493 $wp_rewrite->set_permalink_structure( $permalink_structure ); 494 495 /* 496 * Flush rules with the hard option to force refresh of the web-server's 497 * rewrite config file (e.g. .htaccess or web.config). 498 */ 499 $wp_rewrite->flush_rules( true ); 500 501 $test_url = ''; 502 503 // Test against a real WordPress post. 504 $first_post = get_page_by_path( sanitize_title( _x( 'hello-world', 'Default post slug' ) ), OBJECT, 'post' ); 505 if ( $first_post ) { 506 $test_url = get_permalink( $first_post->ID ); 507 } 508 509 /* 510 * Send a request to the site, and check whether 511 * the 'X-Pingback' header is returned as expected. 512 * 513 * Uses wp_remote_get() instead of wp_remote_head() because web servers 514 * can block head requests. 515 */ 516 $response = wp_remote_get( $test_url, array( 'timeout' => 5 ) ); 517 $x_pingback_header = wp_remote_retrieve_header( $response, 'X-Pingback' ); 518 $pretty_permalinks = $x_pingback_header && get_bloginfo( 'pingback_url' ) === $x_pingback_header; 519 520 if ( $pretty_permalinks ) { 521 return true; 522 } 523 } 524 525 /* 526 * If it makes it this far, pretty permalinks failed. 527 * Fallback to query-string permalinks. 528 */ 529 $wp_rewrite->set_permalink_structure( '' ); 530 $wp_rewrite->flush_rules( true ); 531 532 return false; 533 } 534 535 if ( ! function_exists( 'wp_new_blog_notification' ) ) : 536 /** 537 * Notifies the site admin that the installation of WordPress is complete. 538 * 539 * Sends an email to the new administrator that the installation is complete 540 * and provides them with a record of their login credentials. 541 * 542 * @since 2.1.0 543 * 544 * @param string $blog_title Site title. 545 * @param string $blog_url Site URL. 546 * @param int $user_id Administrator's user ID. 547 * @param string $password Administrator's password. Note that a placeholder message is 548 * usually passed instead of the actual password. 549 */ 550 function wp_new_blog_notification( $blog_title, $blog_url, $user_id, $password ) { 551 $user = new WP_User( $user_id ); 552 $email = $user->user_email; 553 $name = $user->user_login; 554 $login_url = wp_login_url(); 555 556 $message = sprintf( 557 /* translators: New site notification email. 1: New site URL, 2: User login, 3: User password or password reset link, 4: Login URL. */ 558 __( 559 'Your new WordPress site has been successfully set up at: 560 561 %1$s 562 563 You can log in to the administrator account with the following information: 564 565 Username: %2$s 566 Password: %3$s 567 Log in here: %4$s 568 569 We hope you enjoy your new site. Thanks! 570 571 --The WordPress Team 572 https://wordpress.org/ 573 ' 574 ), 575 $blog_url, 576 $name, 577 $password, 578 $login_url 579 ); 580 581 $installed_email = array( 582 'to' => $email, 583 'subject' => __( 'New WordPress Site' ), 584 'message' => $message, 585 'headers' => '', 586 ); 587 588 /** 589 * Filters the contents of the email sent to the site administrator when WordPress is installed. 590 * 591 * @since 5.6.0 592 * 593 * @param array $installed_email { 594 * Used to build wp_mail(). 595 * 596 * @type string $to The email address of the recipient. 597 * @type string $subject The subject of the email. 598 * @type string $message The content of the email. 599 * @type string $headers Headers. 600 * } 601 * @param WP_User $user The site administrator user object. 602 * @param string $blog_title The site title. 603 * @param string $blog_url The site URL. 604 * @param string $password The site administrator's password. Note that a placeholder message 605 * is usually passed instead of the user's actual password. 606 */ 607 $installed_email = apply_filters( 'wp_installed_email', $installed_email, $user, $blog_title, $blog_url, $password ); 608 609 wp_mail( 610 $installed_email['to'], 611 $installed_email['subject'], 612 $installed_email['message'], 613 $installed_email['headers'] 614 ); 615 } 616 endif; 617 618 if ( ! function_exists( 'wp_upgrade' ) ) : 619 /** 620 * Runs WordPress Upgrade functions. 621 * 622 * Upgrades the database if needed during a site update. 623 * 624 * @since 2.1.0 625 * 626 * @global int $wp_current_db_version The old (current) database version. 627 * @global int $wp_db_version The new database version. 628 */ 629 function wp_upgrade() { 630 global $wp_current_db_version, $wp_db_version; 631 632 $wp_current_db_version = __get_option( 'db_version' ); 633 634 // We are up to date. Nothing to do. 635 if ( $wp_db_version == $wp_current_db_version ) { 636 return; 637 } 638 639 if ( ! is_blog_installed() ) { 640 return; 641 } 642 643 wp_check_mysql_version(); 644 wp_cache_flush(); 645 pre_schema_upgrade(); 646 make_db_current_silent(); 647 upgrade_all(); 648 if ( is_multisite() && is_main_site() ) { 649 upgrade_network(); 650 } 651 wp_cache_flush(); 652 653 if ( is_multisite() ) { 654 update_site_meta( get_current_blog_id(), 'db_version', $wp_db_version ); 655 update_site_meta( get_current_blog_id(), 'db_last_updated', microtime() ); 656 } 657 658 delete_transient( 'wp_core_block_css_files' ); 659 660 /** 661 * Fires after a site is fully upgraded. 662 * 663 * @since 3.9.0 664 * 665 * @param int $wp_db_version The new $wp_db_version. 666 * @param int $wp_current_db_version The old (current) $wp_db_version. 667 */ 668 do_action( 'wp_upgrade', $wp_db_version, $wp_current_db_version ); 669 } 670 endif; 671 672 /** 673 * Functions to be called in installation and upgrade scripts. 674 * 675 * Contains conditional checks to determine which upgrade scripts to run, 676 * based on database version and WP version being updated-to. 677 * 678 * @ignore 679 * @since 1.0.1 680 * 681 * @global int $wp_current_db_version The old (current) database version. 682 * @global int $wp_db_version The new database version. 683 */ 684 function upgrade_all() { 685 global $wp_current_db_version, $wp_db_version; 686 687 $wp_current_db_version = __get_option( 'db_version' ); 688 689 // We are up to date. Nothing to do. 690 if ( $wp_db_version == $wp_current_db_version ) { 691 return; 692 } 693 694 // If the version is not set in the DB, try to guess the version. 695 if ( empty( $wp_current_db_version ) ) { 696 $wp_current_db_version = 0; 697 698 // If the template option exists, we have 1.5. 699 $template = __get_option( 'template' ); 700 if ( ! empty( $template ) ) { 701 $wp_current_db_version = 2541; 702 } 703 } 704 705 if ( $wp_current_db_version < 6039 ) { 706 upgrade_230_options_table(); 707 } 708 709 populate_options(); 710 711 if ( $wp_current_db_version < 2541 ) { 712 upgrade_100(); 713 upgrade_101(); 714 upgrade_110(); 715 upgrade_130(); 716 } 717 718 if ( $wp_current_db_version < 3308 ) { 719 upgrade_160(); 720 } 721 722 if ( $wp_current_db_version < 4772 ) { 723 upgrade_210(); 724 } 725 726 if ( $wp_current_db_version < 4351 ) { 727 upgrade_old_slugs(); 728 } 729 730 if ( $wp_current_db_version < 5539 ) { 731 upgrade_230(); 732 } 733 734 if ( $wp_current_db_version < 6124 ) { 735 upgrade_230_old_tables(); 736 } 737 738 if ( $wp_current_db_version < 7499 ) { 739 upgrade_250(); 740 } 741 742 if ( $wp_current_db_version < 7935 ) { 743 upgrade_252(); 744 } 745 746 if ( $wp_current_db_version < 8201 ) { 747 upgrade_260(); 748 } 749 750 if ( $wp_current_db_version < 8989 ) { 751 upgrade_270(); 752 } 753 754 if ( $wp_current_db_version < 10360 ) { 755 upgrade_280(); 756 } 757 758 if ( $wp_current_db_version < 11958 ) { 759 upgrade_290(); 760 } 761 762 if ( $wp_current_db_version < 15260 ) { 763 upgrade_300(); 764 } 765 766 if ( $wp_current_db_version < 19389 ) { 767 upgrade_330(); 768 } 769 770 if ( $wp_current_db_version < 20080 ) { 771 upgrade_340(); 772 } 773 774 if ( $wp_current_db_version < 22422 ) { 775 upgrade_350(); 776 } 777 778 if ( $wp_current_db_version < 25824 ) { 779 upgrade_370(); 780 } 781 782 if ( $wp_current_db_version < 26148 ) { 783 upgrade_372(); 784 } 785 786 if ( $wp_current_db_version < 26691 ) { 787 upgrade_380(); 788 } 789 790 if ( $wp_current_db_version < 29630 ) { 791 upgrade_400(); 792 } 793 794 if ( $wp_current_db_version < 33055 ) { 795 upgrade_430(); 796 } 797 798 if ( $wp_current_db_version < 33056 ) { 799 upgrade_431(); 800 } 801 802 if ( $wp_current_db_version < 35700 ) { 803 upgrade_440(); 804 } 805 806 if ( $wp_current_db_version < 36686 ) { 807 upgrade_450(); 808 } 809 810 if ( $wp_current_db_version < 37965 ) { 811 upgrade_460(); 812 } 813 814 if ( $wp_current_db_version < 44719 ) { 815 upgrade_510(); 816 } 817 818 if ( $wp_current_db_version < 45744 ) { 819 upgrade_530(); 820 } 821 822 if ( $wp_current_db_version < 48575 ) { 823 upgrade_550(); 824 } 825 826 if ( $wp_current_db_version < 49752 ) { 827 upgrade_560(); 828 } 829 830 if ( $wp_current_db_version < 51917 ) { 831 upgrade_590(); 832 } 833 834 if ( $wp_current_db_version < 53011 ) { 835 upgrade_600(); 836 } 837 838 if ( $wp_current_db_version < 55853 ) { 839 upgrade_630(); 840 } 841 842 if ( $wp_current_db_version < 56657 ) { 843 upgrade_640(); 844 } 845 846 if ( $wp_current_db_version < 57155 ) { 847 upgrade_650(); 848 } 849 850 maybe_disable_link_manager(); 851 852 maybe_disable_automattic_widgets(); 853 854 update_option( 'db_version', $wp_db_version ); 855 update_option( 'db_upgraded', true ); 856 } 857 858 /** 859 * Execute changes made in WordPress 1.0. 860 * 861 * @ignore 862 * @since 1.0.0 863 * 864 * @global wpdb $wpdb WordPress database abstraction object. 865 */ 866 function upgrade_100() { 867 global $wpdb; 868 869 // Get the title and ID of every post, post_name to check if it already has a value. 870 $posts = $wpdb->get_results( "SELECT ID, post_title, post_name FROM $wpdb->posts WHERE post_name = ''" ); 871 if ( $posts ) { 872 foreach ( $posts as $post ) { 873 if ( '' === $post->post_name ) { 874 $newtitle = sanitize_title( $post->post_title ); 875 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_name = %s WHERE ID = %d", $newtitle, $post->ID ) ); 876 } 877 } 878 } 879 880 $categories = $wpdb->get_results( "SELECT cat_ID, cat_name, category_nicename FROM $wpdb->categories" ); 881 foreach ( $categories as $category ) { 882 if ( '' === $category->category_nicename ) { 883 $newtitle = sanitize_title( $category->cat_name ); 884 $wpdb->update( $wpdb->categories, array( 'category_nicename' => $newtitle ), array( 'cat_ID' => $category->cat_ID ) ); 885 } 886 } 887 888 $sql = "UPDATE $wpdb->options 889 SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/') 890 WHERE option_name LIKE %s 891 AND option_value LIKE %s"; 892 $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( 'links_rating_image' ) . '%', $wpdb->esc_like( 'wp-links/links-images/' ) . '%' ) ); 893 894 $done_ids = $wpdb->get_results( "SELECT DISTINCT post_id FROM $wpdb->post2cat" ); 895 if ( $done_ids ) : 896 $done_posts = array(); 897 foreach ( $done_ids as $done_id ) : 898 $done_posts[] = $done_id->post_id; 899 endforeach; 900 $catwhere = ' AND ID NOT IN (' . implode( ',', $done_posts ) . ')'; 901 else : 902 $catwhere = ''; 903 endif; 904 905 $allposts = $wpdb->get_results( "SELECT ID, post_category FROM $wpdb->posts WHERE post_category != '0' $catwhere" ); 906 if ( $allposts ) : 907 foreach ( $allposts as $post ) { 908 // Check to see if it's already been imported. 909 $cat = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->post2cat WHERE post_id = %d AND category_id = %d", $post->ID, $post->post_category ) ); 910 if ( ! $cat && 0 != $post->post_category ) { // If there's no result. 911 $wpdb->insert( 912 $wpdb->post2cat, 913 array( 914 'post_id' => $post->ID, 915 'category_id' => $post->post_category, 916 ) 917 ); 918 } 919 } 920 endif; 921 } 922 923 /** 924 * Execute changes made in WordPress 1.0.1. 925 * 926 * @ignore 927 * @since 1.0.1 928 * 929 * @global wpdb $wpdb WordPress database abstraction object. 930 */ 931 function upgrade_101() { 932 global $wpdb; 933 934 // Clean up indices, add a few. 935 add_clean_index( $wpdb->posts, 'post_name' ); 936 add_clean_index( $wpdb->posts, 'post_status' ); 937 add_clean_index( $wpdb->categories, 'category_nicename' ); 938 add_clean_index( $wpdb->comments, 'comment_approved' ); 939 add_clean_index( $wpdb->comments, 'comment_post_ID' ); 940 add_clean_index( $wpdb->links, 'link_category' ); 941 add_clean_index( $wpdb->links, 'link_visible' ); 942 } 943 944 /** 945 * Execute changes made in WordPress 1.2. 946 * 947 * @ignore 948 * @since 1.2.0 949 * 950 * @global wpdb $wpdb WordPress database abstraction object. 951 */ 952 function upgrade_110() { 953 global $wpdb; 954 955 // Set user_nicename. 956 $users = $wpdb->get_results( "SELECT ID, user_nickname, user_nicename FROM $wpdb->users" ); 957 foreach ( $users as $user ) { 958 if ( '' === $user->user_nicename ) { 959 $newname = sanitize_title( $user->user_nickname ); 960 $wpdb->update( $wpdb->users, array( 'user_nicename' => $newname ), array( 'ID' => $user->ID ) ); 961 } 962 } 963 964 $users = $wpdb->get_results( "SELECT ID, user_pass from $wpdb->users" ); 965 foreach ( $users as $row ) { 966 if ( ! preg_match( '/^[A-Fa-f0-9]{32}$/', $row->user_pass ) ) { 967 $wpdb->update( $wpdb->users, array( 'user_pass' => md5( $row->user_pass ) ), array( 'ID' => $row->ID ) ); 968 } 969 } 970 971 // Get the GMT offset, we'll use that later on. 972 $all_options = get_alloptions_110(); 973 974 $time_difference = $all_options->time_difference; 975 976 $server_time = time() + gmdate( 'Z' ); 977 $weblogger_time = $server_time + $time_difference * HOUR_IN_SECONDS; 978 $gmt_time = time(); 979 980 $diff_gmt_server = ( $gmt_time - $server_time ) / HOUR_IN_SECONDS; 981 $diff_weblogger_server = ( $weblogger_time - $server_time ) / HOUR_IN_SECONDS; 982 $diff_gmt_weblogger = $diff_gmt_server - $diff_weblogger_server; 983 $gmt_offset = -$diff_gmt_weblogger; 984 985 // Add a gmt_offset option, with value $gmt_offset. 986 add_option( 'gmt_offset', $gmt_offset ); 987 988 /* 989 * Check if we already set the GMT fields. If we did, then 990 * MAX(post_date_gmt) can't be '0000-00-00 00:00:00'. 991 * <michel_v> I just slapped myself silly for not thinking about it earlier. 992 */ 993 $got_gmt_fields = ( '0000-00-00 00:00:00' !== $wpdb->get_var( "SELECT MAX(post_date_gmt) FROM $wpdb->posts" ) ); 994 995 if ( ! $got_gmt_fields ) { 996 997 // Add or subtract time to all dates, to get GMT dates. 998 $add_hours = (int) $diff_gmt_weblogger; 999 $add_minutes = (int) ( 60 * ( $diff_gmt_weblogger - $add_hours ) ); 1000 $wpdb->query( "UPDATE $wpdb->posts SET post_date_gmt = DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" ); 1001 $wpdb->query( "UPDATE $wpdb->posts SET post_modified = post_date" ); 1002 $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'" ); 1003 $wpdb->query( "UPDATE $wpdb->comments SET comment_date_gmt = DATE_ADD(comment_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" ); 1004 $wpdb->query( "UPDATE $wpdb->users SET user_registered = DATE_ADD(user_registered, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" ); 1005 } 1006 } 1007 1008 /** 1009 * Execute changes made in WordPress 1.5. 1010 * 1011 * @ignore 1012 * @since 1.5.0 1013 * 1014 * @global wpdb $wpdb WordPress database abstraction object. 1015 */ 1016 function upgrade_130() { 1017 global $wpdb; 1018 1019 // Remove extraneous backslashes. 1020 $posts = $wpdb->get_results( "SELECT ID, post_title, post_content, post_excerpt, guid, post_date, post_name, post_status, post_author FROM $wpdb->posts" ); 1021 if ( $posts ) { 1022 foreach ( $posts as $post ) { 1023 $post_content = addslashes( deslash( $post->post_content ) ); 1024 $post_title = addslashes( deslash( $post->post_title ) ); 1025 $post_excerpt = addslashes( deslash( $post->post_excerpt ) ); 1026 if ( empty( $post->guid ) ) { 1027 $guid = get_permalink( $post->ID ); 1028 } else { 1029 $guid = $post->guid; 1030 } 1031 1032 $wpdb->update( $wpdb->posts, compact( 'post_title', 'post_content', 'post_excerpt', 'guid' ), array( 'ID' => $post->ID ) ); 1033 1034 } 1035 } 1036 1037 // Remove extraneous backslashes. 1038 $comments = $wpdb->get_results( "SELECT comment_ID, comment_author, comment_content FROM $wpdb->comments" ); 1039 if ( $comments ) { 1040 foreach ( $comments as $comment ) { 1041 $comment_content = deslash( $comment->comment_content ); 1042 $comment_author = deslash( $comment->comment_author ); 1043 1044 $wpdb->update( $wpdb->comments, compact( 'comment_content', 'comment_author' ), array( 'comment_ID' => $comment->comment_ID ) ); 1045 } 1046 } 1047 1048 // Remove extraneous backslashes. 1049 $links = $wpdb->get_results( "SELECT link_id, link_name, link_description FROM $wpdb->links" ); 1050 if ( $links ) { 1051 foreach ( $links as $link ) { 1052 $link_name = deslash( $link->link_name ); 1053 $link_description = deslash( $link->link_description ); 1054 1055 $wpdb->update( $wpdb->links, compact( 'link_name', 'link_description' ), array( 'link_id' => $link->link_id ) ); 1056 } 1057 } 1058 1059 $active_plugins = __get_option( 'active_plugins' ); 1060 1061 /* 1062 * If plugins are not stored in an array, they're stored in the old 1063 * newline separated format. Convert to new format. 1064 */ 1065 if ( ! is_array( $active_plugins ) ) { 1066 $active_plugins = explode( "\n", trim( $active_plugins ) ); 1067 update_option( 'active_plugins', $active_plugins ); 1068 } 1069 1070 // Obsolete tables. 1071 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optionvalues' ); 1072 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiontypes' ); 1073 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroups' ); 1074 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroup_options' ); 1075 1076 // Update comments table to use comment_type. 1077 $wpdb->query( "UPDATE $wpdb->comments SET comment_type='trackback', comment_content = REPLACE(comment_content, '<trackback />', '') WHERE comment_content LIKE '<trackback />%'" ); 1078 $wpdb->query( "UPDATE $wpdb->comments SET comment_type='pingback', comment_content = REPLACE(comment_content, '<pingback />', '') WHERE comment_content LIKE '<pingback />%'" ); 1079 1080 // Some versions have multiple duplicate option_name rows with the same values. 1081 $options = $wpdb->get_results( "SELECT option_name, COUNT(option_name) AS dupes FROM `$wpdb->options` GROUP BY option_name" ); 1082 foreach ( $options as $option ) { 1083 if ( 1 != $option->dupes ) { // Could this be done in the query? 1084 $limit = $option->dupes - 1; 1085 $dupe_ids = $wpdb->get_col( $wpdb->prepare( "SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT %d", $option->option_name, $limit ) ); 1086 if ( $dupe_ids ) { 1087 $dupe_ids = implode( ',', $dupe_ids ); 1088 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_id IN ($dupe_ids)" ); 1089 } 1090 } 1091 } 1092 1093 make_site_theme(); 1094 } 1095 1096 /** 1097 * Execute changes made in WordPress 2.0. 1098 * 1099 * @ignore 1100 * @since 2.0.0 1101 * 1102 * @global wpdb $wpdb WordPress database abstraction object. 1103 * @global int $wp_current_db_version The old (current) database version. 1104 */ 1105 function upgrade_160() { 1106 global $wpdb, $wp_current_db_version; 1107 1108 populate_roles_160(); 1109 1110 $users = $wpdb->get_results( "SELECT * FROM $wpdb->users" ); 1111 foreach ( $users as $user ) : 1112 if ( ! empty( $user->user_firstname ) ) { 1113 update_user_meta( $user->ID, 'first_name', wp_slash( $user->user_firstname ) ); 1114 } 1115 if ( ! empty( $user->user_lastname ) ) { 1116 update_user_meta( $user->ID, 'last_name', wp_slash( $user->user_lastname ) ); 1117 } 1118 if ( ! empty( $user->user_nickname ) ) { 1119 update_user_meta( $user->ID, 'nickname', wp_slash( $user->user_nickname ) ); 1120 } 1121 if ( ! empty( $user->user_level ) ) { 1122 update_user_meta( $user->ID, $wpdb->prefix . 'user_level', $user->user_level ); 1123 } 1124 if ( ! empty( $user->user_icq ) ) { 1125 update_user_meta( $user->ID, 'icq', wp_slash( $user->user_icq ) ); 1126 } 1127 if ( ! empty( $user->user_aim ) ) { 1128 update_user_meta( $user->ID, 'aim', wp_slash( $user->user_aim ) ); 1129 } 1130 if ( ! empty( $user->user_msn ) ) { 1131 update_user_meta( $user->ID, 'msn', wp_slash( $user->user_msn ) ); 1132 } 1133 if ( ! empty( $user->user_yim ) ) { 1134 update_user_meta( $user->ID, 'yim', wp_slash( $user->user_icq ) ); 1135 } 1136 if ( ! empty( $user->user_description ) ) { 1137 update_user_meta( $user->ID, 'description', wp_slash( $user->user_description ) ); 1138 } 1139 1140 if ( isset( $user->user_idmode ) ) : 1141 $idmode = $user->user_idmode; 1142 if ( 'nickname' === $idmode ) { 1143 $id = $user->user_nickname; 1144 } 1145 if ( 'login' === $idmode ) { 1146 $id = $user->user_login; 1147 } 1148 if ( 'firstname' === $idmode ) { 1149 $id = $user->user_firstname; 1150 } 1151 if ( 'lastname' === $idmode ) { 1152 $id = $user->user_lastname; 1153 } 1154 if ( 'namefl' === $idmode ) { 1155 $id = $user->user_firstname . ' ' . $user->user_lastname; 1156 } 1157 if ( 'namelf' === $idmode ) { 1158 $id = $user->user_lastname . ' ' . $user->user_firstname; 1159 } 1160 if ( ! $idmode ) { 1161 $id = $user->user_nickname; 1162 } 1163 $wpdb->update( $wpdb->users, array( 'display_name' => $id ), array( 'ID' => $user->ID ) ); 1164 endif; 1165 1166 // FIXME: RESET_CAPS is temporary code to reset roles and caps if flag is set. 1167 $caps = get_user_meta( $user->ID, $wpdb->prefix . 'capabilities' ); 1168 if ( empty( $caps ) || defined( 'RESET_CAPS' ) ) { 1169 $level = get_user_meta( $user->ID, $wpdb->prefix . 'user_level', true ); 1170 $role = translate_level_to_role( $level ); 1171 update_user_meta( $user->ID, $wpdb->prefix . 'capabilities', array( $role => true ) ); 1172 } 1173 1174 endforeach; 1175 $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' ); 1176 $wpdb->hide_errors(); 1177 foreach ( $old_user_fields as $old ) { 1178 $wpdb->query( "ALTER TABLE $wpdb->users DROP $old" ); 1179 } 1180 $wpdb->show_errors(); 1181 1182 // Populate comment_count field of posts table. 1183 $comments = $wpdb->get_results( "SELECT comment_post_ID, COUNT(*) as c FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID" ); 1184 if ( is_array( $comments ) ) { 1185 foreach ( $comments as $comment ) { 1186 $wpdb->update( $wpdb->posts, array( 'comment_count' => $comment->c ), array( 'ID' => $comment->comment_post_ID ) ); 1187 } 1188 } 1189 1190 /* 1191 * Some alpha versions used a post status of object instead of attachment 1192 * and put the mime type in post_type instead of post_mime_type. 1193 */ 1194 if ( $wp_current_db_version > 2541 && $wp_current_db_version <= 3091 ) { 1195 $objects = $wpdb->get_results( "SELECT ID, post_type FROM $wpdb->posts WHERE post_status = 'object'" ); 1196 foreach ( $objects as $object ) { 1197 $wpdb->update( 1198 $wpdb->posts, 1199 array( 1200 'post_status' => 'attachment', 1201 'post_mime_type' => $object->post_type, 1202 'post_type' => '', 1203 ), 1204 array( 'ID' => $object->ID ) 1205 ); 1206 1207 $meta = get_post_meta( $object->ID, 'imagedata', true ); 1208 if ( ! empty( $meta['file'] ) ) { 1209 update_attached_file( $object->ID, $meta['file'] ); 1210 } 1211 } 1212 } 1213 } 1214 1215 /** 1216 * Execute changes made in WordPress 2.1. 1217 * 1218 * @ignore 1219 * @since 2.1.0 1220 * 1221 * @global int $wp_current_db_version The old (current) database version. 1222 * @global wpdb $wpdb WordPress database abstraction object. 1223 */ 1224 function upgrade_210() { 1225 global $wp_current_db_version, $wpdb; 1226 1227 if ( $wp_current_db_version < 3506 ) { 1228 // Update status and type. 1229 $posts = $wpdb->get_results( "SELECT ID, post_status FROM $wpdb->posts" ); 1230 1231 if ( ! empty( $posts ) ) { 1232 foreach ( $posts as $post ) { 1233 $status = $post->post_status; 1234 $type = 'post'; 1235 1236 if ( 'static' === $status ) { 1237 $status = 'publish'; 1238 $type = 'page'; 1239 } elseif ( 'attachment' === $status ) { 1240 $status = 'inherit'; 1241 $type = 'attachment'; 1242 } 1243 1244 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_status = %s, post_type = %s WHERE ID = %d", $status, $type, $post->ID ) ); 1245 } 1246 } 1247 } 1248 1249 if ( $wp_current_db_version < 3845 ) { 1250 populate_roles_210(); 1251 } 1252 1253 if ( $wp_current_db_version < 3531 ) { 1254 // Give future posts a post_status of future. 1255 $now = gmdate( 'Y-m-d H:i:59' ); 1256 $wpdb->query( "UPDATE $wpdb->posts SET post_status = 'future' WHERE post_status = 'publish' AND post_date_gmt > '$now'" ); 1257 1258 $posts = $wpdb->get_results( "SELECT ID, post_date FROM $wpdb->posts WHERE post_status ='future'" ); 1259 if ( ! empty( $posts ) ) { 1260 foreach ( $posts as $post ) { 1261 wp_schedule_single_event( mysql2date( 'U', $post->post_date, false ), 'publish_future_post', array( $post->ID ) ); 1262 } 1263 } 1264 } 1265 } 1266 1267 /** 1268 * Execute changes made in WordPress 2.3. 1269 * 1270 * @ignore 1271 * @since 2.3.0 1272 * 1273 * @global int $wp_current_db_version The old (current) database version. 1274 * @global wpdb $wpdb WordPress database abstraction object. 1275 */ 1276 function upgrade_230() { 1277 global $wp_current_db_version, $wpdb; 1278 1279 if ( $wp_current_db_version < 5200 ) { 1280 populate_roles_230(); 1281 } 1282 1283 // Convert categories to terms. 1284 $tt_ids = array(); 1285 $have_tags = false; 1286 $categories = $wpdb->get_results( "SELECT * FROM $wpdb->categories ORDER BY cat_ID" ); 1287 foreach ( $categories as $category ) { 1288 $term_id = (int) $category->cat_ID; 1289 $name = $category->cat_name; 1290 $description = $category->category_description; 1291 $slug = $category->category_nicename; 1292 $parent = $category->category_parent; 1293 $term_group = 0; 1294 1295 // Associate terms with the same slug in a term group and make slugs unique. 1296 $exists = $wpdb->get_results( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug ) ); 1297 if ( $exists ) { 1298 $term_group = $exists[0]->term_group; 1299 $id = $exists[0]->term_id; 1300 $num = 2; 1301 do { 1302 $alt_slug = $slug . "-$num"; 1303 ++$num; 1304 $slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) ); 1305 } while ( $slug_check ); 1306 1307 $slug = $alt_slug; 1308 1309 if ( empty( $term_group ) ) { 1310 $term_group = $wpdb->get_var( "SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group" ) + 1; 1311 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->terms SET term_group = %d WHERE term_id = %d", $term_group, $id ) ); 1312 } 1313 } 1314 1315 $wpdb->query( 1316 $wpdb->prepare( 1317 "INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES 1318 (%d, %s, %s, %d)", 1319 $term_id, 1320 $name, 1321 $slug, 1322 $term_group 1323 ) 1324 ); 1325 1326 $count = 0; 1327 if ( ! empty( $category->category_count ) ) { 1328 $count = (int) $category->category_count; 1329 $taxonomy = 'category'; 1330 $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 ) ); 1331 $tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id; 1332 } 1333 1334 if ( ! empty( $category->link_count ) ) { 1335 $count = (int) $category->link_count; 1336 $taxonomy = 'link_category'; 1337 $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 ) ); 1338 $tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id; 1339 } 1340 1341 if ( ! empty( $category->tag_count ) ) { 1342 $have_tags = true; 1343 $count = (int) $category->tag_count; 1344 $taxonomy = 'post_tag'; 1345 $wpdb->insert( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent', 'count' ) ); 1346 $tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id; 1347 } 1348 1349 if ( empty( $count ) ) { 1350 $count = 0; 1351 $taxonomy = 'category'; 1352 $wpdb->insert( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent', 'count' ) ); 1353 $tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id; 1354 } 1355 } 1356 1357 $select = 'post_id, category_id'; 1358 if ( $have_tags ) { 1359 $select .= ', rel_type'; 1360 } 1361 1362 $posts = $wpdb->get_results( "SELECT $select FROM $wpdb->post2cat GROUP BY post_id, category_id" ); 1363 foreach ( $posts as $post ) { 1364 $post_id = (int) $post->post_id; 1365 $term_id = (int) $post->category_id; 1366 $taxonomy = 'category'; 1367 if ( ! empty( $post->rel_type ) && 'tag' === $post->rel_type ) { 1368 $taxonomy = 'tag'; 1369 } 1370 $tt_id = $tt_ids[ $term_id ][ $taxonomy ]; 1371 if ( empty( $tt_id ) ) { 1372 continue; 1373 } 1374 1375 $wpdb->insert( 1376 $wpdb->term_relationships, 1377 array( 1378 'object_id' => $post_id, 1379 'term_taxonomy_id' => $tt_id, 1380 ) 1381 ); 1382 } 1383 1384 // < 3570 we used linkcategories. >= 3570 we used categories and link2cat. 1385 if ( $wp_current_db_version < 3570 ) { 1386 /* 1387 * Create link_category terms for link categories. Create a map of link 1388 * category IDs to link_category terms. 1389 */ 1390 $link_cat_id_map = array(); 1391 $default_link_cat = 0; 1392 $tt_ids = array(); 1393 $link_cats = $wpdb->get_results( 'SELECT cat_id, cat_name FROM ' . $wpdb->prefix . 'linkcategories' ); 1394 foreach ( $link_cats as $category ) { 1395 $cat_id = (int) $category->cat_id; 1396 $term_id = 0; 1397 $name = wp_slash( $category->cat_name ); 1398 $slug = sanitize_title( $name ); 1399 $term_group = 0; 1400 1401 // Associate terms with the same slug in a term group and make slugs unique. 1402 $exists = $wpdb->get_results( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug ) ); 1403 if ( $exists ) { 1404 $term_group = $exists[0]->term_group; 1405 $term_id = $exists[0]->term_id; 1406 } 1407 1408 if ( empty( $term_id ) ) { 1409 $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ); 1410 $term_id = (int) $wpdb->insert_id; 1411 } 1412 1413 $link_cat_id_map[ $cat_id ] = $term_id; 1414 $default_link_cat = $term_id; 1415 1416 $wpdb->insert( 1417 $wpdb->term_taxonomy, 1418 array( 1419 'term_id' => $term_id, 1420 'taxonomy' => 'link_category', 1421 'description' => '', 1422 'parent' => 0, 1423 'count' => 0, 1424 ) 1425 ); 1426 $tt_ids[ $term_id ] = (int) $wpdb->insert_id; 1427 } 1428 1429 // Associate links to categories. 1430 $links = $wpdb->get_results( "SELECT link_id, link_category FROM $wpdb->links" ); 1431 if ( ! empty( $links ) ) { 1432 foreach ( $links as $link ) { 1433 if ( 0 == $link->link_category ) { 1434 continue; 1435 } 1436 if ( ! isset( $link_cat_id_map[ $link->link_category ] ) ) { 1437 continue; 1438 } 1439 $term_id = $link_cat_id_map[ $link->link_category ]; 1440 $tt_id = $tt_ids[ $term_id ]; 1441 if ( empty( $tt_id ) ) { 1442 continue; 1443 } 1444 1445 $wpdb->insert( 1446 $wpdb->term_relationships, 1447 array( 1448 'object_id' => $link->link_id, 1449 'term_taxonomy_id' => $tt_id, 1450 ) 1451 ); 1452 } 1453 } 1454 1455 // Set default to the last category we grabbed during the upgrade loop. 1456 update_option( 'default_link_category', $default_link_cat ); 1457 } else { 1458 $links = $wpdb->get_results( "SELECT link_id, category_id FROM $wpdb->link2cat GROUP BY link_id, category_id" ); 1459 foreach ( $links as $link ) { 1460 $link_id = (int) $link->link_id; 1461 $term_id = (int) $link->category_id; 1462 $taxonomy = 'link_category'; 1463 $tt_id = $tt_ids[ $term_id ][ $taxonomy ]; 1464 if ( empty( $tt_id ) ) { 1465 continue; 1466 } 1467 $wpdb->insert( 1468 $wpdb->term_relationships, 1469 array( 1470 'object_id' => $link_id, 1471 'term_taxonomy_id' => $tt_id, 1472 ) 1473 ); 1474 } 1475 } 1476 1477 if ( $wp_current_db_version < 4772 ) { 1478 // Obsolete linkcategories table. 1479 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'linkcategories' ); 1480 } 1481 1482 // Recalculate all counts. 1483 $terms = $wpdb->get_results( "SELECT term_taxonomy_id, taxonomy FROM $wpdb->term_taxonomy" ); 1484 foreach ( (array) $terms as $term ) { 1485 if ( 'post_tag' === $term->taxonomy || 'category' === $term->taxonomy ) { 1486 $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 ) ); 1487 } else { 1488 $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term->term_taxonomy_id ) ); 1489 } 1490 $wpdb->update( $wpdb->term_taxonomy, array( 'count' => $count ), array( 'term_taxonomy_id' => $term->term_taxonomy_id ) ); 1491 } 1492 } 1493 1494 /** 1495 * Remove old options from the database. 1496 * 1497 * @ignore 1498 * @since 2.3.0 1499 * 1500 * @global wpdb $wpdb WordPress database abstraction object. 1501 */ 1502 function upgrade_230_options_table() { 1503 global $wpdb; 1504 $old_options_fields = array( 'option_can_override', 'option_type', 'option_width', 'option_height', 'option_description', 'option_admin_level' ); 1505 $wpdb->hide_errors(); 1506 foreach ( $old_options_fields as $old ) { 1507 $wpdb->query( "ALTER TABLE $wpdb->options DROP $old" ); 1508 } 1509 $wpdb->show_errors(); 1510 } 1511 1512 /** 1513 * Remove old categories, link2cat, and post2cat database tables. 1514 * 1515 * @ignore 1516 * @since 2.3.0 1517 * 1518 * @global wpdb $wpdb WordPress database abstraction object. 1519 */ 1520 function upgrade_230_old_tables() { 1521 global $wpdb; 1522 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'categories' ); 1523 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'link2cat' ); 1524 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post2cat' ); 1525 } 1526 1527 /** 1528 * Upgrade old slugs made in version 2.2. 1529 * 1530 * @ignore 1531 * @since 2.2.0 1532 * 1533 * @global wpdb $wpdb WordPress database abstraction object. 1534 */ 1535 function upgrade_old_slugs() { 1536 // Upgrade people who were using the Redirect Old Slugs plugin. 1537 global $wpdb; 1538 $wpdb->query( "UPDATE $wpdb->postmeta SET meta_key = '_wp_old_slug' WHERE meta_key = 'old_slug'" ); 1539 } 1540 1541 /** 1542 * Execute changes made in WordPress 2.5.0. 1543 * 1544 * @ignore 1545 * @since 2.5.0 1546 * 1547 * @global int $wp_current_db_version The old (current) database version. 1548 */ 1549 function upgrade_250() { 1550 global $wp_current_db_version; 1551 1552 if ( $wp_current_db_version < 6689 ) { 1553 populate_roles_250(); 1554 } 1555 } 1556 1557 /** 1558 * Execute changes made in WordPress 2.5.2. 1559 * 1560 * @ignore 1561 * @since 2.5.2 1562 * 1563 * @global wpdb $wpdb WordPress database abstraction object. 1564 */ 1565 function upgrade_252() { 1566 global $wpdb; 1567 1568 $wpdb->query( "UPDATE $wpdb->users SET user_activation_key = ''" ); 1569 } 1570 1571 /** 1572 * Execute changes made in WordPress 2.6. 1573 * 1574 * @ignore 1575 * @since 2.6.0 1576 * 1577 * @global int $wp_current_db_version The old (current) database version. 1578 */ 1579 function upgrade_260() { 1580 global $wp_current_db_version; 1581 1582 if ( $wp_current_db_version < 8000 ) { 1583 populate_roles_260(); 1584 } 1585 } 1586 1587 /** 1588 * Execute changes made in WordPress 2.7. 1589 * 1590 * @ignore 1591 * @since 2.7.0 1592 * 1593 * @global int $wp_current_db_version The old (current) database version. 1594 * @global wpdb $wpdb WordPress database abstraction object. 1595 */ 1596 function upgrade_270() { 1597 global $wp_current_db_version, $wpdb; 1598 1599 if ( $wp_current_db_version < 8980 ) { 1600 populate_roles_270(); 1601 } 1602 1603 // Update post_date for unpublished posts with empty timestamp. 1604 if ( $wp_current_db_version < 8921 ) { 1605 $wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" ); 1606 } 1607 } 1608 1609 /** 1610 * Execute changes made in WordPress 2.8. 1611 * 1612 * @ignore 1613 * @since 2.8.0 1614 * 1615 * @global int $wp_current_db_version The old (current) database version. 1616 * @global wpdb $wpdb WordPress database abstraction object. 1617 */ 1618 function upgrade_280() { 1619 global $wp_current_db_version, $wpdb; 1620 1621 if ( $wp_current_db_version < 10360 ) { 1622 populate_roles_280(); 1623 } 1624 if ( is_multisite() ) { 1625 $start = 0; 1626 while ( $rows = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options ORDER BY option_id LIMIT $start, 20" ) ) { 1627 foreach ( $rows as $row ) { 1628 $value = maybe_unserialize( $row->option_value ); 1629 if ( $value === $row->option_value ) { 1630 $value = stripslashes( $value ); 1631 } 1632 if ( $value !== $row->option_value ) { 1633 update_option( $row->option_name, $value ); 1634 } 1635 } 1636 $start += 20; 1637 } 1638 clean_blog_cache( get_current_blog_id() ); 1639 } 1640 } 1641 1642 /** 1643 * Execute changes made in WordPress 2.9. 1644 * 1645 * @ignore 1646 * @since 2.9.0 1647 * 1648 * @global int $wp_current_db_version The old (current) database version. 1649 */ 1650 function upgrade_290() { 1651 global $wp_current_db_version; 1652 1653 if ( $wp_current_db_version < 11958 ) { 1654 /* 1655 * Previously, setting depth to 1 would redundantly disable threading, 1656 * but now 2 is the minimum depth to avoid confusion. 1657 */ 1658 if ( get_option( 'thread_comments_depth' ) == '1' ) { 1659 update_option( 'thread_comments_depth', 2 ); 1660 update_option( 'thread_comments', 0 ); 1661 } 1662 } 1663 } 1664 1665 /** 1666 * Execute changes made in WordPress 3.0. 1667 * 1668 * @ignore 1669 * @since 3.0.0 1670 * 1671 * @global int $wp_current_db_version The old (current) database version. 1672 * @global wpdb $wpdb WordPress database abstraction object. 1673 */ 1674 function upgrade_300() { 1675 global $wp_current_db_version, $wpdb; 1676 1677 if ( $wp_current_db_version < 15093 ) { 1678 populate_roles_300(); 1679 } 1680 1681 if ( $wp_current_db_version < 14139 && is_multisite() && is_main_site() && ! defined( 'MULTISITE' ) && get_site_option( 'siteurl' ) === false ) { 1682 add_site_option( 'siteurl', '' ); 1683 } 1684 1685 // 3.0 screen options key name changes. 1686 if ( wp_should_upgrade_global_tables() ) { 1687 $sql = "DELETE FROM $wpdb->usermeta 1688 WHERE meta_key LIKE %s 1689 OR meta_key LIKE %s 1690 OR meta_key LIKE %s 1691 OR meta_key LIKE %s 1692 OR meta_key LIKE %s 1693 OR meta_key LIKE %s 1694 OR meta_key = 'manageedittagscolumnshidden' 1695 OR meta_key = 'managecategoriescolumnshidden' 1696 OR meta_key = 'manageedit-tagscolumnshidden' 1697 OR meta_key = 'manageeditcolumnshidden' 1698 OR meta_key = 'categories_per_page' 1699 OR meta_key = 'edit_tags_per_page'"; 1700 $prefix = $wpdb->esc_like( $wpdb->base_prefix ); 1701 $wpdb->query( 1702 $wpdb->prepare( 1703 $sql, 1704 $prefix . '%' . $wpdb->esc_like( 'meta-box-hidden' ) . '%', 1705 $prefix . '%' . $wpdb->esc_like( 'closedpostboxes' ) . '%', 1706 $prefix . '%' . $wpdb->esc_like( 'manage-' ) . '%' . $wpdb->esc_like( '-columns-hidden' ) . '%', 1707 $prefix . '%' . $wpdb->esc_like( 'meta-box-order' ) . '%', 1708 $prefix . '%' . $wpdb->esc_like( 'metaboxorder' ) . '%', 1709 $prefix . '%' . $wpdb->esc_like( 'screen_layout' ) . '%' 1710 ) 1711 ); 1712 } 1713 } 1714 1715 /** 1716 * Execute changes made in WordPress 3.3. 1717 * 1718 * @ignore 1719 * @since 3.3.0 1720 * 1721 * @global int $wp_current_db_version The old (current) database version. 1722 * @global wpdb $wpdb WordPress database abstraction object. 1723 * @global array $wp_registered_widgets 1724 * @global array $sidebars_widgets 1725 */ 1726 function upgrade_330() { 1727 global $wp_current_db_version, $wpdb, $wp_registered_widgets, $sidebars_widgets; 1728 1729 if ( $wp_current_db_version < 19061 && wp_should_upgrade_global_tables() ) { 1730 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" ); 1731 } 1732 1733 if ( $wp_current_db_version >= 11548 ) { 1734 return; 1735 } 1736 1737 $sidebars_widgets = get_option( 'sidebars_widgets', array() ); 1738 $_sidebars_widgets = array(); 1739 1740 if ( isset( $sidebars_widgets['wp_inactive_widgets'] ) || empty( $sidebars_widgets ) ) { 1741 $sidebars_widgets['array_version'] = 3; 1742 } elseif ( ! isset( $sidebars_widgets['array_version'] ) ) { 1743 $sidebars_widgets['array_version'] = 1; 1744 } 1745 1746 switch ( $sidebars_widgets['array_version'] ) { 1747 case 1: 1748 foreach ( (array) $sidebars_widgets as $index => $sidebar ) { 1749 if ( is_array( $sidebar ) ) { 1750 foreach ( (array) $sidebar as $i => $name ) { 1751 $id = strtolower( $name ); 1752 if ( isset( $wp_registered_widgets[ $id ] ) ) { 1753 $_sidebars_widgets[ $index ][ $i ] = $id; 1754 continue; 1755 } 1756 1757 $id = sanitize_title( $name ); 1758 if ( isset( $wp_registered_widgets[ $id ] ) ) { 1759 $_sidebars_widgets[ $index ][ $i ] = $id; 1760 continue; 1761 } 1762 1763 $found = false; 1764 1765 foreach ( $wp_registered_widgets as $widget_id => $widget ) { 1766 if ( strtolower( $widget['name'] ) === strtolower( $name ) ) { 1767 $_sidebars_widgets[ $index ][ $i ] = $widget['id']; 1768 1769 $found = true; 1770 break; 1771 } elseif ( sanitize_title( $widget['name'] ) === sanitize_title( $name ) ) { 1772 $_sidebars_widgets[ $index ][ $i ] = $widget['id']; 1773 1774 $found = true; 1775 break; 1776 } 1777 } 1778 1779 if ( $found ) { 1780 continue; 1781 } 1782 1783 unset( $_sidebars_widgets[ $index ][ $i ] ); 1784 } 1785 } 1786 } 1787 $_sidebars_widgets['array_version'] = 2; 1788 $sidebars_widgets = $_sidebars_widgets; 1789 unset( $_sidebars_widgets ); 1790 1791 // Intentional fall-through to upgrade to the next version. 1792 case 2: 1793 $sidebars_widgets = retrieve_widgets(); 1794 $sidebars_widgets['array_version'] = 3; 1795 update_option( 'sidebars_widgets', $sidebars_widgets ); 1796 } 1797 } 1798 1799 /** 1800 * Execute changes made in WordPress 3.4. 1801 * 1802 * @ignore 1803 * @since 3.4.0 1804 * 1805 * @global int $wp_current_db_version The old (current) database version. 1806 * @global wpdb $wpdb WordPress database abstraction object. 1807 */ 1808 function upgrade_340() { 1809 global $wp_current_db_version, $wpdb; 1810 1811 if ( $wp_current_db_version < 19798 ) { 1812 $wpdb->hide_errors(); 1813 $wpdb->query( "ALTER TABLE $wpdb->options DROP COLUMN blog_id" ); 1814 $wpdb->show_errors(); 1815 } 1816 1817 if ( $wp_current_db_version < 19799 ) { 1818 $wpdb->hide_errors(); 1819 $wpdb->query( "ALTER TABLE $wpdb->comments DROP INDEX comment_approved" ); 1820 $wpdb->show_errors(); 1821 } 1822 1823 if ( $wp_current_db_version < 20022 && wp_should_upgrade_global_tables() ) { 1824 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" ); 1825 } 1826 1827 if ( $wp_current_db_version < 20080 ) { 1828 if ( 'yes' === $wpdb->get_var( "SELECT autoload FROM $wpdb->options WHERE option_name = 'uninstall_plugins'" ) ) { 1829 $uninstall_plugins = get_option( 'uninstall_plugins' ); 1830 delete_option( 'uninstall_plugins' ); 1831 add_option( 'uninstall_plugins', $uninstall_plugins, null, 'no' ); 1832 } 1833 } 1834 } 1835 1836 /** 1837 * Execute changes made in WordPress 3.5. 1838 * 1839 * @ignore 1840 * @since 3.5.0 1841 * 1842 * @global int $wp_current_db_version The old (current) database version. 1843 * @global wpdb $wpdb WordPress database abstraction object. 1844 */ 1845 function upgrade_350() { 1846 global $wp_current_db_version, $wpdb; 1847 1848 if ( $wp_current_db_version < 22006 && $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) { 1849 update_option( 'link_manager_enabled', 1 ); // Previously set to 0 by populate_options(). 1850 } 1851 1852 if ( $wp_current_db_version < 21811 && wp_should_upgrade_global_tables() ) { 1853 $meta_keys = array(); 1854 foreach ( array_merge( get_post_types(), get_taxonomies() ) as $name ) { 1855 if ( str_contains( $name, '-' ) ) { 1856 $meta_keys[] = 'edit_' . str_replace( '-', '_', $name ) . '_per_page'; 1857 } 1858 } 1859 if ( $meta_keys ) { 1860 $meta_keys = implode( "', '", $meta_keys ); 1861 $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('$meta_keys')" ); 1862 } 1863 } 1864 1865 if ( $wp_current_db_version < 22422 ) { 1866 $term = get_term_by( 'slug', 'post-format-standard', 'post_format' ); 1867 if ( $term ) { 1868 wp_delete_term( $term->term_id, 'post_format' ); 1869 } 1870 } 1871 } 1872 1873 /** 1874 * Execute changes made in WordPress 3.7. 1875 * 1876 * @ignore 1877 * @since 3.7.0 1878 * 1879 * @global int $wp_current_db_version The old (current) database version. 1880 */ 1881 function upgrade_370() { 1882 global $wp_current_db_version; 1883 1884 if ( $wp_current_db_version < 25824 ) { 1885 wp_clear_scheduled_hook( 'wp_auto_updates_maybe_update' ); 1886 } 1887 } 1888 1889 /** 1890 * Execute changes made in WordPress 3.7.2. 1891 * 1892 * @ignore 1893 * @since 3.7.2 1894 * 1895 * @global int $wp_current_db_version The old (current) database version. 1896 */ 1897 function upgrade_372() { 1898 global $wp_current_db_version; 1899 1900 if ( $wp_current_db_version < 26148 ) { 1901 wp_clear_scheduled_hook( 'wp_maybe_auto_update' ); 1902 } 1903 } 1904 1905 /** 1906 * Execute changes made in WordPress 3.8.0. 1907 * 1908 * @ignore 1909 * @since 3.8.0 1910 * 1911 * @global int $wp_current_db_version The old (current) database version. 1912 */ 1913 function upgrade_380() { 1914 global $wp_current_db_version; 1915 1916 if ( $wp_current_db_version < 26691 ) { 1917 deactivate_plugins( array( 'mp6/mp6.php' ), true ); 1918 } 1919 } 1920 1921 /** 1922 * Execute changes made in WordPress 4.0.0. 1923 * 1924 * @ignore 1925 * @since 4.0.0 1926 * 1927 * @global int $wp_current_db_version The old (current) database version. 1928 */ 1929 function upgrade_400() { 1930 global $wp_current_db_version; 1931 1932 if ( $wp_current_db_version < 29630 ) { 1933 if ( ! is_multisite() && false === get_option( 'WPLANG' ) ) { 1934 if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) && in_array( WPLANG, get_available_languages(), true ) ) { 1935 update_option( 'WPLANG', WPLANG ); 1936 } else { 1937 update_option( 'WPLANG', '' ); 1938 } 1939 } 1940 } 1941 } 1942 1943 /** 1944 * Execute changes made in WordPress 4.2.0. 1945 * 1946 * @ignore 1947 * @since 4.2.0 1948 */ 1949 function upgrade_420() {} 1950 1951 /** 1952 * Executes changes made in WordPress 4.3.0. 1953 * 1954 * @ignore 1955 * @since 4.3.0 1956 * 1957 * @global int $wp_current_db_version The old (current) database version. 1958 * @global wpdb $wpdb WordPress database abstraction object. 1959 */ 1960 function upgrade_430() { 1961 global $wp_current_db_version, $wpdb; 1962 1963 if ( $wp_current_db_version < 32364 ) { 1964 upgrade_430_fix_comments(); 1965 } 1966 1967 // Shared terms are split in a separate process. 1968 if ( $wp_current_db_version < 32814 ) { 1969 update_option( 'finished_splitting_shared_terms', 0 ); 1970 wp_schedule_single_event( time() + ( 1 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' ); 1971 } 1972 1973 if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) { 1974 if ( is_multisite() ) { 1975 $tables = $wpdb->tables( 'blog' ); 1976 } else { 1977 $tables = $wpdb->tables( 'all' ); 1978 if ( ! wp_should_upgrade_global_tables() ) { 1979 $global_tables = $wpdb->tables( 'global' ); 1980 $tables = array_diff_assoc( $tables, $global_tables ); 1981 } 1982 } 1983 1984 foreach ( $tables as $table ) { 1985 maybe_convert_table_to_utf8mb4( $table ); 1986 } 1987 } 1988 } 1989 1990 /** 1991 * Executes comments changes made in WordPress 4.3.0. 1992 * 1993 * @ignore 1994 * @since 4.3.0 1995 * 1996 * @global wpdb $wpdb WordPress database abstraction object. 1997 */ 1998 function upgrade_430_fix_comments() { 1999 global $wpdb; 2000 2001 $content_length = $wpdb->get_col_length( $wpdb->comments, 'comment_content' ); 2002 2003 if ( is_wp_error( $content_length ) ) { 2004 return; 2005 } 2006 2007 if ( false === $content_length ) { 2008 $content_length = array( 2009 'type' => 'byte', 2010 'length' => 65535, 2011 ); 2012 } elseif ( ! is_array( $content_length ) ) { 2013 $length = (int) $content_length > 0 ? (int) $content_length : 65535; 2014 $content_length = array( 2015 'type' => 'byte', 2016 'length' => $length, 2017 ); 2018 } 2019 2020 if ( 'byte' !== $content_length['type'] || 0 === $content_length['length'] ) { 2021 // Sites with malformed DB schemas are on their own. 2022 return; 2023 } 2024 2025 $allowed_length = (int) $content_length['length'] - 10; 2026 2027 $comments = $wpdb->get_results( 2028 "SELECT `comment_ID` FROM `{$wpdb->comments}` 2029 WHERE `comment_date_gmt` > '2015-04-26' 2030 AND LENGTH( `comment_content` ) >= {$allowed_length} 2031 AND ( `comment_content` LIKE '%<%' OR `comment_content` LIKE '%>%' )" 2032 ); 2033 2034 foreach ( $comments as $comment ) { 2035 wp_delete_comment( $comment->comment_ID, true ); 2036 } 2037 } 2038 2039 /** 2040 * Executes changes made in WordPress 4.3.1. 2041 * 2042 * @ignore 2043 * @since 4.3.1 2044 */ 2045 function upgrade_431() { 2046 // Fix incorrect cron entries for term splitting. 2047 $cron_array = _get_cron_array(); 2048 if ( isset( $cron_array['wp_batch_split_terms'] ) ) { 2049 unset( $cron_array['wp_batch_split_terms'] ); 2050 _set_cron_array( $cron_array ); 2051 } 2052 } 2053 2054 /** 2055 * Executes changes made in WordPress 4.4.0. 2056 * 2057 * @ignore 2058 * @since 4.4.0 2059 * 2060 * @global int $wp_current_db_version The old (current) database version. 2061 * @global wpdb $wpdb WordPress database abstraction object. 2062 */ 2063 function upgrade_440() { 2064 global $wp_current_db_version, $wpdb; 2065 2066 if ( $wp_current_db_version < 34030 ) { 2067 $wpdb->query( "ALTER TABLE {$wpdb->options} MODIFY option_name VARCHAR(191)" ); 2068 } 2069 2070 // Remove the unused 'add_users' role. 2071 $roles = wp_roles(); 2072 foreach ( $roles->role_objects as $role ) { 2073 if ( $role->has_cap( 'add_users' ) ) { 2074 $role->remove_cap( 'add_users' ); 2075 } 2076 } 2077 } 2078 2079 /** 2080 * Executes changes made in WordPress 4.5.0. 2081 * 2082 * @ignore 2083 * @since 4.5.0 2084 * 2085 * @global int $wp_current_db_version The old (current) database version. 2086 * @global wpdb $wpdb WordPress database abstraction object. 2087 */ 2088 function upgrade_450() { 2089 global $wp_current_db_version, $wpdb; 2090 2091 if ( $wp_current_db_version < 36180 ) { 2092 wp_clear_scheduled_hook( 'wp_maybe_auto_update' ); 2093 } 2094 2095 // Remove unused email confirmation options, moved to usermeta. 2096 if ( $wp_current_db_version < 36679 && is_multisite() ) { 2097 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^[0-9]+_new_email$'" ); 2098 } 2099 2100 // Remove unused user setting for wpLink. 2101 delete_user_setting( 'wplink' ); 2102 } 2103 2104 /** 2105 * Executes changes made in WordPress 4.6.0. 2106 * 2107 * @ignore 2108 * @since 4.6.0 2109 * 2110 * @global int $wp_current_db_version The old (current) database version. 2111 */ 2112 function upgrade_460() { 2113 global $wp_current_db_version; 2114 2115 // Remove unused post meta. 2116 if ( $wp_current_db_version < 37854 ) { 2117 delete_post_meta_by_key( '_post_restored_from' ); 2118 } 2119 2120 // Remove plugins with callback as an array object/method as the uninstall hook, see #13786. 2121 if ( $wp_current_db_version < 37965 ) { 2122 $uninstall_plugins = get_option( 'uninstall_plugins', array() ); 2123 2124 if ( ! empty( $uninstall_plugins ) ) { 2125 foreach ( $uninstall_plugins as $basename => $callback ) { 2126 if ( is_array( $callback ) && is_object( $callback[0] ) ) { 2127 unset( $uninstall_plugins[ $basename ] ); 2128 } 2129 } 2130 2131 update_option( 'uninstall_plugins', $uninstall_plugins ); 2132 } 2133 } 2134 } 2135 2136 /** 2137 * Executes changes made in WordPress 5.0.0. 2138 * 2139 * @ignore 2140 * @since 5.0.0 2141 * @deprecated 5.1.0 2142 */ 2143 function upgrade_500() { 2144 } 2145 2146 /** 2147 * Executes changes made in WordPress 5.1.0. 2148 * 2149 * @ignore 2150 * @since 5.1.0 2151 */ 2152 function upgrade_510() { 2153 delete_site_option( 'upgrade_500_was_gutenberg_active' ); 2154 } 2155 2156 /** 2157 * Executes changes made in WordPress 5.3.0. 2158 * 2159 * @ignore 2160 * @since 5.3.0 2161 */ 2162 function upgrade_530() { 2163 /* 2164 * The `admin_email_lifespan` option may have been set by an admin that just logged in, 2165 * saw the verification screen, clicked on a button there, and is now upgrading the db, 2166 * or by populate_options() that is called earlier in upgrade_all(). 2167 * In the second case `admin_email_lifespan` should be reset so the verification screen 2168 * is shown next time an admin logs in. 2169 */ 2170 if ( function_exists( 'current_user_can' ) && ! current_user_can( 'manage_options' ) ) { 2171 update_option( 'admin_email_lifespan', 0 ); 2172 } 2173 } 2174 2175 /** 2176 * Executes changes made in WordPress 5.5.0. 2177 * 2178 * @ignore 2179 * @since 5.5.0 2180 * 2181 * @global int $wp_current_db_version The old (current) database version. 2182 */ 2183 function upgrade_550() { 2184 global $wp_current_db_version; 2185 2186 if ( $wp_current_db_version < 48121 ) { 2187 $comment_previously_approved = get_option( 'comment_whitelist', '' ); 2188 update_option( 'comment_previously_approved', $comment_previously_approved ); 2189 delete_option( 'comment_whitelist' ); 2190 } 2191 2192 if ( $wp_current_db_version < 48575 ) { 2193 // Use more clear and inclusive language. 2194 $disallowed_list = get_option( 'blacklist_keys' ); 2195 2196 /* 2197 * This option key was briefly renamed `blocklist_keys`. 2198 * Account for sites that have this key present when the original key does not exist. 2199 */ 2200 if ( false === $disallowed_list ) { 2201 $disallowed_list = get_option( 'blocklist_keys' ); 2202 } 2203 2204 update_option( 'disallowed_keys', $disallowed_list ); 2205 delete_option( 'blacklist_keys' ); 2206 delete_option( 'blocklist_keys' ); 2207 } 2208 2209 if ( $wp_current_db_version < 48748 ) { 2210 update_option( 'finished_updating_comment_type', 0 ); 2211 wp_schedule_single_event( time() + ( 1 * MINUTE_IN_SECONDS ), 'wp_update_comment_type_batch' ); 2212 } 2213 } 2214 2215 /** 2216 * Executes changes made in WordPress 5.6.0. 2217 * 2218 * @ignore 2219 * @since 5.6.0 2220 * 2221 * @global int $wp_current_db_version The old (current) database version. 2222 * @global wpdb $wpdb WordPress database abstraction object. 2223 */ 2224 function upgrade_560() { 2225 global $wp_current_db_version, $wpdb; 2226 2227 if ( $wp_current_db_version < 49572 ) { 2228 /* 2229 * Clean up the `post_category` column removed from schema in version 2.8.0. 2230 * Its presence may conflict with `WP_Post::__get()`. 2231 */ 2232 $post_category_exists = $wpdb->get_var( "SHOW COLUMNS FROM $wpdb->posts LIKE 'post_category'" ); 2233 if ( ! is_null( $post_category_exists ) ) { 2234 $wpdb->query( "ALTER TABLE $wpdb->posts DROP COLUMN `post_category`" ); 2235 } 2236 2237 /* 2238 * When upgrading from WP < 5.6.0 set the core major auto-updates option to `unset` by default. 2239 * This overrides the same option from populate_options() that is intended for new installs. 2240 * See https://core.trac.wordpress.org/ticket/51742. 2241 */ 2242 update_option( 'auto_update_core_major', 'unset' ); 2243 } 2244 2245 if ( $wp_current_db_version < 49632 ) { 2246 /* 2247 * Regenerate the .htaccess file to add the `HTTP_AUTHORIZATION` rewrite rule. 2248 * See https://core.trac.wordpress.org/ticket/51723. 2249 */ 2250 save_mod_rewrite_rules(); 2251 } 2252 2253 if ( $wp_current_db_version < 49735 ) { 2254 delete_transient( 'dirsize_cache' ); 2255 } 2256 2257 if ( $wp_current_db_version < 49752 ) { 2258 $results = $wpdb->get_results( 2259 $wpdb->prepare( 2260 "SELECT 1 FROM {$wpdb->usermeta} WHERE meta_key = %s LIMIT 1", 2261 WP_Application_Passwords::USERMETA_KEY_APPLICATION_PASSWORDS 2262 ) 2263 ); 2264 2265 if ( ! empty( $results ) ) { 2266 $network_id = get_main_network_id(); 2267 update_network_option( $network_id, WP_Application_Passwords::OPTION_KEY_IN_USE, 1 ); 2268 } 2269 } 2270 } 2271 2272 /** 2273 * Executes changes made in WordPress 5.9.0. 2274 * 2275 * @ignore 2276 * @since 5.9.0 2277 * 2278 * @global int $wp_current_db_version The old (current) database version. 2279 */ 2280 function upgrade_590() { 2281 global $wp_current_db_version; 2282 2283 if ( $wp_current_db_version < 51917 ) { 2284 $crons = _get_cron_array(); 2285 2286 if ( $crons && is_array( $crons ) ) { 2287 // Remove errant `false` values, see #53950, #54906. 2288 $crons = array_filter( $crons ); 2289 _set_cron_array( $crons ); 2290 } 2291 } 2292 } 2293 2294 /** 2295 * Executes changes made in WordPress 6.0.0. 2296 * 2297 * @ignore 2298 * @since 6.0.0 2299 * 2300 * @global int $wp_current_db_version The old (current) database version. 2301 */ 2302 function upgrade_600() { 2303 global $wp_current_db_version; 2304 2305 if ( $wp_current_db_version < 53011 ) { 2306 wp_update_user_counts(); 2307 } 2308 } 2309 2310 /** 2311 * Executes changes made in WordPress 6.3.0. 2312 * 2313 * @ignore 2314 * @since 6.3.0 2315 * 2316 * @global int $wp_current_db_version The old (current) database version. 2317 */ 2318 function upgrade_630() { 2319 global $wp_current_db_version; 2320 2321 if ( $wp_current_db_version < 55853 ) { 2322 if ( ! is_multisite() ) { 2323 // Replace non-autoload option can_compress_scripts with autoload option, see #55270 2324 $can_compress_scripts = get_option( 'can_compress_scripts', false ); 2325 if ( false !== $can_compress_scripts ) { 2326 delete_option( 'can_compress_scripts' ); 2327 add_option( 'can_compress_scripts', $can_compress_scripts, '', 'yes' ); 2328 } 2329 } 2330 } 2331 } 2332 2333 /** 2334 * Executes changes made in WordPress 6.4.0. 2335 * 2336 * @ignore 2337 * @since 6.4.0 2338 * 2339 * @global int $wp_current_db_version The old (current) database version. 2340 */ 2341 function upgrade_640() { 2342 global $wp_current_db_version; 2343 2344 if ( $wp_current_db_version < 56657 ) { 2345 // Enable attachment pages. 2346 update_option( 'wp_attachment_pages_enabled', 1 ); 2347 2348 // Remove the wp_https_detection cron. Https status is checked directly in an async Site Health check. 2349 $scheduled = wp_get_scheduled_event( 'wp_https_detection' ); 2350 if ( $scheduled ) { 2351 wp_clear_scheduled_hook( 'wp_https_detection' ); 2352 } 2353 } 2354 } 2355 2356 /** 2357 * Executes changes made in WordPress 6.5.0. 2358 * 2359 * @ignore 2360 * @since 6.5.0 2361 * 2362 * @global int $wp_current_db_version The old (current) database version. 2363 * @global wpdb $wpdb WordPress database abstraction object. 2364 */ 2365 function upgrade_650() { 2366 global $wp_current_db_version, $wpdb; 2367 2368 if ( $wp_current_db_version < 57155 ) { 2369 $stylesheet = get_stylesheet(); 2370 2371 // Set autoload=no for all themes except the current one. 2372 $theme_mods_options = $wpdb->get_col( 2373 $wpdb->prepare( 2374 "SELECT option_name FROM $wpdb->options WHERE autoload = 'yes' AND option_name != %s AND option_name LIKE %s", 2375 "theme_mods_$stylesheet", 2376 $wpdb->esc_like( 'theme_mods_' ) . '%' 2377 ) 2378 ); 2379 2380 $autoload = array_fill_keys( $theme_mods_options, 'no' ); 2381 wp_set_option_autoload_values( $autoload ); 2382 } 2383 } 2384 2385 /** 2386 * Executes network-level upgrade routines. 2387 * 2388 * @since 3.0.0 2389 * 2390 * @global int $wp_current_db_version The old (current) database version. 2391 * @global wpdb $wpdb WordPress database abstraction object. 2392 */ 2393 function upgrade_network() { 2394 global $wp_current_db_version, $wpdb; 2395 2396 // Always clear expired transients. 2397 delete_expired_transients( true ); 2398 2399 // 2.8.0 2400 if ( $wp_current_db_version < 11549 ) { 2401 $wpmu_sitewide_plugins = get_site_option( 'wpmu_sitewide_plugins' ); 2402 $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' ); 2403 if ( $wpmu_sitewide_plugins ) { 2404 if ( ! $active_sitewide_plugins ) { 2405 $sitewide_plugins = (array) $wpmu_sitewide_plugins; 2406 } else { 2407 $sitewide_plugins = array_merge( (array) $active_sitewide_plugins, (array) $wpmu_sitewide_plugins ); 2408 } 2409 2410 update_site_option( 'active_sitewide_plugins', $sitewide_plugins ); 2411 } 2412 delete_site_option( 'wpmu_sitewide_plugins' ); 2413 delete_site_option( 'deactivated_sitewide_plugins' ); 2414 2415 $start = 0; 2416 while ( $rows = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} ORDER BY meta_id LIMIT $start, 20" ) ) { 2417 foreach ( $rows as $row ) { 2418 $value = $row->meta_value; 2419 if ( ! @unserialize( $value ) ) { 2420 $value = stripslashes( $value ); 2421 } 2422 if ( $value !== $row->meta_value ) { 2423 update_site_option( $row->meta_key, $value ); 2424 } 2425 } 2426 $start += 20; 2427 } 2428 } 2429 2430 // 3.0.0 2431 if ( $wp_current_db_version < 13576 ) { 2432 update_site_option( 'global_terms_enabled', '1' ); 2433 } 2434 2435 // 3.3.0 2436 if ( $wp_current_db_version < 19390 ) { 2437 update_site_option( 'initial_db_version', $wp_current_db_version ); 2438 } 2439 2440 if ( $wp_current_db_version < 19470 ) { 2441 if ( false === get_site_option( 'active_sitewide_plugins' ) ) { 2442 update_site_option( 'active_sitewide_plugins', array() ); 2443 } 2444 } 2445 2446 // 3.4.0 2447 if ( $wp_current_db_version < 20148 ) { 2448 // 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name. 2449 $allowedthemes = get_site_option( 'allowedthemes' ); 2450 $allowed_themes = get_site_option( 'allowed_themes' ); 2451 if ( false === $allowedthemes && is_array( $allowed_themes ) && $allowed_themes ) { 2452 $converted = array(); 2453 $themes = wp_get_themes(); 2454 foreach ( $themes as $stylesheet => $theme_data ) { 2455 if ( isset( $allowed_themes[ $theme_data->get( 'Name' ) ] ) ) { 2456 $converted[ $stylesheet ] = true; 2457 } 2458 } 2459 update_site_option( 'allowedthemes', $converted ); 2460 delete_site_option( 'allowed_themes' ); 2461 } 2462 } 2463 2464 // 3.5.0 2465 if ( $wp_current_db_version < 21823 ) { 2466 update_site_option( 'ms_files_rewriting', '1' ); 2467 } 2468 2469 // 3.5.2 2470 if ( $wp_current_db_version < 24448 ) { 2471 $illegal_names = get_site_option( 'illegal_names' ); 2472 if ( is_array( $illegal_names ) && count( $illegal_names ) === 1 ) { 2473 $illegal_name = reset( $illegal_names ); 2474 $illegal_names = explode( ' ', $illegal_name ); 2475 update_site_option( 'illegal_names', $illegal_names ); 2476 } 2477 } 2478 2479 // 4.2.0 2480 if ( $wp_current_db_version < 31351 && 'utf8mb4' === $wpdb->charset ) { 2481 if ( wp_should_upgrade_global_tables() ) { 2482 $wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 2483 $wpdb->query( "ALTER TABLE $wpdb->site DROP INDEX domain, ADD INDEX domain(domain(140),path(51))" ); 2484 $wpdb->query( "ALTER TABLE $wpdb->sitemeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 2485 $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" ); 2486 2487 $tables = $wpdb->tables( 'global' ); 2488 2489 // sitecategories may not exist. 2490 if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) { 2491 unset( $tables['sitecategories'] ); 2492 } 2493 2494 foreach ( $tables as $table ) { 2495 maybe_convert_table_to_utf8mb4( $table ); 2496 } 2497 } 2498 } 2499 2500 // 4.3.0 2501 if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) { 2502 if ( wp_should_upgrade_global_tables() ) { 2503 $upgrade = false; 2504 $indexes = $wpdb->get_results( "SHOW INDEXES FROM $wpdb->signups" ); 2505 foreach ( $indexes as $index ) { 2506 if ( 'domain_path' === $index->Key_name && 'domain' === $index->Column_name && 140 != $index->Sub_part ) { 2507 $upgrade = true; 2508 break; 2509 } 2510 } 2511 2512 if ( $upgrade ) { 2513 $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" ); 2514 } 2515 2516 $tables = $wpdb->tables( 'global' ); 2517 2518 // sitecategories may not exist. 2519 if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) { 2520 unset( $tables['sitecategories'] ); 2521 } 2522 2523 foreach ( $tables as $table ) { 2524 maybe_convert_table_to_utf8mb4( $table ); 2525 } 2526 } 2527 } 2528 2529 // 5.1.0 2530 if ( $wp_current_db_version < 44467 ) { 2531 $network_id = get_main_network_id(); 2532 delete_network_option( $network_id, 'site_meta_supported' ); 2533 is_site_meta_supported(); 2534 } 2535 } 2536 2537 // 2538 // General functions we use to actually do stuff. 2539 // 2540 2541 /** 2542 * Creates a table in the database, if it doesn't already exist. 2543 * 2544 * This method checks for an existing database table and creates a new one if it's not 2545 * already present. It doesn't rely on MySQL's "IF NOT EXISTS" statement, but chooses 2546 * to query all tables first and then run the SQL statement creating the table. 2547 * 2548 * @since 1.0.0 2549 * 2550 * @global wpdb $wpdb WordPress database abstraction object. 2551 * 2552 * @param string $table_name Database table name. 2553 * @param string $create_ddl SQL statement to create table. 2554 * @return bool True on success or if the table already exists. False on failure. 2555 */ 2556 function maybe_create_table( $table_name, $create_ddl ) { 2557 global $wpdb; 2558 2559 $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) ); 2560 2561 if ( $wpdb->get_var( $query ) === $table_name ) { 2562 return true; 2563 } 2564 2565 // Didn't find it, so try to create it. 2566 $wpdb->query( $create_ddl ); 2567 2568 // We cannot directly tell that whether this succeeded! 2569 if ( $wpdb->get_var( $query ) === $table_name ) { 2570 return true; 2571 } 2572 2573 return false; 2574 } 2575 2576 /** 2577 * Drops a specified index from a table. 2578 * 2579 * @since 1.0.1 2580 * 2581 * @global wpdb $wpdb WordPress database abstraction object. 2582 * 2583 * @param string $table Database table name. 2584 * @param string $index Index name to drop. 2585 * @return true True, when finished. 2586 */ 2587 function drop_index( $table, $index ) { 2588 global $wpdb; 2589 2590 $wpdb->hide_errors(); 2591 2592 $wpdb->query( "ALTER TABLE `$table` DROP INDEX `$index`" ); 2593 2594 // Now we need to take out all the extra ones we may have created. 2595 for ( $i = 0; $i < 25; $i++ ) { 2596 $wpdb->query( "ALTER TABLE `$table` DROP INDEX `{$index}_$i`" ); 2597 } 2598 2599 $wpdb->show_errors(); 2600 2601 return true; 2602 } 2603 2604 /** 2605 * Adds an index to a specified table. 2606 * 2607 * @since 1.0.1 2608 * 2609 * @global wpdb $wpdb WordPress database abstraction object. 2610 * 2611 * @param string $table Database table name. 2612 * @param string $index Database table index column. 2613 * @return true True, when done with execution. 2614 */ 2615 function add_clean_index( $table, $index ) { 2616 global $wpdb; 2617 2618 drop_index( $table, $index ); 2619 $wpdb->query( "ALTER TABLE `$table` ADD INDEX ( `$index` )" ); 2620 2621 return true; 2622 } 2623 2624 /** 2625 * Adds column to a database table, if it doesn't already exist. 2626 * 2627 * @since 1.3.0 2628 * 2629 * @global wpdb $wpdb WordPress database abstraction object. 2630 * 2631 * @param string $table_name Database table name. 2632 * @param string $column_name Table column name. 2633 * @param string $create_ddl SQL statement to add column. 2634 * @return bool True on success or if the column already exists. False on failure. 2635 */ 2636 function maybe_add_column( $table_name, $column_name, $create_ddl ) { 2637 global $wpdb; 2638 2639 foreach ( $wpdb->get_col( "DESC $table_name", 0 ) as $column ) { 2640 if ( $column === $column_name ) { 2641 return true; 2642 } 2643 } 2644 2645 // Didn't find it, so try to create it. 2646 $wpdb->query( $create_ddl ); 2647 2648 // We cannot directly tell that whether this succeeded! 2649 foreach ( $wpdb->get_col( "DESC $table_name", 0 ) as $column ) { 2650 if ( $column === $column_name ) { 2651 return true; 2652 } 2653 } 2654 2655 return false; 2656 } 2657 2658 /** 2659 * If a table only contains utf8 or utf8mb4 columns, convert it to utf8mb4. 2660 * 2661 * @since 4.2.0 2662 * 2663 * @global wpdb $wpdb WordPress database abstraction object. 2664 * 2665 * @param string $table The table to convert. 2666 * @return bool True if the table was converted, false if it wasn't. 2667 */ 2668 function maybe_convert_table_to_utf8mb4( $table ) { 2669 global $wpdb; 2670 2671 $results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `$table`" ); 2672 if ( ! $results ) { 2673 return false; 2674 } 2675 2676 foreach ( $results as $column ) { 2677 if ( $column->Collation ) { 2678 list( $charset ) = explode( '_', $column->Collation ); 2679 $charset = strtolower( $charset ); 2680 if ( 'utf8' !== $charset && 'utf8mb4' !== $charset ) { 2681 // Don't upgrade tables that have non-utf8 columns. 2682 return false; 2683 } 2684 } 2685 } 2686 2687 $table_details = $wpdb->get_row( "SHOW TABLE STATUS LIKE '$table'" ); 2688 if ( ! $table_details ) { 2689 return false; 2690 } 2691 2692 list( $table_charset ) = explode( '_', $table_details->Collation ); 2693 $table_charset = strtolower( $table_charset ); 2694 if ( 'utf8mb4' === $table_charset ) { 2695 return true; 2696 } 2697 2698 return $wpdb->query( "ALTER TABLE $table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" ); 2699 } 2700 2701 /** 2702 * Retrieve all options as it was for 1.2. 2703 * 2704 * @since 1.2.0 2705 * 2706 * @global wpdb $wpdb WordPress database abstraction object. 2707 * 2708 * @return stdClass List of options. 2709 */ 2710 function get_alloptions_110() { 2711 global $wpdb; 2712 $all_options = new stdClass(); 2713 $options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" ); 2714 if ( $options ) { 2715 foreach ( $options as $option ) { 2716 if ( 'siteurl' === $option->option_name || 'home' === $option->option_name || 'category_base' === $option->option_name ) { 2717 $option->option_value = untrailingslashit( $option->option_value ); 2718 } 2719 $all_options->{$option->option_name} = stripslashes( $option->option_value ); 2720 } 2721 } 2722 return $all_options; 2723 } 2724 2725 /** 2726 * Utility version of get_option that is private to installation/upgrade. 2727 * 2728 * @ignore 2729 * @since 1.5.1 2730 * @access private 2731 * 2732 * @global wpdb $wpdb WordPress database abstraction object. 2733 * 2734 * @param string $setting Option name. 2735 * @return mixed 2736 */ 2737 function __get_option( $setting ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore 2738 global $wpdb; 2739 2740 if ( 'home' === $setting && defined( 'WP_HOME' ) ) { 2741 return untrailingslashit( WP_HOME ); 2742 } 2743 2744 if ( 'siteurl' === $setting && defined( 'WP_SITEURL' ) ) { 2745 return untrailingslashit( WP_SITEURL ); 2746 } 2747 2748 $option = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", $setting ) ); 2749 2750 if ( 'home' === $setting && ! $option ) { 2751 return __get_option( 'siteurl' ); 2752 } 2753 2754 if ( in_array( $setting, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) { 2755 $option = untrailingslashit( $option ); 2756 } 2757 2758 return maybe_unserialize( $option ); 2759 } 2760 2761 /** 2762 * Filters for content to remove unnecessary slashes. 2763 * 2764 * @since 1.5.0 2765 * 2766 * @param string $content The content to modify. 2767 * @return string The de-slashed content. 2768 */ 2769 function deslash( $content ) { 2770 // Note: \\\ inside a regex denotes a single backslash. 2771 2772 /* 2773 * Replace one or more backslashes followed by a single quote with 2774 * a single quote. 2775 */ 2776 $content = preg_replace( "/\\\+'/", "'", $content ); 2777 2778 /* 2779 * Replace one or more backslashes followed by a double quote with 2780 * a double quote. 2781 */ 2782 $content = preg_replace( '/\\\+"/', '"', $content ); 2783 2784 // Replace one or more backslashes with one backslash. 2785 $content = preg_replace( '/\\\+/', '\\', $content ); 2786 2787 return $content; 2788 } 2789 2790 /** 2791 * Modifies the database based on specified SQL statements. 2792 * 2793 * Useful for creating new tables and updating existing tables to a new structure. 2794 * 2795 * @since 1.5.0 2796 * @since 6.1.0 Ignores display width for integer data types on MySQL 8.0.17 or later, 2797 * to match MySQL behavior. Note: This does not affect MariaDB. 2798 * 2799 * @global wpdb $wpdb WordPress database abstraction object. 2800 * 2801 * @param string[]|string $queries Optional. The query to run. Can be multiple queries 2802 * in an array, or a string of queries separated by 2803 * semicolons. Default empty string. 2804 * @param bool $execute Optional. Whether or not to execute the query right away. 2805 * Default true. 2806 * @return array Strings containing the results of the various update queries. 2807 */ 2808 function dbDelta( $queries = '', $execute = true ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid 2809 global $wpdb; 2810 2811 if ( in_array( $queries, array( '', 'all', 'blog', 'global', 'ms_global' ), true ) ) { 2812 $queries = wp_get_db_schema( $queries ); 2813 } 2814 2815 // Separate individual queries into an array. 2816 if ( ! is_array( $queries ) ) { 2817 $queries = explode( ';', $queries ); 2818 $queries = array_filter( $queries ); 2819 } 2820 2821 /** 2822 * Filters the dbDelta SQL queries. 2823 * 2824 * @since 3.3.0 2825 * 2826 * @param string[] $queries An array of dbDelta SQL queries. 2827 */ 2828 $queries = apply_filters( 'dbdelta_queries', $queries ); 2829 2830 $cqueries = array(); // Creation queries. 2831 $iqueries = array(); // Insertion queries. 2832 $for_update = array(); 2833 2834 // Create a tablename index for an array ($cqueries) of recognized query types. 2835 foreach ( $queries as $qry ) { 2836 if ( preg_match( '|CREATE TABLE ([^ ]*)|', $qry, $matches ) ) { 2837 $cqueries[ trim( $matches[1], '`' ) ] = $qry; 2838 $for_update[ $matches[1] ] = 'Created table ' . $matches[1]; 2839 continue; 2840 } 2841 2842 if ( preg_match( '|CREATE DATABASE ([^ ]*)|', $qry, $matches ) ) { 2843 array_unshift( $cqueries, $qry ); 2844 continue; 2845 } 2846 2847 if ( preg_match( '|INSERT INTO ([^ ]*)|', $qry, $matches ) ) { 2848 $iqueries[] = $qry; 2849 continue; 2850 } 2851 2852 if ( preg_match( '|UPDATE ([^ ]*)|', $qry, $matches ) ) { 2853 $iqueries[] = $qry; 2854 continue; 2855 } 2856 } 2857 2858 /** 2859 * Filters the dbDelta SQL queries for creating tables and/or databases. 2860 * 2861 * Queries filterable via this hook contain "CREATE TABLE" or "CREATE DATABASE". 2862 * 2863 * @since 3.3.0 2864 * 2865 * @param string[] $cqueries An array of dbDelta create SQL queries. 2866 */ 2867 $cqueries = apply_filters( 'dbdelta_create_queries', $cqueries ); 2868 2869 /** 2870 * Filters the dbDelta SQL queries for inserting or updating. 2871 * 2872 * Queries filterable via this hook contain "INSERT INTO" or "UPDATE". 2873 * 2874 * @since 3.3.0 2875 * 2876 * @param string[] $iqueries An array of dbDelta insert or update SQL queries. 2877 */ 2878 $iqueries = apply_filters( 'dbdelta_insert_queries', $iqueries ); 2879 2880 $text_fields = array( 'tinytext', 'text', 'mediumtext', 'longtext' ); 2881 $blob_fields = array( 'tinyblob', 'blob', 'mediumblob', 'longblob' ); 2882 $int_fields = array( 'tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint' ); 2883 2884 $global_tables = $wpdb->tables( 'global' ); 2885 $db_version = $wpdb->db_version(); 2886 $db_server_info = $wpdb->db_server_info(); 2887 2888 foreach ( $cqueries as $table => $qry ) { 2889 // Upgrade global tables only for the main site. Don't upgrade at all if conditions are not optimal. 2890 if ( in_array( $table, $global_tables, true ) && ! wp_should_upgrade_global_tables() ) { 2891 unset( $cqueries[ $table ], $for_update[ $table ] ); 2892 continue; 2893 } 2894 2895 // Fetch the table column structure from the database. 2896 $suppress = $wpdb->suppress_errors(); 2897 $tablefields = $wpdb->get_results( "DESCRIBE {$table};" ); 2898 $wpdb->suppress_errors( $suppress ); 2899 2900 if ( ! $tablefields ) { 2901 continue; 2902 } 2903 2904 // Clear the field and index arrays. 2905 $cfields = array(); 2906 $indices = array(); 2907 $indices_without_subparts = array(); 2908 2909 // Get all of the field names in the query from between the parentheses. 2910 preg_match( '|\((.*)\)|ms', $qry, $match2 ); 2911 $qryline = trim( $match2[1] ); 2912 2913 // Separate field lines into an array. 2914 $flds = explode( "\n", $qryline ); 2915 2916 // For every field line specified in the query. 2917 foreach ( $flds as $fld ) { 2918 $fld = trim( $fld, " \t\n\r\0\x0B," ); // Default trim characters, plus ','. 2919 2920 // Extract the field name. 2921 preg_match( '|^([^ ]*)|', $fld, $fvals ); 2922 $fieldname = trim( $fvals[1], '`' ); 2923 $fieldname_lowercased = strtolower( $fieldname ); 2924 2925 // Verify the found field name. 2926 $validfield = true; 2927 switch ( $fieldname_lowercased ) { 2928 case '': 2929 case 'primary': 2930 case 'index': 2931 case 'fulltext': 2932 case 'unique': 2933 case 'key': 2934 case 'spatial': 2935 $validfield = false; 2936 2937 /* 2938 * Normalize the index definition. 2939 * 2940 * This is done so the definition can be compared against the result of a 2941 * `SHOW INDEX FROM $table_name` query which returns the current table 2942 * index information. 2943 */ 2944 2945 // Extract type, name and columns from the definition. 2946 preg_match( 2947 '/^ 2948 (?P<index_type> # 1) Type of the index. 2949 PRIMARY\s+KEY|(?:UNIQUE|FULLTEXT|SPATIAL)\s+(?:KEY|INDEX)|KEY|INDEX 2950 ) 2951 \s+ # Followed by at least one white space character. 2952 (?: # Name of the index. Optional if type is PRIMARY KEY. 2953 `? # Name can be escaped with a backtick. 2954 (?P<index_name> # 2) Name of the index. 2955 (?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+ 2956 ) 2957 `? # Name can be escaped with a backtick. 2958 \s+ # Followed by at least one white space character. 2959 )* 2960 \( # Opening bracket for the columns. 2961 (?P<index_columns> 2962 .+? # 3) Column names, index prefixes, and orders. 2963 ) 2964 \) # Closing bracket for the columns. 2965 $/imx', 2966 $fld, 2967 $index_matches 2968 ); 2969 2970 // Uppercase the index type and normalize space characters. 2971 $index_type = strtoupper( preg_replace( '/\s+/', ' ', trim( $index_matches['index_type'] ) ) ); 2972 2973 // 'INDEX' is a synonym for 'KEY', standardize on 'KEY'. 2974 $index_type = str_replace( 'INDEX', 'KEY', $index_type ); 2975 2976 // Escape the index name with backticks. An index for a primary key has no name. 2977 $index_name = ( 'PRIMARY KEY' === $index_type ) ? '' : '`' . strtolower( $index_matches['index_name'] ) . '`'; 2978 2979 // Parse the columns. Multiple columns are separated by a comma. 2980 $index_columns = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) ); 2981 $index_columns_without_subparts = $index_columns; 2982 2983 // Normalize columns. 2984 foreach ( $index_columns as $id => &$index_column ) { 2985 // Extract column name and number of indexed characters (sub_part). 2986 preg_match( 2987 '/ 2988 `? # Name can be escaped with a backtick. 2989 (?P<column_name> # 1) Name of the column. 2990 (?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+ 2991 ) 2992 `? # Name can be escaped with a backtick. 2993 (?: # Optional sub part. 2994 \s* # Optional white space character between name and opening bracket. 2995 \( # Opening bracket for the sub part. 2996 \s* # Optional white space character after opening bracket. 2997 (?P<sub_part> 2998 \d+ # 2) Number of indexed characters. 2999 ) 3000 \s* # Optional white space character before closing bracket. 3001 \) # Closing bracket for the sub part. 3002 )? 3003 /x', 3004 $index_column, 3005 $index_column_matches 3006 ); 3007 3008 // Escape the column name with backticks. 3009 $index_column = '`' . $index_column_matches['column_name'] . '`'; 3010 3011 // We don't need to add the subpart to $index_columns_without_subparts 3012 $index_columns_without_subparts[ $id ] = $index_column; 3013 3014 // Append the optional sup part with the number of indexed characters. 3015 if ( isset( $index_column_matches['sub_part'] ) ) { 3016 $index_column .= '(' . $index_column_matches['sub_part'] . ')'; 3017 } 3018 } 3019 3020 // Build the normalized index definition and add it to the list of indices. 3021 $indices[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns ) . ')'; 3022 $indices_without_subparts[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns_without_subparts ) . ')'; 3023 3024 // Destroy no longer needed variables. 3025 unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns, $index_columns_without_subparts ); 3026 3027 break; 3028 } 3029 3030 // If it's a valid field, add it to the field array. 3031 if ( $validfield ) { 3032 $cfields[ $fieldname_lowercased ] = $fld; 3033 } 3034 } 3035 3036 // For every field in the table. 3037 foreach ( $tablefields as $tablefield ) { 3038 $tablefield_field_lowercased = strtolower( $tablefield->Field ); 3039 $tablefield_type_lowercased = strtolower( $tablefield->Type ); 3040 3041 $tablefield_type_without_parentheses = preg_replace( 3042 '/' 3043 . '(.+)' // Field type, e.g. `int`. 3044 . '\(\d*\)' // Display width. 3045 . '(.*)' // Optional attributes, e.g. `unsigned`. 3046 . '/', 3047 '$1$2', 3048 $tablefield_type_lowercased 3049 ); 3050 3051 // Get the type without attributes, e.g. `int`. 3052 $tablefield_type_base = strtok( $tablefield_type_without_parentheses, ' ' ); 3053 3054 // If the table field exists in the field array... 3055 if ( array_key_exists( $tablefield_field_lowercased, $cfields ) ) { 3056 3057 // Get the field type from the query. 3058 preg_match( '|`?' . $tablefield->Field . '`? ([^ ]*( unsigned)?)|i', $cfields[ $tablefield_field_lowercased ], $matches ); 3059 $fieldtype = $matches[1]; 3060 $fieldtype_lowercased = strtolower( $fieldtype ); 3061 3062 $fieldtype_without_parentheses = preg_replace( 3063 '/' 3064 . '(.+)' // Field type, e.g. `int`. 3065 . '\(\d*\)' // Display width. 3066 . '(.*)' // Optional attributes, e.g. `unsigned`. 3067 . '/', 3068 '$1$2', 3069 $fieldtype_lowercased 3070 ); 3071 3072 // Get the type without attributes, e.g. `int`. 3073 $fieldtype_base = strtok( $fieldtype_without_parentheses, ' ' ); 3074 3075 // Is actual field type different from the field type in query? 3076 if ( $tablefield->Type != $fieldtype ) { 3077 $do_change = true; 3078 if ( in_array( $fieldtype_lowercased, $text_fields, true ) && in_array( $tablefield_type_lowercased, $text_fields, true ) ) { 3079 if ( array_search( $fieldtype_lowercased, $text_fields, true ) < array_search( $tablefield_type_lowercased, $text_fields, true ) ) { 3080 $do_change = false; 3081 } 3082 } 3083 3084 if ( in_array( $fieldtype_lowercased, $blob_fields, true ) && in_array( $tablefield_type_lowercased, $blob_fields, true ) ) { 3085 if ( array_search( $fieldtype_lowercased, $blob_fields, true ) < array_search( $tablefield_type_lowercased, $blob_fields, true ) ) { 3086 $do_change = false; 3087 } 3088 } 3089 3090 if ( in_array( $fieldtype_base, $int_fields, true ) && in_array( $tablefield_type_base, $int_fields, true ) 3091 && $fieldtype_without_parentheses === $tablefield_type_without_parentheses 3092 ) { 3093 /* 3094 * MySQL 8.0.17 or later does not support display width for integer data types, 3095 * so if display width is the only difference, it can be safely ignored. 3096 * Note: This is specific to MySQL and does not affect MariaDB. 3097 */ 3098 if ( version_compare( $db_version, '8.0.17', '>=' ) 3099 && ! str_contains( $db_server_info, 'MariaDB' ) 3100 ) { 3101 $do_change = false; 3102 } 3103 } 3104 3105 if ( $do_change ) { 3106 // Add a query to change the column type. 3107 $cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN `{$tablefield->Field}` " . $cfields[ $tablefield_field_lowercased ]; 3108 3109 $for_update[ $table . '.' . $tablefield->Field ] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}"; 3110 } 3111 } 3112 3113 // Get the default value from the array. 3114 if ( preg_match( "| DEFAULT '(.*?)'|i", $cfields[ $tablefield_field_lowercased ], $matches ) ) { 3115 $default_value = $matches[1]; 3116 if ( $tablefield->Default != $default_value ) { 3117 // Add a query to change the column's default value 3118 $cqueries[] = "ALTER TABLE {$table} ALTER COLUMN `{$tablefield->Field}` SET DEFAULT '{$default_value}'"; 3119 3120 $for_update[ $table . '.' . $tablefield->Field ] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}"; 3121 } 3122 } 3123 3124 // Remove the field from the array (so it's not added). 3125 unset( $cfields[ $tablefield_field_lowercased ] ); 3126 } else { 3127 // This field exists in the table, but not in the creation queries? 3128 } 3129 } 3130 3131 // For every remaining field specified for the table. 3132 foreach ( $cfields as $fieldname => $fielddef ) { 3133 // Push a query line into $cqueries that adds the field to that table. 3134 $cqueries[] = "ALTER TABLE {$table} ADD COLUMN $fielddef"; 3135 3136 $for_update[ $table . '.' . $fieldname ] = 'Added column ' . $table . '.' . $fieldname; 3137 } 3138 3139 // Index stuff goes here. Fetch the table index structure from the database. 3140 $tableindices = $wpdb->get_results( "SHOW INDEX FROM {$table};" ); 3141 3142 if ( $tableindices ) { 3143 // Clear the index array. 3144 $index_ary = array(); 3145 3146 // For every index in the table. 3147 foreach ( $tableindices as $tableindex ) { 3148 $keyname = strtolower( $tableindex->Key_name ); 3149 3150 // Add the index to the index data array. 3151 $index_ary[ $keyname ]['columns'][] = array( 3152 'fieldname' => $tableindex->Column_name, 3153 'subpart' => $tableindex->Sub_part, 3154 ); 3155 $index_ary[ $keyname ]['unique'] = ( 0 == $tableindex->Non_unique ) ? true : false; 3156 $index_ary[ $keyname ]['index_type'] = $tableindex->Index_type; 3157 } 3158 3159 // For each actual index in the index array. 3160 foreach ( $index_ary as $index_name => $index_data ) { 3161 3162 // Build a create string to compare to the query. 3163 $index_string = ''; 3164 if ( 'primary' === $index_name ) { 3165 $index_string .= 'PRIMARY '; 3166 } elseif ( $index_data['unique'] ) { 3167 $index_string .= 'UNIQUE '; 3168 } 3169 3170 if ( 'FULLTEXT' === strtoupper( $index_data['index_type'] ) ) { 3171 $index_string .= 'FULLTEXT '; 3172 } 3173 3174 if ( 'SPATIAL' === strtoupper( $index_data['index_type'] ) ) { 3175 $index_string .= 'SPATIAL '; 3176 } 3177 3178 $index_string .= 'KEY '; 3179 if ( 'primary' !== $index_name ) { 3180 $index_string .= '`' . $index_name . '`'; 3181 } 3182 3183 $index_columns = ''; 3184 3185 // For each column in the index. 3186 foreach ( $index_data['columns'] as $column_data ) { 3187 if ( '' !== $index_columns ) { 3188 $index_columns .= ','; 3189 } 3190 3191 // Add the field to the column list string. 3192 $index_columns .= '`' . $column_data['fieldname'] . '`'; 3193 } 3194 3195 // Add the column list to the index create string. 3196 $index_string .= " ($index_columns)"; 3197 3198 // Check if the index definition exists, ignoring subparts. 3199 $aindex = array_search( $index_string, $indices_without_subparts, true ); 3200 if ( false !== $aindex ) { 3201 // If the index already exists (even with different subparts), we don't need to create it. 3202 unset( $indices_without_subparts[ $aindex ] ); 3203 unset( $indices[ $aindex ] ); 3204 } 3205 } 3206 } 3207 3208 // For every remaining index specified for the table. 3209 foreach ( (array) $indices as $index ) { 3210 // Push a query line into $cqueries that adds the index to that table. 3211 $cqueries[] = "ALTER TABLE {$table} ADD $index"; 3212 3213 $for_update[] = 'Added index ' . $table . ' ' . $index; 3214 } 3215 3216 // Remove the original table creation query from processing. 3217 unset( $cqueries[ $table ], $for_update[ $table ] ); 3218 } 3219 3220 $allqueries = array_merge( $cqueries, $iqueries ); 3221 if ( $execute ) { 3222 foreach ( $allqueries as $query ) { 3223 $wpdb->query( $query ); 3224 } 3225 } 3226 3227 return $for_update; 3228 } 3229 3230 /** 3231 * Updates the database tables to a new schema. 3232 * 3233 * By default, updates all the tables to use the latest defined schema, but can also 3234 * be used to update a specific set of tables in wp_get_db_schema(). 3235 * 3236 * @since 1.5.0 3237 * 3238 * @uses dbDelta 3239 * 3240 * @param string $tables Optional. Which set of tables to update. Default is 'all'. 3241 */ 3242 function make_db_current( $tables = 'all' ) { 3243 $alterations = dbDelta( $tables ); 3244 echo "<ol>\n"; 3245 foreach ( $alterations as $alteration ) { 3246 echo "<li>$alteration</li>\n"; 3247 } 3248 echo "</ol>\n"; 3249 } 3250 3251 /** 3252 * Updates the database tables to a new schema, but without displaying results. 3253 * 3254 * By default, updates all the tables to use the latest defined schema, but can 3255 * also be used to update a specific set of tables in wp_get_db_schema(). 3256 * 3257 * @since 1.5.0 3258 * 3259 * @see make_db_current() 3260 * 3261 * @param string $tables Optional. Which set of tables to update. Default is 'all'. 3262 */ 3263 function make_db_current_silent( $tables = 'all' ) { 3264 dbDelta( $tables ); 3265 } 3266 3267 /** 3268 * Creates a site theme from an existing theme. 3269 * 3270 * {@internal Missing Long Description}} 3271 * 3272 * @since 1.5.0 3273 * 3274 * @param string $theme_name The name of the theme. 3275 * @param string $template The directory name of the theme. 3276 * @return bool 3277 */ 3278 function make_site_theme_from_oldschool( $theme_name, $template ) { 3279 $home_path = get_home_path(); 3280 $site_dir = WP_CONTENT_DIR . "/themes/$template"; 3281 $default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME; 3282 3283 if ( ! file_exists( "$home_path/index.php" ) ) { 3284 return false; 3285 } 3286 3287 /* 3288 * Copy files from the old locations to the site theme. 3289 * TODO: This does not copy arbitrary include dependencies. Only the standard WP files are copied. 3290 */ 3291 $files = array( 3292 'index.php' => 'index.php', 3293 'wp-layout.css' => 'style.css', 3294 'wp-comments.php' => 'comments.php', 3295 'wp-comments-popup.php' => 'comments-popup.php', 3296 ); 3297 3298 foreach ( $files as $oldfile => $newfile ) { 3299 if ( 'index.php' === $oldfile ) { 3300 $oldpath = $home_path; 3301 } else { 3302 $oldpath = ABSPATH; 3303 } 3304 3305 // Check to make sure it's not a new index. 3306 if ( 'index.php' === $oldfile ) { 3307 $index = implode( '', file( "$oldpath/$oldfile" ) ); 3308 if ( str_contains( $index, 'WP_USE_THEMES' ) ) { 3309 if ( ! copy( "$default_dir/$oldfile", "$site_dir/$newfile" ) ) { 3310 return false; 3311 } 3312 3313 // Don't copy anything. 3314 continue; 3315 } 3316 } 3317 3318 if ( ! copy( "$oldpath/$oldfile", "$site_dir/$newfile" ) ) { 3319 return false; 3320 } 3321 3322 chmod( "$site_dir/$newfile", 0777 ); 3323 3324 // Update the blog header include in each file. 3325 $lines = explode( "\n", implode( '', file( "$site_dir/$newfile" ) ) ); 3326 if ( $lines ) { 3327 $f = fopen( "$site_dir/$newfile", 'w' ); 3328 3329 foreach ( $lines as $line ) { 3330 if ( preg_match( '/require.*wp-blog-header/', $line ) ) { 3331 $line = '//' . $line; 3332 } 3333 3334 // Update stylesheet references. 3335 $line = str_replace( 3336 "<?php echo __get_option('siteurl'); ?>/wp-layout.css", 3337 "<?php bloginfo('stylesheet_url'); ?>", 3338 $line 3339 ); 3340 3341 // Update comments template inclusion. 3342 $line = str_replace( 3343 "<?php include(ABSPATH . 'wp-comments.php'); ?>", 3344 '<?php comments_template(); ?>', 3345 $line 3346 ); 3347 3348 fwrite( $f, "{$line}\n" ); 3349 } 3350 fclose( $f ); 3351 } 3352 } 3353 3354 // Add a theme header. 3355 $header = "/*\n" . 3356 "Theme Name: $theme_name\n" . 3357 'Theme URI: ' . __get_option( 'siteurl' ) . "\n" . 3358 "Description: A theme automatically created by the update.\n" . 3359 "Version: 1.0\n" . 3360 "Author: Moi\n" . 3361 "*/\n"; 3362 3363 $stylelines = file_get_contents( "$site_dir/style.css" ); 3364 if ( $stylelines ) { 3365 $f = fopen( "$site_dir/style.css", 'w' ); 3366 3367 fwrite( $f, $header ); 3368 fwrite( $f, $stylelines ); 3369 fclose( $f ); 3370 } 3371 3372 return true; 3373 } 3374 3375 /** 3376 * Creates a site theme from the default theme. 3377 * 3378 * {@internal Missing Long Description}} 3379 * 3380 * @since 1.5.0 3381 * 3382 * @param string $theme_name The name of the theme. 3383 * @param string $template The directory name of the theme. 3384 * @return void|false 3385 */ 3386 function make_site_theme_from_default( $theme_name, $template ) { 3387 $site_dir = WP_CONTENT_DIR . "/themes/$template"; 3388 $default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME; 3389 3390 /* 3391 * Copy files from the default theme to the site theme. 3392 * $files = array( 'index.php', 'comments.php', 'comments-popup.php', 'footer.php', 'header.php', 'sidebar.php', 'style.css' ); 3393 */ 3394 3395 $theme_dir = @opendir( $default_dir ); 3396 if ( $theme_dir ) { 3397 while ( ( $theme_file = readdir( $theme_dir ) ) !== false ) { 3398 if ( is_dir( "$default_dir/$theme_file" ) ) { 3399 continue; 3400 } 3401 3402 if ( ! copy( "$default_dir/$theme_file", "$site_dir/$theme_file" ) ) { 3403 return; 3404 } 3405 3406 chmod( "$site_dir/$theme_file", 0777 ); 3407 } 3408 3409 closedir( $theme_dir ); 3410 } 3411 3412 // Rewrite the theme header. 3413 $stylelines = explode( "\n", implode( '', file( "$site_dir/style.css" ) ) ); 3414 if ( $stylelines ) { 3415 $f = fopen( "$site_dir/style.css", 'w' ); 3416 3417 $headers = array( 3418 'Theme Name:' => $theme_name, 3419 'Theme URI:' => __get_option( 'url' ), 3420 'Description:' => 'Your theme.', 3421 'Version:' => '1', 3422 'Author:' => 'You', 3423 ); 3424 3425 foreach ( $stylelines as $line ) { 3426 foreach ( $headers as $header => $value ) { 3427 if ( str_contains( $line, $header ) ) { 3428 $line = $header . ' ' . $value; 3429 break; 3430 } 3431 } 3432 3433 fwrite( $f, $line . "\n" ); 3434 } 3435 3436 fclose( $f ); 3437 } 3438 3439 // Copy the images. 3440 umask( 0 ); 3441 if ( ! mkdir( "$site_dir/images", 0777 ) ) { 3442 return false; 3443 } 3444 3445 $images_dir = @opendir( "$default_dir/images" ); 3446 if ( $images_dir ) { 3447 while ( ( $image = readdir( $images_dir ) ) !== false ) { 3448 if ( is_dir( "$default_dir/images/$image" ) ) { 3449 continue; 3450 } 3451 3452 if ( ! copy( "$default_dir/images/$image", "$site_dir/images/$image" ) ) { 3453 return; 3454 } 3455 3456 chmod( "$site_dir/images/$image", 0777 ); 3457 } 3458 3459 closedir( $images_dir ); 3460 } 3461 } 3462 3463 /** 3464 * Creates a site theme. 3465 * 3466 * {@internal Missing Long Description}} 3467 * 3468 * @since 1.5.0 3469 * 3470 * @return string|false 3471 */ 3472 function make_site_theme() { 3473 // Name the theme after the blog. 3474 $theme_name = __get_option( 'blogname' ); 3475 $template = sanitize_title( $theme_name ); 3476 $site_dir = WP_CONTENT_DIR . "/themes/$template"; 3477 3478 // If the theme already exists, nothing to do. 3479 if ( is_dir( $site_dir ) ) { 3480 return false; 3481 } 3482 3483 // We must be able to write to the themes dir. 3484 if ( ! is_writable( WP_CONTENT_DIR . '/themes' ) ) { 3485 return false; 3486 } 3487 3488 umask( 0 ); 3489 if ( ! mkdir( $site_dir, 0777 ) ) { 3490 return false; 3491 } 3492 3493 if ( file_exists( ABSPATH . 'wp-layout.css' ) ) { 3494 if ( ! make_site_theme_from_oldschool( $theme_name, $template ) ) { 3495 // TODO: rm -rf the site theme directory. 3496 return false; 3497 } 3498 } else { 3499 if ( ! make_site_theme_from_default( $theme_name, $template ) ) { 3500 // TODO: rm -rf the site theme directory. 3501 return false; 3502 } 3503 } 3504 3505 // Make the new site theme active. 3506 $current_template = __get_option( 'template' ); 3507 if ( WP_DEFAULT_THEME == $current_template ) { 3508 update_option( 'template', $template ); 3509 update_option( 'stylesheet', $template ); 3510 } 3511 return $template; 3512 } 3513 3514 /** 3515 * Translate user level to user role name. 3516 * 3517 * @since 2.0.0 3518 * 3519 * @param int $level User level. 3520 * @return string User role name. 3521 */ 3522 function translate_level_to_role( $level ) { 3523 switch ( $level ) { 3524 case 10: 3525 case 9: 3526 case 8: 3527 return 'administrator'; 3528 case 7: 3529 case 6: 3530 case 5: 3531 return 'editor'; 3532 case 4: 3533 case 3: 3534 case 2: 3535 return 'author'; 3536 case 1: 3537 return 'contributor'; 3538 case 0: 3539 default: 3540 return 'subscriber'; 3541 } 3542 } 3543 3544 /** 3545 * Checks the version of the installed MySQL binary. 3546 * 3547 * @since 2.1.0 3548 * 3549 * @global wpdb $wpdb WordPress database abstraction object. 3550 */ 3551 function wp_check_mysql_version() { 3552 global $wpdb; 3553 $result = $wpdb->check_database_version(); 3554 if ( is_wp_error( $result ) ) { 3555 wp_die( $result ); 3556 } 3557 } 3558 3559 /** 3560 * Disables the Automattic widgets plugin, which was merged into core. 3561 * 3562 * @since 2.2.0 3563 */ 3564 function maybe_disable_automattic_widgets() { 3565 $plugins = __get_option( 'active_plugins' ); 3566 3567 foreach ( (array) $plugins as $plugin ) { 3568 if ( 'widgets.php' === basename( $plugin ) ) { 3569 array_splice( $plugins, array_search( $plugin, $plugins, true ), 1 ); 3570 update_option( 'active_plugins', $plugins ); 3571 break; 3572 } 3573 } 3574 } 3575 3576 /** 3577 * Disables the Link Manager on upgrade if, at the time of upgrade, no links exist in the DB. 3578 * 3579 * @since 3.5.0 3580 * 3581 * @global int $wp_current_db_version The old (current) database version. 3582 * @global wpdb $wpdb WordPress database abstraction object. 3583 */ 3584 function maybe_disable_link_manager() { 3585 global $wp_current_db_version, $wpdb; 3586 3587 if ( $wp_current_db_version >= 22006 && get_option( 'link_manager_enabled' ) && ! $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) { 3588 update_option( 'link_manager_enabled', 0 ); 3589 } 3590 } 3591 3592 /** 3593 * Runs before the schema is upgraded. 3594 * 3595 * @since 2.9.0 3596 * 3597 * @global int $wp_current_db_version The old (current) database version. 3598 * @global wpdb $wpdb WordPress database abstraction object. 3599 */ 3600 function pre_schema_upgrade() { 3601 global $wp_current_db_version, $wpdb; 3602 3603 // Upgrade versions prior to 2.9. 3604 if ( $wp_current_db_version < 11557 ) { 3605 // Delete duplicate options. Keep the option with the highest option_id. 3606 $wpdb->query( "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (`option_name`) WHERE o2.option_id > o1.option_id" ); 3607 3608 // Drop the old primary key and add the new. 3609 $wpdb->query( "ALTER TABLE $wpdb->options DROP PRIMARY KEY, ADD PRIMARY KEY(option_id)" ); 3610 3611 // Drop the old option_name index. dbDelta() doesn't do the drop. 3612 $wpdb->query( "ALTER TABLE $wpdb->options DROP INDEX option_name" ); 3613 } 3614 3615 // Multisite schema upgrades. 3616 if ( $wp_current_db_version < 25448 && is_multisite() && wp_should_upgrade_global_tables() ) { 3617 3618 // Upgrade versions prior to 3.7. 3619 if ( $wp_current_db_version < 25179 ) { 3620 // New primary key for signups. 3621 $wpdb->query( "ALTER TABLE $wpdb->signups ADD signup_id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST" ); 3622 $wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain" ); 3623 } 3624 3625 if ( $wp_current_db_version < 25448 ) { 3626 // Convert archived from enum to tinyint. 3627 $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived varchar(1) NOT NULL default '0'" ); 3628 $wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived tinyint(2) NOT NULL default 0" ); 3629 } 3630 } 3631 3632 // Upgrade versions prior to 4.2. 3633 if ( $wp_current_db_version < 31351 ) { 3634 if ( ! is_multisite() && wp_should_upgrade_global_tables() ) { 3635 $wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 3636 } 3637 $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX slug, ADD INDEX slug(slug(191))" ); 3638 $wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX name, ADD INDEX name(name(191))" ); 3639 $wpdb->query( "ALTER TABLE $wpdb->commentmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 3640 $wpdb->query( "ALTER TABLE $wpdb->postmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 3641 $wpdb->query( "ALTER TABLE $wpdb->posts DROP INDEX post_name, ADD INDEX post_name(post_name(191))" ); 3642 } 3643 3644 // Upgrade versions prior to 4.4. 3645 if ( $wp_current_db_version < 34978 ) { 3646 // If compatible termmeta table is found, use it, but enforce a proper index and update collation. 3647 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->termmeta}'" ) && $wpdb->get_results( "SHOW INDEX FROM {$wpdb->termmeta} WHERE Column_name = 'meta_key'" ) ) { 3648 $wpdb->query( "ALTER TABLE $wpdb->termmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" ); 3649 maybe_convert_table_to_utf8mb4( $wpdb->termmeta ); 3650 } 3651 } 3652 } 3653 3654 /** 3655 * Determine if global tables should be upgraded. 3656 * 3657 * This function performs a series of checks to ensure the environment allows 3658 * for the safe upgrading of global WordPress database tables. It is necessary 3659 * because global tables will commonly grow to millions of rows on large 3660 * installations, and the ability to control their upgrade routines can be 3661 * critical to the operation of large networks. 3662 * 3663 * In a future iteration, this function may use `wp_is_large_network()` to more- 3664 * intelligently prevent global table upgrades. Until then, we make sure 3665 * WordPress is on the main site of the main network, to avoid running queries 3666 * more than once in multi-site or multi-network environments. 3667 * 3668 * @since 4.3.0 3669 * 3670 * @return bool Whether to run the upgrade routines on global tables. 3671 */ 3672 function wp_should_upgrade_global_tables() { 3673 3674 // Return false early if explicitly not upgrading. 3675 if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) { 3676 return false; 3677 } 3678 3679 // Assume global tables should be upgraded. 3680 $should_upgrade = true; 3681 3682 // Set to false if not on main network (does not matter if not multi-network). 3683 if ( ! is_main_network() ) { 3684 $should_upgrade = false; 3685 } 3686 3687 // Set to false if not on main site of current network (does not matter if not multi-site). 3688 if ( ! is_main_site() ) { 3689 $should_upgrade = false; 3690 } 3691 3692 /** 3693 * Filters if upgrade routines should be run on global tables. 3694 * 3695 * @since 4.3.0 3696 * 3697 * @param bool $should_upgrade Whether to run the upgrade routines on global tables. 3698 */ 3699 return apply_filters( 'wp_should_upgrade_global_tables', $should_upgrade ); 3700 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Apr 18 08:20:02 2024 | Cross-referenced by PHPXref |