Wordpress 3.2
[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  * The database character collate.
13  * @var string
14  * @global string
15  * @name $charset_collate
16  */
17 $charset_collate = '';
18
19 // Declare these as global in case schema.php is included from a function.
20 global $wpdb, $wp_queries;
21
22 if ( ! empty($wpdb->charset) )
23         $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
24 if ( ! empty($wpdb->collate) )
25         $charset_collate .= " COLLATE $wpdb->collate";
26
27 /** Create WordPress database tables SQL */
28 $wp_queries = "CREATE TABLE $wpdb->terms (
29  term_id bigint(20) unsigned NOT NULL auto_increment,
30  name varchar(200) NOT NULL default '',
31  slug varchar(200) NOT NULL default '',
32  term_group bigint(10) NOT NULL default 0,
33  PRIMARY KEY  (term_id),
34  UNIQUE KEY slug (slug),
35  KEY name (name)
36 ) $charset_collate;
37 CREATE TABLE $wpdb->term_taxonomy (
38  term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
39  term_id bigint(20) unsigned NOT NULL default 0,
40  taxonomy varchar(32) NOT NULL default '',
41  description longtext NOT NULL,
42  parent bigint(20) unsigned NOT NULL default 0,
43  count bigint(20) NOT NULL default 0,
44  PRIMARY KEY  (term_taxonomy_id),
45  UNIQUE KEY term_id_taxonomy (term_id,taxonomy),
46  KEY taxonomy (taxonomy)
47 ) $charset_collate;
48 CREATE TABLE $wpdb->term_relationships (
49  object_id bigint(20) unsigned NOT NULL default 0,
50  term_taxonomy_id bigint(20) unsigned NOT NULL default 0,
51  term_order int(11) NOT NULL default 0,
52  PRIMARY KEY  (object_id,term_taxonomy_id),
53  KEY term_taxonomy_id (term_taxonomy_id)
54 ) $charset_collate;
55 CREATE TABLE $wpdb->commentmeta (
56   meta_id bigint(20) unsigned NOT NULL auto_increment,
57   comment_id bigint(20) unsigned NOT NULL default '0',
58   meta_key varchar(255) default NULL,
59   meta_value longtext,
60   PRIMARY KEY  (meta_id),
61   KEY comment_id (comment_id),
62   KEY meta_key (meta_key)
63 ) $charset_collate;
64 CREATE TABLE $wpdb->comments (
65   comment_ID bigint(20) unsigned NOT NULL auto_increment,
66   comment_post_ID bigint(20) unsigned NOT NULL default '0',
67   comment_author tinytext NOT NULL,
68   comment_author_email varchar(100) NOT NULL default '',
69   comment_author_url varchar(200) NOT NULL default '',
70   comment_author_IP varchar(100) NOT NULL default '',
71   comment_date datetime NOT NULL default '0000-00-00 00:00:00',
72   comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
73   comment_content text NOT NULL,
74   comment_karma int(11) NOT NULL default '0',
75   comment_approved varchar(20) NOT NULL default '1',
76   comment_agent varchar(255) NOT NULL default '',
77   comment_type varchar(20) NOT NULL default '',
78   comment_parent bigint(20) unsigned NOT NULL default '0',
79   user_id bigint(20) unsigned NOT NULL default '0',
80   PRIMARY KEY  (comment_ID),
81   KEY comment_approved (comment_approved),
82   KEY comment_post_ID (comment_post_ID),
83   KEY comment_approved_date_gmt (comment_approved,comment_date_gmt),
84   KEY comment_date_gmt (comment_date_gmt),
85   KEY comment_parent (comment_parent)
86 ) $charset_collate;
87 CREATE TABLE $wpdb->links (
88   link_id bigint(20) unsigned NOT NULL auto_increment,
89   link_url varchar(255) NOT NULL default '',
90   link_name varchar(255) NOT NULL default '',
91   link_image varchar(255) NOT NULL default '',
92   link_target varchar(25) NOT NULL default '',
93   link_description varchar(255) NOT NULL default '',
94   link_visible varchar(20) NOT NULL default 'Y',
95   link_owner bigint(20) unsigned NOT NULL default '1',
96   link_rating int(11) NOT NULL default '0',
97   link_updated datetime NOT NULL default '0000-00-00 00:00:00',
98   link_rel varchar(255) NOT NULL default '',
99   link_notes mediumtext NOT NULL,
100   link_rss varchar(255) NOT NULL default '',
101   PRIMARY KEY  (link_id),
102   KEY link_visible (link_visible)
103 ) $charset_collate;
104 CREATE TABLE $wpdb->options (
105   option_id bigint(20) unsigned NOT NULL auto_increment,
106   blog_id int(11) NOT NULL default '0',
107   option_name varchar(64) NOT NULL default '',
108   option_value longtext NOT NULL,
109   autoload varchar(20) NOT NULL default 'yes',
110   PRIMARY KEY  (option_id),
111   UNIQUE KEY option_name (option_name)
112 ) $charset_collate;
113 CREATE TABLE $wpdb->postmeta (
114   meta_id bigint(20) unsigned NOT NULL auto_increment,
115   post_id bigint(20) unsigned NOT NULL default '0',
116   meta_key varchar(255) default NULL,
117   meta_value longtext,
118   PRIMARY KEY  (meta_id),
119   KEY post_id (post_id),
120   KEY meta_key (meta_key)
121 ) $charset_collate;
122 CREATE TABLE $wpdb->posts (
123   ID bigint(20) unsigned NOT NULL auto_increment,
124   post_author bigint(20) unsigned NOT NULL default '0',
125   post_date datetime NOT NULL default '0000-00-00 00:00:00',
126   post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
127   post_content longtext NOT NULL,
128   post_title text NOT NULL,
129   post_excerpt text NOT NULL,
130   post_status varchar(20) NOT NULL default 'publish',
131   comment_status varchar(20) NOT NULL default 'open',
132   ping_status varchar(20) NOT NULL default 'open',
133   post_password varchar(20) NOT NULL default '',
134   post_name varchar(200) NOT NULL default '',
135   to_ping text NOT NULL,
136   pinged text NOT NULL,
137   post_modified datetime NOT NULL default '0000-00-00 00:00:00',
138   post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
139   post_content_filtered text NOT NULL,
140   post_parent bigint(20) unsigned NOT NULL default '0',
141   guid varchar(255) NOT NULL default '',
142   menu_order int(11) NOT NULL default '0',
143   post_type varchar(20) NOT NULL default 'post',
144   post_mime_type varchar(100) NOT NULL default '',
145   comment_count bigint(20) NOT NULL default '0',
146   PRIMARY KEY  (ID),
147   KEY post_name (post_name),
148   KEY type_status_date (post_type,post_status,post_date,ID),
149   KEY post_parent (post_parent),
150   KEY post_author (post_author)
151 ) $charset_collate;
152 CREATE TABLE $wpdb->users (
153   ID bigint(20) unsigned NOT NULL auto_increment,
154   user_login varchar(60) NOT NULL default '',
155   user_pass varchar(64) NOT NULL default '',
156   user_nicename varchar(50) NOT NULL default '',
157   user_email varchar(100) NOT NULL default '',
158   user_url varchar(100) NOT NULL default '',
159   user_registered datetime NOT NULL default '0000-00-00 00:00:00',
160   user_activation_key varchar(60) NOT NULL default '',
161   user_status int(11) NOT NULL default '0',
162   display_name varchar(250) NOT NULL default '',
163   PRIMARY KEY  (ID),
164   KEY user_login_key (user_login),
165   KEY user_nicename (user_nicename)
166 ) $charset_collate;
167 CREATE TABLE $wpdb->usermeta (
168   umeta_id bigint(20) unsigned NOT NULL auto_increment,
169   user_id bigint(20) unsigned NOT NULL default '0',
170   meta_key varchar(255) default NULL,
171   meta_value longtext,
172   PRIMARY KEY  (umeta_id),
173   KEY user_id (user_id),
174   KEY meta_key (meta_key)
175 ) $charset_collate;";
176
177 /**
178  * Create WordPress options and set the default values.
179  *
180  * @since 1.5.0
181  * @uses $wpdb
182  * @uses $wp_db_version
183  */
184 function populate_options() {
185         global $wpdb, $wp_db_version, $current_site;
186
187         $guessurl = wp_guess_url();
188
189         do_action('populate_options');
190
191         if ( ini_get('safe_mode') ) {
192                 // Safe mode can break mkdir() so use a flat structure by default.
193                 $uploads_use_yearmonth_folders = 0;
194         } else {
195                 $uploads_use_yearmonth_folders = 1;
196         }
197
198         $options = array(
199         'siteurl' => $guessurl,
200         'blogname' => __('My Site'),
201         /* translators: blog tagline */
202         'blogdescription' => __('Just another WordPress site'),
203         'users_can_register' => 0,
204         'admin_email' => 'you@example.com',
205         'start_of_week' => 1,
206         'use_balanceTags' => 0,
207         'use_smilies' => 1,
208         'require_name_email' => 1,
209         'comments_notify' => 1,
210         'posts_per_rss' => 10,
211         'rss_use_excerpt' => 0,
212         'mailserver_url' => 'mail.example.com',
213         'mailserver_login' => 'login@example.com',
214         'mailserver_pass' => 'password',
215         'mailserver_port' => 110,
216         'default_category' => 1,
217         'default_comment_status' => 'open',
218         'default_ping_status' => 'open',
219         'default_pingback_flag' => 1,
220         'default_post_edit_rows' => 20,
221         'posts_per_page' => 10,
222         /* translators: default date format, see http://php.net/date */
223         'date_format' => __('F j, Y'),
224         /* translators: default time format, see http://php.net/date */
225         'time_format' => __('g:i a'),
226         /* translators: links last updated date format, see http://php.net/date */
227         'links_updated_date_format' => __('F j, Y g:i a'),
228         'links_recently_updated_prepend' => '<em>',
229         'links_recently_updated_append' => '</em>',
230         'links_recently_updated_time' => 120,
231         'comment_moderation' => 0,
232         'moderation_notify' => 1,
233         'permalink_structure' => '',
234         'gzipcompression' => 0,
235         'hack_file' => 0,
236         'blog_charset' => 'UTF-8',
237         'moderation_keys' => '',
238         'active_plugins' => array(),
239         'home' => $guessurl,
240         'category_base' => '',
241         'ping_sites' => 'http://rpc.pingomatic.com/',
242         'advanced_edit' => 0,
243         'comment_max_links' => 2,
244         'gmt_offset' => date('Z') / 3600,
245
246         // 1.5
247         'default_email_category' => 1,
248         'recently_edited' => '',
249         'template' => WP_DEFAULT_THEME,
250         'stylesheet' => WP_DEFAULT_THEME,
251         'comment_whitelist' => 1,
252         'blacklist_keys' => '',
253         'comment_registration' => 0,
254         'rss_language' => 'en',
255         'html_type' => 'text/html',
256
257         // 1.5.1
258         'use_trackback' => 0,
259
260         // 2.0
261         'default_role' => 'subscriber',
262         'db_version' => $wp_db_version,
263
264         // 2.0.1
265         'uploads_use_yearmonth_folders' => $uploads_use_yearmonth_folders,
266         'upload_path' => '',
267
268         // 2.1
269         'blog_public' => '1',
270         'default_link_category' => 2,
271         'show_on_front' => 'posts',
272
273         // 2.2
274         'tag_base' => '',
275
276         // 2.5
277         'show_avatars' => '1',
278         'avatar_rating' => 'G',
279         'upload_url_path' => '',
280         'thumbnail_size_w' => 150,
281         'thumbnail_size_h' => 150,
282         'thumbnail_crop' => 1,
283         'medium_size_w' => 300,
284         'medium_size_h' => 300,
285
286         // 2.6
287         'avatar_default' => 'mystery',
288         'enable_app' => 0,
289         'enable_xmlrpc' => 0,
290
291         // 2.7
292         'large_size_w' => 1024,
293         'large_size_h' => 1024,
294         'image_default_link_type' => 'file',
295         'image_default_size' => '',
296         'image_default_align' => '',
297         'close_comments_for_old_posts' => 0,
298         'close_comments_days_old' => 14,
299         'thread_comments' => 1,
300         'thread_comments_depth' => 5,
301         'page_comments' => 0,
302         'comments_per_page' => 50,
303         'default_comments_page' => 'newest',
304         'comment_order' => 'asc',
305         'sticky_posts' => array(),
306         'widget_categories' => array(),
307         'widget_text' => array(),
308         'widget_rss' => array(),
309
310         // 2.8
311         'timezone_string' => '',
312
313         // 2.9
314         'embed_autourls' => 1,
315         'embed_size_w' => '',
316         'embed_size_h' => 600,
317
318         // 3.0
319         'page_for_posts' => 0,
320         'page_on_front' => 0,
321
322         // 3.1
323         'default_post_format' => 0,
324         );
325
326         // 3.0 multisite
327         if ( is_multisite() ) {
328                 /* translators: blog tagline */
329                 $options[ 'blogdescription' ] = sprintf(__('Just another %s site'), $current_site->site_name );
330                 $options[ 'permalink_structure' ] = '/%year%/%monthnum%/%day%/%postname%/';
331         }
332
333         // Set autoload to no for these options
334         $fat_options = array( 'moderation_keys', 'recently_edited', 'blacklist_keys' );
335
336         $existing_options = $wpdb->get_col("SELECT option_name FROM $wpdb->options");
337
338         $insert = '';
339         foreach ( $options as $option => $value ) {
340                 if ( in_array($option, $existing_options) )
341                         continue;
342                 if ( in_array($option, $fat_options) )
343                         $autoload = 'no';
344                 else
345                         $autoload = 'yes';
346
347                 $option = $wpdb->escape($option);
348                 if ( is_array($value) )
349                         $value = serialize($value);
350                 $value = $wpdb->escape($value);
351                 if ( !empty($insert) )
352                         $insert .= ', ';
353                 $insert .= "('$option', '$value', '$autoload')";
354         }
355
356         if ( !empty($insert) )
357                 $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert);
358
359         // in case it is set, but blank, update "home"
360         if ( !__get_option('home') ) update_option('home', $guessurl);
361
362         // Delete unused options
363         $unusedoptions = array ('blodotgsping_url', 'bodyterminator', 'emailtestonly', 'phoneemail_separator', 'smilies_directory', 'subjectprefix', 'use_bbcode', 'use_blodotgsping', 'use_phoneemail', 'use_quicktags', 'use_weblogsping', 'weblogs_cache_file', 'use_preview', 'use_htmltrans', 'smilies_directory', 'fileupload_allowedusers', 'use_phoneemail', 'default_post_status', 'default_post_category', 'archive_mode', 'time_difference', 'links_minadminlevel', 'links_use_adminlevels', 'links_rating_type', 'links_rating_char', 'links_rating_ignore_zero', 'links_rating_single_image', 'links_rating_image0', 'links_rating_image1', 'links_rating_image2', 'links_rating_image3', 'links_rating_image4', 'links_rating_image5', 'links_rating_image6', 'links_rating_image7', 'links_rating_image8', 'links_rating_image9', 'weblogs_cacheminutes', 'comment_allowed_tags', 'search_engine_friendly_urls', 'default_geourl_lat', 'default_geourl_lon', 'use_default_geourl', 'weblogs_xml_url', 'new_users_can_blog', '_wpnonce', '_wp_http_referer', 'Update', 'action', 'rich_editing', 'autosave_interval', 'deactivated_plugins', 'can_compress_scripts', 'page_uris', 'update_core', 'update_plugins', 'update_themes', 'doing_cron', 'random_seed', 'rss_excerpt_length', 'secret', 'use_linksupdate', 'default_comment_status_page', 'wporg_popular_tags', 'what_to_show');
364         foreach ( $unusedoptions as $option )
365                 delete_option($option);
366
367         // delete obsolete magpie stuff
368         $wpdb->query("DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'");
369 }
370
371 /**
372  * Execute WordPress role creation for the various WordPress versions.
373  *
374  * @since 2.0.0
375  */
376 function populate_roles() {
377         populate_roles_160();
378         populate_roles_210();
379         populate_roles_230();
380         populate_roles_250();
381         populate_roles_260();
382         populate_roles_270();
383         populate_roles_280();
384         populate_roles_300();
385 }
386
387 /**
388  * Create the roles for WordPress 2.0
389  *
390  * @since 2.0.0
391  */
392 function populate_roles_160() {
393         // Add roles
394
395         // Dummy gettext calls to get strings in the catalog.
396         /* translators: user role */
397         _x('Administrator', 'User role');
398         /* translators: user role */
399         _x('Editor', 'User role');
400         /* translators: user role */
401         _x('Author', 'User role');
402         /* translators: user role */
403         _x('Contributor', 'User role');
404         /* translators: user role */
405         _x('Subscriber', 'User role');
406
407         add_role('administrator', 'Administrator');
408         add_role('editor', 'Editor');
409         add_role('author', 'Author');
410         add_role('contributor', 'Contributor');
411         add_role('subscriber', 'Subscriber');
412
413         // Add caps for Administrator role
414         $role =& get_role('administrator');
415         $role->add_cap('switch_themes');
416         $role->add_cap('edit_themes');
417         $role->add_cap('activate_plugins');
418         $role->add_cap('edit_plugins');
419         $role->add_cap('edit_users');
420         $role->add_cap('edit_files');
421         $role->add_cap('manage_options');
422         $role->add_cap('moderate_comments');
423         $role->add_cap('manage_categories');
424         $role->add_cap('manage_links');
425         $role->add_cap('upload_files');
426         $role->add_cap('import');
427         $role->add_cap('unfiltered_html');
428         $role->add_cap('edit_posts');
429         $role->add_cap('edit_others_posts');
430         $role->add_cap('edit_published_posts');
431         $role->add_cap('publish_posts');
432         $role->add_cap('edit_pages');
433         $role->add_cap('read');
434         $role->add_cap('level_10');
435         $role->add_cap('level_9');
436         $role->add_cap('level_8');
437         $role->add_cap('level_7');
438         $role->add_cap('level_6');
439         $role->add_cap('level_5');
440         $role->add_cap('level_4');
441         $role->add_cap('level_3');
442         $role->add_cap('level_2');
443         $role->add_cap('level_1');
444         $role->add_cap('level_0');
445
446         // Add caps for Editor role
447         $role =& get_role('editor');
448         $role->add_cap('moderate_comments');
449         $role->add_cap('manage_categories');
450         $role->add_cap('manage_links');
451         $role->add_cap('upload_files');
452         $role->add_cap('unfiltered_html');
453         $role->add_cap('edit_posts');
454         $role->add_cap('edit_others_posts');
455         $role->add_cap('edit_published_posts');
456         $role->add_cap('publish_posts');
457         $role->add_cap('edit_pages');
458         $role->add_cap('read');
459         $role->add_cap('level_7');
460         $role->add_cap('level_6');
461         $role->add_cap('level_5');
462         $role->add_cap('level_4');
463         $role->add_cap('level_3');
464         $role->add_cap('level_2');
465         $role->add_cap('level_1');
466         $role->add_cap('level_0');
467
468         // Add caps for Author role
469         $role =& get_role('author');
470         $role->add_cap('upload_files');
471         $role->add_cap('edit_posts');
472         $role->add_cap('edit_published_posts');
473         $role->add_cap('publish_posts');
474         $role->add_cap('read');
475         $role->add_cap('level_2');
476         $role->add_cap('level_1');
477         $role->add_cap('level_0');
478
479         // Add caps for Contributor role
480         $role =& get_role('contributor');
481         $role->add_cap('edit_posts');
482         $role->add_cap('read');
483         $role->add_cap('level_1');
484         $role->add_cap('level_0');
485
486         // Add caps for Subscriber role
487         $role =& get_role('subscriber');
488         $role->add_cap('read');
489         $role->add_cap('level_0');
490 }
491
492 /**
493  * Create and modify WordPress roles for WordPress 2.1.
494  *
495  * @since 2.1.0
496  */
497 function populate_roles_210() {
498         $roles = array('administrator', 'editor');
499         foreach ($roles as $role) {
500                 $role =& get_role($role);
501                 if ( empty($role) )
502                         continue;
503
504                 $role->add_cap('edit_others_pages');
505                 $role->add_cap('edit_published_pages');
506                 $role->add_cap('publish_pages');
507                 $role->add_cap('delete_pages');
508                 $role->add_cap('delete_others_pages');
509                 $role->add_cap('delete_published_pages');
510                 $role->add_cap('delete_posts');
511                 $role->add_cap('delete_others_posts');
512                 $role->add_cap('delete_published_posts');
513                 $role->add_cap('delete_private_posts');
514                 $role->add_cap('edit_private_posts');
515                 $role->add_cap('read_private_posts');
516                 $role->add_cap('delete_private_pages');
517                 $role->add_cap('edit_private_pages');
518                 $role->add_cap('read_private_pages');
519         }
520
521         $role =& get_role('administrator');
522         if ( ! empty($role) ) {
523                 $role->add_cap('delete_users');
524                 $role->add_cap('create_users');
525         }
526
527         $role =& get_role('author');
528         if ( ! empty($role) ) {
529                 $role->add_cap('delete_posts');
530                 $role->add_cap('delete_published_posts');
531         }
532
533         $role =& get_role('contributor');
534         if ( ! empty($role) ) {
535                 $role->add_cap('delete_posts');
536         }
537 }
538
539 /**
540  * Create and modify WordPress roles for WordPress 2.3.
541  *
542  * @since 2.3.0
543  */
544 function populate_roles_230() {
545         $role =& get_role( 'administrator' );
546
547         if ( !empty( $role ) ) {
548                 $role->add_cap( 'unfiltered_upload' );
549         }
550 }
551
552 /**
553  * Create and modify WordPress roles for WordPress 2.5.
554  *
555  * @since 2.5.0
556  */
557 function populate_roles_250() {
558         $role =& get_role( 'administrator' );
559
560         if ( !empty( $role ) ) {
561                 $role->add_cap( 'edit_dashboard' );
562         }
563 }
564
565 /**
566  * Create and modify WordPress roles for WordPress 2.6.
567  *
568  * @since 2.6.0
569  */
570 function populate_roles_260() {
571         $role =& get_role( 'administrator' );
572
573         if ( !empty( $role ) ) {
574                 $role->add_cap( 'update_plugins' );
575                 $role->add_cap( 'delete_plugins' );
576         }
577 }
578
579 /**
580  * Create and modify WordPress roles for WordPress 2.7.
581  *
582  * @since 2.7.0
583  */
584 function populate_roles_270() {
585         $role =& get_role( 'administrator' );
586
587         if ( !empty( $role ) ) {
588                 $role->add_cap( 'install_plugins' );
589                 $role->add_cap( 'update_themes' );
590         }
591 }
592
593 /**
594  * Create and modify WordPress roles for WordPress 2.8.
595  *
596  * @since 2.8.0
597  */
598 function populate_roles_280() {
599         $role =& get_role( 'administrator' );
600
601         if ( !empty( $role ) ) {
602                 $role->add_cap( 'install_themes' );
603         }
604 }
605
606 /**
607  * Create and modify WordPress roles for WordPress 3.0.
608  *
609  * @since 3.0.0
610  */
611 function populate_roles_300() {
612         $role =& get_role( 'administrator' );
613
614         if ( !empty( $role ) ) {
615                 $role->add_cap( 'update_core' );
616                 $role->add_cap( 'list_users' );
617                 $role->add_cap( 'remove_users' );
618                 $role->add_cap( 'add_users' );
619                 $role->add_cap( 'promote_users' );
620                 $role->add_cap( 'edit_theme_options' );
621                 $role->add_cap( 'delete_themes' );
622                 $role->add_cap( 'export' );
623         }
624 }
625
626 /**
627  * populate network settings
628  *
629  * @since 3.0.0
630  *
631  * @param int $network_id id of network to populate
632  * @return bool|WP_Error True on success, or WP_Error on warning (with the install otherwise successful,
633  *      so the error code must be checked) or failure.
634  */
635 function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
636         global $wpdb, $current_site, $wp_db_version, $wp_rewrite;
637
638         $errors = new WP_Error();
639         if ( '' == $domain )
640                 $errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
641         if ( '' == $site_name )
642                 $errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
643
644         // check for network collision
645         if ( $network_id == $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id ) ) )
646                 $errors->add( 'siteid_exists', __( 'The network already exists.' ) );
647
648         $site_user = get_user_by_email( $email );
649         if ( ! is_email( $email ) )
650                 $errors->add( 'invalid_email', __( 'You must provide a valid e-mail address.' ) );
651
652         if ( $errors->get_error_code() )
653                 return $errors;
654
655         // set up site tables
656         $template = get_option( 'template' );
657         $stylesheet = get_option( 'stylesheet' );
658         $allowed_themes = array( $stylesheet => true );
659         if ( $template != $stylesheet )
660                 $allowed_themes[ $template ] = true;
661         if ( WP_DEFAULT_THEME != $stylesheet && WP_DEFAULT_THEME != $template )
662                 $allowed_themes[ WP_DEFAULT_THEME ] = true;
663
664         if ( 1 == $network_id ) {
665                 $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path ) );
666                 $network_id = $wpdb->insert_id;
667         } else {
668                 $wpdb->insert( $wpdb->site, array( 'domain' => $domain, 'path' => $path, 'id' => $network_id ) );
669         }
670
671         if ( !is_multisite() ) {
672                 $site_admins = array( $site_user->user_login );
673                 $users = get_users( array( 'fields' => array( 'ID', 'user_login' ) ) );
674                 if ( $users ) {
675                         foreach ( $users as $user ) {
676                                 if ( is_super_admin( $user->ID ) && !in_array( $user->user_login, $site_admins ) )
677                                         $site_admins[] = $user->user_login;
678                         }
679                 }
680         } else {
681                 $site_admins = get_site_option( 'site_admins' );
682         }
683
684         $welcome_email = __( 'Dear User,
685
686 Your new SITE_NAME site has been successfully set up at:
687 BLOG_URL
688
689 You can log in to the administrator account with the following information:
690 Username: USERNAME
691 Password: PASSWORD
692 Log in Here: BLOG_URLwp-login.php
693
694 We hope you enjoy your new site.
695 Thanks!
696
697 --The Team @ SITE_NAME' );
698
699         $sitemeta = array(
700                 'site_name' => $site_name,
701                 'admin_email' => $site_user->user_email,
702                 'admin_user_id' => $site_user->ID,
703                 'registration' => 'none',
704                 'upload_filetypes' => 'jpg jpeg png gif mp3 mov avi wmv midi mid pdf',
705                 'blog_upload_space' => 10,
706                 'fileupload_maxk' => 1500,
707                 'site_admins' => $site_admins,
708                 'allowedthemes' => $allowed_themes,
709                 'illegal_names' => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
710                 'wpmu_upgrade_site' => $wp_db_version,
711                 'welcome_email' => $welcome_email,
712                 'first_post' => __( 'Welcome to <a href="SITE_URL">SITE_NAME</a>. This is your first post. Edit or delete it, then start blogging!' ),
713                 // @todo - network admins should have a method of editing the network siteurl (used for cookie hash)
714                 'siteurl' => get_option( 'siteurl' ) . '/',
715                 'add_new_users' => '0',
716                 'upload_space_check_disabled' => '0',
717                 'subdomain_install' => intval( $subdomain_install ),
718                 'global_terms_enabled' => global_terms_enabled() ? '1' : '0'
719         );
720         if ( ! $subdomain_install )
721                 $sitemeta['illegal_names'][] = 'blog';
722
723         $insert = '';
724         foreach ( $sitemeta as $meta_key => $meta_value ) {
725                 $meta_key = $wpdb->escape( $meta_key );
726                 if ( is_array( $meta_value ) )
727                         $meta_value = serialize( $meta_value );
728                 $meta_value = $wpdb->escape( $meta_value );
729                 if ( !empty( $insert ) )
730                         $insert .= ', ';
731                 $insert .= "( $network_id, '$meta_key', '$meta_value')";
732         }
733         $wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert );
734
735         $current_site->domain = $domain;
736         $current_site->path = $path;
737         $current_site->site_name = ucfirst( $domain );
738
739         if ( !is_multisite() ) {
740                 $wpdb->insert( $wpdb->blogs, array( 'site_id' => $network_id, 'domain' => $domain, 'path' => $path, 'registered' => current_time( 'mysql' ) ) );
741                 $blog_id = $wpdb->insert_id;
742                 update_user_meta( $site_user->ID, 'source_domain', $domain );
743                 update_user_meta( $site_user->ID, 'primary_blog', $blog_id );
744                 if ( !$upload_path = get_option( 'upload_path' ) ) {
745                         $upload_path = substr( WP_CONTENT_DIR, strlen( ABSPATH ) ) . '/uploads';
746                         update_option( 'upload_path', $upload_path );
747                 }
748                 update_option( 'fileupload_url', get_option( 'siteurl' ) . '/' . $upload_path );
749         }
750
751         if ( $subdomain_install )
752                 update_option( 'permalink_structure', '/%year%/%monthnum%/%day%/%postname%/');
753         else
754                 update_option( 'permalink_structure', '/blog/%year%/%monthnum%/%day%/%postname%/');
755
756         $wp_rewrite->flush_rules();
757
758         if ( $subdomain_install ) {
759                 $vhost_ok = false;
760                 $errstr = '';
761                 $hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
762                 $page = wp_remote_get( 'http://' . $hostname, array( 'timeout' => 5, 'httpversion' => '1.1' ) );
763                 if ( is_wp_error( $page ) )
764                         $errstr = $page->get_error_message();
765                 elseif ( 200 == wp_remote_retrieve_response_code( $page ) )
766                                 $vhost_ok = true;
767
768                 if ( ! $vhost_ok ) {
769                         $msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';
770                         $msg .= '<p>' . sprintf( __( 'The installer attempted to contact a random hostname (<code>%1$s</code>) on your domain.' ), $hostname );
771                         if ( ! empty ( $errstr ) )
772                                 $msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
773                         $msg .= '</p>';
774                         $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>';
775                         $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>';
776                         return new WP_Error( 'no_wildcard_dns', $msg );
777                 }
778         }
779
780         return true;
781 }
782
783 ?>