WordPress.org

Make WordPress Core

Ticket #30048: schema.php

File schema.php, 33.4 KB (added by akshay_raje, 7 years ago)
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// Declare these as global in case schema.php is included from a function.
12global $wpdb, $wp_queries, $charset_collate;
13
14/**
15 * The database character collate.
16 * @var string
17 * @global string
18 * @name $charset_collate
19 */
20$charset_collate = $wpdb->get_charset_collate();
21
22/**
23 * Retrieve the SQL for creating database tables.
24 *
25 * @since 3.3.0
26 *
27 * @param string $scope Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all.
28 * @param int $blog_id Optional. The blog ID for which to retrieve SQL. Default is the current blog ID.
29 * @return string The SQL needed to create the requested tables.
30 */
31function wp_get_db_schema( $scope = 'all', $blog_id = null ) {
32        global $wpdb;
33
34        $charset_collate = '';
35
36        if ( ! empty($wpdb->charset) )
37                $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
38        if ( ! empty($wpdb->collate) )
39                $charset_collate .= " COLLATE $wpdb->collate";
40
41        if ( $blog_id && $blog_id != $wpdb->blogid )
42                $old_blog_id = $wpdb->set_blog_id( $blog_id );
43
44        // Engage multisite if in the middle of turning it on from network.php.
45        $is_multisite = is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK );
46
47        // Blog specific tables.
48        $blog_tables = "CREATE TABLE $wpdb->terms (
49 term_id bigint(20) unsigned NOT NULL auto_increment,
50 name varchar(200) NOT NULL default '',
51 slug varchar(200) NOT NULL default '',
52 term_group bigint(10) NOT NULL default 0,
53 PRIMARY KEY  (term_id),
54 UNIQUE KEY slug (slug),
55 KEY name (name)
56) $charset_collate;
57CREATE TABLE $wpdb->term_taxonomy (
58 term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
59 term_id bigint(20) unsigned NOT NULL default 0,
60 taxonomy varchar(32) NOT NULL default '',
61 description longtext NOT NULL,
62 parent bigint(20) unsigned NOT NULL default 0,
63 count bigint(20) NOT NULL default 0,
64 PRIMARY KEY  (term_taxonomy_id),
65 UNIQUE KEY term_id_taxonomy (term_id,taxonomy),
66 KEY taxonomy (taxonomy)
67) $charset_collate;
68CREATE TABLE $wpdb->term_relationships (
69 object_id bigint(20) unsigned NOT NULL default 0,
70 term_taxonomy_id bigint(20) unsigned NOT NULL default 0,
71 term_order int(11) NOT NULL default 0,
72 PRIMARY KEY  (object_id,term_taxonomy_id),
73 KEY term_taxonomy_id (term_taxonomy_id)
74) $charset_collate;
75CREATE TABLE $wpdb->commentmeta (
76  meta_id bigint(20) unsigned NOT NULL auto_increment,
77  comment_id bigint(20) unsigned NOT NULL default '0',
78  meta_key varchar(255) default NULL,
79  meta_value longtext,
80  PRIMARY KEY  (meta_id),
81  KEY comment_id (comment_id),
82  KEY meta_key (meta_key)
83) $charset_collate;
84CREATE TABLE $wpdb->comments (
85  comment_ID bigint(20) unsigned NOT NULL auto_increment,
86  comment_post_ID bigint(20) unsigned NOT NULL default '0',
87  comment_author tinytext NOT NULL,
88  comment_author_email varchar(100) NOT NULL default '',
89  comment_author_url varchar(200) NOT NULL default '',
90  comment_author_IP varchar(100) NOT NULL default '',
91  comment_date datetime NOT NULL default '0000-00-00 00:00:00',
92  comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
93  comment_content text NOT NULL,
94  comment_karma int(11) NOT NULL default '0',
95  comment_approved varchar(20) NOT NULL default '1',
96  comment_agent varchar(255) NOT NULL default '',
97  comment_type varchar(20) NOT NULL default '',
98  comment_parent bigint(20) unsigned NOT NULL default '0',
99  user_id bigint(20) unsigned NOT NULL default '0',
100  PRIMARY KEY  (comment_ID),
101  KEY comment_post_ID (comment_post_ID),
102  KEY comment_approved_date_gmt (comment_approved,comment_date_gmt),
103  KEY comment_date_gmt (comment_date_gmt),
104  KEY comment_parent (comment_parent),
105  KEY comment_author_email (comment_author_email(10))
106) $charset_collate;
107CREATE TABLE $wpdb->links (
108  link_id bigint(20) unsigned NOT NULL auto_increment,
109  link_url varchar(255) NOT NULL default '',
110  link_name varchar(255) NOT NULL default '',
111  link_image varchar(255) NOT NULL default '',
112  link_target varchar(25) NOT NULL default '',
113  link_description varchar(255) NOT NULL default '',
114  link_visible varchar(20) NOT NULL default 'Y',
115  link_owner bigint(20) unsigned NOT NULL default '1',
116  link_rating int(11) NOT NULL default '0',
117  link_updated datetime NOT NULL default '0000-00-00 00:00:00',
118  link_rel varchar(255) NOT NULL default '',
119  link_notes mediumtext NOT NULL,
120  link_rss varchar(255) NOT NULL default '',
121  PRIMARY KEY  (link_id),
122  KEY link_visible (link_visible)
123) $charset_collate;
124CREATE TABLE $wpdb->options (
125  option_id bigint(20) unsigned NOT NULL auto_increment,
126  option_name varchar(255) NOT NULL default '',
127  option_value longtext NOT NULL,
128  autoload varchar(20) NOT NULL default 'yes',
129  PRIMARY KEY  (option_id),
130  UNIQUE KEY option_name (option_name)
131) $charset_collate;
132CREATE TABLE $wpdb->postmeta (
133  meta_id bigint(20) unsigned NOT NULL auto_increment,
134  post_id bigint(20) unsigned NOT NULL default '0',
135  meta_key varchar(255) default NULL,
136  meta_value longtext,
137  PRIMARY KEY  (meta_id),
138  KEY post_id (post_id),
139  KEY meta_key (meta_key)
140) $charset_collate;
141CREATE TABLE $wpdb->posts (
142  ID bigint(20) unsigned NOT NULL auto_increment,
143  post_author bigint(20) unsigned NOT NULL default '0',
144  post_date datetime NOT NULL default '0000-00-00 00:00:00',
145  post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
146  post_content longtext NOT NULL,
147  post_title text NOT NULL,
148  post_excerpt text NOT NULL,
149  post_status varchar(20) NOT NULL default 'publish',
150  comment_status varchar(20) NOT NULL default 'open',
151  ping_status varchar(20) NOT NULL default 'open',
152  post_password varchar(20) NOT NULL default '',
153  post_name varchar(200) NOT NULL default '',
154  to_ping text NOT NULL,
155  pinged text NOT NULL,
156  post_modified datetime NOT NULL default '0000-00-00 00:00:00',
157  post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
158  post_content_filtered longtext NOT NULL,
159  post_parent bigint(20) unsigned NOT NULL default '0',
160  guid varchar(255) NOT NULL default '',
161  menu_order int(11) NOT NULL default '0',
162  post_type varchar(20) NOT NULL default 'post',
163  post_mime_type varchar(100) NOT NULL default '',
164  comment_count bigint(20) NOT NULL default '0',
165  PRIMARY KEY  (ID),
166  KEY post_name (post_name),
167  KEY type_status_date (post_type,post_status,post_date,ID),
168  KEY post_parent (post_parent),
169  KEY post_author (post_author)
170) $charset_collate;\n";
171
172        // Single site users table. The multisite flavor of the users table is handled below.
173        $users_single_table = "CREATE TABLE $wpdb->users (
174  ID bigint(20) unsigned NOT NULL auto_increment,
175  user_login varchar(60) NOT NULL default '',
176  user_pass varchar(64) NOT NULL default '',
177  user_nicename varchar(50) NOT NULL default '',
178  user_email varchar(100) NOT NULL default '',
179  user_url varchar(100) NOT NULL default '',
180  user_registered datetime NOT NULL default '0000-00-00 00:00:00',
181  user_activation_key varchar(60) NOT NULL default '',
182  user_status int(11) NOT NULL default '0',
183  display_name varchar(250) NOT NULL default '',
184  PRIMARY KEY  (ID),
185  KEY user_login_key (user_login),
186  KEY user_nicename (user_nicename)
187) $charset_collate;\n";
188
189        // Multisite users table
190        $users_multi_table = "CREATE TABLE $wpdb->users (
191  ID bigint(20) unsigned NOT NULL auto_increment,
192  user_login varchar(60) NOT NULL default '',
193  user_pass varchar(64) NOT NULL default '',
194  user_nicename varchar(50) NOT NULL default '',
195  user_email varchar(100) NOT NULL default '',
196  user_url varchar(100) NOT NULL default '',
197  user_registered datetime NOT NULL default '0000-00-00 00:00:00',
198  user_activation_key varchar(60) NOT NULL default '',
199  user_status int(11) NOT NULL default '0',
200  display_name varchar(250) NOT NULL default '',
201  spam tinyint(2) NOT NULL default '0',
202  deleted tinyint(2) NOT NULL default '0',
203  PRIMARY KEY  (ID),
204  KEY user_login_key (user_login),
205  KEY user_nicename (user_nicename)
206) $charset_collate;\n";
207
208        // Usermeta.
209        $usermeta_table = "CREATE TABLE $wpdb->usermeta (
210  umeta_id bigint(20) unsigned NOT NULL auto_increment,
211  user_id bigint(20) unsigned NOT NULL default '0',
212  meta_key varchar(255) default NULL,
213  meta_value longtext,
214  PRIMARY KEY  (umeta_id),
215  KEY user_id (user_id),
216  KEY meta_key (meta_key)
217) $charset_collate;\n";
218
219        // Global tables
220        if ( $is_multisite )
221                $global_tables = $users_multi_table . $usermeta_table;
222        else
223                $global_tables = $users_single_table . $usermeta_table;
224
225        // Multisite global tables.
226        $ms_global_tables = "CREATE TABLE $wpdb->blogs (
227  blog_id bigint(20) NOT NULL auto_increment,
228  site_id bigint(20) NOT NULL default '0',
229  domain varchar(200) NOT NULL default '',
230  path varchar(100) NOT NULL default '',
231  registered datetime NOT NULL default '0000-00-00 00:00:00',
232  last_updated datetime NOT NULL default '0000-00-00 00:00:00',
233  public tinyint(2) NOT NULL default '1',
234  archived tinyint(2) NOT NULL default '0',
235  mature tinyint(2) NOT NULL default '0',
236  spam tinyint(2) NOT NULL default '0',
237  deleted tinyint(2) NOT NULL default '0',
238  lang_id int(11) NOT NULL default '0',
239  PRIMARY KEY  (blog_id),
240  KEY domain (domain(50),path(5)),
241  KEY lang_id (lang_id)
242) $charset_collate;
243CREATE TABLE $wpdb->blog_versions (
244  blog_id bigint(20) NOT NULL default '0',
245  db_version varchar(20) NOT NULL default '',
246  last_updated datetime NOT NULL default '0000-00-00 00:00:00',
247  PRIMARY KEY  (blog_id),
248  KEY db_version (db_version)
249) $charset_collate;
250CREATE TABLE $wpdb->registration_log (
251  ID bigint(20) NOT NULL auto_increment,
252  email varchar(255) NOT NULL default '',
253  IP varchar(30) NOT NULL default '',
254  blog_id bigint(20) NOT NULL default '0',
255  date_registered datetime NOT NULL default '0000-00-00 00:00:00',
256  PRIMARY KEY  (ID),
257  KEY IP (IP)
258) $charset_collate;
259CREATE TABLE $wpdb->site (
260  id bigint(20) NOT NULL auto_increment,
261  domain varchar(200) NOT NULL default '',
262  path varchar(100) NOT NULL default '',
263  PRIMARY KEY  (id),
264  KEY domain (domain,path)
265) $charset_collate;
266CREATE TABLE $wpdb->sitemeta (
267  meta_id bigint(20) NOT NULL auto_increment,
268  site_id bigint(20) NOT NULL default '0',
269  meta_key varchar(255) default NULL,
270  meta_value longtext,
271  PRIMARY KEY  (meta_id),
272  KEY meta_key (meta_key),
273  KEY site_id (site_id)
274) $charset_collate;
275CREATE TABLE $wpdb->signups (
276  signup_id bigint(20) NOT NULL auto_increment,
277  domain varchar(200) NOT NULL default '',
278  path varchar(100) NOT NULL default '',
279  title longtext NOT NULL,
280  user_login varchar(60) NOT NULL default '',
281  user_email varchar(100) NOT NULL default '',
282  registered datetime NOT NULL default '0000-00-00 00:00:00',
283  activated datetime NOT NULL default '0000-00-00 00:00:00',
284  active tinyint(1) NOT NULL default '0',
285  activation_key varchar(50) NOT NULL default '',
286  meta longtext,
287  PRIMARY KEY  (signup_id),
288  KEY activation_key (activation_key),
289  KEY user_email (user_email),
290  KEY user_login_email (user_login,user_email),
291  KEY domain_path (domain,path)
292) $charset_collate;";
293
294        switch ( $scope ) {
295                case 'blog' :
296                        $queries = $blog_tables;
297                        break;
298                case 'global' :
299                        $queries = $global_tables;
300                        if ( $is_multisite )
301                                $queries .= $ms_global_tables;
302                        break;
303                case 'ms_global' :
304                        $queries = $ms_global_tables;
305                        break;
306                case 'all' :
307                default:
308                        $queries = $global_tables . $blog_tables;
309                        if ( $is_multisite )
310                                $queries .= $ms_global_tables;
311                        break;
312        }
313
314        if ( isset( $old_blog_id ) )
315                $wpdb->set_blog_id( $old_blog_id );
316
317        return $queries;
318}
319
320// Populate for back compat.
321$wp_queries = wp_get_db_schema( 'all' );
322
323/**
324 * Create WordPress options and set the default values.
325 *
326 * @since 1.5.0
327 * @uses $wpdb
328 * @uses $wp_db_version
329 */
330function populate_options() {
331        global $wpdb, $wp_db_version, $wp_current_db_version;
332
333        $guessurl = wp_guess_url();
334        /**
335         * Fires before creating WordPress options and populating their default values.
336         *
337         * @since 2.6.0
338         */
339        do_action( 'populate_options' );
340
341        if ( ini_get('safe_mode') ) {
342                // Safe mode can break mkdir() so use a flat structure by default.
343                $uploads_use_yearmonth_folders = 0;
344        } else {
345                $uploads_use_yearmonth_folders = 1;
346        }
347
348        $template = WP_DEFAULT_THEME;
349        // If default theme is a child theme, we need to get its template
350        $theme = wp_get_theme( $template );
351        if ( ! $theme->errors() )
352                $template = $theme->get_template();
353
354        $timezone_string = '';
355        $gmt_offset = 0;
356        /* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
357           or a valid timezone string (America/New_York). See http://us3.php.net/manual/en/timezones.php
358           for all timezone strings supported by PHP.
359        */
360        $offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
361        if ( is_numeric( $offset_or_tz ) )
362                $gmt_offset = $offset_or_tz;
363        elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list() ) )
364                        $timezone_string = $offset_or_tz;
365
366        $options = array(
367        'siteurl' => $guessurl,
368        'home' => $guessurl,
369        'blogname' => __('My Site'),
370        /* translators: blog tagline */
371        'blogdescription' => __('Just another WordPress site'),
372        'users_can_register' => 0,
373        'admin_email' => 'you@example.com',
374        /* translators: default start of the week. 0 = Sunday, 1 = Monday */
375        'start_of_week' => _x( '1', 'start of week' ),
376        'use_balanceTags' => 0,
377        'use_smilies' => 1,
378        'require_name_email' => 1,
379        'comments_notify' => 1,
380        'posts_per_rss' => 10,
381        'rss_use_excerpt' => 0,
382        'mailserver_url' => 'mail.example.com',
383        'mailserver_login' => 'login@example.com',
384        'mailserver_pass' => 'password',
385        'mailserver_port' => 110,
386        'default_category' => 1,
387        'default_comment_status' => 'open',
388        'default_ping_status' => 'open',
389        'default_pingback_flag' => 1,
390        'posts_per_page' => 10,
391        /* translators: default date format, see http://php.net/date */
392        'date_format' => __('F j, Y'),
393        /* translators: default time format, see http://php.net/date */
394        'time_format' => __('g:i a'),
395        /* translators: links last updated date format, see http://php.net/date */
396        'links_updated_date_format' => __('F j, Y g:i a'),
397        'comment_moderation' => 0,
398        'moderation_notify' => 1,
399        'permalink_structure' => '',
400        'gzipcompression' => 0,
401        'hack_file' => 0,
402        'blog_charset' => 'UTF-8',
403        'moderation_keys' => '',
404        'active_plugins' => array(),
405        'category_base' => '',
406        'ping_sites' => 'http://rpc.pingomatic.com/',
407        'advanced_edit' => 0,
408        'comment_max_links' => 2,
409        'gmt_offset' => $gmt_offset,
410
411        // 1.5
412        'default_email_category' => 1,
413        'recently_edited' => '',
414        'template' => $template,
415        'stylesheet' => WP_DEFAULT_THEME,
416        'comment_whitelist' => 1,
417        'blacklist_keys' => '',
418        'comment_registration' => 0,
419        'html_type' => 'text/html',
420
421        // 1.5.1
422        'use_trackback' => 0,
423
424        // 2.0
425        'default_role' => 'subscriber',
426        'db_version' => $wp_db_version,
427
428        // 2.0.1
429        'uploads_use_yearmonth_folders' => $uploads_use_yearmonth_folders,
430        'upload_path' => '',
431
432        // 2.1
433        'blog_public' => '1',
434        'default_link_category' => 2,
435        'show_on_front' => 'posts',
436
437        // 2.2
438        'tag_base' => '',
439
440        // 2.5
441        'show_avatars' => '1',
442        'avatar_rating' => 'G',
443        'upload_url_path' => '',
444        'thumbnail_size_w' => 150,
445        'thumbnail_size_h' => 150,
446        'thumbnail_crop' => 1,
447        'medium_size_w' => 300,
448        'medium_size_h' => 300,
449
450        // 2.6
451        'avatar_default' => 'mystery',
452
453        // 2.7
454        'large_size_w' => 1024,
455        'large_size_h' => 1024,
456        'image_default_link_type' => 'file',
457        'image_default_size' => '',
458        'image_default_align' => '',
459        'close_comments_for_old_posts' => 0,
460        'close_comments_days_old' => 14,
461        'thread_comments' => 1,
462        'thread_comments_depth' => 5,
463        'page_comments' => 0,
464        'comments_per_page' => 50,
465        'default_comments_page' => 'newest',
466        'comment_order' => 'asc',
467        'sticky_posts' => array(),
468        'widget_categories' => array(),
469        'widget_text' => array(),
470        'widget_rss' => array(),
471        'uninstall_plugins' => array(),
472
473        // 2.8
474        'timezone_string' => $timezone_string,
475
476        // 3.0
477        'page_for_posts' => 0,
478        'page_on_front' => 0,
479
480        // 3.1
481        'default_post_format' => 0,
482
483        // 3.5
484        'link_manager_enabled' => 0,
485        );
486
487        // 3.3
488        if ( ! is_multisite() ) {
489                $options['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version
490                        ? $wp_current_db_version : $wp_db_version;
491        }
492
493        // 3.0 multisite
494        if ( is_multisite() ) {
495                /* translators: blog tagline */
496                $options[ 'blogdescription' ] = sprintf(__('Just another %s site'), get_current_site()->site_name );
497                $options[ 'permalink_structure' ] = '/%year%/%monthnum%/%day%/%postname%/';
498        }
499
500        // Set autoload to no for these options
501        $fat_options = array( 'moderation_keys', 'recently_edited', 'blacklist_keys', 'uninstall_plugins' );
502
503        $keys = "'" . implode( "', '", array_keys( $options ) ) . "'";
504        $existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" );
505
506        $insert = '';
507        foreach ( $options as $option => $value ) {
508                if ( in_array($option, $existing_options) )
509                        continue;
510                if ( in_array($option, $fat_options) )
511                        $autoload = 'no';
512                else
513                        $autoload = 'yes';
514
515                if ( is_array($value) )
516                        $value = serialize($value);
517                if ( !empty($insert) )
518                        $insert .= ', ';
519                $insert .= $wpdb->prepare( "(%s, %s, %s)", $option, $value, $autoload );
520        }
521
522        if ( !empty($insert) )
523                $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert);
524
525        // In case it is set, but blank, update "home".
526        if ( !__get_option('home') ) update_option('home', $guessurl);
527
528        // Delete unused options.
529        $unusedoptions = array(
530                'blodotgsping_url', 'bodyterminator', 'emailtestonly', 'phoneemail_separator', 'smilies_directory',
531                'subjectprefix', 'use_bbcode', 'use_blodotgsping', 'use_phoneemail', 'use_quicktags', 'use_weblogsping',
532                'weblogs_cache_file', 'use_preview', 'use_htmltrans', 'smilies_directory', 'fileupload_allowedusers',
533                'use_phoneemail', 'default_post_status', 'default_post_category', 'archive_mode', 'time_difference',
534                'links_minadminlevel', 'links_use_adminlevels', 'links_rating_type', 'links_rating_char',
535                'links_rating_ignore_zero', 'links_rating_single_image', 'links_rating_image0', 'links_rating_image1',
536                'links_rating_image2', 'links_rating_image3', 'links_rating_image4', 'links_rating_image5',
537                'links_rating_image6', 'links_rating_image7', 'links_rating_image8', 'links_rating_image9',
538                'links_recently_updated_time', 'links_recently_updated_prepend', 'links_recently_updated_append',
539                'weblogs_cacheminutes', 'comment_allowed_tags', 'search_engine_friendly_urls', 'default_geourl_lat',
540                'default_geourl_lon', 'use_default_geourl', 'weblogs_xml_url', 'new_users_can_blog', '_wpnonce',
541                '_wp_http_referer', 'Update', 'action', 'rich_editing', 'autosave_interval', 'deactivated_plugins',
542                'can_compress_scripts', 'page_uris', 'update_core', 'update_plugins', 'update_themes', 'doing_cron',
543                'random_seed', 'rss_excerpt_length', 'secret', 'use_linksupdate', 'default_comment_status_page',
544                'wporg_popular_tags', 'what_to_show', 'rss_language', 'language', 'enable_xmlrpc', 'enable_app',
545                'embed_autourls', 'default_post_edit_rows',
546        );
547        foreach ( $unusedoptions as $option )
548                delete_option($option);
549
550        // Delete obsolete magpie stuff.
551        $wpdb->query("DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'");
552
553        /*
554         * Deletes all expired transients. The multi-table delete syntax is used
555         * to delete the transient record from table a, and the corresponding
556         * transient_timeout record from table b.
557         */
558        $time = time();
559        $sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
560                WHERE a.option_name LIKE %s
561                AND a.option_name NOT LIKE %s
562                AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
563                AND b.option_value < %d";
564        $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', $time ) );
565
566        if ( is_main_site() && is_main_network() ) {
567                $sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
568                        WHERE a.option_name LIKE %s
569                        AND a.option_name NOT LIKE %s
570                        AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
571                        AND b.option_value < %d";
572                $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_' ) . '%', $time ) );
573        }
574}
575
576/**
577 * Execute WordPress role creation for the various WordPress versions.
578 *
579 * @since 2.0.0
580 */
581function populate_roles() {
582        populate_roles_160();
583        populate_roles_210();
584        populate_roles_230();
585        populate_roles_250();
586        populate_roles_260();
587        populate_roles_270();
588        populate_roles_280();
589        populate_roles_300();
590}
591
592/**
593 * Create the roles for WordPress 2.0
594 *
595 * @since 2.0.0
596 */
597function populate_roles_160() {
598        // Add roles
599
600        // Dummy gettext calls to get strings in the catalog.
601        /* translators: user role */
602        _x('Administrator', 'User role');
603        /* translators: user role */
604        _x('Editor', 'User role');
605        /* translators: user role */
606        _x('Author', 'User role');
607        /* translators: user role */
608        _x('Contributor', 'User role');
609        /* translators: user role */
610        _x('Subscriber', 'User role');
611
612        add_role('administrator', 'Administrator');
613        add_role('editor', 'Editor');
614        add_role('author', 'Author');
615        add_role('contributor', 'Contributor');
616        add_role('subscriber', 'Subscriber');
617
618        // Add caps for Administrator role
619        $role = get_role('administrator');
620        $role->add_cap('switch_themes');
621        $role->add_cap('edit_themes');
622        $role->add_cap('activate_plugins');
623        $role->add_cap('edit_plugins');
624        $role->add_cap('edit_users');
625        $role->add_cap('edit_files');
626        $role->add_cap('manage_options');
627        $role->add_cap('moderate_comments');
628        $role->add_cap('manage_categories');
629        $role->add_cap('manage_links');
630        $role->add_cap('upload_files');
631        $role->add_cap('import');
632        $role->add_cap('unfiltered_html');
633        $role->add_cap('edit_posts');
634        $role->add_cap('edit_others_posts');
635        $role->add_cap('edit_published_posts');
636        $role->add_cap('publish_posts');
637        $role->add_cap('edit_pages');
638        $role->add_cap('read');
639        $role->add_cap('level_10');
640        $role->add_cap('level_9');
641        $role->add_cap('level_8');
642        $role->add_cap('level_7');
643        $role->add_cap('level_6');
644        $role->add_cap('level_5');
645        $role->add_cap('level_4');
646        $role->add_cap('level_3');
647        $role->add_cap('level_2');
648        $role->add_cap('level_1');
649        $role->add_cap('level_0');
650
651        // Add caps for Editor role
652        $role = get_role('editor');
653        $role->add_cap('moderate_comments');
654        $role->add_cap('manage_categories');
655        $role->add_cap('manage_links');
656        $role->add_cap('upload_files');
657        $role->add_cap('unfiltered_html');
658        $role->add_cap('edit_posts');
659        $role->add_cap('edit_others_posts');
660        $role->add_cap('edit_published_posts');
661        $role->add_cap('publish_posts');
662        $role->add_cap('edit_pages');
663        $role->add_cap('read');
664        $role->add_cap('level_7');
665        $role->add_cap('level_6');
666        $role->add_cap('level_5');
667        $role->add_cap('level_4');
668        $role->add_cap('level_3');
669        $role->add_cap('level_2');
670        $role->add_cap('level_1');
671        $role->add_cap('level_0');
672
673        // Add caps for Author role
674        $role = get_role('author');
675        $role->add_cap('upload_files');
676        $role->add_cap('edit_posts');
677        $role->add_cap('edit_published_posts');
678        $role->add_cap('publish_posts');
679        $role->add_cap('read');
680        $role->add_cap('level_2');
681        $role->add_cap('level_1');
682        $role->add_cap('level_0');
683
684        // Add caps for Contributor role
685        $role = get_role('contributor');
686        $role->add_cap('edit_posts');
687        $role->add_cap('read');
688        $role->add_cap('level_1');
689        $role->add_cap('level_0');
690
691        // Add caps for Subscriber role
692        $role = get_role('subscriber');
693        $role->add_cap('read');
694        $role->add_cap('level_0');
695}
696
697/**
698 * Create and modify WordPress roles for WordPress 2.1.
699 *
700 * @since 2.1.0
701 */
702function populate_roles_210() {
703        $roles = array('administrator', 'editor');
704        foreach ($roles as $role) {
705                $role = get_role($role);
706                if ( empty($role) )
707                        continue;
708
709                $role->add_cap('edit_others_pages');
710                $role->add_cap('edit_published_pages');
711                $role->add_cap('publish_pages');
712                $role->add_cap('delete_pages');
713                $role->add_cap('delete_others_pages');
714                $role->add_cap('delete_published_pages');
715                $role->add_cap('delete_posts');
716                $role->add_cap('delete_others_posts');
717                $role->add_cap('delete_published_posts');
718                $role->add_cap('delete_private_posts');
719                $role->add_cap('edit_private_posts');
720                $role->add_cap('read_private_posts');
721                $role->add_cap('delete_private_pages');
722                $role->add_cap('edit_private_pages');
723                $role->add_cap('read_private_pages');
724        }
725
726        $role = get_role('administrator');
727        if ( ! empty($role) ) {
728                $role->add_cap('delete_users');
729                $role->add_cap('create_users');
730        }
731
732        $role = get_role('author');
733        if ( ! empty($role) ) {
734                $role->add_cap('delete_posts');
735                $role->add_cap('delete_published_posts');
736        }
737
738        $role = get_role('contributor');
739        if ( ! empty($role) ) {
740                $role->add_cap('delete_posts');
741        }
742}
743
744/**
745 * Create and modify WordPress roles for WordPress 2.3.
746 *
747 * @since 2.3.0
748 */
749function populate_roles_230() {
750        $role = get_role( 'administrator' );
751
752        if ( !empty( $role ) ) {
753                $role->add_cap( 'unfiltered_upload' );
754        }
755}
756
757/**
758 * Create and modify WordPress roles for WordPress 2.5.
759 *
760 * @since 2.5.0
761 */
762function populate_roles_250() {
763        $role = get_role( 'administrator' );
764
765        if ( !empty( $role ) ) {
766                $role->add_cap( 'edit_dashboard' );
767        }
768}
769
770/**
771 * Create and modify WordPress roles for WordPress 2.6.
772 *
773 * @since 2.6.0
774 */
775function populate_roles_260() {
776        $role = get_role( 'administrator' );
777
778        if ( !empty( $role ) ) {
779                $role->add_cap( 'update_plugins' );
780                $role->add_cap( 'delete_plugins' );
781        }
782}
783
784/**
785 * Create and modify WordPress roles for WordPress 2.7.
786 *
787 * @since 2.7.0
788 */
789function populate_roles_270() {
790        $role = get_role( 'administrator' );
791
792        if ( !empty( $role ) ) {
793                $role->add_cap( 'install_plugins' );
794                $role->add_cap( 'update_themes' );
795        }
796}
797
798/**
799 * Create and modify WordPress roles for WordPress 2.8.
800 *
801 * @since 2.8.0
802 */
803function populate_roles_280() {
804        $role = get_role( 'administrator' );
805
806        if ( !empty( $role ) ) {
807                $role->add_cap( 'install_themes' );
808        }
809}
810
811/**
812 * Create and modify WordPress roles for WordPress 3.0.
813 *
814 * @since 3.0.0
815 */
816function populate_roles_300() {
817        $role = get_role( 'administrator' );
818
819        if ( !empty( $role ) ) {
820                $role->add_cap( 'update_core' );
821                $role->add_cap( 'list_users' );
822                $role->add_cap( 'remove_users' );
823
824                /*
825                 * Never used, will be removed. create_users or promote_users
826                 * is the capability you're looking for.
827                 */
828                $role->add_cap( 'add_users' );
829
830                $role->add_cap( 'promote_users' );
831                $role->add_cap( 'edit_theme_options' );
832                $role->add_cap( 'delete_themes' );
833                $role->add_cap( 'export' );
834        }
835}
836
837/**
838 * Install Network.
839 *
840 * @since 3.0.0
841 *
842 */
843if ( !function_exists( 'install_network' ) ) :
844function install_network() {
845        if ( ! defined( 'WP_INSTALLING_NETWORK' ) )
846                define( 'WP_INSTALLING_NETWORK', true );
847
848        dbDelta( wp_get_db_schema( 'global' ) );
849}
850endif;
851
852/**
853 * Populate network settings.
854 *
855 * @since 3.0.0
856 *
857 * @param int $network_id ID of network to populate.
858 * @return bool|WP_Error True on success, or WP_Error on warning (with the install otherwise successful,
859 *                       so the error code must be checked) or failure.
860 */
861function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
862        global $wpdb, $current_site, $wp_db_version, $wp_rewrite;
863
864        $errors = new WP_Error();
865        if ( '' == $domain )
866                $errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
867        if ( '' == $site_name )
868                $errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
869
870        // Check for network collision.
871        if ( $network_id == $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id ) ) )
872                $errors->add( 'siteid_exists', __( 'The network already exists.' ) );
873
874        $site_user = get_user_by( 'email', $email );
875        if ( ! is_email( $email ) )
876                $errors->add( 'invalid_email', __( 'You must provide a valid e-mail address.' ) );
877
878        if ( $errors->get_error_code() )
879                return $errors;
880
881        // Set up site tables.
882        $template = get_option( 'template' );
883        $stylesheet = get_option( 'stylesheet' );
884        $allowed_themes = array( $stylesheet => true );
885        if ( $template != $stylesheet )
886                $allowed_themes[ $template ] = true;
887        if ( WP_DEFAULT_THEME != $stylesheet && WP_DEFAULT_THEME != $template )
888                $allowed_themes[ WP_DEFAULT_THEME ] = true;
889
890        if ( 1 == $network_id ) {
891                $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path ) );
892                $network_id = $wpdb->insert_id;
893        } else {
894                $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path, 'id' => $network_id ) );
895        }
896
897        wp_cache_delete( 'networks_have_paths', 'site-options' );
898
899        if ( !is_multisite() ) {
900                $site_admins = array( $site_user->user_login );
901                $users = get_users( array( 'fields' => array( 'ID', 'user_login' ) ) );
902                if ( $users ) {
903                        foreach ( $users as $user ) {
904                                if ( is_super_admin( $user->ID ) && !in_array( $user->user_login, $site_admins ) )
905                                        $site_admins[] = $user->user_login;
906                        }
907                }
908        } else {
909                $site_admins = get_site_option( 'site_admins' );
910        }
911
912        $welcome_email = __( 'Dear User,
913
914Your new SITE_NAME site has been successfully set up at:
915BLOG_URL
916
917You can log in to the administrator account with the following information:
918Username: USERNAME
919Password: PASSWORD
920Log in here: BLOG_URLwp-login.php
921
922We hope you enjoy your new site. Thanks!
923
924--The Team @ SITE_NAME' );
925
926        $misc_exts = array(
927                // Images.
928                'jpg', 'jpeg', 'png', 'gif',
929                // Video.
930                'mov', 'avi', 'mpg', '3gp', '3g2',
931                // "audio".
932                'midi', 'mid',
933                // Miscellaneous.
934                'pdf', 'doc', 'ppt', 'odt', 'pptx', 'docx', 'pps', 'ppsx', 'xls', 'xlsx', 'key',
935        );
936        $audio_exts = wp_get_audio_extensions();
937        $video_exts = wp_get_video_extensions();
938        $upload_filetypes = array_unique( array_merge( $misc_exts, $audio_exts, $video_exts ) );
939
940        $sitemeta = array(
941                'site_name' => $site_name,
942                'admin_email' => $site_user->user_email,
943                'admin_user_id' => $site_user->ID,
944                'registration' => 'none',
945                'upload_filetypes' => implode( ' ', $upload_filetypes ),
946                'blog_upload_space' => 100,
947                'fileupload_maxk' => 1500,
948                'site_admins' => $site_admins,
949                'allowedthemes' => $allowed_themes,
950                'illegal_names' => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
951                'wpmu_upgrade_site' => $wp_db_version,
952                'welcome_email' => $welcome_email,
953                'first_post' => __( 'Welcome to <a href="SITE_URL">SITE_NAME</a>. This is your first post. Edit or delete it, then start blogging!' ),
954                // @todo - network admins should have a method of editing the network siteurl (used for cookie hash)
955                'siteurl' => get_option( 'siteurl' ) . '/',
956                'add_new_users' => '0',
957                'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1',
958                'subdomain_install' => intval( $subdomain_install ),
959                'global_terms_enabled' => global_terms_enabled() ? '1' : '0',
960                'ms_files_rewriting' => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0',
961                'initial_db_version' => get_option( 'initial_db_version' ),
962                'active_sitewide_plugins' => array(),
963                'WPLANG' => get_locale(),
964        );
965        if ( ! $subdomain_install )
966                $sitemeta['illegal_names'][] = 'blog';
967
968        /**
969         * Filter meta for a network on creation.
970         *
971         * @since 3.7.0
972         *
973         * @param array $sitemeta   Associative array of network meta keys and values to be inserted.
974         * @param int   $network_id ID of network to populate.
975         */
976        $sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id );
977
978        $insert = '';
979        foreach ( $sitemeta as $meta_key => $meta_value ) {
980                if ( is_array( $meta_value ) )
981                        $meta_value = serialize( $meta_value );
982                if ( !empty( $insert ) )
983                        $insert .= ', ';
984                $insert .= $wpdb->prepare( "( %d, %s, %s)", $network_id, $meta_key, $meta_value );
985        }
986        $wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert );
987
988        /*
989         * When upgrading from single to multisite, assume the current site will
990         * become the main site of the network. When using populate_network()
991         * to create another network in an existing multisite environment, skip
992         * these steps since the main site of the new network has not yet been
993         * created.
994         */
995        if ( ! is_multisite() ) {
996                $current_site = new stdClass;
997                $current_site->domain = $domain;
998                $current_site->path = $path;
999                $current_site->site_name = ucfirst( $domain );
1000                $wpdb->insert( $wpdb->blogs, array( 'site_id' => $network_id, 'blog_id' => 1, 'domain' => $domain, 'path' => $path, 'registered' => current_time( 'mysql' ) ) );
1001                $current_site->blog_id = $blog_id = $wpdb->insert_id;
1002                update_user_meta( $site_user->ID, 'source_domain', $domain );
1003                update_user_meta( $site_user->ID, 'primary_blog', $blog_id );
1004
1005                if ( $subdomain_install )
1006                        $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
1007                else
1008                        $wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
1009
1010                flush_rewrite_rules();
1011
1012                if ( ! $subdomain_install )
1013                        return true;
1014
1015                $vhost_ok = false;
1016                $errstr = '';
1017                $hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
1018                $page = wp_remote_get( 'http://' . $hostname, array( 'timeout' => 5, 'httpversion' => '1.1' ) );
1019                if ( is_wp_error( $page ) )
1020                        $errstr = $page->get_error_message();
1021                elseif ( 200 == wp_remote_retrieve_response_code( $page ) )
1022                                $vhost_ok = true;
1023
1024                if ( ! $vhost_ok ) {
1025                        $msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';
1026                        $msg .= '<p>' . sprintf( __( 'The installer attempted to contact a random hostname (<code>%1$s</code>) on your domain.' ), $hostname );
1027                        if ( ! empty ( $errstr ) )
1028                                $msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
1029                        $msg .= '</p>';
1030                        $msg .= '<p>' . __( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a <code>*</code> hostname record pointing at your web server in your DNS configuration tool.' ) . '</p>';
1031                        $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>';
1032                        return new WP_Error( 'no_wildcard_dns', $msg );
1033                }
1034        }
1035
1036        return true;
1037}