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