]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-admin/includes/schema.php
WordPress 4.1
[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 // Declare these as global in case schema.php is included from a function.
12 global $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  */
31 function 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  KEY slug (slug),
55  KEY name (name)
56 ) $charset_collate;
57 CREATE 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;
68 CREATE 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;
75 CREATE 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;
84 CREATE 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;
107 CREATE 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;
124 CREATE TABLE $wpdb->options (
125   option_id bigint(20) unsigned NOT NULL auto_increment,
126   option_name varchar(64) 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;
132 CREATE 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;
141 CREATE 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;
243 CREATE 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;
250 CREATE 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;
259 CREATE 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;
266 CREATE 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;
275 CREATE 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  *
328  * @global wpdb $wpdb WordPress database abstraction object.
329  * @uses $wp_db_version
330  */
331 function populate_options() {
332         global $wpdb, $wp_db_version, $wp_current_db_version;
333
334         $guessurl = wp_guess_url();
335         /**
336          * Fires before creating WordPress options and populating their default values.
337          *
338          * @since 2.6.0
339          */
340         do_action( 'populate_options' );
341
342         if ( ini_get('safe_mode') ) {
343                 // Safe mode can break mkdir() so use a flat structure by default.
344                 $uploads_use_yearmonth_folders = 0;
345         } else {
346                 $uploads_use_yearmonth_folders = 1;
347         }
348
349         $template = WP_DEFAULT_THEME;
350         // If default theme is a child theme, we need to get its template
351         $theme = wp_get_theme( $template );
352         if ( ! $theme->errors() )
353                 $template = $theme->get_template();
354
355         $timezone_string = '';
356         $gmt_offset = 0;
357         /* translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
358            or a valid timezone string (America/New_York). See http://us3.php.net/manual/en/timezones.php
359            for all timezone strings supported by PHP.
360         */
361         $offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
362         if ( is_numeric( $offset_or_tz ) )
363                 $gmt_offset = $offset_or_tz;
364         elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list() ) )
365                         $timezone_string = $offset_or_tz;
366
367         $options = array(
368         'siteurl' => $guessurl,
369         'home' => $guessurl,
370         'blogname' => __('My Site'),
371         /* translators: blog tagline */
372         'blogdescription' => __('Just another WordPress site'),
373         'users_can_register' => 0,
374         'admin_email' => 'you@example.com',
375         /* translators: default start of the week. 0 = Sunday, 1 = Monday */
376         'start_of_week' => _x( '1', 'start of week' ),
377         'use_balanceTags' => 0,
378         'use_smilies' => 1,
379         'require_name_email' => 1,
380         'comments_notify' => 1,
381         'posts_per_rss' => 10,
382         'rss_use_excerpt' => 0,
383         'mailserver_url' => 'mail.example.com',
384         'mailserver_login' => 'login@example.com',
385         'mailserver_pass' => 'password',
386         'mailserver_port' => 110,
387         'default_category' => 1,
388         'default_comment_status' => 'open',
389         'default_ping_status' => 'open',
390         'default_pingback_flag' => 1,
391         'posts_per_page' => 10,
392         /* translators: default date format, see http://php.net/date */
393         'date_format' => __('F j, Y'),
394         /* translators: default time format, see http://php.net/date */
395         'time_format' => __('g:i a'),
396         /* translators: links last updated date format, see http://php.net/date */
397         'links_updated_date_format' => __('F j, Y g:i a'),
398         'comment_moderation' => 0,
399         'moderation_notify' => 1,
400         'permalink_structure' => '',
401         'gzipcompression' => 0,
402         'hack_file' => 0,
403         'blog_charset' => 'UTF-8',
404         'moderation_keys' => '',
405         'active_plugins' => array(),
406         'category_base' => '',
407         'ping_sites' => 'http://rpc.pingomatic.com/',
408         'advanced_edit' => 0,
409         'comment_max_links' => 2,
410         'gmt_offset' => $gmt_offset,
411
412         // 1.5
413         'default_email_category' => 1,
414         'recently_edited' => '',
415         'template' => $template,
416         'stylesheet' => WP_DEFAULT_THEME,
417         'comment_whitelist' => 1,
418         'blacklist_keys' => '',
419         'comment_registration' => 0,
420         'html_type' => 'text/html',
421
422         // 1.5.1
423         'use_trackback' => 0,
424
425         // 2.0
426         'default_role' => 'subscriber',
427         'db_version' => $wp_db_version,
428
429         // 2.0.1
430         'uploads_use_yearmonth_folders' => $uploads_use_yearmonth_folders,
431         'upload_path' => '',
432
433         // 2.1
434         'blog_public' => '1',
435         'default_link_category' => 2,
436         'show_on_front' => 'posts',
437
438         // 2.2
439         'tag_base' => '',
440
441         // 2.5
442         'show_avatars' => '1',
443         'avatar_rating' => 'G',
444         'upload_url_path' => '',
445         'thumbnail_size_w' => 150,
446         'thumbnail_size_h' => 150,
447         'thumbnail_crop' => 1,
448         'medium_size_w' => 300,
449         'medium_size_h' => 300,
450
451         // 2.6
452         'avatar_default' => 'mystery',
453
454         // 2.7
455         'large_size_w' => 1024,
456         'large_size_h' => 1024,
457         'image_default_link_type' => 'file',
458         'image_default_size' => '',
459         'image_default_align' => '',
460         'close_comments_for_old_posts' => 0,
461         'close_comments_days_old' => 14,
462         'thread_comments' => 1,
463         'thread_comments_depth' => 5,
464         'page_comments' => 0,
465         'comments_per_page' => 50,
466         'default_comments_page' => 'newest',
467         'comment_order' => 'asc',
468         'sticky_posts' => array(),
469         'widget_categories' => array(),
470         'widget_text' => array(),
471         'widget_rss' => array(),
472         'uninstall_plugins' => array(),
473
474         // 2.8
475         'timezone_string' => $timezone_string,
476
477         // 3.0
478         'page_for_posts' => 0,
479         'page_on_front' => 0,
480
481         // 3.1
482         'default_post_format' => 0,
483
484         // 3.5
485         'link_manager_enabled' => 0,
486         );
487
488         // 3.3
489         if ( ! is_multisite() ) {
490                 $options['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version
491                         ? $wp_current_db_version : $wp_db_version;
492         }
493
494         // 3.0 multisite
495         if ( is_multisite() ) {
496                 /* translators: blog tagline */
497                 $options[ 'blogdescription' ] = sprintf(__('Just another %s site'), get_current_site()->site_name );
498                 $options[ 'permalink_structure' ] = '/%year%/%monthnum%/%day%/%postname%/';
499         }
500
501         // Set autoload to no for these options
502         $fat_options = array( 'moderation_keys', 'recently_edited', 'blacklist_keys', 'uninstall_plugins' );
503
504         $keys = "'" . implode( "', '", array_keys( $options ) ) . "'";
505         $existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" );
506
507         $insert = '';
508         foreach ( $options as $option => $value ) {
509                 if ( in_array($option, $existing_options) )
510                         continue;
511                 if ( in_array($option, $fat_options) )
512                         $autoload = 'no';
513                 else
514                         $autoload = 'yes';
515
516                 if ( is_array($value) )
517                         $value = serialize($value);
518                 if ( !empty($insert) )
519                         $insert .= ', ';
520                 $insert .= $wpdb->prepare( "(%s, %s, %s)", $option, $value, $autoload );
521         }
522
523         if ( !empty($insert) )
524                 $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert);
525
526         // In case it is set, but blank, update "home".
527         if ( !__get_option('home') ) update_option('home', $guessurl);
528
529         // Delete unused options.
530         $unusedoptions = array(
531                 'blodotgsping_url', 'bodyterminator', 'emailtestonly', 'phoneemail_separator', 'smilies_directory',
532                 'subjectprefix', 'use_bbcode', 'use_blodotgsping', 'use_phoneemail', 'use_quicktags', 'use_weblogsping',
533                 'weblogs_cache_file', 'use_preview', 'use_htmltrans', 'smilies_directory', 'fileupload_allowedusers',
534                 'use_phoneemail', 'default_post_status', 'default_post_category', 'archive_mode', 'time_difference',
535                 'links_minadminlevel', 'links_use_adminlevels', 'links_rating_type', 'links_rating_char',
536                 'links_rating_ignore_zero', 'links_rating_single_image', 'links_rating_image0', 'links_rating_image1',
537                 'links_rating_image2', 'links_rating_image3', 'links_rating_image4', 'links_rating_image5',
538                 'links_rating_image6', 'links_rating_image7', 'links_rating_image8', 'links_rating_image9',
539                 'links_recently_updated_time', 'links_recently_updated_prepend', 'links_recently_updated_append',
540                 'weblogs_cacheminutes', 'comment_allowed_tags', 'search_engine_friendly_urls', 'default_geourl_lat',
541                 'default_geourl_lon', 'use_default_geourl', 'weblogs_xml_url', 'new_users_can_blog', '_wpnonce',
542                 '_wp_http_referer', 'Update', 'action', 'rich_editing', 'autosave_interval', 'deactivated_plugins',
543                 'can_compress_scripts', 'page_uris', 'update_core', 'update_plugins', 'update_themes', 'doing_cron',
544                 'random_seed', 'rss_excerpt_length', 'secret', 'use_linksupdate', 'default_comment_status_page',
545                 'wporg_popular_tags', 'what_to_show', 'rss_language', 'language', 'enable_xmlrpc', 'enable_app',
546                 'embed_autourls', 'default_post_edit_rows',
547         );
548         foreach ( $unusedoptions as $option )
549                 delete_option($option);
550
551         // Delete obsolete magpie stuff.
552         $wpdb->query("DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'");
553
554         /*
555          * Deletes all expired transients. The multi-table delete syntax is used
556          * to delete the transient record from table a, and the corresponding
557          * transient_timeout record from table b.
558          */
559         $time = time();
560         $sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
561                 WHERE a.option_name LIKE %s
562                 AND a.option_name NOT LIKE %s
563                 AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )
564                 AND b.option_value < %d";
565         $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_transient_' ) . '%', $wpdb->esc_like( '_transient_timeout_' ) . '%', $time ) );
566
567         if ( is_main_site() && is_main_network() ) {
568                 $sql = "DELETE a, b FROM $wpdb->options a, $wpdb->options b
569                         WHERE a.option_name LIKE %s
570                         AND a.option_name NOT LIKE %s
571                         AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
572                         AND b.option_value < %d";
573                 $wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( '_site_transient_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_' ) . '%', $time ) );
574         }
575 }
576
577 /**
578  * Execute WordPress role creation for the various WordPress versions.
579  *
580  * @since 2.0.0
581  */
582 function populate_roles() {
583         populate_roles_160();
584         populate_roles_210();
585         populate_roles_230();
586         populate_roles_250();
587         populate_roles_260();
588         populate_roles_270();
589         populate_roles_280();
590         populate_roles_300();
591 }
592
593 /**
594  * Create the roles for WordPress 2.0
595  *
596  * @since 2.0.0
597  */
598 function populate_roles_160() {
599         // Add roles
600
601         // Dummy gettext calls to get strings in the catalog.
602         /* translators: user role */
603         _x('Administrator', 'User role');
604         /* translators: user role */
605         _x('Editor', 'User role');
606         /* translators: user role */
607         _x('Author', 'User role');
608         /* translators: user role */
609         _x('Contributor', 'User role');
610         /* translators: user role */
611         _x('Subscriber', 'User role');
612
613         add_role('administrator', 'Administrator');
614         add_role('editor', 'Editor');
615         add_role('author', 'Author');
616         add_role('contributor', 'Contributor');
617         add_role('subscriber', 'Subscriber');
618
619         // Add caps for Administrator role
620         $role = get_role('administrator');
621         $role->add_cap('switch_themes');
622         $role->add_cap('edit_themes');
623         $role->add_cap('activate_plugins');
624         $role->add_cap('edit_plugins');
625         $role->add_cap('edit_users');
626         $role->add_cap('edit_files');
627         $role->add_cap('manage_options');
628         $role->add_cap('moderate_comments');
629         $role->add_cap('manage_categories');
630         $role->add_cap('manage_links');
631         $role->add_cap('upload_files');
632         $role->add_cap('import');
633         $role->add_cap('unfiltered_html');
634         $role->add_cap('edit_posts');
635         $role->add_cap('edit_others_posts');
636         $role->add_cap('edit_published_posts');
637         $role->add_cap('publish_posts');
638         $role->add_cap('edit_pages');
639         $role->add_cap('read');
640         $role->add_cap('level_10');
641         $role->add_cap('level_9');
642         $role->add_cap('level_8');
643         $role->add_cap('level_7');
644         $role->add_cap('level_6');
645         $role->add_cap('level_5');
646         $role->add_cap('level_4');
647         $role->add_cap('level_3');
648         $role->add_cap('level_2');
649         $role->add_cap('level_1');
650         $role->add_cap('level_0');
651
652         // Add caps for Editor role
653         $role = get_role('editor');
654         $role->add_cap('moderate_comments');
655         $role->add_cap('manage_categories');
656         $role->add_cap('manage_links');
657         $role->add_cap('upload_files');
658         $role->add_cap('unfiltered_html');
659         $role->add_cap('edit_posts');
660         $role->add_cap('edit_others_posts');
661         $role->add_cap('edit_published_posts');
662         $role->add_cap('publish_posts');
663         $role->add_cap('edit_pages');
664         $role->add_cap('read');
665         $role->add_cap('level_7');
666         $role->add_cap('level_6');
667         $role->add_cap('level_5');
668         $role->add_cap('level_4');
669         $role->add_cap('level_3');
670         $role->add_cap('level_2');
671         $role->add_cap('level_1');
672         $role->add_cap('level_0');
673
674         // Add caps for Author role
675         $role = get_role('author');
676         $role->add_cap('upload_files');
677         $role->add_cap('edit_posts');
678         $role->add_cap('edit_published_posts');
679         $role->add_cap('publish_posts');
680         $role->add_cap('read');
681         $role->add_cap('level_2');
682         $role->add_cap('level_1');
683         $role->add_cap('level_0');
684
685         // Add caps for Contributor role
686         $role = get_role('contributor');
687         $role->add_cap('edit_posts');
688         $role->add_cap('read');
689         $role->add_cap('level_1');
690         $role->add_cap('level_0');
691
692         // Add caps for Subscriber role
693         $role = get_role('subscriber');
694         $role->add_cap('read');
695         $role->add_cap('level_0');
696 }
697
698 /**
699  * Create and modify WordPress roles for WordPress 2.1.
700  *
701  * @since 2.1.0
702  */
703 function populate_roles_210() {
704         $roles = array('administrator', 'editor');
705         foreach ($roles as $role) {
706                 $role = get_role($role);
707                 if ( empty($role) )
708                         continue;
709
710                 $role->add_cap('edit_others_pages');
711                 $role->add_cap('edit_published_pages');
712                 $role->add_cap('publish_pages');
713                 $role->add_cap('delete_pages');
714                 $role->add_cap('delete_others_pages');
715                 $role->add_cap('delete_published_pages');
716                 $role->add_cap('delete_posts');
717                 $role->add_cap('delete_others_posts');
718                 $role->add_cap('delete_published_posts');
719                 $role->add_cap('delete_private_posts');
720                 $role->add_cap('edit_private_posts');
721                 $role->add_cap('read_private_posts');
722                 $role->add_cap('delete_private_pages');
723                 $role->add_cap('edit_private_pages');
724                 $role->add_cap('read_private_pages');
725         }
726
727         $role = get_role('administrator');
728         if ( ! empty($role) ) {
729                 $role->add_cap('delete_users');
730                 $role->add_cap('create_users');
731         }
732
733         $role = get_role('author');
734         if ( ! empty($role) ) {
735                 $role->add_cap('delete_posts');
736                 $role->add_cap('delete_published_posts');
737         }
738
739         $role = get_role('contributor');
740         if ( ! empty($role) ) {
741                 $role->add_cap('delete_posts');
742         }
743 }
744
745 /**
746  * Create and modify WordPress roles for WordPress 2.3.
747  *
748  * @since 2.3.0
749  */
750 function populate_roles_230() {
751         $role = get_role( 'administrator' );
752
753         if ( !empty( $role ) ) {
754                 $role->add_cap( 'unfiltered_upload' );
755         }
756 }
757
758 /**
759  * Create and modify WordPress roles for WordPress 2.5.
760  *
761  * @since 2.5.0
762  */
763 function populate_roles_250() {
764         $role = get_role( 'administrator' );
765
766         if ( !empty( $role ) ) {
767                 $role->add_cap( 'edit_dashboard' );
768         }
769 }
770
771 /**
772  * Create and modify WordPress roles for WordPress 2.6.
773  *
774  * @since 2.6.0
775  */
776 function populate_roles_260() {
777         $role = get_role( 'administrator' );
778
779         if ( !empty( $role ) ) {
780                 $role->add_cap( 'update_plugins' );
781                 $role->add_cap( 'delete_plugins' );
782         }
783 }
784
785 /**
786  * Create and modify WordPress roles for WordPress 2.7.
787  *
788  * @since 2.7.0
789  */
790 function populate_roles_270() {
791         $role = get_role( 'administrator' );
792
793         if ( !empty( $role ) ) {
794                 $role->add_cap( 'install_plugins' );
795                 $role->add_cap( 'update_themes' );
796         }
797 }
798
799 /**
800  * Create and modify WordPress roles for WordPress 2.8.
801  *
802  * @since 2.8.0
803  */
804 function populate_roles_280() {
805         $role = get_role( 'administrator' );
806
807         if ( !empty( $role ) ) {
808                 $role->add_cap( 'install_themes' );
809         }
810 }
811
812 /**
813  * Create and modify WordPress roles for WordPress 3.0.
814  *
815  * @since 3.0.0
816  */
817 function populate_roles_300() {
818         $role = get_role( 'administrator' );
819
820         if ( !empty( $role ) ) {
821                 $role->add_cap( 'update_core' );
822                 $role->add_cap( 'list_users' );
823                 $role->add_cap( 'remove_users' );
824
825                 /*
826                  * Never used, will be removed. create_users or promote_users
827                  * is the capability you're looking for.
828                  */
829                 $role->add_cap( 'add_users' );
830
831                 $role->add_cap( 'promote_users' );
832                 $role->add_cap( 'edit_theme_options' );
833                 $role->add_cap( 'delete_themes' );
834                 $role->add_cap( 'export' );
835         }
836 }
837
838 /**
839  * Install Network.
840  *
841  * @since 3.0.0
842  *
843  */
844 if ( !function_exists( 'install_network' ) ) :
845 function install_network() {
846         if ( ! defined( 'WP_INSTALLING_NETWORK' ) )
847                 define( 'WP_INSTALLING_NETWORK', true );
848
849         dbDelta( wp_get_db_schema( 'global' ) );
850 }
851 endif;
852
853 /**
854  * Populate network settings.
855  *
856  * @since 3.0.0
857  *
858  * @param int $network_id ID of network to populate.
859  * @return bool|WP_Error True on success, or WP_Error on warning (with the install otherwise successful,
860  *                       so the error code must be checked) or failure.
861  */
862 function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
863         global $wpdb, $current_site, $wp_db_version, $wp_rewrite;
864
865         $errors = new WP_Error();
866         if ( '' == $domain )
867                 $errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
868         if ( '' == $site_name )
869                 $errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
870
871         // Check for network collision.
872         if ( $network_id == $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id ) ) )
873                 $errors->add( 'siteid_exists', __( 'The network already exists.' ) );
874
875         $site_user = get_user_by( 'email', $email );
876         if ( ! is_email( $email ) )
877                 $errors->add( 'invalid_email', __( 'You must provide a valid e-mail address.' ) );
878
879         if ( $errors->get_error_code() )
880                 return $errors;
881
882         // Set up site tables.
883         $template = get_option( 'template' );
884         $stylesheet = get_option( 'stylesheet' );
885         $allowed_themes = array( $stylesheet => true );
886         if ( $template != $stylesheet )
887                 $allowed_themes[ $template ] = true;
888         if ( WP_DEFAULT_THEME != $stylesheet && WP_DEFAULT_THEME != $template )
889                 $allowed_themes[ WP_DEFAULT_THEME ] = true;
890
891         if ( 1 == $network_id ) {
892                 $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path ) );
893                 $network_id = $wpdb->insert_id;
894         } else {
895                 $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path, 'id' => $network_id ) );
896         }
897
898         wp_cache_delete( 'networks_have_paths', 'site-options' );
899
900         if ( !is_multisite() ) {
901                 $site_admins = array( $site_user->user_login );
902                 $users = get_users( array( 'fields' => array( 'ID', 'user_login' ) ) );
903                 if ( $users ) {
904                         foreach ( $users as $user ) {
905                                 if ( is_super_admin( $user->ID ) && !in_array( $user->user_login, $site_admins ) )
906                                         $site_admins[] = $user->user_login;
907                         }
908                 }
909         } else {
910                 $site_admins = get_site_option( 'site_admins' );
911         }
912
913         $welcome_email = __( 'Dear User,
914
915 Your new SITE_NAME site has been successfully set up at:
916 BLOG_URL
917
918 You can log in to the administrator account with the following information:
919
920 Username: USERNAME
921 Password: PASSWORD
922 Log in here: BLOG_URLwp-login.php
923
924 We hope you enjoy your new site. Thanks!
925
926 --The Team @ SITE_NAME' );
927
928         $misc_exts = array(
929                 // Images.
930                 'jpg', 'jpeg', 'png', 'gif',
931                 // Video.
932                 'mov', 'avi', 'mpg', '3gp', '3g2',
933                 // "audio".
934                 'midi', 'mid',
935                 // Miscellaneous.
936                 'pdf', 'doc', 'ppt', 'odt', 'pptx', 'docx', 'pps', 'ppsx', 'xls', 'xlsx', 'key',
937         );
938         $audio_exts = wp_get_audio_extensions();
939         $video_exts = wp_get_video_extensions();
940         $upload_filetypes = array_unique( array_merge( $misc_exts, $audio_exts, $video_exts ) );
941
942         $sitemeta = array(
943                 'site_name' => $site_name,
944                 'admin_email' => $site_user->user_email,
945                 'admin_user_id' => $site_user->ID,
946                 'registration' => 'none',
947                 'upload_filetypes' => implode( ' ', $upload_filetypes ),
948                 'blog_upload_space' => 100,
949                 'fileupload_maxk' => 1500,
950                 'site_admins' => $site_admins,
951                 'allowedthemes' => $allowed_themes,
952                 'illegal_names' => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
953                 'wpmu_upgrade_site' => $wp_db_version,
954                 'welcome_email' => $welcome_email,
955                 'first_post' => __( 'Welcome to <a href="SITE_URL">SITE_NAME</a>. This is your first post. Edit or delete it, then start blogging!' ),
956                 // @todo - network admins should have a method of editing the network siteurl (used for cookie hash)
957                 'siteurl' => get_option( 'siteurl' ) . '/',
958                 'add_new_users' => '0',
959                 'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1',
960                 'subdomain_install' => intval( $subdomain_install ),
961                 'global_terms_enabled' => global_terms_enabled() ? '1' : '0',
962                 'ms_files_rewriting' => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0',
963                 'initial_db_version' => get_option( 'initial_db_version' ),
964                 'active_sitewide_plugins' => array(),
965                 'WPLANG' => get_locale(),
966         );
967         if ( ! $subdomain_install )
968                 $sitemeta['illegal_names'][] = 'blog';
969
970         /**
971          * Filter meta for a network on creation.
972          *
973          * @since 3.7.0
974          *
975          * @param array $sitemeta   Associative array of network meta keys and values to be inserted.
976          * @param int   $network_id ID of network to populate.
977          */
978         $sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id );
979
980         $insert = '';
981         foreach ( $sitemeta as $meta_key => $meta_value ) {
982                 if ( is_array( $meta_value ) )
983                         $meta_value = serialize( $meta_value );
984                 if ( !empty( $insert ) )
985                         $insert .= ', ';
986                 $insert .= $wpdb->prepare( "( %d, %s, %s)", $network_id, $meta_key, $meta_value );
987         }
988         $wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert );
989
990         /*
991          * When upgrading from single to multisite, assume the current site will
992          * become the main site of the network. When using populate_network()
993          * to create another network in an existing multisite environment, skip
994          * these steps since the main site of the new network has not yet been
995          * created.
996          */
997         if ( ! is_multisite() ) {
998                 $current_site = new stdClass;
999                 $current_site->domain = $domain;
1000                 $current_site->path = $path;
1001                 $current_site->site_name = ucfirst( $domain );
1002                 $wpdb->insert( $wpdb->blogs, array( 'site_id' => $network_id, 'blog_id' => 1, 'domain' => $domain, 'path' => $path, 'registered' => current_time( 'mysql' ) ) );
1003                 $current_site->blog_id = $blog_id = $wpdb->insert_id;
1004                 update_user_meta( $site_user->ID, 'source_domain', $domain );
1005                 update_user_meta( $site_user->ID, 'primary_blog', $blog_id );
1006
1007                 if ( $subdomain_install )
1008                         $wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
1009                 else
1010                         $wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
1011
1012                 flush_rewrite_rules();
1013
1014                 if ( ! $subdomain_install )
1015                         return true;
1016
1017                 $vhost_ok = false;
1018                 $errstr = '';
1019                 $hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
1020                 $page = wp_remote_get( 'http://' . $hostname, array( 'timeout' => 5, 'httpversion' => '1.1' ) );
1021                 if ( is_wp_error( $page ) )
1022                         $errstr = $page->get_error_message();
1023                 elseif ( 200 == wp_remote_retrieve_response_code( $page ) )
1024                                 $vhost_ok = true;
1025
1026                 if ( ! $vhost_ok ) {
1027                         $msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';
1028                         $msg .= '<p>' . sprintf( __( 'The installer attempted to contact a random hostname (<code>%1$s</code>) on your domain.' ), $hostname );
1029                         if ( ! empty ( $errstr ) )
1030                                 $msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
1031                         $msg .= '</p>';
1032                         $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>';
1033                         $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>';
1034                         return new WP_Error( 'no_wildcard_dns', $msg );
1035                 }
1036         }
1037
1038         return true;
1039 }