Ticket #40647: 40647.3.diff
File 40647.3.diff, 95.8 KB (added by , 6 years ago) |
---|
-
src/wp-includes/ms-blogs.php
8 8 * @since MU (3.0.0) 9 9 */ 10 10 11 require_once( ABSPATH . WPINC . '/ms-site.php' ); 12 require_once( ABSPATH . WPINC . '/ms-network.php' ); 13 11 14 /** 12 15 * Update the last_updated field for the current site. 13 16 * … … 231 234 232 235 if ( ! $get_all ) { 233 236 wp_cache_set( $blog_id . $all, $details, 'blog-details' ); 234 return $details; 235 } 236 237 switch_to_blog( $blog_id ); 238 $details->blogname = get_option( 'blogname' ); 239 $details->siteurl = get_option( 'siteurl' ); 240 $details->post_count = get_option( 'post_count' ); 241 $details->home = get_option( 'home' ); 242 restore_current_blog(); 243 244 /** 245 * Filters a blog's details. 246 * 247 * @since MU (3.0.0) 248 * @deprecated 4.7.0 Use site_details 249 * 250 * @param object $details The blog details. 251 */ 252 $details = apply_filters_deprecated( 'blog_details', array( $details ), '4.7.0', 'site_details' ); 253 254 wp_cache_set( $blog_id . $all, $details, 'blog-details' ); 255 256 $key = md5( $details->domain . $details->path ); 257 wp_cache_set( $key, $details, 'blog-lookup' ); 258 259 return $details; 260 } 261 262 /** 263 * Clear the blog details cache. 264 * 265 * @since MU (3.0.0) 266 * 267 * @param int $blog_id Optional. Blog ID. Defaults to current blog. 268 */ 269 function refresh_blog_details( $blog_id = 0 ) { 270 $blog_id = (int) $blog_id; 271 if ( ! $blog_id ) { 272 $blog_id = get_current_blog_id(); 273 } 274 275 clean_blog_cache( $blog_id ); 276 } 277 278 /** 279 * Update the details for a blog. Updates the blogs table for a given blog id. 280 * 281 * @since MU (3.0.0) 282 * 283 * @global wpdb $wpdb WordPress database abstraction object. 284 * 285 * @param int $blog_id Blog ID 286 * @param array $details Array of details keyed by blogs table field names. 287 * @return bool True if update succeeds, false otherwise. 288 */ 289 function update_blog_details( $blog_id, $details = array() ) { 290 global $wpdb; 291 292 if ( empty( $details ) ) { 293 return false; 294 } 295 296 if ( is_object( $details ) ) { 297 $details = get_object_vars( $details ); 298 } 299 300 $site = wp_update_site( $blog_id, $details ); 301 302 if ( is_wp_error( $site ) ) { 303 return false; 304 } 305 306 return true; 307 } 308 309 /** 310 * Clean the blog cache 311 * 312 * @since 3.5.0 313 * 314 * @global bool $_wp_suspend_cache_invalidation 315 * 316 * @param WP_Site|int $blog The site object or ID to be cleared from cache. 317 */ 318 function clean_blog_cache( $blog ) { 319 global $_wp_suspend_cache_invalidation; 320 321 if ( ! empty( $_wp_suspend_cache_invalidation ) ) { 322 return; 323 } 324 325 if ( empty( $blog ) ) { 326 return; 327 } 328 329 $blog_id = $blog; 330 $blog = get_site( $blog_id ); 331 if ( ! $blog ) { 332 if ( ! is_numeric( $blog_id ) ) { 333 return; 334 } 335 336 // Make sure a WP_Site object exists even when the site has been deleted. 337 $blog = new WP_Site( 338 (object) array( 339 'blog_id' => $blog_id, 340 'domain' => null, 341 'path' => null, 342 ) 343 ); 344 } 345 346 $blog_id = $blog->blog_id; 347 $domain_path_key = md5( $blog->domain . $blog->path ); 348 349 wp_cache_delete( $blog_id, 'sites' ); 350 wp_cache_delete( $blog_id, 'site-details' ); 351 wp_cache_delete( $blog_id, 'blog-details' ); 352 wp_cache_delete( $blog_id . 'short', 'blog-details' ); 353 wp_cache_delete( $domain_path_key, 'blog-lookup' ); 354 wp_cache_delete( $domain_path_key, 'blog-id-cache' ); 355 wp_cache_delete( 'current_blog_' . $blog->domain, 'site-options' ); 356 wp_cache_delete( 'current_blog_' . $blog->domain . $blog->path, 'site-options' ); 357 wp_cache_delete( $blog_id, 'blog_meta' ); 358 359 /** 360 * Fires immediately after a site has been removed from the object cache. 361 * 362 * @since 4.6.0 363 * 364 * @param int $id Blog ID. 365 * @param WP_Site $blog Site object. 366 * @param string $domain_path_key md5 hash of domain and path. 367 */ 368 do_action( 'clean_site_cache', $blog_id, $blog, $domain_path_key ); 369 370 wp_cache_set( 'last_changed', microtime(), 'sites' ); 371 372 /** 373 * Fires after the blog details cache is cleared. 374 * 375 * @since 3.4.0 376 * @deprecated 4.9.0 Use clean_site_cache 377 * 378 * @param int $blog_id Blog ID. 379 */ 380 do_action_deprecated( 'refresh_blog_details', array( $blog_id ), '4.9.0', 'clean_site_cache' ); 381 } 382 383 /** 384 * Cleans the site details cache for a site. 385 * 386 * @since 4.7.4 387 * 388 * @param int $site_id Optional. Site ID. Default is the current site ID. 389 */ 390 function clean_site_details_cache( $site_id = 0 ) { 391 $site_id = (int) $site_id; 392 if ( ! $site_id ) { 393 $site_id = get_current_blog_id(); 394 } 395 396 wp_cache_delete( $site_id, 'site-details' ); 397 wp_cache_delete( $site_id, 'blog-details' ); 398 } 399 400 /** 401 * Inserts a new site into the database. 402 * 403 * @since 5.1.0 404 * 405 * @global wpdb $wpdb WordPress database abstraction object. 406 * 407 * @param array $data { 408 * Data for the new site that should be inserted. 409 * 410 * @type string $domain Site domain. Default empty string. 411 * @type string $path Site path. Default '/'. 412 * @type int $network_id The site's network ID. Default is the current network ID. 413 * @type string $registered When the site was registered, in SQL datetime format. Default is 414 * the current time. 415 * @type string $last_updated When the site was last updated, in SQL datetime format. Default is 416 * the value of $registered. 417 * @type int $public Whether the site is public. Default 1. 418 * @type int $archived Whether the site is archived. Default 0. 419 * @type int $mature Whether the site is mature. Default 0. 420 * @type int $spam Whether the site is spam. Default 0. 421 * @type int $deleted Whether the site is deleted. Default 0. 422 * @type int $lang_id The site's language ID. Currently unused. Default 0. 423 * } 424 * @return int|WP_Error The new site's ID on success, or error object on failure. 425 */ 426 function wp_insert_site( array $data ) { 427 global $wpdb; 428 429 $now = current_time( 'mysql', true ); 430 431 $defaults = array( 432 'domain' => '', 433 'path' => '/', 434 'network_id' => get_current_network_id(), 435 'registered' => $now, 436 'last_updated' => $now, 437 'public' => 1, 438 'archived' => 0, 439 'mature' => 0, 440 'spam' => 0, 441 'deleted' => 0, 442 'lang_id' => 0, 443 ); 444 445 // Extract the passed arguments that may be relevant for site initialization. 446 $args = array_diff_key( $data, $defaults ); 447 if ( isset( $args['site_id'] ) ) { 448 unset( $args['site_id'] ); 449 } 450 451 $data = wp_prepare_site_data( $data, $defaults ); 452 if ( is_wp_error( $data ) ) { 453 return $data; 454 } 455 456 if ( false === $wpdb->insert( $wpdb->blogs, $data ) ) { 457 return new WP_Error( 'db_insert_error', __( 'Could not insert site into the database.' ), $wpdb->last_error ); 458 } 459 460 $new_site = get_site( $wpdb->insert_id ); 461 462 clean_blog_cache( $new_site ); 463 464 /** 465 * Fires once a site has been inserted into the database. 466 * 467 * @since 5.1.0 468 * 469 * @param WP_Site $new_site New site object. 470 */ 471 do_action( 'wp_insert_site', $new_site ); 472 473 /** 474 * Fires when a site's initialization routine should be executed. 475 * 476 * @since 5.1.0 477 * 478 * @param WP_Site $new_site New site object. 479 * @param array $args Arguments for the initialization. 480 */ 481 do_action( 'wp_initialize_site', $new_site, $args ); 482 483 // Only compute extra hook parameters if the deprecated hook is actually in use. 484 if ( has_action( 'wpmu_new_blog' ) ) { 485 $user_id = ! empty( $args['user_id'] ) ? $args['user_id'] : 0; 486 $meta = ! empty( $args['options'] ) ? $args['options'] : array(); 487 488 /** 489 * Fires immediately after a new site is created. 490 * 491 * @since MU (3.0.0) 492 * @deprecated 5.1.0 Use wp_insert_site 493 * 494 * @param int $site_id Site ID. 495 * @param int $user_id User ID. 496 * @param string $domain Site domain. 497 * @param string $path Site path. 498 * @param int $network_id Network ID. Only relevant on multi-network installations. 499 * @param array $meta Meta data. Used to set initial site options. 500 */ 501 do_action_deprecated( 'wpmu_new_blog', array( $new_site->id, $user_id, $new_site->domain, $new_site->path, $new_site->network_id, $meta ), '5.1.0', 'wp_insert_site' ); 502 } 503 504 return (int) $new_site->id; 505 } 506 507 /** 508 * Updates a site in the database. 509 * 510 * @since 5.1.0 511 * 512 * @global wpdb $wpdb WordPress database abstraction object. 513 * 514 * @param int $site_id ID of the site that should be updated. 515 * @param array $data Site data to update. See {@see wp_insert_site()} for the list of supported keys. 516 * @return int|WP_Error The updated site's ID on success, or error object on failure. 517 */ 518 function wp_update_site( $site_id, array $data ) { 519 global $wpdb; 520 521 if ( empty( $site_id ) ) { 522 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 523 } 524 525 $old_site = get_site( $site_id ); 526 if ( ! $old_site ) { 527 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 528 } 529 530 $defaults = $old_site->to_array(); 531 $defaults['network_id'] = (int) $defaults['site_id']; 532 $defaults['last_updated'] = current_time( 'mysql', true ); 533 unset( $defaults['blog_id'], $defaults['site_id'] ); 534 535 $data = wp_prepare_site_data( $data, $defaults, $old_site ); 536 if ( is_wp_error( $data ) ) { 537 return $data; 538 } 539 540 if ( false === $wpdb->update( $wpdb->blogs, $data, array( 'blog_id' => $old_site->id ) ) ) { 541 return new WP_Error( 'db_update_error', __( 'Could not update site in the database.' ), $wpdb->last_error ); 542 } 543 544 clean_blog_cache( $old_site ); 545 546 $new_site = get_site( $old_site->id ); 547 548 /** 549 * Fires once a site has been updated in the database. 550 * 551 * @since 5.1.0 552 * 553 * @param WP_Site $new_site New site object. 554 * @param WP_Site $old_site Old site object. 555 */ 556 do_action( 'wp_update_site', $new_site, $old_site ); 557 558 return (int) $new_site->id; 559 } 560 561 /** 562 * Deletes a site from the database. 563 * 564 * @since 5.1.0 565 * 566 * @global wpdb $wpdb WordPress database abstraction object. 567 * 568 * @param int $site_id ID of the site that should be deleted. 569 * @return WP_Site|WP_Error The deleted site object on success, or error object on failure. 570 */ 571 function wp_delete_site( $site_id ) { 572 global $wpdb; 573 574 if ( empty( $site_id ) ) { 575 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 576 } 577 578 $old_site = get_site( $site_id ); 579 if ( ! $old_site ) { 580 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 581 } 582 583 $errors = new WP_Error(); 584 585 /** 586 * Fires before a site should be deleted from the database. 587 * 588 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. If any errors 589 * are present, the site will not be deleted. 590 * 591 * @since 5.1.0 592 * 593 * @param WP_Error $errors Error object to add validation errors to. 594 * @param WP_Site $old_site The site object to be deleted. 595 */ 596 do_action( 'wp_validate_site_deletion', $errors, $old_site ); 597 598 if ( ! empty( $errors->errors ) ) { 599 return $errors; 600 } 601 602 /** 603 * Fires before a site is deleted. 604 * 605 * @since MU (3.0.0) 606 * @deprecated 5.1.0 607 * 608 * @param int $site_id The site ID. 609 * @param bool $drop True if site's table should be dropped. Default is false. 610 */ 611 do_action_deprecated( 'delete_blog', array( $old_site->id, true ), '5.1.0' ); 612 613 /** 614 * Fires when a site's uninitialization routine should be executed. 615 * 616 * @since 5.1.0 617 * 618 * @param WP_Site $old_site Deleted site object. 619 */ 620 do_action( 'wp_uninitialize_site', $old_site ); 621 622 if ( is_site_meta_supported() ) { 623 $blog_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->blogmeta WHERE blog_id = %d ", $old_site->id ) ); 624 foreach ( $blog_meta_ids as $mid ) { 625 delete_metadata_by_mid( 'blog', $mid ); 626 } 627 } 628 629 if ( false === $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $old_site->id ) ) ) { 630 return new WP_Error( 'db_delete_error', __( 'Could not delete site from the database.' ), $wpdb->last_error ); 631 } 632 633 clean_blog_cache( $old_site ); 634 635 /** 636 * Fires once a site has been deleted from the database. 637 * 638 * @since 5.1.0 639 * 640 * @param WP_Site $old_site Deleted site object. 641 */ 642 do_action( 'wp_delete_site', $old_site ); 643 644 /** 645 * Fires after the site is deleted from the network. 646 * 647 * @since 4.8.0 648 * @deprecated 5.1.0 649 * 650 * @param int $site_id The site ID. 651 * @param bool $drop True if site's tables should be dropped. Default is false. 652 */ 653 do_action_deprecated( 'deleted_blog', array( $old_site->id, true ), '5.1.0' ); 654 655 return $old_site; 656 } 657 658 /** 659 * Retrieves site data given a site ID or site object. 660 * 661 * Site data will be cached and returned after being passed through a filter. 662 * If the provided site is empty, the current site global will be used. 663 * 664 * @since 4.6.0 665 * 666 * @param WP_Site|int|null $site Optional. Site to retrieve. Default is the current site. 667 * @return WP_Site|null The site object or null if not found. 668 */ 669 function get_site( $site = null ) { 670 if ( empty( $site ) ) { 671 $site = get_current_blog_id(); 672 } 673 674 if ( $site instanceof WP_Site ) { 675 $_site = $site; 676 } elseif ( is_object( $site ) ) { 677 $_site = new WP_Site( $site ); 678 } else { 679 $_site = WP_Site::get_instance( $site ); 680 } 681 682 if ( ! $_site ) { 683 return null; 684 } 685 686 /** 687 * Fires after a site is retrieved. 688 * 689 * @since 4.6.0 690 * 691 * @param WP_Site $_site Site data. 692 */ 693 $_site = apply_filters( 'get_site', $_site ); 694 695 return $_site; 696 } 697 698 /** 699 * Adds any sites from the given ids to the cache that do not already exist in cache. 700 * 701 * @since 4.6.0 702 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 703 * @access private 704 * 705 * @see update_site_cache() 706 * @global wpdb $wpdb WordPress database abstraction object. 707 * 708 * @param array $ids ID list. 709 * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. 710 */ 711 function _prime_site_caches( $ids, $update_meta_cache = true ) { 712 global $wpdb; 713 714 $non_cached_ids = _get_non_cached_ids( $ids, 'sites' ); 715 if ( ! empty( $non_cached_ids ) ) { 716 $fresh_sites = $wpdb->get_results( sprintf( "SELECT * FROM $wpdb->blogs WHERE blog_id IN (%s)", join( ',', array_map( 'intval', $non_cached_ids ) ) ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 717 718 update_site_cache( $fresh_sites, $update_meta_cache ); 719 } 720 } 721 722 /** 723 * Updates sites in cache. 724 * 725 * @since 4.6.0 726 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 727 * 728 * @param array $sites Array of site objects. 729 * @param bool $update_meta_cache Whether to update site meta cache. Default true. 730 */ 731 function update_site_cache( $sites, $update_meta_cache = true ) { 732 if ( ! $sites ) { 733 return; 734 } 735 $site_ids = array(); 736 foreach ( $sites as $site ) { 737 $site_ids[] = $site->blog_id; 738 wp_cache_add( $site->blog_id, $site, 'sites' ); 739 wp_cache_add( $site->blog_id . 'short', $site, 'blog-details' ); 740 } 741 742 if ( $update_meta_cache ) { 743 update_sitemeta_cache( $site_ids ); 744 } 745 } 746 747 /** 748 * Updates metadata cache for list of site IDs. 749 * 750 * Performs SQL query to retrieve all metadata for the sites matching `$site_ids` and stores them in the cache. 751 * Subsequent calls to `get_site_meta()` will not need to query the database. 752 * 753 * @since 5.1.0 754 * 755 * @param array $site_ids List of site IDs. 756 * @return array|false Returns false if there is nothing to update. Returns an array of metadata on success. 757 */ 758 function update_sitemeta_cache( $site_ids ) { 759 return update_meta_cache( 'blog', $site_ids ); 760 } 761 762 /** 763 * Retrieves a list of sites matching requested arguments. 764 * 765 * @since 4.6.0 766 * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters. 767 * 768 * @see WP_Site_Query::parse_query() 769 * 770 * @param string|array $args { 771 * Optional. Array or query string of site query parameters. Default empty. 772 * 773 * @type array $site__in Array of site IDs to include. Default empty. 774 * @type array $site__not_in Array of site IDs to exclude. Default empty. 775 * @type bool $count Whether to return a site count (true) or array of site objects. 776 * Default false. 777 * @type array $date_query Date query clauses to limit sites by. See WP_Date_Query. 778 * Default null. 779 * @type string $fields Site fields to return. Accepts 'ids' (returns an array of site IDs) 780 * or empty (returns an array of complete site objects). Default empty. 781 * @type int $ID A site ID to only return that site. Default empty. 782 * @type int $number Maximum number of sites to retrieve. Default 100. 783 * @type int $offset Number of sites to offset the query. Used to build LIMIT clause. 784 * Default 0. 785 * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true. 786 * @type string|array $orderby Site status or array of statuses. Accepts 'id', 'domain', 'path', 787 * 'network_id', 'last_updated', 'registered', 'domain_length', 788 * 'path_length', 'site__in' and 'network__in'. Also accepts false, 789 * an empty array, or 'none' to disable `ORDER BY` clause. 790 * Default 'id'. 791 * @type string $order How to order retrieved sites. Accepts 'ASC', 'DESC'. Default 'ASC'. 792 * @type int $network_id Limit results to those affiliated with a given network ID. If 0, 793 * include all networks. Default 0. 794 * @type array $network__in Array of network IDs to include affiliated sites for. Default empty. 795 * @type array $network__not_in Array of network IDs to exclude affiliated sites for. Default empty. 796 * @type string $domain Limit results to those affiliated with a given domain. Default empty. 797 * @type array $domain__in Array of domains to include affiliated sites for. Default empty. 798 * @type array $domain__not_in Array of domains to exclude affiliated sites for. Default empty. 799 * @type string $path Limit results to those affiliated with a given path. Default empty. 800 * @type array $path__in Array of paths to include affiliated sites for. Default empty. 801 * @type array $path__not_in Array of paths to exclude affiliated sites for. Default empty. 802 * @type int $public Limit results to public sites. Accepts '1' or '0'. Default empty. 803 * @type int $archived Limit results to archived sites. Accepts '1' or '0'. Default empty. 804 * @type int $mature Limit results to mature sites. Accepts '1' or '0'. Default empty. 805 * @type int $spam Limit results to spam sites. Accepts '1' or '0'. Default empty. 806 * @type int $deleted Limit results to deleted sites. Accepts '1' or '0'. Default empty. 807 * @type int $lang_id Limit results to a language ID. Default empty. 808 * @type array $lang__in Array of language IDs to include affiliated sites for. Default empty. 809 * @type array $lang__not_in Array of language IDs to exclude affiliated sites for. Default empty. 810 * @type string $search Search term(s) to retrieve matching sites for. Default empty. 811 * @type array $search_columns Array of column names to be searched. Accepts 'domain' and 'path'. 812 * Default empty array. 813 * @type bool $update_site_cache Whether to prime the cache for found sites. Default true. 814 * } 815 * @return array|int List of WP_Site objects, a list of site ids when 'fields' is set to 'ids', 816 * or the number of sites when 'count' is passed as a query var. 817 */ 818 function get_sites( $args = array() ) { 819 $query = new WP_Site_Query(); 820 821 return $query->query( $args ); 822 } 823 824 /** 825 * Prepares site data for insertion or update in the database. 826 * 827 * @since 5.1.0 828 * 829 * @param array $data Associative array of site data passed to the respective function. 830 * See {@see wp_insert_site()} for the possibly included data. 831 * @param array $defaults Site data defaults to parse $data against. 832 * @param WP_Site|null $old_site Optional. Old site object if an update, or null if an insertion. 833 * Default null. 834 * @return array|WP_Error Site data ready for a database transaction, or WP_Error in case a validation 835 * error occurred. 836 */ 837 function wp_prepare_site_data( $data, $defaults, $old_site = null ) { 838 839 // Maintain backward-compatibility with `$site_id` as network ID. 840 if ( isset( $data['site_id'] ) ) { 841 if ( ! empty( $data['site_id'] ) && empty( $data['network_id'] ) ) { 842 $data['network_id'] = $data['site_id']; 843 } 844 unset( $data['site_id'] ); 845 } 846 847 /** 848 * Filters passed site data in order to normalize it. 849 * 850 * @since 5.1.0 851 * 852 * @param array $data Associative array of site data passed to the respective function. 853 * See {@see wp_insert_site()} for the possibly included data. 854 */ 855 $data = apply_filters( 'wp_normalize_site_data', $data ); 856 857 $whitelist = array( 'domain', 'path', 'network_id', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ); 858 $data = array_intersect_key( wp_parse_args( $data, $defaults ), array_flip( $whitelist ) ); 859 860 $errors = new WP_Error(); 861 862 /** 863 * Fires when data should be validated for a site prior to inserting or updating in the database. 864 * 865 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. 866 * 867 * @since 5.1.0 868 * 869 * @param WP_Error $errors Error object to add validation errors to. 870 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 871 * for the included data. 872 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 873 * or null if it is a new site being inserted. 874 */ 875 do_action( 'wp_validate_site_data', $errors, $data, $old_site ); 876 877 if ( ! empty( $errors->errors ) ) { 878 return $errors; 879 } 880 881 // Prepare for database. 882 $data['site_id'] = $data['network_id']; 883 unset( $data['network_id'] ); 884 885 return $data; 886 } 887 888 /** 889 * Normalizes data for a site prior to inserting or updating in the database. 890 * 891 * @since 5.1.0 892 * 893 * @param array $data Associative array of site data passed to the respective function. 894 * See {@see wp_insert_site()} for the possibly included data. 895 * @return array Normalized site data. 896 */ 897 function wp_normalize_site_data( $data ) { 898 // Sanitize domain if passed. 899 if ( array_key_exists( 'domain', $data ) ) { 900 $data['domain'] = trim( $data['domain'] ); 901 $data['domain'] = preg_replace( '/\s+/', '', sanitize_user( $data['domain'], true ) ); 902 if ( is_subdomain_install() ) { 903 $data['domain'] = str_replace( '@', '', $data['domain'] ); 904 } 905 } 906 907 // Sanitize path if passed. 908 if ( array_key_exists( 'path', $data ) ) { 909 $data['path'] = trailingslashit( '/' . trim( $data['path'], '/' ) ); 910 } 911 912 // Sanitize network ID if passed. 913 if ( array_key_exists( 'network_id', $data ) ) { 914 $data['network_id'] = (int) $data['network_id']; 915 } 916 917 // Sanitize status fields if passed. 918 $status_fields = array( 'public', 'archived', 'mature', 'spam', 'deleted' ); 919 foreach ( $status_fields as $status_field ) { 920 if ( array_key_exists( $status_field, $data ) ) { 921 $data[ $status_field ] = (int) $data[ $status_field ]; 922 } 923 } 924 925 // Strip date fields if empty. 926 $date_fields = array( 'registered', 'last_updated' ); 927 foreach ( $date_fields as $date_field ) { 928 if ( ! array_key_exists( $date_field, $data ) ) { 929 continue; 930 } 931 932 if ( empty( $data[ $date_field ] ) || '0000-00-00 00:00:00' === $data[ $date_field ] ) { 933 unset( $data[ $date_field ] ); 934 } 935 } 936 937 return $data; 938 } 939 940 /** 941 * Validates data for a site prior to inserting or updating in the database. 942 * 943 * @since 5.1.0 944 * 945 * @param WP_Error $errors Error object, passed by reference. Will contain validation errors if 946 * any occurred. 947 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 948 * for the included data. 949 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 950 * or null if it is a new site being inserted. 951 */ 952 function wp_validate_site_data( $errors, $data, $old_site = null ) { 953 // A domain must always be present. 954 if ( empty( $data['domain'] ) ) { 955 $errors->add( 'site_empty_domain', __( 'Site domain must not be empty.' ) ); 956 } 957 958 // A path must always be present. 959 if ( empty( $data['path'] ) ) { 960 $errors->add( 'site_empty_path', __( 'Site path must not be empty.' ) ); 961 } 962 963 // A network ID must always be present. 964 if ( empty( $data['network_id'] ) ) { 965 $errors->add( 'site_empty_network_id', __( 'Site network ID must be provided.' ) ); 966 } 967 968 // Both registration and last updated dates must always be present and valid. 969 $date_fields = array( 'registered', 'last_updated' ); 970 foreach ( $date_fields as $date_field ) { 971 if ( empty( $data[ $date_field ] ) ) { 972 $errors->add( 'site_empty_' . $date_field, __( 'Both registration and last updated dates must be provided.' ) ); 973 break; 974 } 975 976 // Allow '0000-00-00 00:00:00', although it be stripped out at this point. 977 if ( '0000-00-00 00:00:00' !== $data[ $date_field ] ) { 978 $month = substr( $data[ $date_field ], 5, 2 ); 979 $day = substr( $data[ $date_field ], 8, 2 ); 980 $year = substr( $data[ $date_field ], 0, 4 ); 981 $valid_date = wp_checkdate( $month, $day, $year, $data[ $date_field ] ); 982 if ( ! $valid_date ) { 983 $errors->add( 'site_invalid_' . $date_field, __( 'Both registration and last updated dates must be valid dates.' ) ); 984 break; 985 } 986 } 987 } 988 989 if ( ! empty( $errors->errors ) ) { 990 return; 991 } 992 993 // If a new site, or domain/path/network ID have changed, ensure uniqueness. 994 if ( ! $old_site 995 || $data['domain'] !== $old_site->domain 996 || $data['path'] !== $old_site->path 997 || $data['network_id'] !== $old_site->network_id 998 ) { 999 if ( domain_exists( $data['domain'], $data['path'], $data['network_id'] ) ) { 1000 $errors->add( 'site_taken', __( 'Sorry, that site already exists!' ) ); 1001 } 1002 } 1003 } 1004 1005 /** 1006 * Runs the initialization routine for a given site. 1007 * 1008 * This process includes creating the site's database tables and 1009 * populating them with defaults. 1010 * 1011 * @since 5.1.0 1012 * 1013 * @global wpdb $wpdb WordPress database abstraction object. 1014 * @global WP_Roles $wp_roles WordPress role management object. 1015 * 1016 * @param int|WP_Site $site_id Site ID or object. 1017 * @param array $args { 1018 * Optional. Arguments to modify the initialization behavior. 1019 * 1020 * @type int $user_id Required. User ID for the site administrator. 1021 * @type string $title Site title. Default is 'Site %d' where %d is the 1022 * site ID. 1023 * @type array $options Custom option $key => $value pairs to use. Default 1024 * empty array. 1025 * @type array $meta Custom site metadata $key => $value pairs to use. 1026 * Default empty array. 1027 * } 1028 * @return bool|WP_Error True on success, or error object on failure. 1029 */ 1030 function wp_initialize_site( $site_id, array $args = array() ) { 1031 global $wpdb, $wp_roles; 1032 1033 if ( empty( $site_id ) ) { 1034 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 1035 } 1036 1037 $site = get_site( $site_id ); 1038 if ( ! $site ) { 1039 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 1040 } 1041 1042 if ( wp_is_site_initialized( $site ) ) { 1043 return new WP_Error( 'site_already_initialized', __( 'The site appears to be already initialized.' ) ); 1044 } 1045 1046 $network = get_network( $site->network_id ); 1047 if ( ! $network ) { 1048 $network = get_network(); 1049 } 1050 1051 $args = wp_parse_args( 1052 $args, 1053 array( 1054 'user_id' => 0, 1055 /* translators: %d: site ID */ 1056 'title' => sprintf( __( 'Site %d' ), $site->id ), 1057 'options' => array(), 1058 'meta' => array(), 1059 ) 1060 ); 1061 1062 /** 1063 * Filters the arguments for initializing a site. 1064 * 1065 * @since 5.1.0 1066 * 1067 * @param array $args Arguments to modify the initialization behavior. 1068 * @param WP_Site $site Site that is being initialized. 1069 * @param WP_Network $network Network that the site belongs to. 1070 */ 1071 $args = apply_filters( 'wp_initialize_site_args', $args, $site, $network ); 1072 1073 $orig_installing = wp_installing(); 1074 if ( ! $orig_installing ) { 1075 wp_installing( true ); 1076 } 1077 1078 $switch = false; 1079 if ( get_current_blog_id() !== $site->id ) { 1080 $switch = true; 1081 switch_to_blog( $site->id ); 1082 } 1083 1084 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 1085 1086 // Set up the database tables. 1087 make_db_current_silent( 'blog' ); 1088 1089 $home_scheme = 'http'; 1090 $siteurl_scheme = 'http'; 1091 if ( ! is_subdomain_install() ) { 1092 if ( 'https' === parse_url( get_home_url( $network->site_id ), PHP_URL_SCHEME ) ) { 1093 $home_scheme = 'https'; 1094 } 1095 if ( 'https' === parse_url( get_network_option( $network->id, 'siteurl' ), PHP_URL_SCHEME ) ) { 1096 $siteurl_scheme = 'https'; 1097 } 1098 } 1099 1100 // Populate the site's options. 1101 populate_options( 1102 array_merge( 1103 array( 1104 'home' => untrailingslashit( $home_scheme . '://' . $site->domain . $site->path ), 1105 'siteurl' => untrailingslashit( $siteurl_scheme . '://' . $site->domain . $site->path ), 1106 'blogname' => wp_unslash( $args['title'] ), 1107 'admin_email' => '', 1108 'upload_path' => get_network_option( $network->id, 'ms_files_rewriting' ) ? UPLOADBLOGSDIR . "/{$site->id}/files" : get_blog_option( $network->site_id, 'upload_path' ), 1109 'blog_public' => (int) $site->public, 1110 'WPLANG' => get_network_option( $network->id, 'WPLANG' ), 1111 ), 1112 $args['options'] 1113 ) 1114 ); 1115 1116 // Populate the site's roles. 1117 populate_roles(); 1118 $wp_roles = new WP_Roles(); 1119 1120 // Populate metadata for the site. 1121 populate_site_meta( $site->id, $args['meta'] ); 1122 1123 // Remove all permissions that may exist for the site. 1124 $table_prefix = $wpdb->get_blog_prefix(); 1125 delete_metadata( 'user', 0, $table_prefix . 'user_level', null, true ); // delete all 1126 delete_metadata( 'user', 0, $table_prefix . 'capabilities', null, true ); // delete all 1127 1128 // Install default site content. 1129 wp_install_defaults( $args['user_id'] ); 1130 1131 // Set the site administrator. 1132 add_user_to_blog( $site->id, $args['user_id'], 'administrator' ); 1133 if ( ! user_can( $args['user_id'], 'manage_network' ) && ! get_user_meta( $args['user_id'], 'primary_blog', true ) ) { 1134 update_user_meta( $args['user_id'], 'primary_blog', $site->id ); 1135 } 1136 1137 if ( $switch ) { 1138 restore_current_blog(); 1139 } 1140 1141 wp_installing( $orig_installing ); 1142 1143 return true; 1144 } 1145 1146 /** 1147 * Runs the uninitialization routine for a given site. 1148 * 1149 * This process includes dropping the site's database tables and deleting its uploads directory. 1150 * 1151 * @since 5.1.0 1152 * 1153 * @global wpdb $wpdb WordPress database abstraction object. 1154 * 1155 * @param int|WP_Site $site_id Site ID or object. 1156 * @return bool|WP_Error True on success, or error object on failure. 1157 */ 1158 function wp_uninitialize_site( $site_id ) { 1159 global $wpdb; 1160 1161 if ( empty( $site_id ) ) { 1162 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 1163 } 1164 1165 $site = get_site( $site_id ); 1166 if ( ! $site ) { 1167 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 1168 } 1169 1170 if ( ! wp_is_site_initialized( $site ) ) { 1171 return new WP_Error( 'site_already_uninitialized', __( 'The site appears to be already uninitialized.' ) ); 1172 } 1173 1174 $users = get_users( 1175 array( 1176 'blog_id' => $site->id, 1177 'fields' => 'ids', 1178 ) 1179 ); 1180 1181 // Remove users from the site. 1182 if ( ! empty( $users ) ) { 1183 foreach ( $users as $user_id ) { 1184 remove_user_from_blog( $user_id, $site->id ); 1185 } 1186 } 1187 1188 $switch = false; 1189 if ( get_current_blog_id() !== $site->id ) { 1190 $switch = true; 1191 switch_to_blog( $site->id ); 1192 } 1193 1194 $uploads = wp_get_upload_dir(); 1195 1196 $tables = $wpdb->tables( 'blog' ); 1197 1198 /** 1199 * Filters the tables to drop when the site is deleted. 1200 * 1201 * @since MU (3.0.0) 1202 * 1203 * @param string[] $tables Array of names of the site tables to be dropped. 1204 * @param int $site_id The ID of the site to drop tables for. 1205 */ 1206 $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $site->id ); 1207 1208 foreach ( (array) $drop_tables as $table ) { 1209 $wpdb->query( "DROP TABLE IF EXISTS `$table`" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 237 return $details; 1210 238 } 1211 239 240 switch_to_blog( $blog_id ); 241 $details->blogname = get_option( 'blogname' ); 242 $details->siteurl = get_option( 'siteurl' ); 243 $details->post_count = get_option( 'post_count' ); 244 $details->home = get_option( 'home' ); 245 restore_current_blog(); 246 1212 247 /** 1213 * Filters the upload base directory to delete when the site is deleted.248 * Filters a blog's details. 1214 249 * 1215 250 * @since MU (3.0.0) 251 * @deprecated 4.7.0 Use site_details 1216 252 * 1217 * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir() 1218 * @param int $site_id The site ID. 253 * @param object $details The blog details. 1219 254 */ 1220 $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $site->id ); 1221 $dir = rtrim( $dir, DIRECTORY_SEPARATOR ); 1222 $top_dir = $dir; 1223 $stack = array( $dir ); 1224 $index = 0; 1225 1226 while ( $index < count( $stack ) ) { 1227 // Get indexed directory from stack 1228 $dir = $stack[ $index ]; 1229 1230 // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged 1231 $dh = @opendir( $dir ); 1232 if ( $dh ) { 1233 $file = @readdir( $dh ); 1234 while ( false !== $file ) { 1235 if ( '.' === $file || '..' === $file ) { 1236 $file = @readdir( $dh ); 1237 continue; 1238 } 255 $details = apply_filters_deprecated( 'blog_details', array( $details ), '4.7.0', 'site_details' ); 1239 256 1240 if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) ) { 1241 $stack[] = $dir . DIRECTORY_SEPARATOR . $file; 1242 } elseif ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) ) { 1243 @unlink( $dir . DIRECTORY_SEPARATOR . $file ); 1244 } 257 wp_cache_set( $blog_id . $all, $details, 'blog-details' ); 1245 258 1246 $file = @readdir( $dh ); 1247 } 1248 @closedir( $dh ); 1249 } 1250 $index++; 1251 } 259 $key = md5( $details->domain . $details->path ); 260 wp_cache_set( $key, $details, 'blog-lookup' ); 1252 261 1253 $stack = array_reverse( $stack ); // Last added dirs are deepest 1254 foreach ( (array) $stack as $dir ) { 1255 if ( $dir != $top_dir ) { 1256 @rmdir( $dir ); 1257 } 1258 } 262 return $details; 263 } 1259 264 1260 // phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged 1261 if ( $switch ) { 1262 restore_current_blog(); 265 /** 266 * Clear the blog details cache. 267 * 268 * @since MU (3.0.0) 269 * 270 * @param int $blog_id Optional. Blog ID. Defaults to current blog. 271 */ 272 function refresh_blog_details( $blog_id = 0 ) { 273 $blog_id = (int) $blog_id; 274 if ( ! $blog_id ) { 275 $blog_id = get_current_blog_id(); 1263 276 } 1264 277 1265 return true;278 clean_blog_cache( $blog_id ); 1266 279 } 1267 280 1268 281 /** 1269 * Checks whether a site is initialized. 1270 * 1271 * A site is considered initialized when its database tables are present. 282 * Update the details for a blog. Updates the blogs table for a given blog id. 1272 283 * 1273 * @since 5.1.0284 * @since MU (3.0.0) 1274 285 * 1275 286 * @global wpdb $wpdb WordPress database abstraction object. 1276 287 * 1277 * @param int|WP_Site $site_id Site ID or object. 1278 * @return bool True if the site is initialized, false otherwise. 288 * @param int $blog_id Blog ID 289 * @param array $details Array of details keyed by blogs table field names. 290 * @return bool True if update succeeds, false otherwise. 1279 291 */ 1280 function wp_is_site_initialized( $site_id) {292 function update_blog_details( $blog_id, $details = array() ) { 1281 293 global $wpdb; 1282 294 1283 if ( is_object( $site_id) ) {1284 $site_id = $site_id->blog_id;295 if ( empty( $details ) ) { 296 return false; 1285 297 } 1286 $site_id = (int) $site_id;1287 298 1288 /** 1289 * Filters the check for whether a site is initialized before the database is accessed. 1290 * 1291 * Returning a non-null value will effectively short-circuit the function, returning 1292 * that value instead. 1293 * 1294 * @since 5.1.0 1295 * 1296 * @param bool|null $pre The value to return, if not null. 1297 * @param int $site_id The site ID that is being checked. 1298 */ 1299 $pre = apply_filters( 'pre_wp_is_site_initialized', null, $site_id ); 1300 if ( null !== $pre ) { 1301 return (bool) $pre; 299 if ( is_object( $details ) ) { 300 $details = get_object_vars( $details ); 1302 301 } 1303 302 1304 $switch = false; 1305 if ( get_current_blog_id() !== $site_id ) { 1306 $switch = true; 1307 remove_action( 'switch_blog', 'wp_switch_roles_and_user', 1 ); 1308 switch_to_blog( $site_id ); 303 $site = wp_update_site( $blog_id, $details ); 304 305 if ( is_wp_error( $site ) ) { 306 return false; 1309 307 } 1310 308 1311 $suppress = $wpdb->suppress_errors(); 1312 $result = (bool) $wpdb->get_results( "DESCRIBE {$wpdb->posts}" ); 1313 $wpdb->suppress_errors( $suppress ); 309 return true; 310 } 1314 311 1315 if ( $switch ) { 1316 restore_current_blog(); 1317 add_action( 'switch_blog', 'wp_switch_roles_and_user', 1, 2 ); 312 /** 313 * Cleans the site details cache for a site. 314 * 315 * @since 4.7.4 316 * 317 * @param int $site_id Optional. Site ID. Default is the current site ID. 318 */ 319 function clean_site_details_cache( $site_id = 0 ) { 320 $site_id = (int) $site_id; 321 if ( ! $site_id ) { 322 $site_id = get_current_blog_id(); 1318 323 } 1319 324 1320 return $result; 325 wp_cache_delete( $site_id, 'site-details' ); 326 wp_cache_delete( $site_id, 'blog-details' ); 1321 327 } 1322 328 1323 329 /** … … 1459 465 } 1460 466 1461 467 /** 1462 * Adds metadata to a site.1463 *1464 * @since 5.1.01465 *1466 * @param int $site_id Site ID.1467 * @param string $meta_key Metadata name.1468 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.1469 * @param bool $unique Optional. Whether the same key should not be added.1470 * Default false.1471 * @return int|false Meta ID on success, false on failure.1472 */1473 function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) {1474 return add_metadata( 'blog', $site_id, $meta_key, $meta_value, $unique );1475 }1476 1477 /**1478 * Removes metadata matching criteria from a site.1479 *1480 * You can match based on the key, or key and value. Removing based on key and1481 * value, will keep from removing duplicate metadata with the same key. It also1482 * allows removing all metadata matching key, if needed.1483 *1484 * @since 5.1.01485 *1486 * @param int $site_id Site ID.1487 * @param string $meta_key Metadata name.1488 * @param mixed $meta_value Optional. Metadata value. Must be serializable if1489 * non-scalar. Default empty.1490 * @return bool True on success, false on failure.1491 */1492 function delete_site_meta( $site_id, $meta_key, $meta_value = '' ) {1493 return delete_metadata( 'blog', $site_id, $meta_key, $meta_value );1494 }1495 1496 /**1497 * Retrieves metadata for a site.1498 *1499 * @since 5.1.01500 *1501 * @param int $site_id Site ID.1502 * @param string $key Optional. The meta key to retrieve. By default, returns1503 * data for all keys. Default empty.1504 * @param bool $single Optional. Whether to return a single value. Default false.1505 * @return mixed Will be an array if $single is false. Will be value of meta data1506 * field if $single is true.1507 */1508 function get_site_meta( $site_id, $key = '', $single = false ) {1509 return get_metadata( 'blog', $site_id, $key, $single );1510 }1511 1512 /**1513 * Updates metadata for a site.1514 *1515 * Use the $prev_value parameter to differentiate between meta fields with the1516 * same key and site ID.1517 *1518 * If the meta field for the site does not exist, it will be added.1519 *1520 * @since 5.1.01521 *1522 * @param int $site_id Site ID.1523 * @param string $meta_key Metadata key.1524 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.1525 * @param mixed $prev_value Optional. Previous value to check before removing.1526 * Default empty.1527 * @return int|bool Meta ID if the key didn't exist, true on successful update,1528 * false on failure.1529 */1530 function update_site_meta( $site_id, $meta_key, $meta_value, $prev_value = '' ) {1531 return update_metadata( 'blog', $site_id, $meta_key, $meta_value, $prev_value );1532 }1533 1534 /**1535 * Deletes everything from site meta matching meta key.1536 *1537 * @since 5.1.01538 *1539 * @param string $meta_key Metadata key to search for when deleting.1540 * @return bool Whether the site meta key was deleted from the database.1541 */1542 function delete_site_meta_by_key( $meta_key ) {1543 return delete_metadata( 'blog', null, $meta_key, '', true );1544 }1545 1546 /**1547 468 * Switch the current blog. 1548 469 * 1549 470 * This function is useful if you need to pull posts, or other information, … … 1843 764 } 1844 765 1845 766 /** 1846 * Retrieves a list of networks.1847 *1848 * @since 4.6.01849 *1850 * @param string|array $args Optional. Array or string of arguments. See WP_Network_Query::parse_query()1851 * for information on accepted arguments. Default empty array.1852 * @return array|int List of WP_Network objects, a list of network ids when 'fields' is set to 'ids',1853 * or the number of networks when 'count' is passed as a query var.1854 */1855 function get_networks( $args = array() ) {1856 $query = new WP_Network_Query();1857 1858 return $query->query( $args );1859 }1860 1861 /**1862 * Retrieves network data given a network ID or network object.1863 *1864 * Network data will be cached and returned after being passed through a filter.1865 * If the provided network is empty, the current network global will be used.1866 *1867 * @since 4.6.01868 *1869 * @global WP_Network $current_site1870 *1871 * @param WP_Network|int|null $network Optional. Network to retrieve. Default is the current network.1872 * @return WP_Network|null The network object or null if not found.1873 */1874 function get_network( $network = null ) {1875 global $current_site;1876 if ( empty( $network ) && isset( $current_site ) ) {1877 $network = $current_site;1878 }1879 1880 if ( $network instanceof WP_Network ) {1881 $_network = $network;1882 } elseif ( is_object( $network ) ) {1883 $_network = new WP_Network( $network );1884 } else {1885 $_network = WP_Network::get_instance( $network );1886 }1887 1888 if ( ! $_network ) {1889 return null;1890 }1891 1892 /**1893 * Fires after a network is retrieved.1894 *1895 * @since 4.6.01896 *1897 * @param WP_Network $_network Network data.1898 */1899 $_network = apply_filters( 'get_network', $_network );1900 1901 return $_network;1902 }1903 1904 /**1905 * Removes a network from the object cache.1906 *1907 * @since 4.6.01908 *1909 * @global bool $_wp_suspend_cache_invalidation1910 *1911 * @param int|array $ids Network ID or an array of network IDs to remove from cache.1912 */1913 function clean_network_cache( $ids ) {1914 global $_wp_suspend_cache_invalidation;1915 1916 if ( ! empty( $_wp_suspend_cache_invalidation ) ) {1917 return;1918 }1919 1920 foreach ( (array) $ids as $id ) {1921 wp_cache_delete( $id, 'networks' );1922 1923 /**1924 * Fires immediately after a network has been removed from the object cache.1925 *1926 * @since 4.6.01927 *1928 * @param int $id Network ID.1929 */1930 do_action( 'clean_network_cache', $id );1931 }1932 1933 wp_cache_set( 'last_changed', microtime(), 'networks' );1934 }1935 1936 /**1937 * Updates the network cache of given networks.1938 *1939 * Will add the networks in $networks to the cache. If network ID already exists1940 * in the network cache then it will not be updated. The network is added to the1941 * cache using the network group with the key using the ID of the networks.1942 *1943 * @since 4.6.01944 *1945 * @param array $networks Array of network row objects.1946 */1947 function update_network_cache( $networks ) {1948 foreach ( (array) $networks as $network ) {1949 wp_cache_add( $network->id, $network, 'networks' );1950 }1951 }1952 1953 /**1954 * Adds any networks from the given IDs to the cache that do not already exist in cache.1955 *1956 * @since 4.6.01957 * @access private1958 *1959 * @see update_network_cache()1960 * @global wpdb $wpdb WordPress database abstraction object.1961 *1962 * @param array $network_ids Array of network IDs.1963 */1964 function _prime_network_caches( $network_ids ) {1965 global $wpdb;1966 1967 $non_cached_ids = _get_non_cached_ids( $network_ids, 'networks' );1968 if ( ! empty( $non_cached_ids ) ) {1969 $fresh_networks = $wpdb->get_results( sprintf( "SELECT $wpdb->site.* FROM $wpdb->site WHERE id IN (%s)", join( ',', array_map( 'intval', $non_cached_ids ) ) ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared1970 1971 update_network_cache( $fresh_networks );1972 }1973 }1974 1975 /**1976 767 * Handler for updating the site's last updated date when a post is published or 1977 768 * an already published post is changed. 1978 769 * … … 2062 853 2063 854 update_posts_count(); 2064 855 } 2065 2066 /**2067 * Updates the count of sites for a network based on a changed site.2068 *2069 * @since 5.1.02070 *2071 * @param WP_Site $new_site The site object that has been inserted, updated or deleted.2072 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous2073 * state of that site. Default null.2074 */2075 function wp_maybe_update_network_site_counts_on_update( $new_site, $old_site = null ) {2076 if ( null === $old_site ) {2077 wp_maybe_update_network_site_counts( $new_site->network_id );2078 return;2079 }2080 2081 if ( $new_site->network_id != $old_site->network_id ) {2082 wp_maybe_update_network_site_counts( $new_site->network_id );2083 wp_maybe_update_network_site_counts( $old_site->network_id );2084 }2085 }2086 2087 /**2088 * Triggers actions on site status updates.2089 *2090 * @since 5.1.02091 *2092 * @param WP_Site $new_site The site object after the update.2093 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous2094 * state of that site. Default null.2095 */2096 function wp_maybe_transition_site_statuses_on_update( $new_site, $old_site = null ) {2097 $site_id = $new_site->id;2098 2099 // Use the default values for a site if no previous state is given.2100 if ( ! $old_site ) {2101 $old_site = new WP_Site( new stdClass() );2102 }2103 2104 if ( $new_site->spam != $old_site->spam ) {2105 if ( 1 == $new_site->spam ) {2106 2107 /**2108 * Fires when the 'spam' status is added to a site.2109 *2110 * @since MU (3.0.0)2111 *2112 * @param int $site_id Site ID.2113 */2114 do_action( 'make_spam_blog', $site_id );2115 } else {2116 2117 /**2118 * Fires when the 'spam' status is removed from a site.2119 *2120 * @since MU (3.0.0)2121 *2122 * @param int $site_id Site ID.2123 */2124 do_action( 'make_ham_blog', $site_id );2125 }2126 }2127 2128 if ( $new_site->mature != $old_site->mature ) {2129 if ( 1 == $new_site->mature ) {2130 2131 /**2132 * Fires when the 'mature' status is added to a site.2133 *2134 * @since 3.1.02135 *2136 * @param int $site_id Site ID.2137 */2138 do_action( 'mature_blog', $site_id );2139 } else {2140 2141 /**2142 * Fires when the 'mature' status is removed from a site.2143 *2144 * @since 3.1.02145 *2146 * @param int $site_id Site ID.2147 */2148 do_action( 'unmature_blog', $site_id );2149 }2150 }2151 2152 if ( $new_site->archived != $old_site->archived ) {2153 if ( 1 == $new_site->archived ) {2154 2155 /**2156 * Fires when the 'archived' status is added to a site.2157 *2158 * @since MU (3.0.0)2159 *2160 * @param int $site_id Site ID.2161 */2162 do_action( 'archive_blog', $site_id );2163 } else {2164 2165 /**2166 * Fires when the 'archived' status is removed from a site.2167 *2168 * @since MU (3.0.0)2169 *2170 * @param int $site_id Site ID.2171 */2172 do_action( 'unarchive_blog', $site_id );2173 }2174 }2175 2176 if ( $new_site->deleted != $old_site->deleted ) {2177 if ( 1 == $new_site->deleted ) {2178 2179 /**2180 * Fires when the 'deleted' status is added to a site.2181 *2182 * @since 3.5.02183 *2184 * @param int $site_id Site ID.2185 */2186 do_action( 'make_delete_blog', $site_id );2187 } else {2188 2189 /**2190 * Fires when the 'deleted' status is removed from a site.2191 *2192 * @since 3.5.02193 *2194 * @param int $site_id Site ID.2195 */2196 do_action( 'make_undelete_blog', $site_id );2197 }2198 }2199 2200 if ( $new_site->public != $old_site->public ) {2201 2202 /**2203 * Fires after the current blog's 'public' setting is updated.2204 *2205 * @since MU (3.0.0)2206 *2207 * @param int $site_id Site ID.2208 * @param string $value The value of the site status.2209 */2210 do_action( 'update_blog_public', $site_id, $new_site->public );2211 }2212 }2213 2214 /**2215 * Cleans the necessary caches after specific site data has been updated.2216 *2217 * @since 5.1.02218 *2219 * @param WP_Site $new_site The site object after the update.2220 * @param WP_Site $old_site The site obejct prior to the update.2221 */2222 function wp_maybe_clean_new_site_cache_on_update( $new_site, $old_site ) {2223 if ( $old_site->domain !== $new_site->domain || $old_site->path !== $new_site->path ) {2224 clean_blog_cache( $new_site );2225 }2226 }2227 2228 /**2229 * Updates the `blog_public` option for a given site ID.2230 *2231 * @since 5.1.02232 *2233 * @param int $site_id Site ID.2234 * @param string $public The value of the site status.2235 */2236 function wp_update_blog_public_option_on_site_update( $site_id, $public ) {2237 2238 // Bail if the site's database tables do not exist (yet).2239 if ( ! wp_is_site_initialized( $site_id ) ) {2240 return;2241 }2242 2243 update_blog_option( $site_id, 'blog_public', $public );2244 }2245 2246 /**2247 * Sets the last changed time for the 'sites' cache group.2248 *2249 * @since 5.1.02250 */2251 function wp_cache_set_sites_last_changed() {2252 wp_cache_set( 'last_changed', microtime(), 'sites' );2253 }2254 2255 /**2256 * Aborts calls to site meta if it is not supported.2257 *2258 * @since 5.1.02259 *2260 * @global wpdb $wpdb WordPress database abstraction object.2261 *2262 * @param mixed $check Skip-value for whether to proceed site meta function execution.2263 * @return mixed Original value of $check, or false if site meta is not supported.2264 */2265 function wp_check_site_meta_support_prefilter( $check ) {2266 if ( ! is_site_meta_supported() ) {2267 /* translators: %s: database table name */2268 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The %s table is not installed. Please run the network database upgrade.' ), $GLOBALS['wpdb']->blogmeta ), '5.1.0' );2269 return false;2270 }2271 2272 return $check;2273 } -
src/wp-includes/ms-network.php
1 <?php 2 /** 3 * Network API 4 * 5 * @package WordPress 6 * @subpackage Multisite 7 * @since 5.1.0 8 */ 9 10 /** 11 * Retrieves network data given a network ID or network object. 12 * 13 * Network data will be cached and returned after being passed through a filter. 14 * If the provided network is empty, the current network global will be used. 15 * 16 * @since 4.6.0 17 * 18 * @global WP_Network $current_site 19 * 20 * @param WP_Network|int|null $network Optional. Network to retrieve. Default is the current network. 21 * @return WP_Network|null The network object or null if not found. 22 */ 23 function get_network( $network = null ) { 24 global $current_site; 25 if ( empty( $network ) && isset( $current_site ) ) { 26 $network = $current_site; 27 } 28 29 if ( $network instanceof WP_Network ) { 30 $_network = $network; 31 } elseif ( is_object( $network ) ) { 32 $_network = new WP_Network( $network ); 33 } else { 34 $_network = WP_Network::get_instance( $network ); 35 } 36 37 if ( ! $_network ) { 38 return null; 39 } 40 41 /** 42 * Fires after a network is retrieved. 43 * 44 * @since 4.6.0 45 * 46 * @param WP_Network $_network Network data. 47 */ 48 $_network = apply_filters( 'get_network', $_network ); 49 50 return $_network; 51 } 52 53 /** 54 * Retrieves a list of networks. 55 * 56 * @since 4.6.0 57 * 58 * @param string|array $args Optional. Array or string of arguments. See WP_Network_Query::parse_query() 59 * for information on accepted arguments. Default empty array. 60 * @return array|int List of WP_Network objects, a list of network ids when 'fields' is set to 'ids', 61 * or the number of networks when 'count' is passed as a query var. 62 */ 63 function get_networks( $args = array() ) { 64 $query = new WP_Network_Query(); 65 66 return $query->query( $args ); 67 } 68 69 /** 70 * Removes a network from the object cache. 71 * 72 * @since 4.6.0 73 * 74 * @global bool $_wp_suspend_cache_invalidation 75 * 76 * @param int|array $ids Network ID or an array of network IDs to remove from cache. 77 */ 78 function clean_network_cache( $ids ) { 79 global $_wp_suspend_cache_invalidation; 80 81 if ( ! empty( $_wp_suspend_cache_invalidation ) ) { 82 return; 83 } 84 85 foreach ( (array) $ids as $id ) { 86 wp_cache_delete( $id, 'networks' ); 87 88 /** 89 * Fires immediately after a network has been removed from the object cache. 90 * 91 * @since 4.6.0 92 * 93 * @param int $id Network ID. 94 */ 95 do_action( 'clean_network_cache', $id ); 96 } 97 98 wp_cache_set( 'last_changed', microtime(), 'networks' ); 99 } 100 101 /** 102 * Updates the network cache of given networks. 103 * 104 * Will add the networks in $networks to the cache. If network ID already exists 105 * in the network cache then it will not be updated. The network is added to the 106 * cache using the network group with the key using the ID of the networks. 107 * 108 * @since 4.6.0 109 * 110 * @param array $networks Array of network row objects. 111 */ 112 function update_network_cache( $networks ) { 113 foreach ( (array) $networks as $network ) { 114 wp_cache_add( $network->id, $network, 'networks' ); 115 } 116 } 117 118 /** 119 * Adds any networks from the given IDs to the cache that do not already exist in cache. 120 * 121 * @since 4.6.0 122 * @access private 123 * 124 * @see update_network_cache() 125 * @global wpdb $wpdb WordPress database abstraction object. 126 * 127 * @param array $network_ids Array of network IDs. 128 */ 129 function _prime_network_caches( $network_ids ) { 130 global $wpdb; 131 132 $non_cached_ids = _get_non_cached_ids( $network_ids, 'networks' ); 133 if ( ! empty( $non_cached_ids ) ) { 134 $fresh_networks = $wpdb->get_results( sprintf( "SELECT $wpdb->site.* FROM $wpdb->site WHERE id IN (%s)", join( ',', array_map( 'intval', $non_cached_ids ) ) ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 135 136 update_network_cache( $fresh_networks ); 137 } 138 } -
src/wp-includes/ms-site.php
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 * } 34 * @return int|WP_Error The new site's ID on success, or error object on failure. 35 */ 36 function wp_insert_site( array $data ) { 37 global $wpdb; 38 39 $now = current_time( 'mysql', true ); 40 41 $defaults = array( 42 'domain' => '', 43 'path' => '/', 44 'network_id' => get_current_network_id(), 45 'registered' => $now, 46 'last_updated' => $now, 47 'public' => 1, 48 'archived' => 0, 49 'mature' => 0, 50 'spam' => 0, 51 'deleted' => 0, 52 'lang_id' => 0, 53 ); 54 55 // Extract the passed arguments that may be relevant for site initialization. 56 $args = array_diff_key( $data, $defaults ); 57 if ( isset( $args['site_id'] ) ) { 58 unset( $args['site_id'] ); 59 } 60 61 $data = wp_prepare_site_data( $data, $defaults ); 62 if ( is_wp_error( $data ) ) { 63 return $data; 64 } 65 66 if ( false === $wpdb->insert( $wpdb->blogs, $data ) ) { 67 return new WP_Error( 'db_insert_error', __( 'Could not insert site into the database.' ), $wpdb->last_error ); 68 } 69 70 $new_site = get_site( $wpdb->insert_id ); 71 72 clean_blog_cache( $new_site ); 73 74 /** 75 * Fires once a site has been inserted into the database. 76 * 77 * @since 5.1.0 78 * 79 * @param WP_Site $new_site New site object. 80 */ 81 do_action( 'wp_insert_site', $new_site ); 82 83 /** 84 * Fires when a site's initialization routine should be executed. 85 * 86 * @since 5.1.0 87 * 88 * @param WP_Site $new_site New site object. 89 * @param array $args Arguments for the initialization. 90 */ 91 do_action( 'wp_initialize_site', $new_site, $args ); 92 93 // Only compute extra hook parameters if the deprecated hook is actually in use. 94 if ( has_action( 'wpmu_new_blog' ) ) { 95 $user_id = ! empty( $args['user_id'] ) ? $args['user_id'] : 0; 96 $meta = ! empty( $args['options'] ) ? $args['options'] : array(); 97 98 /** 99 * Fires immediately after a new site is created. 100 * 101 * @since MU (3.0.0) 102 * @deprecated 5.1.0 Use wp_insert_site 103 * 104 * @param int $site_id Site ID. 105 * @param int $user_id User ID. 106 * @param string $domain Site domain. 107 * @param string $path Site path. 108 * @param int $network_id Network ID. Only relevant on multi-network installations. 109 * @param array $meta Meta data. Used to set initial site options. 110 */ 111 do_action_deprecated( 'wpmu_new_blog', array( $new_site->id, $user_id, $new_site->domain, $new_site->path, $new_site->network_id, $meta ), '5.1.0', 'wp_insert_site' ); 112 } 113 114 return (int) $new_site->id; 115 } 116 117 /** 118 * Updates a site in the database. 119 * 120 * @since 5.1.0 121 * 122 * @global wpdb $wpdb WordPress database abstraction object. 123 * 124 * @param int $site_id ID of the site that should be updated. 125 * @param array $data Site data to update. See {@see wp_insert_site()} for the list of supported keys. 126 * @return int|WP_Error The updated site's ID on success, or error object on failure. 127 */ 128 function wp_update_site( $site_id, array $data ) { 129 global $wpdb; 130 131 if ( empty( $site_id ) ) { 132 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 133 } 134 135 $old_site = get_site( $site_id ); 136 if ( ! $old_site ) { 137 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 138 } 139 140 $defaults = $old_site->to_array(); 141 $defaults['network_id'] = (int) $defaults['site_id']; 142 $defaults['last_updated'] = current_time( 'mysql', true ); 143 unset( $defaults['blog_id'], $defaults['site_id'] ); 144 145 $data = wp_prepare_site_data( $data, $defaults, $old_site ); 146 if ( is_wp_error( $data ) ) { 147 return $data; 148 } 149 150 if ( false === $wpdb->update( $wpdb->blogs, $data, array( 'blog_id' => $old_site->id ) ) ) { 151 return new WP_Error( 'db_update_error', __( 'Could not update site in the database.' ), $wpdb->last_error ); 152 } 153 154 clean_blog_cache( $old_site ); 155 156 $new_site = get_site( $old_site->id ); 157 158 /** 159 * Fires once a site has been updated in the database. 160 * 161 * @since 5.1.0 162 * 163 * @param WP_Site $new_site New site object. 164 * @param WP_Site $old_site Old site object. 165 */ 166 do_action( 'wp_update_site', $new_site, $old_site ); 167 168 return (int) $new_site->id; 169 } 170 171 /** 172 * Deletes a site from the database. 173 * 174 * @since 5.1.0 175 * 176 * @global wpdb $wpdb WordPress database abstraction object. 177 * 178 * @param int $site_id ID of the site that should be deleted. 179 * @return WP_Site|WP_Error The deleted site object on success, or error object on failure. 180 */ 181 function wp_delete_site( $site_id ) { 182 global $wpdb; 183 184 if ( empty( $site_id ) ) { 185 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 186 } 187 188 $old_site = get_site( $site_id ); 189 if ( ! $old_site ) { 190 return new WP_Error( 'site_not_exist', __( 'Site does not exist.' ) ); 191 } 192 193 $errors = new WP_Error(); 194 195 /** 196 * Fires before a site should be deleted from the database. 197 * 198 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. If any errors 199 * are present, the site will not be deleted. 200 * 201 * @since 5.1.0 202 * 203 * @param WP_Error $errors Error object to add validation errors to. 204 * @param WP_Site $old_site The site object to be deleted. 205 */ 206 do_action( 'wp_validate_site_deletion', $errors, $old_site ); 207 208 if ( ! empty( $errors->errors ) ) { 209 return $errors; 210 } 211 212 /** 213 * Fires before a site is deleted. 214 * 215 * @since MU (3.0.0) 216 * @deprecated 5.1.0 217 * 218 * @param int $site_id The site ID. 219 * @param bool $drop True if site's table should be dropped. Default is false. 220 */ 221 do_action_deprecated( 'delete_blog', array( $old_site->id, true ), '5.1.0' ); 222 223 /** 224 * Fires when a site's uninitialization routine should be executed. 225 * 226 * @since 5.1.0 227 * 228 * @param WP_Site $old_site Deleted site object. 229 */ 230 do_action( 'wp_uninitialize_site', $old_site ); 231 232 if ( is_site_meta_supported() ) { 233 $blog_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->blogmeta WHERE blog_id = %d ", $old_site->id ) ); 234 foreach ( $blog_meta_ids as $mid ) { 235 delete_metadata_by_mid( 'blog', $mid ); 236 } 237 } 238 239 if ( false === $wpdb->delete( $wpdb->blogs, array( 'blog_id' => $old_site->id ) ) ) { 240 return new WP_Error( 'db_delete_error', __( 'Could not delete site from the database.' ), $wpdb->last_error ); 241 } 242 243 clean_blog_cache( $old_site ); 244 245 /** 246 * Fires once a site has been deleted from the database. 247 * 248 * @since 5.1.0 249 * 250 * @param WP_Site $old_site Deleted site object. 251 */ 252 do_action( 'wp_delete_site', $old_site ); 253 254 /** 255 * Fires after the site is deleted from the network. 256 * 257 * @since 4.8.0 258 * @deprecated 5.1.0 259 * 260 * @param int $site_id The site ID. 261 * @param bool $drop True if site's tables should be dropped. Default is false. 262 */ 263 do_action_deprecated( 'deleted_blog', array( $old_site->id, true ), '5.1.0' ); 264 265 return $old_site; 266 } 267 268 /** 269 * Retrieves site data given a site ID or site object. 270 * 271 * Site data will be cached and returned after being passed through a filter. 272 * If the provided site is empty, the current site global will be used. 273 * 274 * @since 4.6.0 275 * 276 * @param WP_Site|int|null $site Optional. Site to retrieve. Default is the current site. 277 * @return WP_Site|null The site object or null if not found. 278 */ 279 function get_site( $site = null ) { 280 if ( empty( $site ) ) { 281 $site = get_current_blog_id(); 282 } 283 284 if ( $site instanceof WP_Site ) { 285 $_site = $site; 286 } elseif ( is_object( $site ) ) { 287 $_site = new WP_Site( $site ); 288 } else { 289 $_site = WP_Site::get_instance( $site ); 290 } 291 292 if ( ! $_site ) { 293 return null; 294 } 295 296 /** 297 * Fires after a site is retrieved. 298 * 299 * @since 4.6.0 300 * 301 * @param WP_Site $_site Site data. 302 */ 303 $_site = apply_filters( 'get_site', $_site ); 304 305 return $_site; 306 } 307 308 /** 309 * Adds any sites from the given ids to the cache that do not already exist in cache. 310 * 311 * @since 4.6.0 312 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 313 * @access private 314 * 315 * @see update_site_cache() 316 * @global wpdb $wpdb WordPress database abstraction object. 317 * 318 * @param array $ids ID list. 319 * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true. 320 */ 321 function _prime_site_caches( $ids, $update_meta_cache = true ) { 322 global $wpdb; 323 324 $non_cached_ids = _get_non_cached_ids( $ids, 'sites' ); 325 if ( ! empty( $non_cached_ids ) ) { 326 $fresh_sites = $wpdb->get_results( sprintf( "SELECT * FROM $wpdb->blogs WHERE blog_id IN (%s)", join( ',', array_map( 'intval', $non_cached_ids ) ) ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 327 328 update_site_cache( $fresh_sites, $update_meta_cache ); 329 } 330 } 331 332 /** 333 * Updates sites in cache. 334 * 335 * @since 4.6.0 336 * @since 5.1.0 Introduced the `$update_meta_cache` parameter. 337 * 338 * @param array $sites Array of site objects. 339 * @param bool $update_meta_cache Whether to update site meta cache. Default true. 340 */ 341 function update_site_cache( $sites, $update_meta_cache = true ) { 342 if ( ! $sites ) { 343 return; 344 } 345 $site_ids = array(); 346 foreach ( $sites as $site ) { 347 $site_ids[] = $site->blog_id; 348 wp_cache_add( $site->blog_id, $site, 'sites' ); 349 wp_cache_add( $site->blog_id . 'short', $site, 'blog-details' ); 350 } 351 352 if ( $update_meta_cache ) { 353 update_sitemeta_cache( $site_ids ); 354 } 355 } 356 357 /** 358 * Updates metadata cache for list of site IDs. 359 * 360 * Performs SQL query to retrieve all metadata for the sites matching `$site_ids` and stores them in the cache. 361 * Subsequent calls to `get_site_meta()` will not need to query the database. 362 * 363 * @since 5.1.0 364 * 365 * @param array $site_ids List of site IDs. 366 * @return array|false Returns false if there is nothing to update. Returns an array of metadata on success. 367 */ 368 function update_sitemeta_cache( $site_ids ) { 369 return update_meta_cache( 'blog', $site_ids ); 370 } 371 372 /** 373 * Retrieves a list of sites matching requested arguments. 374 * 375 * @since 4.6.0 376 * @since 4.8.0 Introduced the 'lang_id', 'lang__in', and 'lang__not_in' parameters. 377 * 378 * @see WP_Site_Query::parse_query() 379 * 380 * @param string|array $args { 381 * Optional. Array or query string of site query parameters. Default empty. 382 * 383 * @type array $site__in Array of site IDs to include. Default empty. 384 * @type array $site__not_in Array of site IDs to exclude. Default empty. 385 * @type bool $count Whether to return a site count (true) or array of site objects. 386 * Default false. 387 * @type array $date_query Date query clauses to limit sites by. See WP_Date_Query. 388 * Default null. 389 * @type string $fields Site fields to return. Accepts 'ids' (returns an array of site IDs) 390 * or empty (returns an array of complete site objects). Default empty. 391 * @type int $ID A site ID to only return that site. Default empty. 392 * @type int $number Maximum number of sites to retrieve. Default 100. 393 * @type int $offset Number of sites to offset the query. Used to build LIMIT clause. 394 * Default 0. 395 * @type bool $no_found_rows Whether to disable the `SQL_CALC_FOUND_ROWS` query. Default true. 396 * @type string|array $orderby Site status or array of statuses. Accepts 'id', 'domain', 'path', 397 * 'network_id', 'last_updated', 'registered', 'domain_length', 398 * 'path_length', 'site__in' and 'network__in'. Also accepts false, 399 * an empty array, or 'none' to disable `ORDER BY` clause. 400 * Default 'id'. 401 * @type string $order How to order retrieved sites. Accepts 'ASC', 'DESC'. Default 'ASC'. 402 * @type int $network_id Limit results to those affiliated with a given network ID. If 0, 403 * include all networks. Default 0. 404 * @type array $network__in Array of network IDs to include affiliated sites for. Default empty. 405 * @type array $network__not_in Array of network IDs to exclude affiliated sites for. Default empty. 406 * @type string $domain Limit results to those affiliated with a given domain. Default empty. 407 * @type array $domain__in Array of domains to include affiliated sites for. Default empty. 408 * @type array $domain__not_in Array of domains to exclude affiliated sites for. Default empty. 409 * @type string $path Limit results to those affiliated with a given path. Default empty. 410 * @type array $path__in Array of paths to include affiliated sites for. Default empty. 411 * @type array $path__not_in Array of paths to exclude affiliated sites for. Default empty. 412 * @type int $public Limit results to public sites. Accepts '1' or '0'. Default empty. 413 * @type int $archived Limit results to archived sites. Accepts '1' or '0'. Default empty. 414 * @type int $mature Limit results to mature sites. Accepts '1' or '0'. Default empty. 415 * @type int $spam Limit results to spam sites. Accepts '1' or '0'. Default empty. 416 * @type int $deleted Limit results to deleted sites. Accepts '1' or '0'. Default empty. 417 * @type int $lang_id Limit results to a language ID. Default empty. 418 * @type array $lang__in Array of language IDs to include affiliated sites for. Default empty. 419 * @type array $lang__not_in Array of language IDs to exclude affiliated sites for. Default empty. 420 * @type string $search Search term(s) to retrieve matching sites for. Default empty. 421 * @type array $search_columns Array of column names to be searched. Accepts 'domain' and 'path'. 422 * Default empty array. 423 * @type bool $update_site_cache Whether to prime the cache for found sites. Default true. 424 * } 425 * @return array|int List of WP_Site objects, a list of site ids when 'fields' is set to 'ids', 426 * or the number of sites when 'count' is passed as a query var. 427 */ 428 function get_sites( $args = array() ) { 429 $query = new WP_Site_Query(); 430 431 return $query->query( $args ); 432 } 433 434 /** 435 * Prepares site data for insertion or update in the database. 436 * 437 * @since 5.1.0 438 * 439 * @param array $data Associative array of site data passed to the respective function. 440 * See {@see wp_insert_site()} for the possibly included data. 441 * @param array $defaults Site data defaults to parse $data against. 442 * @param WP_Site|null $old_site Optional. Old site object if an update, or null if an insertion. 443 * Default null. 444 * @return array|WP_Error Site data ready for a database transaction, or WP_Error in case a validation 445 * error occurred. 446 */ 447 function wp_prepare_site_data( $data, $defaults, $old_site = null ) { 448 449 // Maintain backward-compatibility with `$site_id` as network ID. 450 if ( isset( $data['site_id'] ) ) { 451 if ( ! empty( $data['site_id'] ) && empty( $data['network_id'] ) ) { 452 $data['network_id'] = $data['site_id']; 453 } 454 unset( $data['site_id'] ); 455 } 456 457 /** 458 * Filters passed site data in order to normalize it. 459 * 460 * @since 5.1.0 461 * 462 * @param array $data Associative array of site data passed to the respective function. 463 * See {@see wp_insert_site()} for the possibly included data. 464 */ 465 $data = apply_filters( 'wp_normalize_site_data', $data ); 466 467 $whitelist = array( 'domain', 'path', 'network_id', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ); 468 $data = array_intersect_key( wp_parse_args( $data, $defaults ), array_flip( $whitelist ) ); 469 470 $errors = new WP_Error(); 471 472 /** 473 * Fires when data should be validated for a site prior to inserting or updating in the database. 474 * 475 * Plugins should amend the `$errors` object via its `WP_Error::add()` method. 476 * 477 * @since 5.1.0 478 * 479 * @param WP_Error $errors Error object to add validation errors to. 480 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 481 * for the included data. 482 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 483 * or null if it is a new site being inserted. 484 */ 485 do_action( 'wp_validate_site_data', $errors, $data, $old_site ); 486 487 if ( ! empty( $errors->errors ) ) { 488 return $errors; 489 } 490 491 // Prepare for database. 492 $data['site_id'] = $data['network_id']; 493 unset( $data['network_id'] ); 494 495 return $data; 496 } 497 498 /** 499 * Normalizes data for a site prior to inserting or updating in the database. 500 * 501 * @since 5.1.0 502 * 503 * @param array $data Associative array of site data passed to the respective function. 504 * See {@see wp_insert_site()} for the possibly included data. 505 * @return array Normalized site data. 506 */ 507 function wp_normalize_site_data( $data ) { 508 // Sanitize domain if passed. 509 if ( array_key_exists( 'domain', $data ) ) { 510 $data['domain'] = trim( $data['domain'] ); 511 $data['domain'] = preg_replace( '/\s+/', '', sanitize_user( $data['domain'], true ) ); 512 if ( is_subdomain_install() ) { 513 $data['domain'] = str_replace( '@', '', $data['domain'] ); 514 } 515 } 516 517 // Sanitize path if passed. 518 if ( array_key_exists( 'path', $data ) ) { 519 $data['path'] = trailingslashit( '/' . trim( $data['path'], '/' ) ); 520 } 521 522 // Sanitize network ID if passed. 523 if ( array_key_exists( 'network_id', $data ) ) { 524 $data['network_id'] = (int) $data['network_id']; 525 } 526 527 // Sanitize status fields if passed. 528 $status_fields = array( 'public', 'archived', 'mature', 'spam', 'deleted' ); 529 foreach ( $status_fields as $status_field ) { 530 if ( array_key_exists( $status_field, $data ) ) { 531 $data[ $status_field ] = (int) $data[ $status_field ]; 532 } 533 } 534 535 // Strip date fields if empty. 536 $date_fields = array( 'registered', 'last_updated' ); 537 foreach ( $date_fields as $date_field ) { 538 if ( ! array_key_exists( $date_field, $data ) ) { 539 continue; 540 } 541 542 if ( empty( $data[ $date_field ] ) || '0000-00-00 00:00:00' === $data[ $date_field ] ) { 543 unset( $data[ $date_field ] ); 544 } 545 } 546 547 return $data; 548 } 549 550 /** 551 * Validates data for a site prior to inserting or updating in the database. 552 * 553 * @since 5.1.0 554 * 555 * @param WP_Error $errors Error object, passed by reference. Will contain validation errors if 556 * any occurred. 557 * @param array $data Associative array of complete site data. See {@see wp_insert_site()} 558 * for the included data. 559 * @param WP_Site|null $old_site The old site object if the data belongs to a site being updated, 560 * or null if it is a new site being inserted. 561 */ 562 function wp_validate_site_data( $errors, $data, $old_site = null ) { 563 // A domain must always be present. 564 if ( empty( $data['domain'] ) ) { 565 $errors->add( 'site_empty_domain', __( 'Site domain must not be empty.' ) ); 566 } 567 568 // A path must always be present. 569 if ( empty( $data['path'] ) ) { 570 $errors->add( 'site_empty_path', __( 'Site path must not be empty.' ) ); 571 } 572 573 // A network ID must always be present. 574 if ( empty( $data['network_id'] ) ) { 575 $errors->add( 'site_empty_network_id', __( 'Site network ID must be provided.' ) ); 576 } 577 578 // Both registration and last updated dates must always be present and valid. 579 $date_fields = array( 'registered', 'last_updated' ); 580 foreach ( $date_fields as $date_field ) { 581 if ( empty( $data[ $date_field ] ) ) { 582 $errors->add( 'site_empty_' . $date_field, __( 'Both registration and last updated dates must be provided.' ) ); 583 break; 584 } 585 586 // Allow '0000-00-00 00:00:00', although it be stripped out at this point. 587 if ( '0000-00-00 00:00:00' !== $data[ $date_field ] ) { 588 $month = substr( $data[ $date_field ], 5, 2 ); 589 $day = substr( $data[ $date_field ], 8, 2 ); 590 $year = substr( $data[ $date_field ], 0, 4 ); 591 $valid_date = wp_checkdate( $month, $day, $year, $data[ $date_field ] ); 592 if ( ! $valid_date ) { 593 $errors->add( 'site_invalid_' . $date_field, __( 'Both registration and last updated dates must be valid dates.' ) ); 594 break; 595 } 596 } 597 } 598 599 if ( ! empty( $errors->errors ) ) { 600 return; 601 } 602 603 // If a new site, or domain/path/network ID have changed, ensure uniqueness. 604 if ( ! $old_site 605 || $data['domain'] !== $old_site->domain 606 || $data['path'] !== $old_site->path 607 || $data['network_id'] !== $old_site->network_id 608 ) { 609 if ( domain_exists( $data['domain'], $data['path'], $data['network_id'] ) ) { 610 $errors->add( 'site_taken', __( 'Sorry, that site already exists!' ) ); 611 } 612 } 613 } 614 615 /** 616 * Runs the initialization routine for a given site. 617 * 618 * This process includes creating the site's database tables and 619 * populating them with defaults. 620 * 621 * @since 5.1.0 622 * 623 * @global wpdb $wpdb WordPress database abstraction object. 624 * @global WP_Roles $wp_roles WordPress role management object. 625 * 626 * @param int|WP_Site $site_id Site ID or object. 627 * @param array $args { 628 * Optional. Arguments to modify the initialization behavior. 629 * 630 * @type int $user_id Required. User ID for the site administrator. 631 * @type string $title Site title. Default is 'Site %d' where %d is the 632 * site ID. 633 * @type array $options Custom option $key => $value pairs to use. Default 634 * empty array. 635 * @type array $meta Custom site metadata $key => $value pairs to use. 636 * Default empty array. 637 * } 638 * @return bool|WP_Error True on success, or error object on failure. 639 */ 640 function wp_initialize_site( $site_id, array $args = array() ) { 641 global $wpdb, $wp_roles; 642 643 if ( empty( $site_id ) ) { 644 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 645 } 646 647 $site = get_site( $site_id ); 648 if ( ! $site ) { 649 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 650 } 651 652 if ( wp_is_site_initialized( $site ) ) { 653 return new WP_Error( 'site_already_initialized', __( 'The site appears to be already initialized.' ) ); 654 } 655 656 $network = get_network( $site->network_id ); 657 if ( ! $network ) { 658 $network = get_network(); 659 } 660 661 $args = wp_parse_args( 662 $args, 663 array( 664 'user_id' => 0, 665 /* translators: %d: site ID */ 666 'title' => sprintf( __( 'Site %d' ), $site->id ), 667 'options' => array(), 668 'meta' => array(), 669 ) 670 ); 671 672 /** 673 * Filters the arguments for initializing a site. 674 * 675 * @since 5.1.0 676 * 677 * @param array $args Arguments to modify the initialization behavior. 678 * @param WP_Site $site Site that is being initialized. 679 * @param WP_Network $network Network that the site belongs to. 680 */ 681 $args = apply_filters( 'wp_initialize_site_args', $args, $site, $network ); 682 683 $orig_installing = wp_installing(); 684 if ( ! $orig_installing ) { 685 wp_installing( true ); 686 } 687 688 $switch = false; 689 if ( get_current_blog_id() !== $site->id ) { 690 $switch = true; 691 switch_to_blog( $site->id ); 692 } 693 694 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 695 696 // Set up the database tables. 697 make_db_current_silent( 'blog' ); 698 699 $home_scheme = 'http'; 700 $siteurl_scheme = 'http'; 701 if ( ! is_subdomain_install() ) { 702 if ( 'https' === parse_url( get_home_url( $network->site_id ), PHP_URL_SCHEME ) ) { 703 $home_scheme = 'https'; 704 } 705 if ( 'https' === parse_url( get_network_option( $network->id, 'siteurl' ), PHP_URL_SCHEME ) ) { 706 $siteurl_scheme = 'https'; 707 } 708 } 709 710 // Populate the site's options. 711 populate_options( 712 array_merge( 713 array( 714 'home' => untrailingslashit( $home_scheme . '://' . $site->domain . $site->path ), 715 'siteurl' => untrailingslashit( $siteurl_scheme . '://' . $site->domain . $site->path ), 716 'blogname' => wp_unslash( $args['title'] ), 717 'admin_email' => '', 718 'upload_path' => get_network_option( $network->id, 'ms_files_rewriting' ) ? UPLOADBLOGSDIR . "/{$site->id}/files" : get_blog_option( $network->site_id, 'upload_path' ), 719 'blog_public' => (int) $site->public, 720 'WPLANG' => get_network_option( $network->id, 'WPLANG' ), 721 ), 722 $args['options'] 723 ) 724 ); 725 726 // Populate the site's roles. 727 populate_roles(); 728 $wp_roles = new WP_Roles(); 729 730 // Populate metadata for the site. 731 populate_site_meta( $site->id, $args['meta'] ); 732 733 // Remove all permissions that may exist for the site. 734 $table_prefix = $wpdb->get_blog_prefix(); 735 delete_metadata( 'user', 0, $table_prefix . 'user_level', null, true ); // delete all 736 delete_metadata( 'user', 0, $table_prefix . 'capabilities', null, true ); // delete all 737 738 // Install default site content. 739 wp_install_defaults( $args['user_id'] ); 740 741 // Set the site administrator. 742 add_user_to_blog( $site->id, $args['user_id'], 'administrator' ); 743 if ( ! user_can( $args['user_id'], 'manage_network' ) && ! get_user_meta( $args['user_id'], 'primary_blog', true ) ) { 744 update_user_meta( $args['user_id'], 'primary_blog', $site->id ); 745 } 746 747 if ( $switch ) { 748 restore_current_blog(); 749 } 750 751 wp_installing( $orig_installing ); 752 753 return true; 754 } 755 756 /** 757 * Runs the uninitialization routine for a given site. 758 * 759 * This process includes dropping the site's database tables and deleting its uploads directory. 760 * 761 * @since 5.1.0 762 * 763 * @global wpdb $wpdb WordPress database abstraction object. 764 * 765 * @param int|WP_Site $site_id Site ID or object. 766 * @return bool|WP_Error True on success, or error object on failure. 767 */ 768 function wp_uninitialize_site( $site_id ) { 769 global $wpdb; 770 771 if ( empty( $site_id ) ) { 772 return new WP_Error( 'site_empty_id', __( 'Site ID must not be empty.' ) ); 773 } 774 775 $site = get_site( $site_id ); 776 if ( ! $site ) { 777 return new WP_Error( 'site_invalid_id', __( 'Site with the ID does not exist.' ) ); 778 } 779 780 if ( ! wp_is_site_initialized( $site ) ) { 781 return new WP_Error( 'site_already_uninitialized', __( 'The site appears to be already uninitialized.' ) ); 782 } 783 784 $users = get_users( 785 array( 786 'blog_id' => $site->id, 787 'fields' => 'ids', 788 ) 789 ); 790 791 // Remove users from the site. 792 if ( ! empty( $users ) ) { 793 foreach ( $users as $user_id ) { 794 remove_user_from_blog( $user_id, $site->id ); 795 } 796 } 797 798 $switch = false; 799 if ( get_current_blog_id() !== $site->id ) { 800 $switch = true; 801 switch_to_blog( $site->id ); 802 } 803 804 $uploads = wp_get_upload_dir(); 805 806 $tables = $wpdb->tables( 'blog' ); 807 808 /** 809 * Filters the tables to drop when the site is deleted. 810 * 811 * @since MU (3.0.0) 812 * 813 * @param string[] $tables Array of names of the site tables to be dropped. 814 * @param int $site_id The ID of the site to drop tables for. 815 */ 816 $drop_tables = apply_filters( 'wpmu_drop_tables', $tables, $site->id ); 817 818 foreach ( (array) $drop_tables as $table ) { 819 $wpdb->query( "DROP TABLE IF EXISTS `$table`" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared 820 } 821 822 /** 823 * Filters the upload base directory to delete when the site is deleted. 824 * 825 * @since MU (3.0.0) 826 * 827 * @param string $uploads['basedir'] Uploads path without subdirectory. @see wp_upload_dir() 828 * @param int $site_id The site ID. 829 */ 830 $dir = apply_filters( 'wpmu_delete_blog_upload_dir', $uploads['basedir'], $site->id ); 831 $dir = rtrim( $dir, DIRECTORY_SEPARATOR ); 832 $top_dir = $dir; 833 $stack = array( $dir ); 834 $index = 0; 835 836 while ( $index < count( $stack ) ) { 837 // Get indexed directory from stack 838 $dir = $stack[ $index ]; 839 840 // phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged 841 $dh = @opendir( $dir ); 842 if ( $dh ) { 843 $file = @readdir( $dh ); 844 while ( false !== $file ) { 845 if ( '.' === $file || '..' === $file ) { 846 $file = @readdir( $dh ); 847 continue; 848 } 849 850 if ( @is_dir( $dir . DIRECTORY_SEPARATOR . $file ) ) { 851 $stack[] = $dir . DIRECTORY_SEPARATOR . $file; 852 } elseif ( @is_file( $dir . DIRECTORY_SEPARATOR . $file ) ) { 853 @unlink( $dir . DIRECTORY_SEPARATOR . $file ); 854 } 855 856 $file = @readdir( $dh ); 857 } 858 @closedir( $dh ); 859 } 860 $index++; 861 } 862 863 $stack = array_reverse( $stack ); // Last added dirs are deepest 864 foreach ( (array) $stack as $dir ) { 865 if ( $dir != $top_dir ) { 866 @rmdir( $dir ); 867 } 868 } 869 870 // phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged 871 if ( $switch ) { 872 restore_current_blog(); 873 } 874 875 return true; 876 } 877 878 /** 879 * Checks whether a site is initialized. 880 * 881 * A site is considered initialized when its database tables are present. 882 * 883 * @since 5.1.0 884 * 885 * @global wpdb $wpdb WordPress database abstraction object. 886 * 887 * @param int|WP_Site $site_id Site ID or object. 888 * @return bool True if the site is initialized, false otherwise. 889 */ 890 function wp_is_site_initialized( $site_id ) { 891 global $wpdb; 892 893 if ( is_object( $site_id ) ) { 894 $site_id = $site_id->blog_id; 895 } 896 $site_id = (int) $site_id; 897 898 /** 899 * Filters the check for whether a site is initialized before the database is accessed. 900 * 901 * Returning a non-null value will effectively short-circuit the function, returning 902 * that value instead. 903 * 904 * @since 5.1.0 905 * 906 * @param bool|null $pre The value to return, if not null. 907 * @param int $site_id The site ID that is being checked. 908 */ 909 $pre = apply_filters( 'pre_wp_is_site_initialized', null, $site_id ); 910 if ( null !== $pre ) { 911 return (bool) $pre; 912 } 913 914 $switch = false; 915 if ( get_current_blog_id() !== $site_id ) { 916 $switch = true; 917 remove_action( 'switch_blog', 'wp_switch_roles_and_user', 1 ); 918 switch_to_blog( $site_id ); 919 } 920 921 $suppress = $wpdb->suppress_errors(); 922 $result = (bool) $wpdb->get_results( "DESCRIBE {$wpdb->posts}" ); 923 $wpdb->suppress_errors( $suppress ); 924 925 if ( $switch ) { 926 restore_current_blog(); 927 add_action( 'switch_blog', 'wp_switch_roles_and_user', 1, 2 ); 928 } 929 930 return $result; 931 } 932 933 /** 934 * Clean the blog cache 935 * 936 * @since 3.5.0 937 * 938 * @global bool $_wp_suspend_cache_invalidation 939 * 940 * @param WP_Site|int $blog The site object or ID to be cleared from cache. 941 */ 942 function clean_blog_cache( $blog ) { 943 global $_wp_suspend_cache_invalidation; 944 945 if ( ! empty( $_wp_suspend_cache_invalidation ) ) { 946 return; 947 } 948 949 if ( empty( $blog ) ) { 950 return; 951 } 952 953 $blog_id = $blog; 954 $blog = get_site( $blog_id ); 955 if ( ! $blog ) { 956 if ( ! is_numeric( $blog_id ) ) { 957 return; 958 } 959 960 // Make sure a WP_Site object exists even when the site has been deleted. 961 $blog = new WP_Site( 962 (object) array( 963 'blog_id' => $blog_id, 964 'domain' => null, 965 'path' => null, 966 ) 967 ); 968 } 969 970 $blog_id = $blog->blog_id; 971 $domain_path_key = md5( $blog->domain . $blog->path ); 972 973 wp_cache_delete( $blog_id, 'sites' ); 974 wp_cache_delete( $blog_id, 'site-details' ); 975 wp_cache_delete( $blog_id, 'blog-details' ); 976 wp_cache_delete( $blog_id . 'short', 'blog-details' ); 977 wp_cache_delete( $domain_path_key, 'blog-lookup' ); 978 wp_cache_delete( $domain_path_key, 'blog-id-cache' ); 979 wp_cache_delete( 'current_blog_' . $blog->domain, 'site-options' ); 980 wp_cache_delete( 'current_blog_' . $blog->domain . $blog->path, 'site-options' ); 981 wp_cache_delete( $blog_id, 'blog_meta' ); 982 983 /** 984 * Fires immediately after a site has been removed from the object cache. 985 * 986 * @since 4.6.0 987 * 988 * @param int $id Blog ID. 989 * @param WP_Site $blog Site object. 990 * @param string $domain_path_key md5 hash of domain and path. 991 */ 992 do_action( 'clean_site_cache', $blog_id, $blog, $domain_path_key ); 993 994 wp_cache_set( 'last_changed', microtime(), 'sites' ); 995 996 /** 997 * Fires after the blog details cache is cleared. 998 * 999 * @since 3.4.0 1000 * @deprecated 4.9.0 Use clean_site_cache 1001 * 1002 * @param int $blog_id Blog ID. 1003 */ 1004 do_action_deprecated( 'refresh_blog_details', array( $blog_id ), '4.9.0', 'clean_site_cache' ); 1005 } 1006 1007 /** 1008 * Adds metadata to a site. 1009 * 1010 * @since 5.1.0 1011 * 1012 * @param int $site_id Site ID. 1013 * @param string $meta_key Metadata name. 1014 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. 1015 * @param bool $unique Optional. Whether the same key should not be added. 1016 * Default false. 1017 * @return int|false Meta ID on success, false on failure. 1018 */ 1019 function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) { 1020 return add_metadata( 'blog', $site_id, $meta_key, $meta_value, $unique ); 1021 } 1022 1023 /** 1024 * Removes metadata matching criteria from a site. 1025 * 1026 * You can match based on the key, or key and value. Removing based on key and 1027 * value, will keep from removing duplicate metadata with the same key. It also 1028 * allows removing all metadata matching key, if needed. 1029 * 1030 * @since 5.1.0 1031 * 1032 * @param int $site_id Site ID. 1033 * @param string $meta_key Metadata name. 1034 * @param mixed $meta_value Optional. Metadata value. Must be serializable if 1035 * non-scalar. Default empty. 1036 * @return bool True on success, false on failure. 1037 */ 1038 function delete_site_meta( $site_id, $meta_key, $meta_value = '' ) { 1039 return delete_metadata( 'blog', $site_id, $meta_key, $meta_value ); 1040 } 1041 1042 /** 1043 * Retrieves metadata for a site. 1044 * 1045 * @since 5.1.0 1046 * 1047 * @param int $site_id Site ID. 1048 * @param string $key Optional. The meta key to retrieve. By default, returns 1049 * data for all keys. Default empty. 1050 * @param bool $single Optional. Whether to return a single value. Default false. 1051 * @return mixed Will be an array if $single is false. Will be value of meta data 1052 * field if $single is true. 1053 */ 1054 function get_site_meta( $site_id, $key = '', $single = false ) { 1055 return get_metadata( 'blog', $site_id, $key, $single ); 1056 } 1057 1058 /** 1059 * Updates metadata for a site. 1060 * 1061 * Use the $prev_value parameter to differentiate between meta fields with the 1062 * same key and site ID. 1063 * 1064 * If the meta field for the site does not exist, it will be added. 1065 * 1066 * @since 5.1.0 1067 * 1068 * @param int $site_id Site ID. 1069 * @param string $meta_key Metadata key. 1070 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar. 1071 * @param mixed $prev_value Optional. Previous value to check before removing. 1072 * Default empty. 1073 * @return int|bool Meta ID if the key didn't exist, true on successful update, 1074 * false on failure. 1075 */ 1076 function update_site_meta( $site_id, $meta_key, $meta_value, $prev_value = '' ) { 1077 return update_metadata( 'blog', $site_id, $meta_key, $meta_value, $prev_value ); 1078 } 1079 1080 /** 1081 * Deletes everything from site meta matching meta key. 1082 * 1083 * @since 5.1.0 1084 * 1085 * @param string $meta_key Metadata key to search for when deleting. 1086 * @return bool Whether the site meta key was deleted from the database. 1087 */ 1088 function delete_site_meta_by_key( $meta_key ) { 1089 return delete_metadata( 'blog', null, $meta_key, '', true ); 1090 } 1091 1092 /** 1093 * Updates the count of sites for a network based on a changed site. 1094 * 1095 * @since 5.1.0 1096 * 1097 * @param WP_Site $new_site The site object that has been inserted, updated or deleted. 1098 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous 1099 * state of that site. Default null. 1100 */ 1101 function wp_maybe_update_network_site_counts_on_update( $new_site, $old_site = null ) { 1102 if ( null === $old_site ) { 1103 wp_maybe_update_network_site_counts( $new_site->network_id ); 1104 return; 1105 } 1106 1107 if ( $new_site->network_id != $old_site->network_id ) { 1108 wp_maybe_update_network_site_counts( $new_site->network_id ); 1109 wp_maybe_update_network_site_counts( $old_site->network_id ); 1110 } 1111 } 1112 1113 /** 1114 * Triggers actions on site status updates. 1115 * 1116 * @since 5.1.0 1117 * 1118 * @param WP_Site $new_site The site object after the update. 1119 * @param WP_Site|null $old_site Optional. If $new_site has been updated, this must be the previous 1120 * state of that site. Default null. 1121 */ 1122 function wp_maybe_transition_site_statuses_on_update( $new_site, $old_site = null ) { 1123 $site_id = $new_site->id; 1124 1125 // Use the default values for a site if no previous state is given. 1126 if ( ! $old_site ) { 1127 $old_site = new WP_Site( new stdClass() ); 1128 } 1129 1130 if ( $new_site->spam != $old_site->spam ) { 1131 if ( 1 == $new_site->spam ) { 1132 1133 /** 1134 * Fires when the 'spam' status is added to a site. 1135 * 1136 * @since MU (3.0.0) 1137 * 1138 * @param int $site_id Site ID. 1139 */ 1140 do_action( 'make_spam_blog', $site_id ); 1141 } else { 1142 1143 /** 1144 * Fires when the 'spam' status is removed from a site. 1145 * 1146 * @since MU (3.0.0) 1147 * 1148 * @param int $site_id Site ID. 1149 */ 1150 do_action( 'make_ham_blog', $site_id ); 1151 } 1152 } 1153 1154 if ( $new_site->mature != $old_site->mature ) { 1155 if ( 1 == $new_site->mature ) { 1156 1157 /** 1158 * Fires when the 'mature' status is added to a site. 1159 * 1160 * @since 3.1.0 1161 * 1162 * @param int $site_id Site ID. 1163 */ 1164 do_action( 'mature_blog', $site_id ); 1165 } else { 1166 1167 /** 1168 * Fires when the 'mature' status is removed from a site. 1169 * 1170 * @since 3.1.0 1171 * 1172 * @param int $site_id Site ID. 1173 */ 1174 do_action( 'unmature_blog', $site_id ); 1175 } 1176 } 1177 1178 if ( $new_site->archived != $old_site->archived ) { 1179 if ( 1 == $new_site->archived ) { 1180 1181 /** 1182 * Fires when the 'archived' status is added to a site. 1183 * 1184 * @since MU (3.0.0) 1185 * 1186 * @param int $site_id Site ID. 1187 */ 1188 do_action( 'archive_blog', $site_id ); 1189 } else { 1190 1191 /** 1192 * Fires when the 'archived' status is removed from a site. 1193 * 1194 * @since MU (3.0.0) 1195 * 1196 * @param int $site_id Site ID. 1197 */ 1198 do_action( 'unarchive_blog', $site_id ); 1199 } 1200 } 1201 1202 if ( $new_site->deleted != $old_site->deleted ) { 1203 if ( 1 == $new_site->deleted ) { 1204 1205 /** 1206 * Fires when the 'deleted' status is added to a site. 1207 * 1208 * @since 3.5.0 1209 * 1210 * @param int $site_id Site ID. 1211 */ 1212 do_action( 'make_delete_blog', $site_id ); 1213 } else { 1214 1215 /** 1216 * Fires when the 'deleted' status is removed from a site. 1217 * 1218 * @since 3.5.0 1219 * 1220 * @param int $site_id Site ID. 1221 */ 1222 do_action( 'make_undelete_blog', $site_id ); 1223 } 1224 } 1225 1226 if ( $new_site->public != $old_site->public ) { 1227 1228 /** 1229 * Fires after the current blog's 'public' setting is updated. 1230 * 1231 * @since MU (3.0.0) 1232 * 1233 * @param int $site_id Site ID. 1234 * @param string $value The value of the site status. 1235 */ 1236 do_action( 'update_blog_public', $site_id, $new_site->public ); 1237 } 1238 } 1239 1240 /** 1241 * Cleans the necessary caches after specific site data has been updated. 1242 * 1243 * @since 5.1.0 1244 * 1245 * @param WP_Site $new_site The site object after the update. 1246 * @param WP_Site $old_site The site obejct prior to the update. 1247 */ 1248 function wp_maybe_clean_new_site_cache_on_update( $new_site, $old_site ) { 1249 if ( $old_site->domain !== $new_site->domain || $old_site->path !== $new_site->path ) { 1250 clean_blog_cache( $new_site ); 1251 } 1252 } 1253 1254 /** 1255 * Updates the `blog_public` option for a given site ID. 1256 * 1257 * @since 5.1.0 1258 * 1259 * @param int $site_id Site ID. 1260 * @param string $public The value of the site status. 1261 */ 1262 function wp_update_blog_public_option_on_site_update( $site_id, $public ) { 1263 1264 // Bail if the site's database tables do not exist (yet). 1265 if ( ! wp_is_site_initialized( $site_id ) ) { 1266 return; 1267 } 1268 1269 update_blog_option( $site_id, 'blog_public', $public ); 1270 } 1271 1272 /** 1273 * Sets the last changed time for the 'sites' cache group. 1274 * 1275 * @since 5.1.0 1276 */ 1277 function wp_cache_set_sites_last_changed() { 1278 wp_cache_set( 'last_changed', microtime(), 'sites' ); 1279 } 1280 1281 /** 1282 * Aborts calls to site meta if it is not supported. 1283 * 1284 * @since 5.1.0 1285 * 1286 * @global wpdb $wpdb WordPress database abstraction object. 1287 * 1288 * @param mixed $check Skip-value for whether to proceed site meta function execution. 1289 * @return mixed Original value of $check, or false if site meta is not supported. 1290 */ 1291 function wp_check_site_meta_support_prefilter( $check ) { 1292 if ( ! is_site_meta_supported() ) { 1293 /* translators: %s: database table name */ 1294 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The %s table is not installed. Please run the network database upgrade.' ), $GLOBALS['wpdb']->blogmeta ), '5.1.0' ); 1295 return false; 1296 } 1297 1298 return $check; 1299 }