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