Make WordPress Core

source: trunk/src/wp-admin/includes/schema.php

Last change on this file was 62058, checked in by ellatrix, 10 days ago

Real-time collaboration: change to opt-in (off-by-default).

See: https://wordpress.slack.com/archives/C07NVJ51X6K/p1773850504196589.

We are intentionally changing the option name so that it will be off-by-default for everyone, including those that installed a beta release where the feature was on-by-default.

Developed in: https://github.com/WordPress/wordpress-develop/pull/11289.

Fixes #64845.
Props czarate, peterwilsoncc, jorbin.

  • Property svn:eol-style set to native
File size: 44.6 KB
Line 
1<?php
2/**
3 * WordPress Administration Scheme API
4 *
5 * Here we keep the DB structure and option values.
6 *
7 * @package WordPress
8 * @subpackage Administration
9 */
10
11/**
12 * Declare these as global in case schema.php is included from a function.
13 *
14 * @global wpdb   $wpdb            WordPress database abstraction object.
15 * @global array  $wp_queries      Global database queries array.
16 * @global string $charset_collate Database charset and collation.
17 */
18global $wpdb, $wp_queries, $charset_collate;
19
20/**
21 * The database character collate.
22 */
23$charset_collate = $wpdb->get_charset_collate();
24
25/**
26 * Retrieve the SQL for creating database tables.
27 *
28 * @since 3.3.0
29 *
30 * @global wpdb $wpdb WordPress database abstraction object.
31 *
32 * @param string $scope   Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all.
33 * @param int    $blog_id Optional. The site ID for which to retrieve SQL. Default is the current site ID.
34 * @return string The SQL needed to create the requested tables.
35 */
36function wp_get_db_schema( $scope = 'all', $blog_id = null ) {
37        global $wpdb;
38
39        $charset_collate = $wpdb->get_charset_collate();
40
41        if ( $blog_id && (int) $blog_id !== $wpdb->blogid ) {
42                $old_blog_id = $wpdb->set_blog_id( $blog_id );
43        }
44
45        // Engage multisite if in the middle of turning it on from network.php.
46        $is_multisite = is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK );
47
48        /*
49         * Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
50         * As of 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
51         * used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
52         */
53        $max_index_length = 191;
54
55        // Blog-specific tables.
56        $blog_tables = "CREATE TABLE $wpdb->termmeta (
57        meta_id bigint(20) unsigned NOT NULL auto_increment,
58        term_id bigint(20) unsigned NOT NULL default '0',
59        meta_key varchar(255) default NULL,
60        meta_value longtext,
61        PRIMARY KEY  (meta_id),
62        KEY term_id (term_id),
63        KEY meta_key (meta_key($max_index_length))
64) $charset_collate;
65CREATE TABLE $wpdb->terms (
66 term_id bigint(20) unsigned NOT NULL auto_increment,
67 name varchar(200) NOT NULL default '',
68 slug varchar(200) NOT NULL default '',
69 term_group bigint(10) NOT NULL default 0,
70 PRIMARY KEY  (term_id),
71 KEY slug (slug($max_index_length)),
72 KEY name (name($max_index_length))
73) $charset_collate;
74CREATE TABLE $wpdb->term_taxonomy (
75 term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
76 term_id bigint(20) unsigned NOT NULL default 0,
77 taxonomy varchar(32) NOT NULL default '',
78 description longtext NOT NULL,
79 parent bigint(20) unsigned NOT NULL default 0,
80 count bigint(20) NOT NULL default 0,
81 PRIMARY KEY  (term_taxonomy_id),
82 UNIQUE KEY term_id_taxonomy (term_id,taxonomy),
83 KEY taxonomy (taxonomy)
84) $charset_collate;
85CREATE TABLE $wpdb->term_relationships (
86 object_id bigint(20) unsigned NOT NULL default 0,
87 term_taxonomy_id bigint(20) unsigned NOT NULL default 0,
88 term_order int(11) NOT NULL default 0,
89 PRIMARY KEY  (object_id,term_taxonomy_id),
90 KEY term_taxonomy_id (term_taxonomy_id)
91) $charset_collate;
92CREATE TABLE $wpdb->commentmeta (
93        meta_id bigint(20) unsigned NOT NULL auto_increment,
94        comment_id bigint(20) unsigned NOT NULL default '0',
95        meta_key varchar(255) default NULL,
96        meta_value longtext,
97        PRIMARY KEY  (meta_id),
98        KEY comment_id (comment_id),
99        KEY meta_key (meta_key($max_index_length))
100) $charset_collate;
101CREATE TABLE $wpdb->comments (
102        comment_ID bigint(20) unsigned NOT NULL auto_increment,
103        comment_post_ID bigint(20) unsigned NOT NULL default '0',
104        comment_author tinytext NOT NULL,
105        comment_author_email varchar(100) NOT NULL default '',
106        comment_author_url varchar(200) NOT NULL default '',
107        comment_author_IP varchar(100) NOT NULL default '',
108        comment_date datetime NOT NULL default '0000-00-00 00:00:00',
109        comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
110        comment_content text NOT NULL,
111        comment_karma int(11) NOT NULL default '0',
112        comment_approved varchar(20) NOT NULL default '1',
113        comment_agent varchar(255) NOT NULL default '',
114        comment_type varchar(20) NOT NULL default 'comment',
115        comment_parent bigint(20) unsigned NOT NULL default '0',
116        user_id bigint(20) unsigned NOT NULL default '0',
117        PRIMARY KEY  (comment_ID),
118        KEY comment_post_ID (comment_post_ID),
119        KEY comment_approved_date_gmt (comment_approved,comment_date_gmt),
120        KEY comment_date_gmt (comment_date_gmt),
121        KEY comment_parent (comment_parent),
122        KEY comment_author_email (comment_author_email(10))
123) $charset_collate;
124CREATE TABLE $wpdb->links (
125        link_id bigint(20) unsigned NOT NULL auto_increment,
126        link_url varchar(255) NOT NULL default '',
127        link_name varchar(255) NOT NULL default '',
128        link_image varchar(255) NOT NULL default '',
129        link_target varchar(25) NOT NULL default '',
130        link_description varchar(255) NOT NULL default '',
131        link_visible varchar(20) NOT NULL default 'Y',
132        link_owner bigint(20) unsigned NOT NULL default '1',
133        link_rating int(11) NOT NULL default '0',
134        link_updated datetime NOT NULL default '0000-00-00 00:00:00',
135        link_rel varchar(255) NOT NULL default '',
136        link_notes mediumtext NOT NULL,
137        link_rss varchar(255) NOT NULL default '',
138        PRIMARY KEY  (link_id),
139        KEY link_visible (link_visible)
140) $charset_collate;
141CREATE TABLE $wpdb->options (
142        option_id bigint(20) unsigned NOT NULL auto_increment,
143        option_name varchar(191) NOT NULL default '',
144        option_value longtext NOT NULL,
145        autoload varchar(20) NOT NULL default 'yes',
146        PRIMARY KEY  (option_id),
147        UNIQUE KEY option_name (option_name),
148        KEY autoload (autoload)
149) $charset_collate;
150CREATE TABLE $wpdb->postmeta (
151        meta_id bigint(20) unsigned NOT NULL auto_increment,
152        post_id bigint(20) unsigned NOT NULL default '0',
153        meta_key varchar(255) default NULL,
154        meta_value longtext,
155        PRIMARY KEY  (meta_id),
156        KEY post_id (post_id),
157        KEY meta_key (meta_key($max_index_length))
158) $charset_collate;
159CREATE TABLE $wpdb->posts (
160        ID bigint(20) unsigned NOT NULL auto_increment,
161        post_author bigint(20) unsigned NOT NULL default '0',
162        post_date datetime NOT NULL default '0000-00-00 00:00:00',
163        post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
164        post_content longtext NOT NULL,
165        post_title text NOT NULL,
166        post_excerpt text NOT NULL,
167        post_status varchar(20) NOT NULL default 'publish',
168        comment_status varchar(20) NOT NULL default 'open',
169        ping_status varchar(20) NOT NULL default 'open',
170        post_password varchar(255) NOT NULL default '',
171        post_name varchar(200) NOT NULL default '',
172        to_ping text NOT NULL,
173        pinged text NOT NULL,
174        post_modified datetime NOT NULL default '0000-00-00 00:00:00',
175        post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
176        post_content_filtered longtext NOT NULL,
177        post_parent bigint(20) unsigned NOT NULL default '0',
178        guid varchar(255) NOT NULL default '',
179        menu_order int(11) NOT NULL default '0',
180        post_type varchar(20) NOT NULL default 'post',
181        post_mime_type varchar(100) NOT NULL default '',
182        comment_count bigint(20) NOT NULL default '0',
183        PRIMARY KEY  (ID),
184        KEY post_name (post_name($max_index_length)),
185        KEY type_status_date (post_type,post_status,post_date,ID),
186        KEY post_parent (post_parent),
187        KEY post_author (post_author),
188        KEY type_status_author (post_type,post_status,post_author)
189) $charset_collate;\n";
190
191        // Single site users table. The multisite flavor of the users table is handled below.
192        $users_single_table = "CREATE TABLE $wpdb->users (
193        ID bigint(20) unsigned NOT NULL auto_increment,
194        user_login varchar(60) NOT NULL default '',
195        user_pass varchar(255) NOT NULL default '',
196        user_nicename varchar(50) NOT NULL default '',
197        user_email varchar(100) NOT NULL default '',
198        user_url varchar(100) NOT NULL default '',
199        user_registered datetime NOT NULL default '0000-00-00 00:00:00',
200        user_activation_key varchar(255) NOT NULL default '',
201        user_status int(11) NOT NULL default '0',
202        display_name varchar(250) NOT NULL default '',
203        PRIMARY KEY  (ID),
204        KEY user_login_key (user_login),
205        KEY user_nicename (user_nicename),
206        KEY user_email (user_email)
207) $charset_collate;\n";
208
209        // Multisite users table.
210        $users_multi_table = "CREATE TABLE $wpdb->users (
211        ID bigint(20) unsigned NOT NULL auto_increment,
212        user_login varchar(60) NOT NULL default '',
213        user_pass varchar(255) NOT NULL default '',
214        user_nicename varchar(50) NOT NULL default '',
215        user_email varchar(100) NOT NULL default '',
216        user_url varchar(100) NOT NULL default '',
217        user_registered datetime NOT NULL default '0000-00-00 00:00:00',
218        user_activation_key varchar(255) NOT NULL default '',
219        user_status int(11) NOT NULL default '0',
220        display_name varchar(250) NOT NULL default '',
221        spam tinyint(2) NOT NULL default '0',
222        deleted tinyint(2) NOT NULL default '0',
223        PRIMARY KEY  (ID),
224        KEY user_login_key (user_login),
225        KEY user_nicename (user_nicename),
226        KEY user_email (user_email)
227) $charset_collate;\n";
228
229        // Usermeta.
230        $usermeta_table = "CREATE TABLE $wpdb->usermeta (
231        umeta_id bigint(20) unsigned NOT NULL auto_increment,
232        user_id bigint(20) unsigned NOT NULL default '0',
233        meta_key varchar(255) default NULL,
234        meta_value longtext,
235        PRIMARY KEY  (umeta_id),
236        KEY user_id (user_id),
237        KEY meta_key (meta_key($max_index_length))
238) $charset_collate;\n";
239
240        // Global tables.
241        if ( $is_multisite ) {
242                $global_tables = $users_multi_table . $usermeta_table;
243        } else {
244                $global_tables = $users_single_table . $usermeta_table;
245        }
246
247        // Multisite global tables.
248        $ms_global_tables = "CREATE TABLE $wpdb->blogs (
249        blog_id bigint(20) unsigned NOT NULL auto_increment,
250        site_id bigint(20) unsigned NOT NULL default '0',
251        domain varchar(200) NOT NULL default '',
252        path varchar(100) NOT NULL default '',
253        registered datetime NOT NULL default '0000-00-00 00:00:00',
254        last_updated datetime NOT NULL default '0000-00-00 00:00:00',
255        public tinyint(2) NOT NULL default '1',
256        archived tinyint(2) NOT NULL default '0',
257        mature tinyint(2) NOT NULL default '0',
258        spam tinyint(2) NOT NULL default '0',
259        deleted tinyint(2) NOT NULL default '0',
260        lang_id int(11) NOT NULL default '0',
261        PRIMARY KEY  (blog_id),
262        KEY domain (domain(50),path(5)),
263        KEY lang_id (lang_id)
264) $charset_collate;
265CREATE TABLE $wpdb->blogmeta (
266        meta_id bigint(20) unsigned NOT NULL auto_increment,
267        blog_id bigint(20) unsigned NOT NULL default '0',
268        meta_key varchar(255) default NULL,
269        meta_value longtext,
270        PRIMARY KEY  (meta_id),
271        KEY meta_key (meta_key($max_index_length)),
272        KEY blog_id (blog_id)
273) $charset_collate;
274CREATE TABLE $wpdb->registration_log (
275        ID bigint(20) unsigned NOT NULL auto_increment,
276        email varchar(255) NOT NULL default '',
277        IP varchar(30) NOT NULL default '',
278        blog_id bigint(20) unsigned NOT NULL default '0',
279        date_registered datetime NOT NULL default '0000-00-00 00:00:00',
280        PRIMARY KEY  (ID),
281        KEY IP (IP)
282) $charset_collate;
283CREATE TABLE $wpdb->site (
284        id bigint(20) unsigned NOT NULL auto_increment,
285        domain varchar(200) NOT NULL default '',
286        path varchar(100) NOT NULL default '',
287        PRIMARY KEY  (id),
288        KEY domain (domain(140),path(51))
289) $charset_collate;
290CREATE TABLE $wpdb->sitemeta (
291        meta_id bigint(20) unsigned NOT NULL auto_increment,
292        site_id bigint(20) unsigned NOT NULL default '0',
293        meta_key varchar(255) default NULL,
294        meta_value longtext,
295        PRIMARY KEY  (meta_id),
296        KEY meta_key (meta_key($max_index_length)),
297        KEY site_id (site_id)
298) $charset_collate;
299CREATE TABLE $wpdb->signups (
300        signup_id bigint(20) unsigned NOT NULL auto_increment,
301        domain varchar(200) NOT NULL default '',
302        path varchar(100) NOT NULL default '',
303        title longtext NOT NULL,
304        user_login varchar(60) NOT NULL default '',
305        user_email varchar(100) NOT NULL default '',
306        registered datetime NOT NULL default '0000-00-00 00:00:00',
307        activated datetime NOT NULL default '0000-00-00 00:00:00',
308        active tinyint(1) NOT NULL default '0',
309        activation_key varchar(50) NOT NULL default '',
310        meta longtext,
311        PRIMARY KEY  (signup_id),
312        KEY activation_key (activation_key),
313        KEY user_email (user_email),
314        KEY user_login_email (user_login,user_email),
315        KEY domain_path (domain(140),path(51))
316) $charset_collate;";
317
318        switch ( $scope ) {
319                case 'blog':
320                        $queries = $blog_tables;
321                        break;
322                case 'global':
323                        $queries = $global_tables;
324                        if ( $is_multisite ) {
325                                $queries .= $ms_global_tables;
326                        }
327                        break;
328                case 'ms_global':
329                        $queries = $ms_global_tables;
330                        break;
331                case 'all':
332                default:
333                        $queries = $global_tables . $blog_tables;
334                        if ( $is_multisite ) {
335                                $queries .= $ms_global_tables;
336                        }
337                        break;
338        }
339
340        if ( isset( $old_blog_id ) ) {
341                $wpdb->set_blog_id( $old_blog_id );
342        }
343
344        return $queries;
345}
346
347// Populate for back compat.
348$wp_queries = wp_get_db_schema( 'all' );
349
350/**
351 * Create WordPress options and set the default values.
352 *
353 * @since 1.5.0
354 * @since 5.1.0 The $options parameter has been added.
355 *
356 * @global wpdb $wpdb                  WordPress database abstraction object.
357 * @global int  $wp_db_version         WordPress database version.
358 * @global int  $wp_current_db_version The old (current) database version.
359 *
360 * @param array $options Optional. Custom option $key => $value pairs to use. Default empty array.
361 */
362function populate_options( array $options = array() ) {
363        global $wpdb, $wp_db_version, $wp_current_db_version;
364
365        $guessurl = wp_guess_url();
366        /**
367         * Fires before creating WordPress options and populating their default values.
368         *
369         * @since 2.6.0
370         */
371        do_action( 'populate_options' );
372
373        // If WP_DEFAULT_THEME doesn't exist, fall back to the latest core default theme.
374        $stylesheet = WP_DEFAULT_THEME;
375        $template   = WP_DEFAULT_THEME;
376        $theme      = wp_get_theme( WP_DEFAULT_THEME );
377        if ( ! $theme->exists() ) {
378                $theme = WP_Theme::get_core_default_theme();
379        }
380
381        // If we can't find a core default theme, WP_DEFAULT_THEME is the best we can do.
382        if ( $theme ) {
383                $stylesheet = $theme->get_stylesheet();
384                $template   = $theme->get_template();
385        }
386
387        $timezone_string = '';
388        $gmt_offset      = 0;
389        /*
390         * translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
391         * or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php
392         * for all timezone strings currently supported by PHP.
393         *
394         * Important: When a previous timezone string, like `Europe/Kiev`, has been superseded by an
395         * updated one, like `Europe/Kyiv`, as a rule of thumb, the **old** timezone name should be used
396         * in the "translation" to allow for the default timezone setting to be PHP cross-version compatible,
397         * as old timezone names will be recognized in new PHP versions, while new timezone names cannot
398         * be recognized in old PHP versions.
399         *
400         * To verify which timezone strings are available in the _oldest_ PHP version supported, you can
401         * use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
402         * country code for which you want to look up the supported timezone names.
403         */
404        $offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
405        if ( is_numeric( $offset_or_tz ) ) {
406                $gmt_offset = $offset_or_tz;
407        } elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
408                $timezone_string = $offset_or_tz;
409        }
410
411        $defaults = array(
412                'siteurl'                         => $guessurl,
413                'home'                            => $guessurl,
414                'blogname'                        => __( 'My Site' ),
415                'blogdescription'                 => '',
416                'users_can_register'              => 0,
417                'admin_email'                     => '[email protected]',
418                /* translators: Default start of the week. 0 = Sunday, 1 = Monday. */
419                'start_of_week'                   => _x( '1', 'start of week' ),
420                'use_balanceTags'                 => 0,
421                'use_smilies'                     => 1,
422                'require_name_email'              => 1,
423                'comments_notify'                 => 1,
424                'posts_per_rss'                   => 10,
425                'rss_use_excerpt'                 => 0,
426                'mailserver_url'                  => 'mail.example.com',
427                'mailserver_login'                => '[email protected]',
428                'mailserver_pass'                 => '',
429                'mailserver_port'                 => 110,
430                'default_category'                => 1,
431                'default_comment_status'          => 'open',
432                'default_ping_status'             => 'open',
433                'default_pingback_flag'           => 1,
434                'posts_per_page'                  => 10,
435                /* translators: Default date format, see https://www.php.net/manual/datetime.format.php */
436                'date_format'                     => __( 'F j, Y' ),
437                /* translators: Default time format, see https://www.php.net/manual/datetime.format.php */
438                'time_format'                     => __( 'g:i a' ),
439                /* translators: Links last updated date format, see https://www.php.net/manual/datetime.format.php */
440                'links_updated_date_format'       => __( 'F j, Y g:i a' ),
441                'comment_moderation'              => 0,
442                'moderation_notify'               => 1,
443                'permalink_structure'             => '',
444                'rewrite_rules'                   => '',
445                'hack_file'                       => 0,
446                'blog_charset'                    => 'UTF-8',
447                'moderation_keys'                 => '',
448                'active_plugins'                  => array(),
449                'category_base'                   => '',
450                'ping_sites'                      => 'https://rpc.pingomatic.com/',
451                'comment_max_links'               => 2,
452                'gmt_offset'                      => $gmt_offset,
453
454                // 1.5.0
455                'default_email_category'          => 1,
456                'recently_edited'                 => '',
457                'template'                        => $template,
458                'stylesheet'                      => $stylesheet,
459                'comment_registration'            => 0,
460                'html_type'                       => 'text/html',
461
462                // 1.5.1
463                'use_trackback'                   => 0,
464
465                // 2.0.0
466                'default_role'                    => 'subscriber',
467                'db_version'                      => $wp_db_version,
468
469                // 2.0.1
470                'uploads_use_yearmonth_folders'   => 1,
471                'upload_path'                     => '',
472
473                // 2.1.0
474                'blog_public'                     => '1',
475                'default_link_category'           => 2,
476                'show_on_front'                   => 'posts',
477
478                // 2.2.0
479                'tag_base'                        => '',
480
481                // 2.5.0
482                'show_avatars'                    => '1',
483                'avatar_rating'                   => 'G',
484                'upload_url_path'                 => '',
485                'thumbnail_size_w'                => 150,
486                'thumbnail_size_h'                => 150,
487                'thumbnail_crop'                  => 1,
488                'medium_size_w'                   => 300,
489                'medium_size_h'                   => 300,
490
491                // 2.6.0
492                'avatar_default'                  => 'mystery',
493
494                // 2.7.0
495                'large_size_w'                    => 1024,
496                'large_size_h'                    => 1024,
497                'image_default_link_type'         => 'none',
498                'image_default_size'              => '',
499                'image_default_align'             => '',
500                'close_comments_for_old_posts'    => 0,
501                'close_comments_days_old'         => 14,
502                'thread_comments'                 => 1,
503                'thread_comments_depth'           => 5,
504                'page_comments'                   => 0,
505                'comments_per_page'               => 50,
506                'default_comments_page'           => 'newest',
507                'comment_order'                   => 'asc',
508                'sticky_posts'                    => array(),
509                'widget_categories'               => array(),
510                'widget_text'                     => array(),
511                'widget_rss'                      => array(),
512                'uninstall_plugins'               => array(),
513
514                // 2.8.0
515                'timezone_string'                 => $timezone_string,
516
517                // 3.0.0
518                'page_for_posts'                  => 0,
519                'page_on_front'                   => 0,
520
521                // 3.1.0
522                'default_post_format'             => 0,
523
524                // 3.5.0
525                'link_manager_enabled'            => 0,
526
527                // 4.3.0
528                'finished_splitting_shared_terms' => 1,
529                'site_icon'                       => 0,
530
531                // 4.4.0
532                'medium_large_size_w'             => 768,
533                'medium_large_size_h'             => 0,
534
535                // 4.9.6
536                'wp_page_for_privacy_policy'      => 0,
537
538                // 4.9.8
539                'show_comments_cookies_opt_in'    => 1,
540
541                // 5.3.0
542                'admin_email_lifespan'            => ( time() + 6 * MONTH_IN_SECONDS ),
543
544                // 5.5.0
545                'disallowed_keys'                 => '',
546                'comment_previously_approved'     => 1,
547                'auto_plugin_theme_update_emails' => array(),
548
549                // 5.6.0
550                'auto_update_core_dev'            => 'enabled',
551                'auto_update_core_minor'          => 'enabled',
552                /*
553                 * Default to enabled for new installs.
554                 * See https://core.trac.wordpress.org/ticket/51742.
555                 */
556                'auto_update_core_major'          => 'enabled',
557
558                // 5.8.0
559                'wp_force_deactivated_plugins'    => array(),
560
561                // 6.4.0
562                'wp_attachment_pages_enabled'     => 0,
563
564                // 6.9.0
565                'wp_notes_notify'                 => 1,
566
567                // 7.0.0
568                'wp_collaboration_enabled'        => 0,
569        );
570
571        // 3.3.0
572        if ( ! is_multisite() ) {
573                $defaults['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version
574                        ? $wp_current_db_version : $wp_db_version;
575        }
576
577        // 3.0.0 multisite.
578        if ( is_multisite() ) {
579                $defaults['permalink_structure'] = '/%year%/%monthnum%/%day%/%postname%/';
580        }
581
582        $options = wp_parse_args( $options, $defaults );
583
584        // Set autoload to no for these options.
585        $fat_options = array(
586                'moderation_keys',
587                'recently_edited',
588                'disallowed_keys',
589                'uninstall_plugins',
590                'auto_plugin_theme_update_emails',
591        );
592
593        $keys             = "'" . implode( "', '", array_keys( $options ) ) . "'";
594        $existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
595
596        $insert = '';
597
598        foreach ( $options as $option => $value ) {
599                if ( in_array( $option, $existing_options, true ) ) {
600                        continue;
601                }
602
603                if ( in_array( $option, $fat_options, true ) ) {
604                        $autoload = 'off';
605                } else {
606                        $autoload = 'on';
607                }
608
609                if ( ! empty( $insert ) ) {
610                        $insert .= ', ';
611                }
612
613                $value = maybe_serialize( sanitize_option( $option, $value ) );
614
615                $insert .= $wpdb->prepare( '(%s, %s, %s)', $option, $value, $autoload );
616        }
617
618        if ( ! empty( $insert ) ) {
619                $wpdb->query( "INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
620        }
621
622        // In case it is set, but blank, update "home".
623        if ( ! __get_option( 'home' ) ) {
624                update_option( 'home', $guessurl );
625        }
626
627        // Delete unused options.
628        $unusedoptions = array(
629                'blodotgsping_url',
630                'bodyterminator',
631                'emailtestonly',
632                'phoneemail_separator',
633                'smilies_directory',
634                'subjectprefix',
635                'use_bbcode',
636                'use_blodotgsping',
637                'use_phoneemail',
638                'use_quicktags',
639                'use_weblogsping',
640                'weblogs_cache_file',
641                'use_preview',
642                'use_htmltrans',
643                'smilies_directory',
644                'fileupload_allowedusers',
645                'use_phoneemail',
646                'default_post_status',
647                'default_post_category',
648                'archive_mode',
649                'time_difference',
650                'links_minadminlevel',
651                'links_use_adminlevels',
652                'links_rating_type',
653                'links_rating_char',
654                'links_rating_ignore_zero',
655                'links_rating_single_image',
656                'links_rating_image0',
657                'links_rating_image1',
658                'links_rating_image2',
659                'links_rating_image3',
660                'links_rating_image4',
661                'links_rating_image5',
662                'links_rating_image6',
663                'links_rating_image7',
664                'links_rating_image8',
665                'links_rating_image9',
666                'links_recently_updated_time',
667                'links_recently_updated_prepend',
668                'links_recently_updated_append',
669                'weblogs_cacheminutes',
670                'comment_allowed_tags',
671                'search_engine_friendly_urls',
672                'default_geourl_lat',
673                'default_geourl_lon',
674                'use_default_geourl',
675                'weblogs_xml_url',
676                'new_users_can_blog',
677                '_wpnonce',
678                '_wp_http_referer',
679                'Update',
680                'action',
681                'rich_editing',
682                'autosave_interval',
683                'deactivated_plugins',
684                'can_compress_scripts',
685                'page_uris',
686                'update_core',
687                'update_plugins',
688                'update_themes',
689                'doing_cron',
690                'random_seed',
691                'rss_excerpt_length',
692                'secret',
693                'use_linksupdate',
694                'default_comment_status_page',
695                'wporg_popular_tags',
696                'what_to_show',
697                'rss_language',
698                'language',
699                'enable_xmlrpc',
700                'enable_app',
701                'embed_autourls',
702                'default_post_edit_rows',
703                'gzipcompression',
704                'advanced_edit',
705        );
706        foreach ( $unusedoptions as $option ) {
707                delete_option( $option );
708        }
709
710        // Delete obsolete magpie stuff.
711        $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'" );
712
713        // Clear expired transients.
714        delete_expired_transients( true );
715}
716
717/**
718 * Execute WordPress role creation for the various WordPress versions.
719 *
720 * @since 2.0.0
721 */
722function populate_roles() {
723        $wp_roles = wp_roles();
724
725        // Disable role updates to the database while populating roles.
726        $original_use_db  = $wp_roles->use_db;
727        $wp_roles->use_db = false;
728
729        // Populate roles
730        populate_roles_160();
731        populate_roles_210();
732        populate_roles_230();
733        populate_roles_250();
734        populate_roles_260();
735        populate_roles_270();
736        populate_roles_280();
737        populate_roles_300();
738
739        // Save the updated roles to the database.
740        if ( $original_use_db ) {
741                update_option( $wp_roles->role_key, $wp_roles->roles, true );
742        }
743
744        // Restore original value for writing to database.
745        $wp_roles->use_db = $original_use_db;
746}
747
748/**
749 * Create the roles for WordPress 2.0
750 *
751 * @since 2.0.0
752 */
753function populate_roles_160() {
754        // Add roles.
755        add_role( 'administrator', 'Administrator' );
756        add_role( 'editor', 'Editor' );
757        add_role( 'author', 'Author' );
758        add_role( 'contributor', 'Contributor' );
759        add_role( 'subscriber', 'Subscriber' );
760
761        // Add caps for Administrator role.
762        $role = get_role( 'administrator' );
763        $role->add_cap( 'switch_themes' );
764        $role->add_cap( 'edit_themes' );
765        $role->add_cap( 'activate_plugins' );
766        $role->add_cap( 'edit_plugins' );
767        $role->add_cap( 'edit_users' );
768        $role->add_cap( 'edit_files' );
769        $role->add_cap( 'manage_options' );
770        $role->add_cap( 'moderate_comments' );
771        $role->add_cap( 'manage_categories' );
772        $role->add_cap( 'manage_links' );
773        $role->add_cap( 'upload_files' );
774        $role->add_cap( 'import' );
775        $role->add_cap( 'unfiltered_html' );
776        $role->add_cap( 'edit_posts' );
777        $role->add_cap( 'edit_others_posts' );
778        $role->add_cap( 'edit_published_posts' );
779        $role->add_cap( 'publish_posts' );
780        $role->add_cap( 'edit_pages' );
781        $role->add_cap( 'read' );
782        $role->add_cap( 'level_10' );
783        $role->add_cap( 'level_9' );
784        $role->add_cap( 'level_8' );
785        $role->add_cap( 'level_7' );
786        $role->add_cap( 'level_6' );
787        $role->add_cap( 'level_5' );
788        $role->add_cap( 'level_4' );
789        $role->add_cap( 'level_3' );
790        $role->add_cap( 'level_2' );
791        $role->add_cap( 'level_1' );
792        $role->add_cap( 'level_0' );
793
794        // Add caps for Editor role.
795        $role = get_role( 'editor' );
796        $role->add_cap( 'moderate_comments' );
797        $role->add_cap( 'manage_categories' );
798        $role->add_cap( 'manage_links' );
799        $role->add_cap( 'upload_files' );
800        $role->add_cap( 'unfiltered_html' );
801        $role->add_cap( 'edit_posts' );
802        $role->add_cap( 'edit_others_posts' );
803        $role->add_cap( 'edit_published_posts' );
804        $role->add_cap( 'publish_posts' );
805        $role->add_cap( 'edit_pages' );
806        $role->add_cap( 'read' );
807        $role->add_cap( 'level_7' );
808        $role->add_cap( 'level_6' );
809        $role->add_cap( 'level_5' );
810        $role->add_cap( 'level_4' );
811        $role->add_cap( 'level_3' );
812        $role->add_cap( 'level_2' );
813        $role->add_cap( 'level_1' );
814        $role->add_cap( 'level_0' );
815
816        // Add caps for Author role.
817        $role = get_role( 'author' );
818        $role->add_cap( 'upload_files' );
819        $role->add_cap( 'edit_posts' );
820        $role->add_cap( 'edit_published_posts' );
821        $role->add_cap( 'publish_posts' );
822        $role->add_cap( 'read' );
823        $role->add_cap( 'level_2' );
824        $role->add_cap( 'level_1' );
825        $role->add_cap( 'level_0' );
826
827        // Add caps for Contributor role.
828        $role = get_role( 'contributor' );
829        $role->add_cap( 'edit_posts' );
830        $role->add_cap( 'read' );
831        $role->add_cap( 'level_1' );
832        $role->add_cap( 'level_0' );
833
834        // Add caps for Subscriber role.
835        $role = get_role( 'subscriber' );
836        $role->add_cap( 'read' );
837        $role->add_cap( 'level_0' );
838}
839
840/**
841 * Create and modify WordPress roles for WordPress 2.1.
842 *
843 * @since 2.1.0
844 */
845function populate_roles_210() {
846        $roles = array( 'administrator', 'editor' );
847        foreach ( $roles as $role ) {
848                $role = get_role( $role );
849                if ( empty( $role ) ) {
850                        continue;
851                }
852
853                $role->add_cap( 'edit_others_pages' );
854                $role->add_cap( 'edit_published_pages' );
855                $role->add_cap( 'publish_pages' );
856                $role->add_cap( 'delete_pages' );
857                $role->add_cap( 'delete_others_pages' );
858                $role->add_cap( 'delete_published_pages' );
859                $role->add_cap( 'delete_posts' );
860                $role->add_cap( 'delete_others_posts' );
861                $role->add_cap( 'delete_published_posts' );
862                $role->add_cap( 'delete_private_posts' );
863                $role->add_cap( 'edit_private_posts' );
864                $role->add_cap( 'read_private_posts' );
865                $role->add_cap( 'delete_private_pages' );
866                $role->add_cap( 'edit_private_pages' );
867                $role->add_cap( 'read_private_pages' );
868        }
869
870        $role = get_role( 'administrator' );
871        if ( ! empty( $role ) ) {
872                $role->add_cap( 'delete_users' );
873                $role->add_cap( 'create_users' );
874        }
875
876        $role = get_role( 'author' );
877        if ( ! empty( $role ) ) {
878                $role->add_cap( 'delete_posts' );
879                $role->add_cap( 'delete_published_posts' );
880        }
881
882        $role = get_role( 'contributor' );
883        if ( ! empty( $role ) ) {
884                $role->add_cap( 'delete_posts' );
885        }
886}
887
888/**
889 * Create and modify WordPress roles for WordPress 2.3.
890 *
891 * @since 2.3.0
892 */
893function populate_roles_230() {
894        $role = get_role( 'administrator' );
895
896        if ( ! empty( $role ) ) {
897                $role->add_cap( 'unfiltered_upload' );
898        }
899}
900
901/**
902 * Create and modify WordPress roles for WordPress 2.5.
903 *
904 * @since 2.5.0
905 */
906function populate_roles_250() {
907        $role = get_role( 'administrator' );
908
909        if ( ! empty( $role ) ) {
910                $role->add_cap( 'edit_dashboard' );
911        }
912}
913
914/**
915 * Create and modify WordPress roles for WordPress 2.6.
916 *
917 * @since 2.6.0
918 */
919function populate_roles_260() {
920        $role = get_role( 'administrator' );
921
922        if ( ! empty( $role ) ) {
923                $role->add_cap( 'update_plugins' );
924                $role->add_cap( 'delete_plugins' );
925        }
926}
927
928/**
929 * Create and modify WordPress roles for WordPress 2.7.
930 *
931 * @since 2.7.0
932 */
933function populate_roles_270() {
934        $role = get_role( 'administrator' );
935
936        if ( ! empty( $role ) ) {
937                $role->add_cap( 'install_plugins' );
938                $role->add_cap( 'update_themes' );
939        }
940}
941
942/**
943 * Create and modify WordPress roles for WordPress 2.8.
944 *
945 * @since 2.8.0
946 */
947function populate_roles_280() {
948        $role = get_role( 'administrator' );
949
950        if ( ! empty( $role ) ) {
951                $role->add_cap( 'install_themes' );
952        }
953}
954
955/**
956 * Create and modify WordPress roles for WordPress 3.0.
957 *
958 * @since 3.0.0
959 */
960function populate_roles_300() {
961        $role = get_role( 'administrator' );
962
963        if ( ! empty( $role ) ) {
964                $role->add_cap( 'update_core' );
965                $role->add_cap( 'list_users' );
966                $role->add_cap( 'remove_users' );
967                $role->add_cap( 'promote_users' );
968                $role->add_cap( 'edit_theme_options' );
969                $role->add_cap( 'delete_themes' );
970                $role->add_cap( 'export' );
971        }
972}
973
974if ( ! function_exists( 'install_network' ) ) :
975        /**
976         * Install Network.
977         *
978         * @since 3.0.0
979         */
980        function install_network() {
981                if ( ! defined( 'WP_INSTALLING_NETWORK' ) ) {
982                        define( 'WP_INSTALLING_NETWORK', true );
983                }
984
985                dbDelta( wp_get_db_schema( 'global' ) );
986        }
987endif;
988
989/**
990 * Populate network settings.
991 *
992 * @since 3.0.0
993 *
994 * @global wpdb       $wpdb         WordPress database abstraction object.
995 * @global object     $current_site
996 * @global WP_Rewrite $wp_rewrite   WordPress rewrite component.
997 *
998 * @param int    $network_id        ID of network to populate.
999 * @param string $domain            The domain name for the network. Example: "example.com".
1000 * @param string $email             Email address for the network administrator.
1001 * @param string $site_name         The name of the network.
1002 * @param string $path              Optional. The path to append to the network's domain name. Default '/'.
1003 * @param bool   $subdomain_install Optional. Whether the network is a subdomain installation or a subdirectory installation.
1004 *                                  Default false, meaning the network is a subdirectory installation.
1005 * @return true|WP_Error True on success, or WP_Error on warning (with the installation otherwise successful,
1006 *                       so the error code must be checked) or failure.
1007 */
1008function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
1009        global $wpdb, $current_site, $wp_rewrite;
1010
1011        $network_id = (int) $network_id;
1012
1013        /**
1014         * Fires before a network is populated.
1015         *
1016         * @since 6.9.0
1017         *
1018         * @param int    $network_id        ID of network to populate.
1019         * @param string $domain            The domain name for the network.
1020         * @param string $email             Email address for the network administrator.
1021         * @param string $site_name         The name of the network.
1022         * @param string $path              The path to append to the network's domain name.
1023         * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
1024         */
1025        do_action( 'before_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
1026
1027        $errors = new WP_Error();
1028        if ( '' === $domain ) {
1029                $errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
1030        }
1031        if ( '' === $site_name ) {
1032                $errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
1033        }
1034
1035        // Check for network collision.
1036        if ( is_multisite() ) {
1037                if ( get_network( $network_id ) ) {
1038                        $errors->add( 'siteid_exists', __( 'The network already exists.' ) );
1039                }
1040        } else {
1041                if ( $network_id === (int) $wpdb->get_var(
1042                        $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id )
1043                ) ) {
1044                        $errors->add( 'siteid_exists', __( 'The network already exists.' ) );
1045                }
1046        }
1047
1048        if ( ! is_email( $email ) ) {
1049                $errors->add( 'invalid_email', __( 'You must provide a valid email address.' ) );
1050        }
1051
1052        if ( $errors->has_errors() ) {
1053                return $errors;
1054        }
1055
1056        if ( 1 === $network_id ) {
1057                $wpdb->insert(
1058                        $wpdb->site,
1059                        array(
1060                                'domain' => $domain,
1061                                'path'   => $path,
1062                        )
1063                );
1064                $network_id = $wpdb->insert_id;
1065        } else {
1066                $wpdb->insert(
1067                        $wpdb->site,
1068                        array(
1069                                'domain' => $domain,
1070                                'path'   => $path,
1071                                'id'     => $network_id,
1072                        )
1073                );
1074        }
1075
1076        populate_network_meta(
1077                $network_id,
1078                array(
1079                        'admin_email'       => $email,
1080                        'site_name'         => $site_name,
1081                        'subdomain_install' => $subdomain_install,
1082                )
1083        );
1084
1085        // Remove the cron event since Recovery Mode is not used in Multisite.
1086        if ( wp_next_scheduled( 'recovery_mode_clean_expired_keys' ) ) {
1087                wp_clear_scheduled_hook( 'recovery_mode_clean_expired_keys' );
1088        }
1089
1090        /*
1091         * When upgrading from single to multisite, assume the current site will
1092         * become the main site of the network. When using populate_network()
1093         * to create another network in an existing multisite environment, skip
1094         * these steps since the main site of the new network has not yet been
1095         * created.
1096         */
1097        if ( ! is_multisite() ) {
1098                $current_site            = new stdClass();
1099                $current_site->domain    = $domain;
1100                $current_site->path      = $path;
1101                $current_site->site_name = ucfirst( $domain );
1102                $wpdb->insert(
1103                        $wpdb->blogs,
1104                        array(
1105                                'site_id'    => $network_id,
1106                                'blog_id'    => 1,
1107                                'domain'     => $domain,
1108                                'path'       => $path,
1109                                'registered' => current_time( 'mysql' ),
1110                        )
1111                );
1112                $current_site->blog_id = $wpdb->insert_id;
1113
1114                $site_user_id = (int) $wpdb->get_var(
1115                        $wpdb->prepare(
1116                                "SELECT meta_value
1117                                FROM $wpdb->sitemeta
1118                                WHERE meta_key = %s AND site_id = %d",
1119                                'admin_user_id',
1120                                $network_id
1121                        )
1122                );
1123
1124                update_user_meta( $site_user_id, 'source_domain', $domain );
1125                update_user_meta( $site_user_id, 'primary_blog', $current_site->blog_id );
1126
1127                // Unable to use update_network_option() while populating the network.
1128                $wpdb->insert(
1129                        $wpdb->sitemeta,
1130                        array(
1131                                'site_id'    => $network_id,
1132                                'meta_key'   => 'main_site',
1133                                'meta_value' => $current_site->blog_id,
1134                        )
1135                );
1136
1137                if ( $subdomain_install ) {
1138                        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
1139                } else {
1140                        $wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
1141                }
1142
1143                flush_rewrite_rules();
1144
1145                /**
1146                 * Fires after a network is created when converting a single site to multisite.
1147                 *
1148                 * @since 6.9.0
1149                 *
1150                 * @param int    $network_id        ID of network created.
1151                 * @param string $domain            The domain name for the network.
1152                 * @param string $email             Email address for the network administrator.
1153                 * @param string $site_name         The name of the network.
1154                 * @param string $path              The path to append to the network's domain name.
1155                 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
1156                 */
1157                do_action( 'after_upgrade_to_multisite', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
1158
1159                if ( ! $subdomain_install ) {
1160                        return true;
1161                }
1162
1163                $vhost_ok = false;
1164                $errstr   = '';
1165                $hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
1166                $page     = wp_remote_get(
1167                        'http://' . $hostname,
1168                        array(
1169                                'timeout'     => 5,
1170                                'httpversion' => '1.1',
1171                        )
1172                );
1173                if ( is_wp_error( $page ) ) {
1174                        $errstr = $page->get_error_message();
1175                } elseif ( 200 === wp_remote_retrieve_response_code( $page ) ) {
1176                                $vhost_ok = true;
1177                }
1178
1179                if ( ! $vhost_ok ) {
1180                        $msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';
1181
1182                        $msg .= '<p>' . sprintf(
1183                                /* translators: %s: Host name. */
1184                                __( 'The installer attempted to contact a random hostname (%s) on your domain.' ),
1185                                '<code>' . $hostname . '</code>'
1186                        );
1187                        if ( ! empty( $errstr ) ) {
1188                                /* translators: %s: Error message. */
1189                                $msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
1190                        }
1191                        $msg .= '</p>';
1192
1193                        $msg .= '<p>' . sprintf(
1194                                /* translators: %s: Asterisk symbol (*). */
1195                                __( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a %s hostname record pointing at your web server in your DNS configuration tool.' ),
1196                                '<code>*</code>'
1197                        ) . '</p>';
1198
1199                        $msg .= '<p>' . __( 'You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.' ) . '</p>';
1200
1201                        return new WP_Error( 'no_wildcard_dns', $msg );
1202                }
1203        }
1204
1205        /**
1206         * Fires after a network is fully populated.
1207         *
1208         * @since 6.9.0
1209         *
1210         * @param int    $network_id        ID of network created.
1211         * @param string $domain            The domain name for the network.
1212         * @param string $email             Email address for the network administrator.
1213         * @param string $site_name         The name of the network.
1214         * @param string $path              The path to append to the network's domain name.
1215         * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
1216         */
1217        do_action( 'after_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );
1218
1219        return true;
1220}
1221
1222/**
1223 * Creates WordPress network meta and sets the default values.
1224 *
1225 * @since 5.1.0
1226 *
1227 * @global wpdb $wpdb          WordPress database abstraction object.
1228 * @global int  $wp_db_version WordPress database version.
1229 *
1230 * @param int   $network_id Network ID to populate meta for.
1231 * @param array $meta       Optional. Custom meta $key => $value pairs to use. Default empty array.
1232 */
1233function populate_network_meta( $network_id, array $meta = array() ) {
1234        global $wpdb, $wp_db_version;
1235
1236        $network_id = (int) $network_id;
1237
1238        $email             = ! empty( $meta['admin_email'] ) ? $meta['admin_email'] : '';
1239        $subdomain_install = isset( $meta['subdomain_install'] ) ? (int) $meta['subdomain_install'] : 0;
1240
1241        // If a user with the provided email does not exist, default to the current user as the new network admin.
1242        $site_user = ! empty( $email ) ? get_user_by( 'email', $email ) : false;
1243        if ( false === $site_user ) {
1244                $site_user = wp_get_current_user();
1245        }
1246
1247        if ( empty( $email ) ) {
1248                $email = $site_user->user_email;
1249        }
1250
1251        $template       = get_option( 'template' );
1252        $stylesheet     = get_option( 'stylesheet' );
1253        $allowed_themes = array( $stylesheet => true );
1254
1255        if ( $template !== $stylesheet ) {
1256                $allowed_themes[ $template ] = true;
1257        }
1258
1259        if ( WP_DEFAULT_THEME !== $stylesheet && WP_DEFAULT_THEME !== $template ) {
1260                $allowed_themes[ WP_DEFAULT_THEME ] = true;
1261        }
1262
1263        // If WP_DEFAULT_THEME doesn't exist, also include the latest core default theme.
1264        if ( ! wp_get_theme( WP_DEFAULT_THEME )->exists() ) {
1265                $core_default = WP_Theme::get_core_default_theme();
1266                if ( $core_default ) {
1267                        $allowed_themes[ $core_default->get_stylesheet() ] = true;
1268                }
1269        }
1270
1271        if ( function_exists( 'clean_network_cache' ) ) {
1272                clean_network_cache( $network_id );
1273        } else {
1274                wp_cache_delete( $network_id, 'networks' );
1275        }
1276
1277        if ( ! is_multisite() ) {
1278                $site_admins = array( $site_user->user_login );
1279                $users       = get_users(
1280                        array(
1281                                'fields' => array( 'user_login' ),
1282                                'role'   => 'administrator',
1283                        )
1284                );
1285                if ( $users ) {
1286                        foreach ( $users as $user ) {
1287                                $site_admins[] = $user->user_login;
1288                        }
1289
1290                        $site_admins = array_unique( $site_admins );
1291                }
1292        } else {
1293                $site_admins = get_site_option( 'site_admins' );
1294        }
1295
1296        /* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */
1297        $welcome_email = __(
1298                'Howdy USERNAME,
1299
1300Your new SITE_NAME site has been successfully set up at:
1301BLOG_URL
1302
1303You can log in to the administrator account with the following information:
1304
1305Username: USERNAME
1306Password: PASSWORD
1307Log in here: BLOG_URLwp-login.php
1308
1309We hope you enjoy your new site. Thanks!
1310
1311--The Team @ SITE_NAME'
1312        );
1313
1314        $allowed_file_types = array();
1315        $all_mime_types     = get_allowed_mime_types();
1316
1317        foreach ( $all_mime_types as $ext => $mime ) {
1318                array_push( $allowed_file_types, ...explode( '|', $ext ) );
1319        }
1320        $upload_filetypes = array_unique( $allowed_file_types );
1321
1322        $sitemeta = array(
1323                'site_name'                   => __( 'My Network' ),
1324                'admin_email'                 => $email,
1325                'admin_user_id'               => $site_user->ID,
1326                'registration'                => 'none',
1327                'upload_filetypes'            => implode( ' ', $upload_filetypes ),
1328                'blog_upload_space'           => 100,
1329                'fileupload_maxk'             => 1500,
1330                'site_admins'                 => $site_admins,
1331                'allowedthemes'               => $allowed_themes,
1332                'illegal_names'               => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
1333                'wpmu_upgrade_site'           => $wp_db_version,
1334                'welcome_email'               => $welcome_email,
1335                /* translators: %s: Site link. */
1336                'first_post'                  => __( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ),
1337                // @todo - Network admins should have a method of editing the network siteurl (used for cookie hash).
1338                'siteurl'                     => get_option( 'siteurl' ) . '/',
1339                'add_new_users'               => '0',
1340                'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1',
1341                'subdomain_install'           => $subdomain_install,
1342                'ms_files_rewriting'          => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0',
1343                'user_count'                  => get_site_option( 'user_count' ),
1344                'initial_db_version'          => get_option( 'initial_db_version' ),
1345                'active_sitewide_plugins'     => array(),
1346                'WPLANG'                      => get_locale(),
1347        );
1348        if ( ! $subdomain_install ) {
1349                $sitemeta['illegal_names'][] = 'blog';
1350        }
1351
1352        $sitemeta = wp_parse_args( $meta, $sitemeta );
1353
1354        /**
1355         * Filters meta for a network on creation.
1356         *
1357         * @since 3.7.0
1358         *
1359         * @param array $sitemeta   Associative array of network meta keys and values to be inserted.
1360         * @param int   $network_id ID of network to populate.
1361         */
1362        $sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id );
1363
1364        $insert = '';
1365        foreach ( $sitemeta as $meta_key => $meta_value ) {
1366                if ( is_array( $meta_value ) ) {
1367                        $meta_value = serialize( $meta_value );
1368                }
1369                if ( ! empty( $insert ) ) {
1370                        $insert .= ', ';
1371                }
1372                $insert .= $wpdb->prepare( '( %d, %s, %s)', $network_id, $meta_key, $meta_value );
1373        }
1374        $wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
1375}
1376
1377/**
1378 * Creates WordPress site meta and sets the default values.
1379 *
1380 * @since 5.1.0
1381 *
1382 * @global wpdb $wpdb WordPress database abstraction object.
1383 *
1384 * @param int   $site_id Site ID to populate meta for.
1385 * @param array $meta    Optional. Custom meta $key => $value pairs to use. Default empty array.
1386 */
1387function populate_site_meta( $site_id, array $meta = array() ) {
1388        global $wpdb;
1389
1390        $site_id = (int) $site_id;
1391
1392        if ( ! is_site_meta_supported() ) {
1393                return;
1394        }
1395
1396        if ( empty( $meta ) ) {
1397                return;
1398        }
1399
1400        /**
1401         * Filters meta for a site on creation.
1402         *
1403         * @since 5.2.0
1404         *
1405         * @param array $meta    Associative array of site meta keys and values to be inserted.
1406         * @param int   $site_id ID of site to populate.
1407         */
1408        $site_meta = apply_filters( 'populate_site_meta', $meta, $site_id );
1409
1410        $insert = '';
1411        foreach ( $site_meta as $meta_key => $meta_value ) {
1412                if ( is_array( $meta_value ) ) {
1413                        $meta_value = serialize( $meta_value );
1414                }
1415                if ( ! empty( $insert ) ) {
1416                        $insert .= ', ';
1417                }
1418                $insert .= $wpdb->prepare( '( %d, %s, %s)', $site_id, $meta_key, $meta_value );
1419        }
1420
1421        $wpdb->query( "INSERT INTO $wpdb->blogmeta ( blog_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
1422
1423        wp_cache_delete( $site_id, 'blog_meta' );
1424        wp_cache_set_sites_last_changed();
1425}
Note: See TracBrowser for help on using the repository browser.