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