* Most of the functions are pluggable and can be overwritten.
* @subpackage Administration
/** Include user installation customization script. */
if ( file_exists( WP_CONTENT_DIR . '/install.php' ) ) {
require WP_CONTENT_DIR . '/install.php';
/** WordPress Administration API */
require_once ABSPATH . 'wp-admin/includes/admin.php';
/** WordPress Schema API */
require_once ABSPATH . 'wp-admin/includes/schema.php';
if ( ! function_exists( 'wp_install' ) ) :
* Runs the required functions to set up and populate the database,
* including primary admin user and initial options.
* @param string $blog_title Site title.
* @param string $user_name User's username.
* @param string $user_email User's email.
* @param bool $public Whether site is public.
* @param string $deprecated Optional. Not used.
* @param string $user_password Optional. User's chosen password. Default empty (random password).
* @param string $language Optional. Language chosen. Default empty.
* Data for the newly installed site.
* @type string $url The URL of the site.
* @type int $user_id The ID of the site owner.
* @type string $password The password of the site owner, if their user account didn't already exist.
* @type string $password_message The explanatory message regarding the password.
function wp_install( $blog_title, $user_name, $user_email, $public, $deprecated = '', $user_password = '', $language = '' ) {
if ( ! empty( $deprecated ) ) {
_deprecated_argument( __FUNCTION__, '2.6.0' );
wp_check_mysql_version();
make_db_current_silent();
update_option( 'blogname', $blog_title );
update_option( 'admin_email', $user_email );
update_option( 'blog_public', $public );
// Freshness of site - in the future, this could get more specific about actions taken, perhaps.
update_option( 'fresh_site', 1 );
update_option( 'WPLANG', $language );
$guessurl = wp_guess_url();
update_option( 'siteurl', $guessurl );
// If not a public site, don't ping.
update_option( 'default_pingback_flag', 0 );
* Create default user. If the user already exists, the user tables are
* being shared among sites. Just set the role in that case.
$user_id = username_exists( $user_name );
$user_password = trim( $user_password );
if ( ! $user_id && empty( $user_password ) ) {
$user_password = wp_generate_password( 12, false );
$message = __( '<strong><em>Note that password</em></strong> carefully! It is a <em>random</em> password that was generated just for you.' );
$user_id = wp_create_user( $user_name, $user_password, $user_email );
update_user_option( $user_id, 'default_password_nag', true, true );
} elseif ( ! $user_id ) {
// Password has been provided.
$message = '<em>' . __( 'Your chosen password.' ) . '</em>';
$user_id = wp_create_user( $user_name, $user_password, $user_email );
$message = __( 'User already exists. Password inherited.' );
$user = new WP_User( $user_id );
$user->set_role( 'administrator' );
$user->user_url = $guessurl;
wp_install_defaults( $user_id );
wp_install_maybe_enable_pretty_permalinks();
wp_new_blog_notification( $blog_title, $guessurl, $user_id, ( $email_password ? $user_password : __( 'The password you chose during installation.' ) ) );
* Fires after a site is fully installed.
* @param WP_User $user The site owner.
do_action( 'wp_install', $user );
'password' => $user_password,
'password_message' => $message,
if ( ! function_exists( 'wp_install_defaults' ) ) :
* Creates the initial content for a newly-installed site.
* Adds the default "Uncategorized" category, the first post (with comment),
* first page, and default widgets for default theme for the current version.
* @global wpdb $wpdb WordPress database abstraction object.
* @global WP_Rewrite $wp_rewrite WordPress rewrite component.
* @global string $table_prefix
* @param int $user_id User ID.
function wp_install_defaults( $user_id ) {
global $wpdb, $wp_rewrite, $table_prefix;
$cat_name = __( 'Uncategorized' );
/* translators: Default category slug. */
$cat_slug = sanitize_title( _x( 'Uncategorized', 'Default category slug' ) );
if ( global_terms_enabled() ) {
$cat_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM {$wpdb->sitecategories} WHERE category_nicename = %s", $cat_slug ) );
'category_nicename' => $cat_slug,
'last_updated' => current_time( 'mysql', true ),
$cat_id = $wpdb->insert_id;
update_option( 'default_category', $cat_id );
'taxonomy' => 'category',
$cat_tt_id = $wpdb->insert_id;
$now = current_time( 'mysql' );
$now_gmt = current_time( 'mysql', 1 );
$first_post_guid = get_option( 'home' ) . '/?p=1';
$first_post = get_site_option( 'first_post' );
$first_post = "<!-- wp:paragraph -->\n<p>" .
/* translators: First post content. %s: Site link. */
__( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ) .
"</p>\n<!-- /wp:paragraph -->";
sprintf( '<a href="%s">%s</a>', esc_url( network_home_url() ), get_network()->site_name )
// Back-compat for pre-4.4.
$first_post = str_replace( 'SITE_URL', esc_url( network_home_url() ), $first_post );
$first_post = str_replace( 'SITE_NAME', get_network()->site_name, $first_post );
$first_post = "<!-- wp:paragraph -->\n<p>" .
/* translators: First post content. %s: Site link. */
__( 'Welcome to WordPress. This is your first post. Edit or delete it, then start writing!' ) .
"</p>\n<!-- /wp:paragraph -->";
'post_author' => $user_id,
'post_date_gmt' => $now_gmt,
'post_content' => $first_post,
'post_title' => __( 'Hello world!' ),
/* translators: Default post slug. */
'post_name' => sanitize_title( _x( 'hello-world', 'Default post slug' ) ),
'post_modified_gmt' => $now_gmt,
'guid' => $first_post_guid,
'post_content_filtered' => '',
$wpdb->term_relationships,
'term_taxonomy_id' => $cat_tt_id,
$first_comment_author = get_site_option( 'first_comment_author' );
$first_comment_email = get_site_option( 'first_comment_email' );
$first_comment_url = get_site_option( 'first_comment_url', network_home_url() );
$first_comment = get_site_option( 'first_comment' );
$first_comment_author = ! empty( $first_comment_author ) ? $first_comment_author : __( 'A WordPress Commenter' );
$first_comment_email = ! empty( $first_comment_email ) ? $first_comment_email : 'wapuu@wordpress.example';
$first_comment_url = ! empty( $first_comment_url ) ? $first_comment_url : 'https://wordpress.org/';
$first_comment = ! empty( $first_comment ) ? $first_comment : __(
To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
Commenter avatars come from <a href="https://gravatar.com">Gravatar</a>.'
'comment_author' => $first_comment_author,
'comment_author_email' => $first_comment_email,
'comment_author_url' => $first_comment_url,
'comment_date_gmt' => $now_gmt,
'comment_content' => $first_comment,
'comment_type' => 'comment',
$first_page = get_site_option( 'first_page' );
if ( empty( $first_page ) ) {
$first_page = "<!-- wp:paragraph -->\n<p>";
/* translators: First page content. */
$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:" );
$first_page .= "</p>\n<!-- /wp:paragraph -->\n\n";
$first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>";
/* translators: First page content. */
$first_page .= __( "Hi there! I'm a bike messenger by day, aspiring actor by night, and this is my website. I live in Los Angeles, have a great dog named Jack, and I like piña coladas. (And gettin' caught in the rain.)" );
$first_page .= "</p></blockquote>\n<!-- /wp:quote -->\n\n";
$first_page .= "<!-- wp:paragraph -->\n<p>";
/* translators: First page content. */
$first_page .= __( '...or something like this:' );
$first_page .= "</p>\n<!-- /wp:paragraph -->\n\n";
$first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\"><p>";
/* translators: First page content. */
$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.' );
$first_page .= "</p></blockquote>\n<!-- /wp:quote -->\n\n";
$first_page .= "<!-- wp:paragraph -->\n<p>";
/* translators: First page content. %s: Site admin URL. */
__( '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!' ),
$first_page .= "</p>\n<!-- /wp:paragraph -->";
$first_post_guid = get_option( 'home' ) . '/?page_id=2';
'post_author' => $user_id,
'post_date_gmt' => $now_gmt,
'post_content' => $first_page,
'comment_status' => 'closed',
'post_title' => __( 'Sample Page' ),
/* translators: Default page slug. */
'post_name' => __( 'sample-page' ),
'post_modified_gmt' => $now_gmt,
'guid' => $first_post_guid,
'post_content_filtered' => '',
'meta_key' => '_wp_page_template',
'meta_value' => 'default',
// Disable by default unless the suggested content is provided.
$privacy_policy_content = get_site_option( 'default_privacy_policy_content' );
if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) {
include_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php';
$privacy_policy_content = WP_Privacy_Policy_Content::get_default_content();
if ( ! empty( $privacy_policy_content ) ) {
$privacy_policy_guid = get_option( 'home' ) . '/?page_id=3';
'post_author' => $user_id,
'post_date_gmt' => $now_gmt,
'post_content' => $privacy_policy_content,
'comment_status' => 'closed',
'post_title' => __( 'Privacy Policy' ),
/* translators: Privacy Policy page slug. */
'post_name' => __( 'privacy-policy' ),
'post_modified_gmt' => $now_gmt,
'guid' => $privacy_policy_guid,
'post_status' => 'draft',
'post_content_filtered' => '',
'meta_key' => '_wp_page_template',
'meta_value' => 'default',
update_option( 'wp_page_for_privacy_policy', 3 );
// Set up default widgets for default theme.
2 => array( 'title' => '' ),
'widget_recent-comments',
2 => array( 'title' => '' ),
'wp_inactive_widgets' => array(),
2 => 'recent-comments-2',
if ( ! is_multisite() ) {
update_user_meta( $user_id, 'show_welcome_panel', 1 );
} elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) ) {
update_user_meta( $user_id, 'show_welcome_panel', 2 );
// Flush rules to pick up the new page.
$wp_rewrite->flush_rules();
$user = new WP_User( $user_id );
$wpdb->update( $wpdb->options, array( 'option_value' => $user->user_email ), array( 'option_name' => 'admin_email' ) );
// Remove all perms except for the login user.
$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'user_level' ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'capabilities' ) );
// Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.)
// TODO: Get previous_blog_id.
if ( ! is_super_admin( $user_id ) && 1 != $user_id ) {