[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Site API 4 * 5 * @package WordPress 6 * @subpackage Multisite 7 * @since 5.1.0 8 */ 9 10 /** 11 * Inserts a new site into the database. 12 * 13 * @since 5.1.0 14 * 15 * @global wpdb $wpdb WordPress database abstraction object. 16 * 17 * @param array $data { 18 * Data for the new site that should be inserted. 19 * 20 * @type string $domain Site domain. Default empty string. 21 * @type string $path Site path. Default '/'. 22 * @type int $network_id The site's network ID. Default is the current network ID. 23 * @type string $registered When the site was registered, in SQL datetime format. Default is 24 * the current time. 25 * @type string $last_updated When the site was last updated, in SQL datetime format. Default is 26 * the value of $registered. 27 * @type int $public Whether the site is public. Default 1. 28 * @type int $archived Whether the site is archived. Default 0. 29 * @type int $mature Whether the site is mature. Default 0. 30 * @type int $spam Whether the site is spam. Default 0. 31 * @type int $deleted Whether the site is deleted. Default 0. 32 * @type int $lang_id The site's language ID. Currently unused. Default 0. 33 * @type int $user_id User ID for the site administrator. Passed to the 34 * `wp_initialize_site` hook. 35 * @type string $title Site title. Default is 'Site %d' where %d is the site ID. Passed 36 * to the `wp_initialize_site` hook. 37 * @type array $options Custom option $key => $value pairs to use. Default empty array. Passed 38 * to the `wp_initialize_site` hook. 39 * @type array $meta Custom site metadata $key => $value pairs to use. Default empty array. 40 * Passed to the `wp_initialize_site` hook. 41 * } 42 * @return int|WP_Error The new site's ID on success, or error object on failure. 43 */ 44 function wp_insert_site( array $data ) { 45 global $wpdb; 46 47 $now = current_time( 'mysql', true ); 48 49 $defaults = array( 50 'domain' => '', 51 'path' => '/', 52 'network_id' => get_current_network_id(), 53 'registered' => $now, 54 'last_updated' => $now, 55 'public' => 1, 56 'archived' => 0, 57 'mature' => 0, 58 'spam' => 0, 59 'deleted' => 0, 60 'lang_id' => 0, 61 ); 62 63 $prepared_data = wp_prepare_site_data( $data, $defaults ); 64 if ( is_wp_error( $prepared_data ) ) { 65 return $prepared_data; 66 } 67 68 if ( false === $wpdb->insert( $wpdb->blogs, $prepared_data ) ) { 69 return new WP_Error( 'db_insert_error', __( 'Could not insert site into the database.' ), $wpdb->last_error ); 70 } 71 72 $site_id = (int) $wpdb->insert_id; 73 74 clean_blog_cache( $site_id ); 75 76 $new_site = get_site( $site_id ); 77 78 if ( ! $new_site ) { 79 return new WP_Error( 'get_site_error', __( 'Could not retrieve site data.' ) ); 80 } 81 82 /** 83 * Fires once a site has been inserted into the database. 84 * 85 * @since 5.1.0 86 * 87 * @param WP_Site $new_site New site object. 88 */ 89 do_action( 'wp_insert_site', $new_site ); 90 91 // Extract the passed arguments that may be relevant for site initialization. 92 $args = array_diff_key( $data, $defaults ); 93 if ( isset( $args['site_id'] ) ) { 94 unset( $args['site_id'] ); 95 } 96 97 /** 98 * Fires when a site's initialization routine should be executed. 99 * 100 * @since 5.1.0 101 * 102 * @param WP_Site $new_site New site object. 103 * @param array $args Arguments for the initialization. 104 */ 105 do_action( 'wp_initialize_site', $new_site, $args ); 106 107 // Only compute extra hook parameters if the deprecated hook is actually in use. 108 if ( has_action( 'wpmu_new_blog' ) ) { 109 $user_id = ! empty( $args['user_id'] ) ? $args['user_id'] : 0; 110 $meta = ! empty( $args['options'] ) ? $args['options'] : array(); 111 112 // WPLANG was passed with `$meta` to the `wpmu_new_blog` hook prior to 5.1.0. 113 if ( ! array_key_exists( 'WPLANG', $meta ) ) { 114 $meta['WPLANG'] = get_network_option( $new_site->network_id, 'WPLANG' ); 115 } 116 117 // Rebuild the data expected by the `wpmu_new_blog` hook prior to 5.1.0 using allowed keys. 118 // The `$allowed_data_fields` matches the one used in `wpmu_create_blog()`. 119 $allowed_data_fields = array( 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ); 120 $meta = array_merge( array_intersect_key( $data, array_flip( $allowed_data_fields ) ), $meta ); 121 122 /** 123 * Fires immediately after a new site is created. 124 * 125 * @since MU (3.0.0) 126 * @deprecated 5.1.0 Use {@see 'wp_initialize_site'} instead. 127 * 128 * @param int $site_id Site ID. 129 * @param int $user_id User ID. 130 * @param string $domain Site domain. 131 * @param string $path Site path. 132 * @param int $network_id Network ID. Only relevant on multi-network installations. 133 * @param array $meta Meta data. Used to set initial site options. 134 */ 135 do_action_deprecated( 136 'wpmu_new_blog', 137 array( $new_site->id, $user_id, $new_site->domain, $new_site->path, $new_site->network_id, $meta ), 138 '5.1.0', 139 'wp_initialize_site' 140 ); 141 } 142 143 return (int) $new_site->id; 144 } 145 146 /** 147 * Updates a site in the database. 148 * 149 * @since 5.1.0 150 * 151 * @global wpdb $wpdb WordPress database abstraction object. 152 * 153 * @param int $site_id ID of the site that should be updated. 154 * @param array $data Site data to update. See {@see wp_insert_site()} for the list of supported keys. 155 * @return int|WP_Error The updated site's ID on success, or error object on failure. 156 */ 157 function wp_update_site( $site_id, array $data ) { 158 global $wpdb; 159 160 if ( empty( $site_id ) ) { 161 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 162 } 163 164 $old_site = get_site( $site_id ); 165 if ( ! $old_site ) { 166 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 167 } 168 169 $defaults = $old_site->to_array(); 170 $defaults['network_id'] = (int) $defaults['site_id']; 171 $defaults['last_updated'] = current_time( 'mysql', true ); 172 unset( $defaults['blog_id'], $defaults['site_id'] ); 173 174 $data = wp_prepare_site_data( $data, $defaults, $old_site ); 175 if ( is_wp_error( $data ) ) { 176 return $data; 177 } 178 179 if ( false === $wpdb->update( $wpdb->blogs, $data, array( 'blog_id' => $old_site->id ) ) ) { 180 return new WP_Error( 'db_update_error', __( 'Could not update site in the database.' ), $wpdb->last_error ); 181 } 182 183 clean_blog_cache( $old_site ); 184 185 $new_site = get_site( $old_site->id ); 186 187 /** 188 * Fires once a site has been updated in the database. 189 * 190 * @since 5.1.0 191 * 192 * @param WP_Site $new_site New site object. 193 * @param WP_Site $old_site Old site object. 194 */ 195 do_action( 'wp_update_site', $new_site, $old_site ); 196 197 return (int) $new_site->id; 198 } 199 200 /** 201 * Deletes a site from the database. 202 * 203 * @since 5.1.0 204 * 205 * @global wpdb $wpdb WordPress database abstraction object. 206 * 207 * @param int $site_id ID of the site that should be deleted. 208 * @return WP_Site|WP_Error The deleted site object on success, or error object on failure. 209 */ 210 function wp_delete_site( $site_id ) { 211 global $wpdb; 212 213 if ( empty( $site_id ) ) { 214 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 215 } 216 217 $old_site = get_site( $site_id ); 218 if ( ! $old_site ) { 219 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 220 } 221 222 $errors = new WP_Error(); 223 224 /** 225 * Fires before a site should be deleted from the database. 226 * 227 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. If any errors 228 * are present, the site will not be deleted. 229 * 230 * @since 5.1.0 231 * 232 * @param WP_Error $errors Error object to add validation errors to. 233 * @param WP_Site $old_site The site object to be deleted. 234 */ 235 do_action( 'wp_validate_site_deletion', $errors, $old_site ); 236 237 if ( ! empty( $errors->errors ) ) { 238 return $errors; 239 } 240 241 /** 242 * Fires before a site is deleted. 243 * 244 * @since MU (3.0.0) 245 * @deprecated 5.1.0 246 * 247 * @param int $site_id The site ID. 248 * @param bool $drop True if site's table should be dropped. Default false. 249 */ 250 do_action_deprecated( 'delete_blog', array( $old_site->id, true ), '5.1.0' ); 251 252 /** 253 * Fires when a site's uninitialization routine should be executed. 254 * 255 * @since 5.1.0 256 * 257 * @param WP_Site $old_site Deleted site object. 258 */ 259 do_action( 'wp_uninitialize_site', $old_site ); 260 261 if ( is_site_meta_supported() ) { 262 $blog_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->blogmeta WHERE blog_id = %d ", $old_site->id ) ); 263 foreach ( $blog_meta_ids as $mid ) { 264 delete_metadata_by_mid( 'blog', $mid ); 265 } 266 } 267 268 if ( false === $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $old_site->id ) ) ) { 269 return new WP_Error( 'db_delete_error', __( 'Could not delete site from the database.' ), $wpdb->last_error ); 270 } 271 272 clean_blog_cache( $old_site ); 273 274 /** 275 * Fires once a site has been deleted from the database. 276 * 277 * @since 5.1.0 278 * 279 * @param WP_Site $old_site Deleted site object. 280 */ 281 do_action( 'wp_delete_site', $old_site ); 282 283 /** 284 * Fires after the site is deleted from the network. 285 * 286 * @since 4.8.0 287 * @deprecated 5.1.0 288 * 289 * @param int $site_id The site ID. 290 * @param bool $drop True if site's tables should be dropped. Default false. 291 */ 292 do_action_deprecated( 'deleted_blog', array( $old_site->id, true ), '5.1.0' ); 293 294 return $old_site; 295 } 296 297 /** 298 * Retrieves site data given a site ID or site object. 299 * 300 * Site data will be cached and returned after being passed through a filter. 301 * If the provided site is empty, the current site global will be used. 302 * 303 * @since 4.6.0 304 * 305 * @param WP_Site|int|null $site Optional. Site to retrieve. Default is the current site. 306 * @return WP_Site|null The site object or null if not found. 307 */ 308 function get_site( $site = null ) { 309 if ( empty( $site ) ) { 310 $site = get_current_blog_id(); 311 } 312 313 if ( $site instanceof WP_Site ) { 314 $_site = $site; 315 } elseif ( is_object( $site ) ) { 316 $_site = new WP_Site( $site ); 317 } else { 318 $_site = WP_Site::get_instance( $site ); 319 } 320 321 if ( ! $_site ) { 322 return null; 323 } 324 325 /** 326 * Fires after a site is retrieved. 327 * 328 * @since 4.6.0 329 * 330 * @param WP_Site $_site Site data. 331 */ 332 $_site = apply_filters( 'get_site', $_site ); 333 334 return $_site; 335 } 336 337 /** 338 * Adds any sites from the given IDs to the cache that do not already exist in cache. 339 * 340 * @since 4.6.0 341 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 342 * @access private 343 * 344 * @see update_site_cache() 345 * @global wpdb $wpdb WordPress database abstraction object. 346 * 347 * @param array $ids ID list. 348 * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. 349 */ 350 function _prime_site_caches( $ids, $update_meta_cache = true ) { 351 global $wpdb; 352 353 $non_cached_ids = _get_non_cached_ids( $ids, 'sites' ); 354 if ( ! empty( $non_cached_ids ) ) { 355 $fresh_sites = $wpdb->get_results( sprintf( "SELECT * FROM $wpdb->blogs WHERE blog_id IN (%s)", implode( ',', array_map( 'intval', $non_cached_ids ) ) ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 356 357 update_site_cache( $fresh_sites, $update_meta_cache ); 358 } 359 } 360 361 /** 362 * Updates sites in cache. 363 * 364 * @since 4.6.0 365 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 366 * 367 * @param array $sites Array of site objects. 368 * @param bool $update_meta_cache Whether to update site meta cache. Default true. 369 */ 370 function update_site_cache( $sites, $update_meta_cache = true ) { 371 if ( ! $sites ) { 372 return; 373 } 374 $site_ids = array(); 375 $site_data = array(); 376 $blog_details_data = array(); 377 foreach ( $sites as $site ) { 378 $site_ids[] = $site->blog_id; 379 $site_data[ $site->blog_id ] = $site; 380 $blog_details_data[ $site->blog_id . 'short' ] = $site; 381 382 } 383 wp_cache_add_multiple( $site_data, 'sites' ); 384 wp_cache_add_multiple( $blog_details_data, 'blog-details' ); 385 386 if ( $update_meta_cache ) { 387 update_sitemeta_cache( $site_ids ); 388 } 389 } 390 391 /** 392 * Updates metadata cache for list of site IDs. 393 * 394 * Performs SQL query to retrieve all metadata for the sites matching `$site_ids` and stores them in the cache. 395 * Subsequent calls to `get_site_meta()` will not need to query the database. 396 * 397 * @since 5.1.0 398 * 399 * @param array $site_ids List of site IDs. 400 * @return array|false An array of metadata on success, false if there is nothing to update. 401 */ 402 function update_sitemeta_cache( $site_ids ) { 403 // Ensure this filter is hooked in even if the function is called early. 404 if ( ! has_filter( 'update_blog_metadata_cache', 'wp_check_site_meta_support_prefilter' ) ) { 405 add_filter( 'update_blog_metadata_cache', 'wp_check_site_meta_support_prefilter' ); 406 } 407 return update_meta_cache( 'blog', $site_ids ); 408 } 409 410 /** 411 * Retrieves a list of sites matching requested arguments. 412 * 413 * @since 4.6.0 414 * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters. 415 * 416 * @see WP_Site_Query::parse_query() 417 * 418 * @param string|array $args Optional. Array or string of arguments. See WP_Site_Query::__construct() 419 * for information on accepted arguments. Default empty array. 420 * @return array|int List of WP_Site objects, a list of site IDs when 'fields' is set to 'ids', 421 * or the number of sites when 'count' is passed as a query var. 422 */ 423 function get_sites( $args = array() ) { 424 $query = new WP_Site_Query(); 425 426 return $query->query( $args ); 427 } 428 429 /** 430 * Prepares site data for insertion or update in the database. 431 * 432 * @since 5.1.0 433 * 434 * @param array $data Associative array of site data passed to the respective function. 435 * See {@see wp_insert_site()} for the possibly included data. 436 * @param array $defaults Site data defaults to parse $data against. 437 * @param WP_Site|null $old_site Optional. Old site object if an update, or null if an insertion. 438 * Default null. 439 * @return array|WP_Error Site data ready for a database transaction, or WP_Error in case a validation 440 * error occurred. 441 */ 442 function wp_prepare_site_data( $data, $defaults, $old_site = null ) { 443 444 // Maintain backward-compatibility with `$site_id` as network ID. 445 if ( isset( $data['site_id'] ) ) { 446 if ( ! empty( $data['site_id'] ) && empty( $data['network_id'] ) ) { 447 $data['network_id'] = $data['site_id']; 448 } 449 unset( $data['site_id'] ); 450 } 451 452 /** 453 * Filters passed site data in order to normalize it. 454 * 455 * @since 5.1.0 456 * 457 * @param array $data Associative array of site data passed to the respective function. 458 * See {@see wp_insert_site()} for the possibly included data. 459 */ 460 $data = apply_filters( 'wp_normalize_site_data', $data ); 461 462 $allowed_data_fields = array( 'domain', 'path', 'network_id', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ); 463 $data = array_intersect_key( wp_parse_args( $data, $defaults ), array_flip( $allowed_data_fields ) ); 464 465 $errors = new WP_Error(); 466 467 /** 468 * Fires when data should be validated for a site prior to inserting or updating in the database. 469 * 470 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. 471 * 472 * @since 5.1.0 473 * 474 * @param WP_Error $errors Error object to add validation errors to. 475 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 476 * for the included data. 477 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 478 * or null if it is a new site being inserted. 479 */ 480 do_action( 'wp_validate_site_data', $errors, $data, $old_site ); 481 482 if ( ! empty( $errors->errors ) ) { 483 return $errors; 484 } 485 486 // Prepare for database. 487 $data['site_id'] = $data['network_id']; 488 unset( $data['network_id'] ); 489 490 return $data; 491 } 492 493 /** 494 * Normalizes data for a site prior to inserting or updating in the database. 495 * 496 * @since 5.1.0 497 * 498 * @param array $data Associative array of site data passed to the respective function. 499 * See {@see wp_insert_site()} for the possibly included data. 500 * @return array Normalized site data. 501 */ 502 function wp_normalize_site_data( $data ) { 503 // Sanitize domain if passed. 504 if ( array_key_exists( 'domain', $data ) ) { 505 $data['domain'] = trim( $data['domain'] ); 506 $data['domain'] = preg_replace( '/\s+/', '', sanitize_user( $data['domain'], true ) ); 507 if ( is_subdomain_install() ) { 508 $data['domain'] = str_replace( '@', '', $data['domain'] ); 509 } 510 } 511 512 // Sanitize path if passed. 513 if ( array_key_exists( 'path', $data ) ) { 514 $data['path'] = trailingslashit( '/' . trim( $data['path'], '/' ) ); 515 } 516 517 // Sanitize network ID if passed. 518 if ( array_key_exists( 'network_id', $data ) ) { 519 $data['network_id'] = (int) $data['network_id']; 520 } 521 522 // Sanitize status fields if passed. 523 $status_fields = array( 'public', 'archived', 'mature', 'spam', 'deleted' ); 524 foreach ( $status_fields as $status_field ) { 525 if ( array_key_exists( $status_field, $data ) ) { 526 $data[ $status_field ] = (int) $data[ $status_field ]; 527 } 528 } 529 530 // Strip date fields if empty. 531 $date_fields = array( 'registered', 'last_updated' ); 532 foreach ( $date_fields as $date_field ) { 533 if ( ! array_key_exists( $date_field, $data ) ) { 534 continue; 535 } 536 537 if ( empty( $data[ $date_field ] ) || '0000-00-00 00:00:00' === $data[ $date_field ] ) { 538 unset( $data[ $date_field ] ); 539 } 540 } 541 542 return $data; 543 } 544 545 /** 546 * Validates data for a site prior to inserting or updating in the database. 547 * 548 * @since 5.1.0 549 * 550 * @param WP_Error $errors Error object, passed by reference. Will contain validation errors if 551 * any occurred. 552 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 553 * for the included data. 554 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 555 * or null if it is a new site being inserted. 556 */ 557 function wp_validate_site_data( $errors, $data, $old_site = null ) { 558 // A domain must always be present. 559 if ( empty( $data['domain'] ) ) { 560 $errors->add( 'site_empty_domain', __( 'Site domain must not be empty.' ) ); 561 } 562 563 // A path must always be present. 564 if ( empty( $data['path'] ) ) { 565 $errors->add( 'site_empty_path', __( 'Site path must not be empty.' ) ); 566 } 567 568 // A network ID must always be present. 569 if ( empty( $data['network_id'] ) ) { 570 $errors->add( 'site_empty_network_id', __( 'Site network ID must be provided.' ) ); 571 } 572 573 // Both registration and last updated dates must always be present and valid. 574 $date_fields = array( 'registered', 'last_updated' ); 575 foreach ( $date_fields as $date_field ) { 576 if ( empty( $data[ $date_field ] ) ) { 577 $errors->add( 'site_empty_' . $date_field, __( 'Both registration and last updated dates must be provided.' ) ); 578 break; 579 } 580 581 // Allow '0000-00-00 00:00:00', although it be stripped out at this point. 582 if ( '0000-00-00 00:00:00' !== $data[ $date_field ] ) { 583 $month = substr( $data[ $date_field ], 5, 2 ); 584 $day = substr( $data[ $date_field ], 8, 2 ); 585 $year = substr( $data[ $date_field ], 0, 4 ); 586 $valid_date = wp_checkdate( $month, $day, $year, $data[ $date_field ] ); 587 if ( ! $valid_date ) { 588 $errors->add( 'site_invalid_' . $date_field, __( 'Both registration and last updated dates must be valid dates.' ) ); 589 break; 590 } 591 } 592 } 593 594 if ( ! empty( $errors->errors ) ) { 595 return; 596 } 597 598 // If a new site, or domain/path/network ID have changed, ensure uniqueness. 599 if ( ! $old_site 600 || $data['domain'] !== $old_site->domain 601 || $data['path'] !== $old_site->path 602 || $data['network_id'] !== $old_site->network_id 603 ) { 604 if ( domain_exists( $data['domain'], $data['path'], $data['network_id'] ) ) { 605 $errors->add( 'site_taken', __( 'Sorry, that site already exists!' ) ); 606 } 607 } 608 } 609 610 /** 611 * Runs the initialization routine for a given site. 612 * 613 * This process includes creating the site's database tables and 614 * populating them with defaults. 615 * 616 * @since 5.1.0 617 * 618 * @global wpdb $wpdb WordPress database abstraction object. 619 * @global WP_Roles $wp_roles WordPress role management object. 620 * 621 * @param int|WP_Site $site_id Site ID or object. 622 * @param array $args { 623 * Optional. Arguments to modify the initialization behavior. 624 * 625 * @type int $user_id Required. User ID for the site administrator. 626 * @type string $title Site title. Default is 'Site %d' where %d is the 627 * site ID. 628 * @type array $options Custom option $key => $value pairs to use. Default 629 * empty array. 630 * @type array $meta Custom site metadata $key => $value pairs to use. 631 * Default empty array. 632 * } 633 * @return true|WP_Error True on success, or error object on failure. 634 */ 635 function wp_initialize_site( $site_id, array $args = array() ) { 636 global $wpdb, $wp_roles; 637 638 if ( empty( $site_id ) ) { 639 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 640 } 641 642 $site = get_site( $site_id ); 643 if ( ! $site ) { 644 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 645 } 646 647 if ( wp_is_site_initialized( $site ) ) { 648 return new WP_Error( 'site_already_initialized', __( 'The site appears to be already initialized.' ) ); 649 } 650 651 $network = get_network( $site->network_id ); 652 if ( ! $network ) { 653 $network = get_network(); 654 } 655 656 $args = wp_parse_args( 657 $args, 658 array( 659 'user_id' => 0, 660 /* translators: %d: Site ID. */ 661 'title' => sprintf( __( 'Site %d' ), $site->id ), 662 'options' => array(), 663 'meta' => array(), 664 ) 665 ); 666 667 /** 668 * Filters the arguments for initializing a site. 669 * 670 * @since 5.1.0 671 * 672 * @param array $args Arguments to modify the initialization behavior. 673 * @param WP_Site $site Site that is being initialized. 674 * @param WP_Network $network Network that the site belongs to. 675 */ 676 $args = apply_filters( 'wp_initialize_site_args', $args, $site, $network ); 677 678 $orig_installing = wp_installing(); 679 if ( ! $orig_installing ) { 680 wp_installing( true ); 681 } 682 683 $switch = false; 684 if ( get_current_blog_id() !== $site->id ) { 685 $switch = true; 686 switch_to_blog( $site->id ); 687 } 688 689 require_once ABSPATH . 'wp-admin/includes/upgrade.php'; 690 691 // Set up the database tables. 692 make_db_current_silent( 'blog' ); 693 694 $home_scheme = 'http'; 695 $siteurl_scheme = 'http'; 696 if ( ! is_subdomain_install() ) { 697 if ( 'https' === parse_url( get_home_url( $network->site_id ), PHP_URL_SCHEME ) ) { 698 $home_scheme = 'https'; 699 } 700 if ( 'https' === parse_url( get_network_option( $network->id, 'siteurl' ), PHP_URL_SCHEME ) ) { 701 $siteurl_scheme = 'https'; 702 } 703 } 704 705 // Populate the site's options. 706 populate_options( 707 array_merge( 708 array( 709 'home' => untrailingslashit( $home_scheme . '://' . $site->domain . $site->path ), 710 'siteurl' => untrailingslashit( $siteurl_scheme . '://' . $site->domain . $site->path ), 711 'blogname' => wp_unslash( $args['title'] ), 712 'admin_email' => '', 713 'upload_path' => get_network_option( $network->id, 'ms_files_rewriting' ) ? UPLOADBLOGSDIR . "/{$site->id}/files" : get_blog_option( $network->site_id, 'upload_path' ), 714 'blog_public' => (int) $site->public, 715 'WPLANG' => get_network_option( $network->id, 'WPLANG' ), 716 ), 717 $args['options'] 718 ) 719 ); 720 721 // Clean blog cache after populating options. 722 clean_blog_cache( $site ); 723 724 // Populate the site's roles. 725 populate_roles(); 726 $wp_roles = new WP_Roles(); 727 728 // Populate metadata for the site. 729 populate_site_meta( $site->id, $args['meta'] ); 730 731 // Remove all permissions that may exist for the site. 732 $table_prefix = $wpdb->get_blog_prefix(); 733 delete_metadata( 'user', 0, $table_prefix . 'user_level', null, true ); // Delete all. 734 delete_metadata( 'user', 0, $table_prefix . 'capabilities', null, true ); // Delete all. 735 736 // Install default site content. 737 wp_install_defaults( $args['user_id'] ); 738 739 // Set the site administrator. 740 add_user_to_blog( $site->id, $args['user_id'], 'administrator' ); 741 if ( ! user_can( $args['user_id'], 'manage_network' ) && ! get_user_meta( $args['user_id'], 'primary_blog', true ) ) { 742 update_user_meta( $args['user_id'], 'primary_blog', $site->id ); 743 } 744 745 if ( $switch ) { 746 restore_current_blog(); 747 } 748 749 wp_installing( $orig_installing ); 750 751 return true; 752 } 753 754 /** 755 * Runs the uninitialization routine for a given site. 756 * 757 * This process includes dropping the site's database tables and deleting its uploads directory. 758 * 759 * @since 5.1.0 760 * 761 * @global wpdb $wpdb WordPress database abstraction object. 762 * 763 * @param int|WP_Site $site_id Site ID or object. 764 * @return true|WP_Error True on success, or error object on failure. 765 */ 766 function wp_uninitialize_site( $site_id ) { 767 global $wpdb; 768 769 if ( empty( $site_id ) ) { 770 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 771 } 772 773 $site = get_site( $site_id ); 774 if ( ! $site ) { 775 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 776 } 777 778 if ( ! wp_is_site_initialized( $site ) ) { 779 return new WP_Error( 'site_already_uninitialized', __( 'The site appears to be already uninitialized.' ) ); 780 } 781 782 $users = get_users( 783 array( 784 'blog_id' => $site->id, 785 'fields' => 'ids', 786 ) 787 ); 788 789 // Remove users from the site. 790 if ( ! empty( $users ) ) { 791 foreach ( $users as $user_id ) { 792 remove_user_from_blog( $user_id, $site->id ); 793 } 794 } 795 796 $switch = false; 797 if ( get_current_blog_id() !== $site->id ) { 798 $switch = true; 799 switch_to_blog( $site->id ); 800 } 801 802 $uploads = wp_get_upload_dir(); 803 804 $tables = $wpdb->tables( 'blog' ); 805 806 /** 807 * Filters the tables to drop when the site is deleted. 808 * 809 * @since MU (3.0.0) 810 * 811 * @param string[] $tables Array of names of the site tables to be dropped. 812 * @param int $site_id The ID of the site to drop tables for. 813 */ 814 $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $site->id ); 815 816 foreach ( (array) $drop_tables as $table ) { 817 $wpdb->query( "DROP TABLE IF EXISTS `$table`" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 818 } 819 820 /** 821 * Filters the upload base directory to delete when the site is deleted. 822 * 823 * @since MU (3.0.0) 824 * 825 * @param string $basedir Uploads path without subdirectory. @see wp_upload_dir() 826 * @param int $site_id The site ID. 827 */ 828 $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $site->id ); 829 $dir = rtrim( $dir, DIRECTORY_SEPARATOR ); 830 $top_dir = $dir; 831 $stack = array( $dir ); 832 $index = 0; 833 834 while ( $index < count( $stack ) ) { 835 // Get indexed directory from stack. 836 $dir = $stack[ $index ]; 837 838 // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged 839 $dh = @opendir( $dir ); 840 if ( $dh ) { 841 $file = @readdir( $dh ); 842 while ( false !== $file ) { 843 if ( '.' === $file || '..' === $file ) { 844 $file = @readdir( $dh ); 845 continue; 846 } 847 848 if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) ) { 849 $stack[] = $dir . DIRECTORY_SEPARATOR . $file; 850 } elseif ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) ) { 851 @unlink( $dir . DIRECTORY_SEPARATOR . $file ); 852 } 853 854 $file = @readdir( $dh ); 855 } 856 @closedir( $dh ); 857 } 858 $index++; 859 } 860 861 $stack = array_reverse( $stack ); // Last added directories are deepest. 862 foreach ( (array) $stack as $dir ) { 863 if ( $dir != $top_dir ) { 864 @rmdir( $dir ); 865 } 866 } 867 868 // phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged 869 if ( $switch ) { 870 restore_current_blog(); 871 } 872 873 return true; 874 } 875 876 /** 877 * Checks whether a site is initialized. 878 * 879 * A site is considered initialized when its database tables are present. 880 * 881 * @since 5.1.0 882 * 883 * @global wpdb $wpdb WordPress database abstraction object. 884 * 885 * @param int|WP_Site $site_id Site ID or object. 886 * @return bool True if the site is initialized, false otherwise. 887 */ 888 function wp_is_site_initialized( $site_id ) { 889 global $wpdb; 890 891 if ( is_object( $site_id ) ) { 892 $site_id = $site_id->blog_id; 893 } 894 $site_id = (int) $site_id; 895 896 /** 897 * Filters the check for whether a site is initialized before the database is accessed. 898 * 899 * Returning a non-null value will effectively short-circuit the function, returning 900 * that value instead. 901 * 902 * @since 5.1.0 903 * 904 * @param bool|null $pre The value to return instead. Default null 905 * to continue with the check. 906 * @param int $site_id The site ID that is being checked. 907 */ 908 $pre = apply_filters( 'pre_wp_is_site_initialized', null, $site_id ); 909 if ( null !== $pre ) { 910 return (bool) $pre; 911 } 912 913 $switch = false; 914 if ( get_current_blog_id() !== $site_id ) { 915 $switch = true; 916 remove_action( 'switch_blog', 'wp_switch_roles_and_user', 1 ); 917 switch_to_blog( $site_id ); 918 } 919 920 $suppress = $wpdb->suppress_errors(); 921 $result = (bool) $wpdb->get_results( "DESCRIBE {$wpdb->posts}" ); 922 $wpdb->suppress_errors( $suppress ); 923 924 if ( $switch ) { 925 restore_current_blog(); 926 add_action( 'switch_blog', 'wp_switch_roles_and_user', 1, 2 ); 927 } 928 929 return $result; 930 } 931 932 /** 933 * Clean the blog cache 934 * 935 * @since 3.5.0 936 * 937 * @global bool $_wp_suspend_cache_invalidation 938 * 939 * @param WP_Site|int $blog The site object or ID to be cleared from cache. 940 */ 941 function clean_blog_cache( $blog ) { 942 global $_wp_suspend_cache_invalidation; 943 944 if ( ! empty( $_wp_suspend_cache_invalidation ) ) { 945 return; 946 } 947 948 if ( empty( $blog ) ) { 949 return; 950 } 951 952 $blog_id = $blog; 953 $blog = get_site( $blog_id ); 954 if ( ! $blog ) { 955 if ( ! is_numeric( $blog_id ) ) { 956 return; 957 } 958 959 // Make sure a WP_Site object exists even when the site has been deleted. 960 $blog = new WP_Site( 961 (object) array( 962 'blog_id' => $blog_id, 963 'domain' => null, 964 'path' => null, 965 ) 966 ); 967 } 968 969 $blog_id = $blog->blog_id; 970 $domain_path_key = md5( $blog->domain . $blog->path ); 971 972 wp_cache_delete( $blog_id, 'sites' ); 973 wp_cache_delete( $blog_id, 'site-details' ); 974 wp_cache_delete( $blog_id, 'blog-details' ); 975 wp_cache_delete( $blog_id . 'short', 'blog-details' ); 976 wp_cache_delete( $domain_path_key, 'blog-lookup' ); 977 wp_cache_delete( $domain_path_key, 'blog-id-cache' ); 978 wp_cache_delete( $blog_id, 'blog_meta' ); 979 980 /** 981 * Fires immediately after a site has been removed from the object cache. 982 * 983 * @since 4.6.0 984 * 985 * @param string $id Site ID as a numeric string. 986 * @param WP_Site $blog Site object. 987 * @param string $domain_path_key md5 hash of domain and path. 988 */ 989 do_action( 'clean_site_cache', $blog_id, $blog, $domain_path_key ); 990 991 wp_cache_set( 'last_changed', microtime(), 'sites' ); 992 993 /** 994 * Fires after the blog details cache is cleared. 995 * 996 * @since 3.4.0 997 * @deprecated 4.9.0 Use {@see 'clean_site_cache'} instead. 998 * 999 * @param int $blog_id Blog ID. 1000 */ 1001 do_action_deprecated( 'refresh_blog_details', array( $blog_id ), '4.9.0', 'clean_site_cache' ); 1002 } 1003 1004 /** 1005 * Adds metadata to a site. 1006 * 1007 * @since 5.1.0 1008 * 1009 * @param int $site_id Site ID. 1010 * @param string $meta_key Metadata name. 1011 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. 1012 * @param bool $unique Optional. Whether the same key should not be added. 1013 * Default false. 1014 * @return int|false Meta ID on success, false on failure. 1015 */ 1016 function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) { 1017 return add_metadata( 'blog', $site_id, $meta_key, $meta_value, $unique ); 1018 } 1019 1020 /** 1021 * Removes metadata matching criteria from a site. 1022 * 1023 * You can match based on the key, or key and value. Removing based on key and 1024 * value, will keep from removing duplicate metadata with the same key. It also 1025 * allows removing all metadata matching key, if needed. 1026 * 1027 * @since 5.1.0 1028 * 1029 * @param int $site_id Site ID. 1030 * @param string $meta_key Metadata name. 1031 * @param mixed $meta_value Optional. Metadata value. If provided, 1032 * rows will only be removed that match the value. 1033 * Must be serializable if non-scalar. Default empty. 1034 * @return bool True on success, false on failure. 1035 */ 1036 function delete_site_meta( $site_id, $meta_key, $meta_value = '' ) { 1037 return delete_metadata( 'blog', $site_id, $meta_key, $meta_value ); 1038 } 1039 1040 /** 1041 * Retrieves metadata for a site. 1042 * 1043 * @since 5.1.0 1044 * 1045 * @param int $site_id Site ID. 1046 * @param string $key Optional. The meta key to retrieve. By default, 1047 * returns data for all keys. Default empty. 1048 * @param bool $single Optional. Whether to return a single value. 1049 * This parameter has no effect if `$key` is not specified. 1050 * Default false. 1051 * @return mixed An array of values if `$single` is false. 1052 * The value of meta data field if `$single` is true. 1053 * False for an invalid `$site_id` (non-numeric, zero, or negative value). 1054 * An empty string if a valid but non-existing site ID is passed. 1055 */ 1056 function get_site_meta( $site_id, $key = '', $single = false ) { 1057 return get_metadata( 'blog', $site_id, $key, $single ); 1058 } 1059 1060 /** 1061 * Updates metadata for a site. 1062 * 1063 * Use the $prev_value parameter to differentiate between meta fields with the 1064 * same key and site ID. 1065 * 1066 * If the meta field for the site does not exist, it will be added. 1067 * 1068 * @since 5.1.0 1069 * 1070 * @param int $site_id Site ID. 1071 * @param string $meta_key Metadata key. 1072 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. 1073 * @param mixed $prev_value Optional. Previous value to check before updating. 1074 * If specified, only update existing metadata entries with 1075 * this value. Otherwise, update all entries. Default empty. 1076 * @return int|bool Meta ID if the key didn't exist, true on successful update, 1077 * false on failure or if the value passed to the function 1078 * is the same as the one that is already in the database. 1079 */ 1080 function update_site_meta( $site_id, $meta_key, $meta_value, $prev_value = '' ) { 1081 return update_metadata( 'blog', $site_id, $meta_key, $meta_value, $prev_value ); 1082 } 1083 1084 /** 1085 * Deletes everything from site meta matching meta key. 1086 * 1087 * @since 5.1.0 1088 * 1089 * @param string $meta_key Metadata key to search for when deleting. 1090 * @return bool Whether the site meta key was deleted from the database. 1091 */ 1092 function delete_site_meta_by_key( $meta_key ) { 1093 return delete_metadata( 'blog', null, $meta_key, '', true ); 1094 } 1095 1096 /** 1097 * Updates the count of sites for a network based on a changed site. 1098 * 1099 * @since 5.1.0 1100 * 1101 * @param WP_Site $new_site The site object that has been inserted, updated or deleted. 1102 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous 1103 * state of that site. Default null. 1104 */ 1105 function wp_maybe_update_network_site_counts_on_update( $new_site, $old_site = null ) { 1106 if ( null === $old_site ) { 1107 wp_maybe_update_network_site_counts( $new_site->network_id ); 1108 return; 1109 } 1110 1111 if ( $new_site->network_id != $old_site->network_id ) { 1112 wp_maybe_update_network_site_counts( $new_site->network_id ); 1113 wp_maybe_update_network_site_counts( $old_site->network_id ); 1114 } 1115 } 1116 1117 /** 1118 * Triggers actions on site status updates. 1119 * 1120 * @since 5.1.0 1121 * 1122 * @param WP_Site $new_site The site object after the update. 1123 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous 1124 * state of that site. Default null. 1125 */ 1126 function wp_maybe_transition_site_statuses_on_update( $new_site, $old_site = null ) { 1127 $site_id = $new_site->id; 1128 1129 // Use the default values for a site if no previous state is given. 1130 if ( ! $old_site ) { 1131 $old_site = new WP_Site( new stdClass() ); 1132 } 1133 1134 if ( $new_site->spam != $old_site->spam ) { 1135 if ( 1 == $new_site->spam ) { 1136 1137 /** 1138 * Fires when the 'spam' status is added to a site. 1139 * 1140 * @since MU (3.0.0) 1141 * 1142 * @param int $site_id Site ID. 1143 */ 1144 do_action( 'make_spam_blog', $site_id ); 1145 } else { 1146 1147 /** 1148 * Fires when the 'spam' status is removed from a site. 1149 * 1150 * @since MU (3.0.0) 1151 * 1152 * @param int $site_id Site ID. 1153 */ 1154 do_action( 'make_ham_blog', $site_id ); 1155 } 1156 } 1157 1158 if ( $new_site->mature != $old_site->mature ) { 1159 if ( 1 == $new_site->mature ) { 1160 1161 /** 1162 * Fires when the 'mature' status is added to a site. 1163 * 1164 * @since 3.1.0 1165 * 1166 * @param int $site_id Site ID. 1167 */ 1168 do_action( 'mature_blog', $site_id ); 1169 } else { 1170 1171 /** 1172 * Fires when the 'mature' status is removed from a site. 1173 * 1174 * @since 3.1.0 1175 * 1176 * @param int $site_id Site ID. 1177 */ 1178 do_action( 'unmature_blog', $site_id ); 1179 } 1180 } 1181 1182 if ( $new_site->archived != $old_site->archived ) { 1183 if ( 1 == $new_site->archived ) { 1184 1185 /** 1186 * Fires when the 'archived' status is added to a site. 1187 * 1188 * @since MU (3.0.0) 1189 * 1190 * @param int $site_id Site ID. 1191 */ 1192 do_action( 'archive_blog', $site_id ); 1193 } else { 1194 1195 /** 1196 * Fires when the 'archived' status is removed from a site. 1197 * 1198 * @since MU (3.0.0) 1199 * 1200 * @param int $site_id Site ID. 1201 */ 1202 do_action( 'unarchive_blog', $site_id ); 1203 } 1204 } 1205 1206 if ( $new_site->deleted != $old_site->deleted ) { 1207 if ( 1 == $new_site->deleted ) { 1208 1209 /** 1210 * Fires when the 'deleted' status is added to a site. 1211 * 1212 * @since 3.5.0 1213 * 1214 * @param int $site_id Site ID. 1215 */ 1216 do_action( 'make_delete_blog', $site_id ); 1217 } else { 1218 1219 /** 1220 * Fires when the 'deleted' status is removed from a site. 1221 * 1222 * @since 3.5.0 1223 * 1224 * @param int $site_id Site ID. 1225 */ 1226 do_action( 'make_undelete_blog', $site_id ); 1227 } 1228 } 1229 1230 if ( $new_site->public != $old_site->public ) { 1231 1232 /** 1233 * Fires after the current blog's 'public' setting is updated. 1234 * 1235 * @since MU (3.0.0) 1236 * 1237 * @param int $site_id Site ID. 1238 * @param string $value The value of the site status. 1239 */ 1240 do_action( 'update_blog_public', $site_id, $new_site->public ); 1241 } 1242 } 1243 1244 /** 1245 * Cleans the necessary caches after specific site data has been updated. 1246 * 1247 * @since 5.1.0 1248 * 1249 * @param WP_Site $new_site The site object after the update. 1250 * @param WP_Site $old_site The site obejct prior to the update. 1251 */ 1252 function wp_maybe_clean_new_site_cache_on_update( $new_site, $old_site ) { 1253 if ( $old_site->domain !== $new_site->domain || $old_site->path !== $new_site->path ) { 1254 clean_blog_cache( $new_site ); 1255 } 1256 } 1257 1258 /** 1259 * Updates the `blog_public` option for a given site ID. 1260 * 1261 * @since 5.1.0 1262 * 1263 * @param int $site_id Site ID. 1264 * @param string $public The value of the site status. 1265 */ 1266 function wp_update_blog_public_option_on_site_update( $site_id, $public ) { 1267 1268 // Bail if the site's database tables do not exist (yet). 1269 if ( ! wp_is_site_initialized( $site_id ) ) { 1270 return; 1271 } 1272 1273 update_blog_option( $site_id, 'blog_public', $public ); 1274 } 1275 1276 /** 1277 * Sets the last changed time for the 'sites' cache group. 1278 * 1279 * @since 5.1.0 1280 */ 1281 function wp_cache_set_sites_last_changed() { 1282 wp_cache_set( 'last_changed', microtime(), 'sites' ); 1283 } 1284 1285 /** 1286 * Aborts calls to site meta if it is not supported. 1287 * 1288 * @since 5.1.0 1289 * 1290 * @global wpdb $wpdb WordPress database abstraction object. 1291 * 1292 * @param mixed $check Skip-value for whether to proceed site meta function execution. 1293 * @return mixed Original value of $check, or false if site meta is not supported. 1294 */ 1295 function wp_check_site_meta_support_prefilter( $check ) { 1296 if ( ! is_site_meta_supported() ) { 1297 /* translators: %s: Database table name. */ 1298 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The %s table is not installed. Please run the network database upgrade.' ), $GLOBALS['wpdb']->blogmeta ), '5.1.0' ); 1299 return false; 1300 } 1301 1302 return $check; 1303 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Dec 24 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |