[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Multisite WordPress API 4 * 5 * @package WordPress 6 * @subpackage Multisite 7 * @since 3.0.0 8 */ 9 10 /** 11 * Gets the network's site and user counts. 12 * 13 * @since MU (3.0.0) 14 * 15 * @return int[] { 16 * Site and user count for the network. 17 * 18 * @type int $blogs Number of sites on the network. 19 * @type int $users Number of users on the network. 20 * } 21 */ 22 function get_sitestats() { 23 $stats = array( 24 'blogs' => get_blog_count(), 25 'users' => get_user_count(), 26 ); 27 28 return $stats; 29 } 30 31 /** 32 * Gets one of a user's active blogs. 33 * 34 * Returns the user's primary blog, if they have one and 35 * it is active. If it's inactive, function returns another 36 * active blog of the user. If none are found, the user 37 * is added as a Subscriber to the Dashboard Blog and that blog 38 * is returned. 39 * 40 * @since MU (3.0.0) 41 * 42 * @param int $user_id The unique ID of the user 43 * @return WP_Site|void The blog object 44 */ 45 function get_active_blog_for_user( $user_id ) { 46 $blogs = get_blogs_of_user( $user_id ); 47 if ( empty( $blogs ) ) { 48 return; 49 } 50 51 if ( ! is_multisite() ) { 52 return $blogs[ get_current_blog_id() ]; 53 } 54 55 $primary_blog = get_user_meta( $user_id, 'primary_blog', true ); 56 $first_blog = current( $blogs ); 57 if ( false !== $primary_blog ) { 58 if ( ! isset( $blogs[ $primary_blog ] ) ) { 59 update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id ); 60 $primary = get_site( $first_blog->userblog_id ); 61 } else { 62 $primary = get_site( $primary_blog ); 63 } 64 } else { 65 // TODO: Review this call to add_user_to_blog too - to get here the user must have a role on this blog? 66 $result = add_user_to_blog( $first_blog->userblog_id, $user_id, 'subscriber' ); 67 68 if ( ! is_wp_error( $result ) ) { 69 update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id ); 70 $primary = $first_blog; 71 } 72 } 73 74 if ( ( ! is_object( $primary ) ) 75 || ( '1' === $primary->archived || '1' === $primary->spam || '1' === $primary->deleted ) 76 ) { 77 $blogs = get_blogs_of_user( $user_id, true ); // If a user's primary blog is shut down, check their other blogs. 78 $ret = false; 79 if ( is_array( $blogs ) && count( $blogs ) > 0 ) { 80 foreach ( (array) $blogs as $blog_id => $blog ) { 81 if ( get_current_network_id() !== $blog->site_id ) { 82 continue; 83 } 84 85 $details = get_site( $blog_id ); 86 if ( is_object( $details ) 87 && '0' === $details->archived && '0' === $details->spam && '0' === $details->deleted 88 ) { 89 $ret = $details; 90 if ( (int) get_user_meta( $user_id, 'primary_blog', true ) !== $blog_id ) { 91 update_user_meta( $user_id, 'primary_blog', $blog_id ); 92 } 93 if ( ! get_user_meta( $user_id, 'source_domain', true ) ) { 94 update_user_meta( $user_id, 'source_domain', $details->domain ); 95 } 96 break; 97 } 98 } 99 } else { 100 return; 101 } 102 return $ret; 103 } else { 104 return $primary; 105 } 106 } 107 108 /** 109 * Gets the number of active sites on the installation. 110 * 111 * The count is cached and updated twice daily. This is not a live count. 112 * 113 * @since MU (3.0.0) 114 * @since 3.7.0 The `$network_id` parameter has been deprecated. 115 * @since 4.8.0 The `$network_id` parameter is now being used. 116 * 117 * @param int|null $network_id ID of the network. Default is the current network. 118 * @return int Number of active sites on the network. 119 */ 120 function get_blog_count( $network_id = null ) { 121 return get_network_option( $network_id, 'blog_count' ); 122 } 123 124 /** 125 * Gets a blog post from any site on the network. 126 * 127 * This function is similar to get_post(), except that it can retrieve a post 128 * from any site on the network, not just the current site. 129 * 130 * @since MU (3.0.0) 131 * 132 * @param int $blog_id ID of the blog. 133 * @param int $post_id ID of the post being looked for. 134 * @return WP_Post|null WP_Post object on success, null on failure 135 */ 136 function get_blog_post( $blog_id, $post_id ) { 137 switch_to_blog( $blog_id ); 138 $post = get_post( $post_id ); 139 restore_current_blog(); 140 141 return $post; 142 } 143 144 /** 145 * Adds a user to a blog, along with specifying the user's role. 146 * 147 * Use the {@see 'add_user_to_blog'} action to fire an event when users are added to a blog. 148 * 149 * @since MU (3.0.0) 150 * 151 * @param int $blog_id ID of the blog the user is being added to. 152 * @param int $user_id ID of the user being added. 153 * @param string $role User role. 154 * @return true|WP_Error True on success or a WP_Error object if the user doesn't exist 155 * or could not be added. 156 */ 157 function add_user_to_blog( $blog_id, $user_id, $role ) { 158 switch_to_blog( $blog_id ); 159 160 $user = get_userdata( $user_id ); 161 162 if ( ! $user ) { 163 restore_current_blog(); 164 return new WP_Error( 'user_does_not_exist', __( 'The requested user does not exist.' ) ); 165 } 166 167 /** 168 * Filters whether a user should be added to a site. 169 * 170 * @since 4.9.0 171 * 172 * @param true|WP_Error $retval True if the user should be added to the site, error 173 * object otherwise. 174 * @param int $user_id User ID. 175 * @param string $role User role. 176 * @param int $blog_id Site ID. 177 */ 178 $can_add_user = apply_filters( 'can_add_user_to_blog', true, $user_id, $role, $blog_id ); 179 180 if ( true !== $can_add_user ) { 181 restore_current_blog(); 182 183 if ( is_wp_error( $can_add_user ) ) { 184 return $can_add_user; 185 } 186 187 return new WP_Error( 'user_cannot_be_added', __( 'User cannot be added to this site.' ) ); 188 } 189 190 if ( ! get_user_meta( $user_id, 'primary_blog', true ) ) { 191 update_user_meta( $user_id, 'primary_blog', $blog_id ); 192 $site = get_site( $blog_id ); 193 update_user_meta( $user_id, 'source_domain', $site->domain ); 194 } 195 196 $user->set_role( $role ); 197 198 /** 199 * Fires immediately after a user is added to a site. 200 * 201 * @since MU (3.0.0) 202 * 203 * @param int $user_id User ID. 204 * @param string $role User role. 205 * @param int $blog_id Blog ID. 206 */ 207 do_action( 'add_user_to_blog', $user_id, $role, $blog_id ); 208 209 clean_user_cache( $user_id ); 210 wp_cache_delete( $blog_id . '_user_count', 'blog-details' ); 211 212 restore_current_blog(); 213 214 return true; 215 } 216 217 /** 218 * Removes a user from a blog. 219 * 220 * Use the {@see 'remove_user_from_blog'} action to fire an event when 221 * users are removed from a blog. 222 * 223 * Accepts an optional `$reassign` parameter, if you want to 224 * reassign the user's blog posts to another user upon removal. 225 * 226 * @since MU (3.0.0) 227 * 228 * @global wpdb $wpdb WordPress database abstraction object. 229 * 230 * @param int $user_id ID of the user being removed. 231 * @param int $blog_id Optional. ID of the blog the user is being removed from. Default 0. 232 * @param int $reassign Optional. ID of the user to whom to reassign posts. Default 0. 233 * @return true|WP_Error True on success or a WP_Error object if the user doesn't exist. 234 */ 235 function remove_user_from_blog( $user_id, $blog_id = 0, $reassign = 0 ) { 236 global $wpdb; 237 238 $user_id = (int) $user_id; 239 $blog_id = (int) $blog_id; 240 241 switch_to_blog( $blog_id ); 242 243 /** 244 * Fires before a user is removed from a site. 245 * 246 * @since MU (3.0.0) 247 * @since 5.4.0 Added the `$reassign` parameter. 248 * 249 * @param int $user_id ID of the user being removed. 250 * @param int $blog_id ID of the blog the user is being removed from. 251 * @param int $reassign ID of the user to whom to reassign posts. 252 */ 253 do_action( 'remove_user_from_blog', $user_id, $blog_id, $reassign ); 254 255 /* 256 * If being removed from the primary blog, set a new primary 257 * if the user is assigned to multiple blogs. 258 */ 259 $primary_blog = (int) get_user_meta( $user_id, 'primary_blog', true ); 260 if ( $primary_blog === $blog_id ) { 261 $new_id = ''; 262 $new_domain = ''; 263 $blogs = get_blogs_of_user( $user_id ); 264 foreach ( (array) $blogs as $blog ) { 265 if ( $blog->userblog_id === $blog_id ) { 266 continue; 267 } 268 $new_id = $blog->userblog_id; 269 $new_domain = $blog->domain; 270 break; 271 } 272 273 update_user_meta( $user_id, 'primary_blog', $new_id ); 274 update_user_meta( $user_id, 'source_domain', $new_domain ); 275 } 276 277 $user = get_userdata( $user_id ); 278 if ( ! $user ) { 279 restore_current_blog(); 280 return new WP_Error( 'user_does_not_exist', __( 'That user does not exist.' ) ); 281 } 282 283 $user->remove_all_caps(); 284 285 $blogs = get_blogs_of_user( $user_id ); 286 if ( count( $blogs ) === 0 ) { 287 update_user_meta( $user_id, 'primary_blog', '' ); 288 update_user_meta( $user_id, 'source_domain', '' ); 289 } 290 291 if ( $reassign ) { 292 $reassign = (int) $reassign; 293 $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $user_id ) ); 294 $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $user_id ) ); 295 296 if ( ! empty( $post_ids ) ) { 297 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_author = %d WHERE post_author = %d", $reassign, $user_id ) ); 298 array_walk( $post_ids, 'clean_post_cache' ); 299 } 300 301 if ( ! empty( $link_ids ) ) { 302 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->links SET link_owner = %d WHERE link_owner = %d", $reassign, $user_id ) ); 303 array_walk( $link_ids, 'clean_bookmark_cache' ); 304 } 305 } 306 307 clean_user_cache( $user_id ); 308 restore_current_blog(); 309 310 return true; 311 } 312 313 /** 314 * Gets the permalink for a post on another blog. 315 * 316 * @since MU (3.0.0) 1.0 317 * 318 * @param int $blog_id ID of the source blog. 319 * @param int $post_id ID of the desired post. 320 * @return string The post's permalink. 321 */ 322 function get_blog_permalink( $blog_id, $post_id ) { 323 switch_to_blog( $blog_id ); 324 $link = get_permalink( $post_id ); 325 restore_current_blog(); 326 327 return $link; 328 } 329 330 /** 331 * Gets a blog's numeric ID from its URL. 332 * 333 * On a subdirectory installation like example.com/blog1/, 334 * $domain will be the root 'example.com' and $path the 335 * subdirectory '/blog1/'. With subdomains like blog1.example.com, 336 * $domain is 'blog1.example.com' and $path is '/'. 337 * 338 * @since MU (3.0.0) 339 * 340 * @global wpdb $wpdb WordPress database abstraction object. 341 * 342 * @param string $domain Website domain. 343 * @param string $path Optional. Not required for subdomain installations. Default '/'. 344 * @return int 0 if no blog found, otherwise the ID of the matching blog. 345 */ 346 function get_blog_id_from_url( $domain, $path = '/' ) { 347 $domain = strtolower( $domain ); 348 $path = strtolower( $path ); 349 $id = wp_cache_get( md5( $domain . $path ), 'blog-id-cache' ); 350 351 if ( -1 === $id ) { // Blog does not exist. 352 return 0; 353 } elseif ( $id ) { 354 return (int) $id; 355 } 356 357 $args = array( 358 'domain' => $domain, 359 'path' => $path, 360 'fields' => 'ids', 361 'number' => 1, 362 'update_site_meta_cache' => false, 363 ); 364 $result = get_sites( $args ); 365 $id = array_shift( $result ); 366 367 if ( ! $id ) { 368 wp_cache_set( md5( $domain . $path ), -1, 'blog-id-cache' ); 369 return 0; 370 } 371 372 wp_cache_set( md5( $domain . $path ), $id, 'blog-id-cache' ); 373 374 return $id; 375 } 376 377 // 378 // Admin functions. 379 // 380 381 /** 382 * Checks an email address against a list of banned domains. 383 * 384 * This function checks against the Banned Email Domains list 385 * at wp-admin/network/settings.php. The check is only run on 386 * self-registrations; user creation at wp-admin/network/users.php 387 * bypasses this check. 388 * 389 * @since MU (3.0.0) 390 * 391 * @param string $user_email The email provided by the user at registration. 392 * @return bool True when the email address is banned, false otherwise. 393 */ 394 function is_email_address_unsafe( $user_email ) { 395 $banned_names = get_site_option( 'banned_email_domains' ); 396 if ( $banned_names && ! is_array( $banned_names ) ) { 397 $banned_names = explode( "\n", $banned_names ); 398 } 399 400 $is_email_address_unsafe = false; 401 402 if ( $banned_names && is_array( $banned_names ) && false !== strpos( $user_email, '@', 1 ) ) { 403 $banned_names = array_map( 'strtolower', $banned_names ); 404 $normalized_email = strtolower( $user_email ); 405 406 list( $email_local_part, $email_domain ) = explode( '@', $normalized_email ); 407 408 foreach ( $banned_names as $banned_domain ) { 409 if ( ! $banned_domain ) { 410 continue; 411 } 412 413 if ( $email_domain === $banned_domain ) { 414 $is_email_address_unsafe = true; 415 break; 416 } 417 418 if ( str_ends_with( $normalized_email, ".$banned_domain" ) ) { 419 $is_email_address_unsafe = true; 420 break; 421 } 422 } 423 } 424 425 /** 426 * Filters whether an email address is unsafe. 427 * 428 * @since 3.5.0 429 * 430 * @param bool $is_email_address_unsafe Whether the email address is "unsafe". Default false. 431 * @param string $user_email User email address. 432 */ 433 return apply_filters( 'is_email_address_unsafe', $is_email_address_unsafe, $user_email ); 434 } 435 436 /** 437 * Sanitizes and validates data required for a user sign-up. 438 * 439 * Verifies the validity and uniqueness of user names and user email addresses, 440 * and checks email addresses against allowed and disallowed domains provided by 441 * administrators. 442 * 443 * The {@see 'wpmu_validate_user_signup'} hook provides an easy way to modify the sign-up 444 * process. The value $result, which is passed to the hook, contains both the user-provided 445 * info and the error messages created by the function. {@see 'wpmu_validate_user_signup'} 446 * allows you to process the data in any way you'd like, and unset the relevant errors if 447 * necessary. 448 * 449 * @since MU (3.0.0) 450 * 451 * @global wpdb $wpdb WordPress database abstraction object. 452 * 453 * @param string $user_name The login name provided by the user. 454 * @param string $user_email The email provided by the user. 455 * @return array { 456 * The array of user name, email, and the error messages. 457 * 458 * @type string $user_name Sanitized and unique username. 459 * @type string $orig_username Original username. 460 * @type string $user_email User email address. 461 * @type WP_Error $errors WP_Error object containing any errors found. 462 * } 463 */ 464 function wpmu_validate_user_signup( $user_name, $user_email ) { 465 global $wpdb; 466 467 $errors = new WP_Error(); 468 469 $orig_username = $user_name; 470 $user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) ); 471 472 if ( $user_name !== $orig_username || preg_match( '/[^a-z0-9]/', $user_name ) ) { 473 $errors->add( 'user_name', __( 'Usernames can only contain lowercase letters (a-z) and numbers.' ) ); 474 $user_name = $orig_username; 475 } 476 477 $user_email = sanitize_email( $user_email ); 478 479 if ( empty( $user_name ) ) { 480 $errors->add( 'user_name', __( 'Please enter a username.' ) ); 481 } 482 483 $illegal_names = get_site_option( 'illegal_names' ); 484 485 if ( ! is_array( $illegal_names ) ) { 486 $illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' ); 487 add_site_option( 'illegal_names', $illegal_names ); 488 } 489 490 if ( in_array( $user_name, $illegal_names, true ) ) { 491 $errors->add( 'user_name', __( 'Sorry, that username is not allowed.' ) ); 492 } 493 494 /** This filter is documented in wp-includes/user.php */ 495 $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); 496 497 if ( in_array( strtolower( $user_name ), array_map( 'strtolower', $illegal_logins ), true ) ) { 498 $errors->add( 'user_name', __( 'Sorry, that username is not allowed.' ) ); 499 } 500 501 if ( ! is_email( $user_email ) ) { 502 $errors->add( 'user_email', __( 'Please enter a valid email address.' ) ); 503 } elseif ( is_email_address_unsafe( $user_email ) ) { 504 $errors->add( 'user_email', __( 'You cannot use that email address to signup. There are problems with them blocking some emails from WordPress. Please use another email provider.' ) ); 505 } 506 507 if ( strlen( $user_name ) < 4 ) { 508 $errors->add( 'user_name', __( 'Username must be at least 4 characters.' ) ); 509 } 510 511 if ( strlen( $user_name ) > 60 ) { 512 $errors->add( 'user_name', __( 'Username may not be longer than 60 characters.' ) ); 513 } 514 515 // All numeric? 516 if ( preg_match( '/^[0-9]*$/', $user_name ) ) { 517 $errors->add( 'user_name', __( 'Sorry, usernames must have letters too!' ) ); 518 } 519 520 $limited_email_domains = get_site_option( 'limited_email_domains' ); 521 522 if ( is_array( $limited_email_domains ) && ! empty( $limited_email_domains ) ) { 523 $limited_email_domains = array_map( 'strtolower', $limited_email_domains ); 524 $email_domain = strtolower( substr( $user_email, 1 + strpos( $user_email, '@' ) ) ); 525 526 if ( ! in_array( $email_domain, $limited_email_domains, true ) ) { 527 $errors->add( 'user_email', __( 'Sorry, that email address is not allowed!' ) ); 528 } 529 } 530 531 // Check if the username has been used already. 532 if ( username_exists( $user_name ) ) { 533 $errors->add( 'user_name', __( 'Sorry, that username already exists!' ) ); 534 } 535 536 // Check if the email address has been used already. 537 if ( email_exists( $user_email ) ) { 538 $errors->add( 539 'user_email', 540 sprintf( 541 /* translators: %s: Link to the login page. */ 542 __( '<strong>Error:</strong> This email address is already registered. <a href="%s">Log in</a> with this address or choose another one.' ), 543 wp_login_url() 544 ) 545 ); 546 } 547 548 // Has someone already signed up for this username? 549 $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name ) ); 550 if ( $signup instanceof stdClass ) { 551 $registered_at = mysql2date( 'U', $signup->registered ); 552 $now = time(); 553 $diff = $now - $registered_at; 554 // If registered more than two days ago, cancel registration and let this signup go through. 555 if ( $diff > 2 * DAY_IN_SECONDS ) { 556 $wpdb->delete( $wpdb->signups, array( 'user_login' => $user_name ) ); 557 } else { 558 $errors->add( 'user_name', __( 'That username is currently reserved but may be available in a couple of days.' ) ); 559 } 560 } 561 562 $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email ) ); 563 if ( $signup instanceof stdClass ) { 564 $diff = time() - mysql2date( 'U', $signup->registered ); 565 // If registered more than two days ago, cancel registration and let this signup go through. 566 if ( $diff > 2 * DAY_IN_SECONDS ) { 567 $wpdb->delete( $wpdb->signups, array( 'user_email' => $user_email ) ); 568 } else { 569 $errors->add( 'user_email', __( 'That email address has already been used. Please check your inbox for an activation email. It will become available in a couple of days if you do nothing.' ) ); 570 } 571 } 572 573 $result = array( 574 'user_name' => $user_name, 575 'orig_username' => $orig_username, 576 'user_email' => $user_email, 577 'errors' => $errors, 578 ); 579 580 /** 581 * Filters the validated user registration details. 582 * 583 * This does not allow you to override the username or email of the user during 584 * registration. The values are solely used for validation and error handling. 585 * 586 * @since MU (3.0.0) 587 * 588 * @param array $result { 589 * The array of user name, email, and the error messages. 590 * 591 * @type string $user_name Sanitized and unique username. 592 * @type string $orig_username Original username. 593 * @type string $user_email User email address. 594 * @type WP_Error $errors WP_Error object containing any errors found. 595 * } 596 */ 597 return apply_filters( 'wpmu_validate_user_signup', $result ); 598 } 599 600 /** 601 * Processes new site registrations. 602 * 603 * Checks the data provided by the user during blog signup. Verifies 604 * the validity and uniqueness of blog paths and domains. 605 * 606 * This function prevents the current user from registering a new site 607 * with a blogname equivalent to another user's login name. Passing the 608 * $user parameter to the function, where $user is the other user, is 609 * effectively an override of this limitation. 610 * 611 * Filter {@see 'wpmu_validate_blog_signup'} if you want to modify 612 * the way that WordPress validates new site signups. 613 * 614 * @since MU (3.0.0) 615 * 616 * @global wpdb $wpdb WordPress database abstraction object. 617 * @global string $domain 618 * 619 * @param string $blogname The site name provided by the user. Must be unique. 620 * @param string $blog_title The site title provided by the user. 621 * @param WP_User|string $user Optional. The user object to check against the new site name. 622 * Default empty string. 623 * @return array { 624 * Array of domain, path, site name, site title, user and error messages. 625 * 626 * @type string $domain Domain for the site. 627 * @type string $path Path for the site. Used in subdirectory installations. 628 * @type string $blogname The unique site name (slug). 629 * @type string $blog_title Blog title. 630 * @type string|WP_User $user By default, an empty string. A user object if provided. 631 * @type WP_Error $errors WP_Error containing any errors found. 632 * } 633 */ 634 function wpmu_validate_blog_signup( $blogname, $blog_title, $user = '' ) { 635 global $wpdb, $domain; 636 637 $current_network = get_network(); 638 $base = $current_network->path; 639 640 $blog_title = strip_tags( $blog_title ); 641 642 $errors = new WP_Error(); 643 $illegal_names = get_site_option( 'illegal_names' ); 644 645 if ( ! is_array( $illegal_names ) ) { 646 $illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' ); 647 add_site_option( 'illegal_names', $illegal_names ); 648 } 649 650 /* 651 * On sub dir installations, some names are so illegal, only a filter can 652 * spring them from jail. 653 */ 654 if ( ! is_subdomain_install() ) { 655 $illegal_names = array_merge( $illegal_names, get_subdirectory_reserved_names() ); 656 } 657 658 if ( empty( $blogname ) ) { 659 $errors->add( 'blogname', __( 'Please enter a site name.' ) ); 660 } 661 662 if ( preg_match( '/[^a-z0-9]+/', $blogname ) ) { 663 $errors->add( 'blogname', __( 'Site names can only contain lowercase letters (a-z) and numbers.' ) ); 664 } 665 666 if ( in_array( $blogname, $illegal_names, true ) ) { 667 $errors->add( 'blogname', __( 'That name is not allowed.' ) ); 668 } 669 670 /** 671 * Filters the minimum site name length required when validating a site signup. 672 * 673 * @since 4.8.0 674 * 675 * @param int $length The minimum site name length. Default 4. 676 */ 677 $minimum_site_name_length = apply_filters( 'minimum_site_name_length', 4 ); 678 679 if ( strlen( $blogname ) < $minimum_site_name_length ) { 680 /* translators: %s: Minimum site name length. */ 681 $errors->add( 'blogname', sprintf( _n( 'Site name must be at least %s character.', 'Site name must be at least %s characters.', $minimum_site_name_length ), number_format_i18n( $minimum_site_name_length ) ) ); 682 } 683 684 // Do not allow users to create a site that conflicts with a page on the main blog. 685 if ( ! is_subdomain_install() && $wpdb->get_var( $wpdb->prepare( 'SELECT post_name FROM ' . $wpdb->get_blog_prefix( $current_network->site_id ) . "posts WHERE post_type = 'page' AND post_name = %s", $blogname ) ) ) { 686 $errors->add( 'blogname', __( 'Sorry, you may not use that site name.' ) ); 687 } 688 689 // All numeric? 690 if ( preg_match( '/^[0-9]*$/', $blogname ) ) { 691 $errors->add( 'blogname', __( 'Sorry, site names must have letters too!' ) ); 692 } 693 694 /** 695 * Filters the new site name during registration. 696 * 697 * The name is the site's subdomain or the site's subdirectory 698 * path depending on the network settings. 699 * 700 * @since MU (3.0.0) 701 * 702 * @param string $blogname Site name. 703 */ 704 $blogname = apply_filters( 'newblogname', $blogname ); 705 706 $blog_title = wp_unslash( $blog_title ); 707 708 if ( empty( $blog_title ) ) { 709 $errors->add( 'blog_title', __( 'Please enter a site title.' ) ); 710 } 711 712 // Check if the domain/path has been used already. 713 if ( is_subdomain_install() ) { 714 $mydomain = $blogname . '.' . preg_replace( '|^www\.|', '', $domain ); 715 $path = $base; 716 } else { 717 $mydomain = $domain; 718 $path = $base . $blogname . '/'; 719 } 720 if ( domain_exists( $mydomain, $path, $current_network->id ) ) { 721 $errors->add( 'blogname', __( 'Sorry, that site already exists!' ) ); 722 } 723 724 /* 725 * Do not allow users to create a site that matches an existing user's login name, 726 * unless it's the user's own username. 727 */ 728 if ( username_exists( $blogname ) ) { 729 if ( ! is_object( $user ) || ( is_object( $user ) && $user->user_login !== $blogname ) ) { 730 $errors->add( 'blogname', __( 'Sorry, that site is reserved!' ) ); 731 } 732 } 733 734 /* 735 * Has someone already signed up for this domain? 736 * TODO: Check email too? 737 */ 738 $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE domain = %s AND path = %s", $mydomain, $path ) ); 739 if ( $signup instanceof stdClass ) { 740 $diff = time() - mysql2date( 'U', $signup->registered ); 741 // If registered more than two days ago, cancel registration and let this signup go through. 742 if ( $diff > 2 * DAY_IN_SECONDS ) { 743 $wpdb->delete( 744 $wpdb->signups, 745 array( 746 'domain' => $mydomain, 747 'path' => $path, 748 ) 749 ); 750 } else { 751 $errors->add( 'blogname', __( 'That site is currently reserved but may be available in a couple days.' ) ); 752 } 753 } 754 755 $result = array( 756 'domain' => $mydomain, 757 'path' => $path, 758 'blogname' => $blogname, 759 'blog_title' => $blog_title, 760 'user' => $user, 761 'errors' => $errors, 762 ); 763 764 /** 765 * Filters site details and error messages following registration. 766 * 767 * @since MU (3.0.0) 768 * 769 * @param array $result { 770 * Array of domain, path, site name, site title, user and error messages. 771 * 772 * @type string $domain Domain for the site. 773 * @type string $path Path for the site. Used in subdirectory installations. 774 * @type string $blogname The unique site name (slug). 775 * @type string $blog_title Site title. 776 * @type string|WP_User $user By default, an empty string. A user object if provided. 777 * @type WP_Error $errors WP_Error containing any errors found. 778 * } 779 */ 780 return apply_filters( 'wpmu_validate_blog_signup', $result ); 781 } 782 783 /** 784 * Records site signup information for future activation. 785 * 786 * @since MU (3.0.0) 787 * 788 * @global wpdb $wpdb WordPress database abstraction object. 789 * 790 * @param string $domain The requested domain. 791 * @param string $path The requested path. 792 * @param string $title The requested site title. 793 * @param string $user The user's requested login name. 794 * @param string $user_email The user's email address. 795 * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. 796 */ 797 function wpmu_signup_blog( $domain, $path, $title, $user, $user_email, $meta = array() ) { 798 global $wpdb; 799 800 $key = substr( md5( time() . wp_rand() . $domain ), 0, 16 ); 801 802 /** 803 * Filters the metadata for a site signup. 804 * 805 * The metadata will be serialized prior to storing it in the database. 806 * 807 * @since 4.8.0 808 * 809 * @param array $meta Signup meta data. Default empty array. 810 * @param string $domain The requested domain. 811 * @param string $path The requested path. 812 * @param string $title The requested site title. 813 * @param string $user The user's requested login name. 814 * @param string $user_email The user's email address. 815 * @param string $key The user's activation key. 816 */ 817 $meta = apply_filters( 'signup_site_meta', $meta, $domain, $path, $title, $user, $user_email, $key ); 818 819 $wpdb->insert( 820 $wpdb->signups, 821 array( 822 'domain' => $domain, 823 'path' => $path, 824 'title' => $title, 825 'user_login' => $user, 826 'user_email' => $user_email, 827 'registered' => current_time( 'mysql', true ), 828 'activation_key' => $key, 829 'meta' => serialize( $meta ), 830 ) 831 ); 832 833 /** 834 * Fires after site signup information has been written to the database. 835 * 836 * @since 4.4.0 837 * 838 * @param string $domain The requested domain. 839 * @param string $path The requested path. 840 * @param string $title The requested site title. 841 * @param string $user The user's requested login name. 842 * @param string $user_email The user's email address. 843 * @param string $key The user's activation key. 844 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 845 */ 846 do_action( 'after_signup_site', $domain, $path, $title, $user, $user_email, $key, $meta ); 847 } 848 849 /** 850 * Records user signup information for future activation. 851 * 852 * This function is used when user registration is open but 853 * new site registration is not. 854 * 855 * @since MU (3.0.0) 856 * 857 * @global wpdb $wpdb WordPress database abstraction object. 858 * 859 * @param string $user The user's requested login name. 860 * @param string $user_email The user's email address. 861 * @param array $meta Optional. Signup meta data. Default empty array. 862 */ 863 function wpmu_signup_user( $user, $user_email, $meta = array() ) { 864 global $wpdb; 865 866 // Format data. 867 $user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) ); 868 $user_email = sanitize_email( $user_email ); 869 $key = substr( md5( time() . wp_rand() . $user_email ), 0, 16 ); 870 871 /** 872 * Filters the metadata for a user signup. 873 * 874 * The metadata will be serialized prior to storing it in the database. 875 * 876 * @since 4.8.0 877 * 878 * @param array $meta Signup meta data. Default empty array. 879 * @param string $user The user's requested login name. 880 * @param string $user_email The user's email address. 881 * @param string $key The user's activation key. 882 */ 883 $meta = apply_filters( 'signup_user_meta', $meta, $user, $user_email, $key ); 884 885 $wpdb->insert( 886 $wpdb->signups, 887 array( 888 'domain' => '', 889 'path' => '', 890 'title' => '', 891 'user_login' => $user, 892 'user_email' => $user_email, 893 'registered' => current_time( 'mysql', true ), 894 'activation_key' => $key, 895 'meta' => serialize( $meta ), 896 ) 897 ); 898 899 /** 900 * Fires after a user's signup information has been written to the database. 901 * 902 * @since 4.4.0 903 * 904 * @param string $user The user's requested login name. 905 * @param string $user_email The user's email address. 906 * @param string $key The user's activation key. 907 * @param array $meta Signup meta data. Default empty array. 908 */ 909 do_action( 'after_signup_user', $user, $user_email, $key, $meta ); 910 } 911 912 /** 913 * Sends a confirmation request email to a user when they sign up for a new site. The new site will not become active 914 * until the confirmation link is clicked. 915 * 916 * This is the notification function used when site registration 917 * is enabled. 918 * 919 * Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or 920 * replace it with your own notification behavior. 921 * 922 * Filter {@see 'wpmu_signup_blog_notification_email'} and 923 * {@see 'wpmu_signup_blog_notification_subject'} to change the content 924 * and subject line of the email sent to newly registered users. 925 * 926 * @since MU (3.0.0) 927 * 928 * @param string $domain The new blog domain. 929 * @param string $path The new blog path. 930 * @param string $title The site title. 931 * @param string $user_login The user's login name. 932 * @param string $user_email The user's email address. 933 * @param string $key The activation key created in wpmu_signup_blog(). 934 * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. 935 * @return bool 936 */ 937 function wpmu_signup_blog_notification( $domain, $path, $title, $user_login, $user_email, $key, $meta = array() ) { 938 /** 939 * Filters whether to bypass the new site email notification. 940 * 941 * @since MU (3.0.0) 942 * 943 * @param string|false $domain Site domain, or false to prevent the email from sending. 944 * @param string $path Site path. 945 * @param string $title Site title. 946 * @param string $user_login User login name. 947 * @param string $user_email User email address. 948 * @param string $key Activation key created in wpmu_signup_blog(). 949 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 950 */ 951 if ( ! apply_filters( 'wpmu_signup_blog_notification', $domain, $path, $title, $user_login, $user_email, $key, $meta ) ) { 952 return false; 953 } 954 955 // Send email with activation link. 956 if ( ! is_subdomain_install() || get_current_network_id() !== 1 ) { 957 $activate_url = network_site_url( "wp-activate.php?key=$key" ); 958 } else { 959 $activate_url = "http://{$domain}{$path}wp-activate.php?key=$key"; // @todo Use *_url() API. 960 } 961 962 $activate_url = esc_url( $activate_url ); 963 964 $admin_email = get_site_option( 'admin_email' ); 965 966 if ( '' === $admin_email ) { 967 $admin_email = 'support@' . wp_parse_url( network_home_url(), PHP_URL_HOST ); 968 } 969 970 $from_name = ( '' !== get_site_option( 'site_name' ) ) ? esc_html( get_site_option( 'site_name' ) ) : 'WordPress'; 971 $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n"; 972 973 $user = get_user_by( 'login', $user_login ); 974 $switched_locale = $user && switch_to_user_locale( $user->ID ); 975 976 $message = sprintf( 977 /** 978 * Filters the message content of the new blog notification email. 979 * 980 * Content should be formatted for transmission via wp_mail(). 981 * 982 * @since MU (3.0.0) 983 * 984 * @param string $content Content of the notification email. 985 * @param string $domain Site domain. 986 * @param string $path Site path. 987 * @param string $title Site title. 988 * @param string $user_login User login name. 989 * @param string $user_email User email address. 990 * @param string $key Activation key created in wpmu_signup_blog(). 991 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 992 */ 993 apply_filters( 994 'wpmu_signup_blog_notification_email', 995 /* translators: New site notification email. 1: Activation URL, 2: New site URL. */ 996 __( "To activate your site, please click the following link:\n\n%1\$s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%2\$s" ), 997 $domain, 998 $path, 999 $title, 1000 $user_login, 1001 $user_email, 1002 $key, 1003 $meta 1004 ), 1005 $activate_url, 1006 esc_url( "http://{$domain}{$path}" ), 1007 $key 1008 ); 1009 1010 $subject = sprintf( 1011 /** 1012 * Filters the subject of the new blog notification email. 1013 * 1014 * @since MU (3.0.0) 1015 * 1016 * @param string $subject Subject of the notification email. 1017 * @param string $domain Site domain. 1018 * @param string $path Site path. 1019 * @param string $title Site title. 1020 * @param string $user_login User login name. 1021 * @param string $user_email User email address. 1022 * @param string $key Activation key created in wpmu_signup_blog(). 1023 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 1024 */ 1025 apply_filters( 1026 'wpmu_signup_blog_notification_subject', 1027 /* translators: New site notification email subject. 1: Network title, 2: New site URL. */ 1028 _x( '[%1$s] Activate %2$s', 'New site notification email subject' ), 1029 $domain, 1030 $path, 1031 $title, 1032 $user_login, 1033 $user_email, 1034 $key, 1035 $meta 1036 ), 1037 $from_name, 1038 esc_url( 'http://' . $domain . $path ) 1039 ); 1040 1041 wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 1042 1043 if ( $switched_locale ) { 1044 restore_previous_locale(); 1045 } 1046 1047 return true; 1048 } 1049 1050 /** 1051 * Sends a confirmation request email to a user when they sign up for a new user account (without signing up for a site 1052 * at the same time). The user account will not become active until the confirmation link is clicked. 1053 * 1054 * This is the notification function used when no new site has 1055 * been requested. 1056 * 1057 * Filter {@see 'wpmu_signup_user_notification'} to bypass this function or 1058 * replace it with your own notification behavior. 1059 * 1060 * Filter {@see 'wpmu_signup_user_notification_email'} and 1061 * {@see 'wpmu_signup_user_notification_subject'} to change the content 1062 * and subject line of the email sent to newly registered users. 1063 * 1064 * @since MU (3.0.0) 1065 * 1066 * @param string $user_login The user's login name. 1067 * @param string $user_email The user's email address. 1068 * @param string $key The activation key created in wpmu_signup_user() 1069 * @param array $meta Optional. Signup meta data. Default empty array. 1070 * @return bool 1071 */ 1072 function wpmu_signup_user_notification( $user_login, $user_email, $key, $meta = array() ) { 1073 /** 1074 * Filters whether to bypass the email notification for new user sign-up. 1075 * 1076 * @since MU (3.0.0) 1077 * 1078 * @param string $user_login User login name. 1079 * @param string $user_email User email address. 1080 * @param string $key Activation key created in wpmu_signup_user(). 1081 * @param array $meta Signup meta data. Default empty array. 1082 */ 1083 if ( ! apply_filters( 'wpmu_signup_user_notification', $user_login, $user_email, $key, $meta ) ) { 1084 return false; 1085 } 1086 1087 $user = get_user_by( 'login', $user_login ); 1088 $switched_locale = $user && switch_to_user_locale( $user->ID ); 1089 1090 // Send email with activation link. 1091 $admin_email = get_site_option( 'admin_email' ); 1092 1093 if ( '' === $admin_email ) { 1094 $admin_email = 'support@' . wp_parse_url( network_home_url(), PHP_URL_HOST ); 1095 } 1096 1097 $from_name = ( '' !== get_site_option( 'site_name' ) ) ? esc_html( get_site_option( 'site_name' ) ) : 'WordPress'; 1098 $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n"; 1099 $message = sprintf( 1100 /** 1101 * Filters the content of the notification email for new user sign-up. 1102 * 1103 * Content should be formatted for transmission via wp_mail(). 1104 * 1105 * @since MU (3.0.0) 1106 * 1107 * @param string $content Content of the notification email. 1108 * @param string $user_login User login name. 1109 * @param string $user_email User email address. 1110 * @param string $key Activation key created in wpmu_signup_user(). 1111 * @param array $meta Signup meta data. Default empty array. 1112 */ 1113 apply_filters( 1114 'wpmu_signup_user_notification_email', 1115 /* translators: New user notification email. %s: Activation URL. */ 1116 __( "To activate your user, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login." ), 1117 $user_login, 1118 $user_email, 1119 $key, 1120 $meta 1121 ), 1122 site_url( "wp-activate.php?key=$key" ) 1123 ); 1124 1125 $subject = sprintf( 1126 /** 1127 * Filters the subject of the notification email of new user signup. 1128 * 1129 * @since MU (3.0.0) 1130 * 1131 * @param string $subject Subject of the notification email. 1132 * @param string $user_login User login name. 1133 * @param string $user_email User email address. 1134 * @param string $key Activation key created in wpmu_signup_user(). 1135 * @param array $meta Signup meta data. Default empty array. 1136 */ 1137 apply_filters( 1138 'wpmu_signup_user_notification_subject', 1139 /* translators: New user notification email subject. 1: Network title, 2: New user login. */ 1140 _x( '[%1$s] Activate %2$s', 'New user notification email subject' ), 1141 $user_login, 1142 $user_email, 1143 $key, 1144 $meta 1145 ), 1146 $from_name, 1147 $user_login 1148 ); 1149 1150 wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 1151 1152 if ( $switched_locale ) { 1153 restore_previous_locale(); 1154 } 1155 1156 return true; 1157 } 1158 1159 /** 1160 * Activates a signup. 1161 * 1162 * Hook to {@see 'wpmu_activate_user'} or {@see 'wpmu_activate_blog'} for events 1163 * that should happen only when users or sites are self-created (since 1164 * those actions are not called when users and sites are created 1165 * by a Super Admin). 1166 * 1167 * @since MU (3.0.0) 1168 * 1169 * @global wpdb $wpdb WordPress database abstraction object. 1170 * 1171 * @param string $key The activation key provided to the user. 1172 * @return array|WP_Error An array containing information about the activated user and/or blog. 1173 */ 1174 function wpmu_activate_signup( $key ) { 1175 global $wpdb; 1176 1177 $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE activation_key = %s", $key ) ); 1178 1179 if ( empty( $signup ) ) { 1180 return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) ); 1181 } 1182 1183 if ( $signup->active ) { 1184 if ( empty( $signup->domain ) ) { 1185 return new WP_Error( 'already_active', __( 'The user is already active.' ), $signup ); 1186 } else { 1187 return new WP_Error( 'already_active', __( 'The site is already active.' ), $signup ); 1188 } 1189 } 1190 1191 $meta = maybe_unserialize( $signup->meta ); 1192 $password = wp_generate_password( 12, false ); 1193 1194 $user_id = username_exists( $signup->user_login ); 1195 1196 if ( ! $user_id ) { 1197 $user_id = wpmu_create_user( $signup->user_login, $password, $signup->user_email ); 1198 } else { 1199 $user_already_exists = true; 1200 } 1201 1202 if ( ! $user_id ) { 1203 return new WP_Error( 'create_user', __( 'Could not create user' ), $signup ); 1204 } 1205 1206 $now = current_time( 'mysql', true ); 1207 1208 if ( empty( $signup->domain ) ) { 1209 $wpdb->update( 1210 $wpdb->signups, 1211 array( 1212 'active' => 1, 1213 'activated' => $now, 1214 ), 1215 array( 'activation_key' => $key ) 1216 ); 1217 1218 if ( isset( $user_already_exists ) ) { 1219 return new WP_Error( 'user_already_exists', __( 'That username is already activated.' ), $signup ); 1220 } 1221 1222 /** 1223 * Fires immediately after a new user is activated. 1224 * 1225 * @since MU (3.0.0) 1226 * 1227 * @param int $user_id User ID. 1228 * @param string $password User password. 1229 * @param array $meta Signup meta data. 1230 */ 1231 do_action( 'wpmu_activate_user', $user_id, $password, $meta ); 1232 1233 return array( 1234 'user_id' => $user_id, 1235 'password' => $password, 1236 'meta' => $meta, 1237 ); 1238 } 1239 1240 $blog_id = wpmu_create_blog( $signup->domain, $signup->path, $signup->title, $user_id, $meta, get_current_network_id() ); 1241 1242 // TODO: What to do if we create a user but cannot create a blog? 1243 if ( is_wp_error( $blog_id ) ) { 1244 /* 1245 * If blog is taken, that means a previous attempt to activate this blog 1246 * failed in between creating the blog and setting the activation flag. 1247 * Let's just set the active flag and instruct the user to reset their password. 1248 */ 1249 if ( 'blog_taken' === $blog_id->get_error_code() ) { 1250 $blog_id->add_data( $signup ); 1251 $wpdb->update( 1252 $wpdb->signups, 1253 array( 1254 'active' => 1, 1255 'activated' => $now, 1256 ), 1257 array( 'activation_key' => $key ) 1258 ); 1259 } 1260 return $blog_id; 1261 } 1262 1263 $wpdb->update( 1264 $wpdb->signups, 1265 array( 1266 'active' => 1, 1267 'activated' => $now, 1268 ), 1269 array( 'activation_key' => $key ) 1270 ); 1271 1272 /** 1273 * Fires immediately after a site is activated. 1274 * 1275 * @since MU (3.0.0) 1276 * 1277 * @param int $blog_id Blog ID. 1278 * @param int $user_id User ID. 1279 * @param string $password User password. 1280 * @param string $signup_title Site title. 1281 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 1282 */ 1283 do_action( 'wpmu_activate_blog', $blog_id, $user_id, $password, $signup->title, $meta ); 1284 1285 return array( 1286 'blog_id' => $blog_id, 1287 'user_id' => $user_id, 1288 'password' => $password, 1289 'title' => $signup->title, 1290 'meta' => $meta, 1291 ); 1292 } 1293 1294 /** 1295 * Deletes an associated signup entry when a user is deleted from the database. 1296 * 1297 * @since 5.5.0 1298 * 1299 * @global wpdb $wpdb WordPress database abstraction object. 1300 * 1301 * @param int $id ID of the user to delete. 1302 * @param int|null $reassign ID of the user to reassign posts and links to. 1303 * @param WP_User $user User object. 1304 */ 1305 function wp_delete_signup_on_user_delete( $id, $reassign, $user ) { 1306 global $wpdb; 1307 1308 $wpdb->delete( $wpdb->signups, array( 'user_login' => $user->user_login ) ); 1309 } 1310 1311 /** 1312 * Creates a user. 1313 * 1314 * This function runs when a user self-registers as well as when 1315 * a Super Admin creates a new user. Hook to {@see 'wpmu_new_user'} for events 1316 * that should affect all new users, but only on Multisite (otherwise 1317 * use {@see 'user_register'}). 1318 * 1319 * @since MU (3.0.0) 1320 * 1321 * @param string $user_name The new user's login name. 1322 * @param string $password The new user's password. 1323 * @param string $email The new user's email address. 1324 * @return int|false Returns false on failure, or int $user_id on success. 1325 */ 1326 function wpmu_create_user( $user_name, $password, $email ) { 1327 $user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) ); 1328 1329 $user_id = wp_create_user( $user_name, $password, $email ); 1330 if ( is_wp_error( $user_id ) ) { 1331 return false; 1332 } 1333 1334 // Newly created users have no roles or caps until they are added to a blog. 1335 delete_user_option( $user_id, 'capabilities' ); 1336 delete_user_option( $user_id, 'user_level' ); 1337 1338 /** 1339 * Fires immediately after a new user is created. 1340 * 1341 * @since MU (3.0.0) 1342 * 1343 * @param int $user_id User ID. 1344 */ 1345 do_action( 'wpmu_new_user', $user_id ); 1346 1347 return $user_id; 1348 } 1349 1350 /** 1351 * Creates a site. 1352 * 1353 * This function runs when a user self-registers a new site as well 1354 * as when a Super Admin creates a new site. Hook to {@see 'wpmu_new_blog'} 1355 * for events that should affect all new sites. 1356 * 1357 * On subdirectory installations, $domain is the same as the main site's 1358 * domain, and the path is the subdirectory name (eg 'example.com' 1359 * and '/blog1/'). On subdomain installations, $domain is the new subdomain + 1360 * root domain (eg 'blog1.example.com'), and $path is '/'. 1361 * 1362 * @since MU (3.0.0) 1363 * 1364 * @param string $domain The new site's domain. 1365 * @param string $path The new site's path. 1366 * @param string $title The new site's title. 1367 * @param int $user_id The user ID of the new site's admin. 1368 * @param array $options Optional. Array of key=>value pairs used to set initial site options. 1369 * If valid status keys are included ('public', 'archived', 'mature', 1370 * 'spam', 'deleted', or 'lang_id') the given site status(es) will be 1371 * updated. Otherwise, keys and values will be used to set options for 1372 * the new site. Default empty array. 1373 * @param int $network_id Optional. Network ID. Only relevant on multi-network installations. 1374 * Default 1. 1375 * @return int|WP_Error Returns WP_Error object on failure, the new site ID on success. 1376 */ 1377 function wpmu_create_blog( $domain, $path, $title, $user_id, $options = array(), $network_id = 1 ) { 1378 $defaults = array( 1379 'public' => 0, 1380 ); 1381 $options = wp_parse_args( $options, $defaults ); 1382 1383 $title = strip_tags( $title ); 1384 $user_id = (int) $user_id; 1385 1386 // Check if the domain has been used already. We should return an error message. 1387 if ( domain_exists( $domain, $path, $network_id ) ) { 1388 return new WP_Error( 'blog_taken', __( 'Sorry, that site already exists!' ) ); 1389 } 1390 1391 if ( ! wp_installing() ) { 1392 wp_installing( true ); 1393 } 1394 1395 $allowed_data_fields = array( 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ); 1396 1397 $site_data = array_merge( 1398 array( 1399 'domain' => $domain, 1400 'path' => $path, 1401 'network_id' => $network_id, 1402 ), 1403 array_intersect_key( $options, array_flip( $allowed_data_fields ) ) 1404 ); 1405 1406 // Data to pass to wp_initialize_site(). 1407 $site_initialization_data = array( 1408 'title' => $title, 1409 'user_id' => $user_id, 1410 'options' => array_diff_key( $options, array_flip( $allowed_data_fields ) ), 1411 ); 1412 1413 $blog_id = wp_insert_site( array_merge( $site_data, $site_initialization_data ) ); 1414 1415 if ( is_wp_error( $blog_id ) ) { 1416 return $blog_id; 1417 } 1418 1419 wp_cache_set_sites_last_changed(); 1420 1421 return $blog_id; 1422 } 1423 1424 /** 1425 * Notifies the network admin that a new site has been activated. 1426 * 1427 * Filter {@see 'newblog_notify_siteadmin'} to change the content of 1428 * the notification email. 1429 * 1430 * @since MU (3.0.0) 1431 * @since 5.1.0 $blog_id now supports input from the {@see 'wp_initialize_site'} action. 1432 * 1433 * @param WP_Site|int $blog_id The new site's object or ID. 1434 * @param string $deprecated Not used. 1435 * @return bool 1436 */ 1437 function newblog_notify_siteadmin( $blog_id, $deprecated = '' ) { 1438 if ( is_object( $blog_id ) ) { 1439 $blog_id = $blog_id->blog_id; 1440 } 1441 1442 if ( 'yes' !== get_site_option( 'registrationnotification' ) ) { 1443 return false; 1444 } 1445 1446 $email = get_site_option( 'admin_email' ); 1447 1448 if ( ! is_email( $email ) ) { 1449 return false; 1450 } 1451 1452 $options_site_url = esc_url( network_admin_url( 'settings.php' ) ); 1453 1454 switch_to_blog( $blog_id ); 1455 $blogname = get_option( 'blogname' ); 1456 $siteurl = site_url(); 1457 restore_current_blog(); 1458 1459 $msg = sprintf( 1460 /* translators: New site notification email. 1: Site URL, 2: User IP address, 3: URL to Network Settings screen. */ 1461 __( 1462 'New Site: %1$s 1463 URL: %2$s 1464 Remote IP address: %3$s 1465 1466 Disable these notifications: %4$s' 1467 ), 1468 $blogname, 1469 $siteurl, 1470 wp_unslash( $_SERVER['REMOTE_ADDR'] ), 1471 $options_site_url 1472 ); 1473 /** 1474 * Filters the message body of the new site activation email sent 1475 * to the network administrator. 1476 * 1477 * @since MU (3.0.0) 1478 * @since 5.4.0 The `$blog_id` parameter was added. 1479 * 1480 * @param string $msg Email body. 1481 * @param int|string $blog_id The new site's ID as an integer or numeric string. 1482 */ 1483 $msg = apply_filters( 'newblog_notify_siteadmin', $msg, $blog_id ); 1484 1485 /* translators: New site notification email subject. %s: New site URL. */ 1486 wp_mail( $email, sprintf( __( 'New Site Registration: %s' ), $siteurl ), $msg ); 1487 1488 return true; 1489 } 1490 1491 /** 1492 * Notifies the network admin that a new user has been activated. 1493 * 1494 * Filter {@see 'newuser_notify_siteadmin'} to change the content of 1495 * the notification email. 1496 * 1497 * @since MU (3.0.0) 1498 * 1499 * @param int $user_id The new user's ID. 1500 * @return bool 1501 */ 1502 function newuser_notify_siteadmin( $user_id ) { 1503 if ( 'yes' !== get_site_option( 'registrationnotification' ) ) { 1504 return false; 1505 } 1506 1507 $email = get_site_option( 'admin_email' ); 1508 1509 if ( ! is_email( $email ) ) { 1510 return false; 1511 } 1512 1513 $user = get_userdata( $user_id ); 1514 1515 $options_site_url = esc_url( network_admin_url( 'settings.php' ) ); 1516 1517 $msg = sprintf( 1518 /* translators: New user notification email. 1: User login, 2: User IP address, 3: URL to Network Settings screen. */ 1519 __( 1520 'New User: %1$s 1521 Remote IP address: %2$s 1522 1523 Disable these notifications: %3$s' 1524 ), 1525 $user->user_login, 1526 wp_unslash( $_SERVER['REMOTE_ADDR'] ), 1527 $options_site_url 1528 ); 1529 1530 /** 1531 * Filters the message body of the new user activation email sent 1532 * to the network administrator. 1533 * 1534 * @since MU (3.0.0) 1535 * 1536 * @param string $msg Email body. 1537 * @param WP_User $user WP_User instance of the new user. 1538 */ 1539 $msg = apply_filters( 'newuser_notify_siteadmin', $msg, $user ); 1540 1541 /* translators: New user notification email subject. %s: User login. */ 1542 wp_mail( $email, sprintf( __( 'New User Registration: %s' ), $user->user_login ), $msg ); 1543 1544 return true; 1545 } 1546 1547 /** 1548 * Checks whether a site name is already taken. 1549 * 1550 * The name is the site's subdomain or the site's subdirectory 1551 * path depending on the network settings. 1552 * 1553 * Used during the new site registration process to ensure 1554 * that each site name is unique. 1555 * 1556 * @since MU (3.0.0) 1557 * 1558 * @param string $domain The domain to be checked. 1559 * @param string $path The path to be checked. 1560 * @param int $network_id Optional. Network ID. Only relevant on multi-network installations. 1561 * Default 1. 1562 * @return int|null The site ID if the site name exists, null otherwise. 1563 */ 1564 function domain_exists( $domain, $path, $network_id = 1 ) { 1565 $path = trailingslashit( $path ); 1566 $args = array( 1567 'network_id' => $network_id, 1568 'domain' => $domain, 1569 'path' => $path, 1570 'fields' => 'ids', 1571 'number' => 1, 1572 'update_site_meta_cache' => false, 1573 ); 1574 $result = get_sites( $args ); 1575 $result = array_shift( $result ); 1576 1577 /** 1578 * Filters whether a site name is taken. 1579 * 1580 * The name is the site's subdomain or the site's subdirectory 1581 * path depending on the network settings. 1582 * 1583 * @since 3.5.0 1584 * 1585 * @param int|null $result The site ID if the site name exists, null otherwise. 1586 * @param string $domain Domain to be checked. 1587 * @param string $path Path to be checked. 1588 * @param int $network_id Network ID. Only relevant on multi-network installations. 1589 */ 1590 return apply_filters( 'domain_exists', $result, $domain, $path, $network_id ); 1591 } 1592 1593 /** 1594 * Notifies the site administrator that their site activation was successful. 1595 * 1596 * Filter {@see 'wpmu_welcome_notification'} to disable or bypass. 1597 * 1598 * Filter {@see 'update_welcome_email'} and {@see 'update_welcome_subject'} to 1599 * modify the content and subject line of the notification email. 1600 * 1601 * @since MU (3.0.0) 1602 * 1603 * @param int $blog_id Site ID. 1604 * @param int $user_id User ID. 1605 * @param string $password User password, or "N/A" if the user account is not new. 1606 * @param string $title Site title. 1607 * @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id. 1608 * @return bool Whether the email notification was sent. 1609 */ 1610 function wpmu_welcome_notification( $blog_id, $user_id, $password, $title, $meta = array() ) { 1611 $current_network = get_network(); 1612 1613 /** 1614 * Filters whether to bypass the welcome email sent to the site administrator after site activation. 1615 * 1616 * Returning false disables the welcome email. 1617 * 1618 * @since MU (3.0.0) 1619 * 1620 * @param int|false $blog_id Site ID, or false to prevent the email from sending. 1621 * @param int $user_id User ID of the site administrator. 1622 * @param string $password User password, or "N/A" if the user account is not new. 1623 * @param string $title Site title. 1624 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 1625 */ 1626 if ( ! apply_filters( 'wpmu_welcome_notification', $blog_id, $user_id, $password, $title, $meta ) ) { 1627 return false; 1628 } 1629 1630 $user = get_userdata( $user_id ); 1631 1632 $switched_locale = switch_to_user_locale( $user_id ); 1633 1634 $welcome_email = get_site_option( 'welcome_email' ); 1635 1636 if ( ! $welcome_email ) { 1637 /* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */ 1638 $welcome_email = __( 1639 'Howdy USERNAME, 1640 1641 Your new SITE_NAME site has been successfully set up at: 1642 BLOG_URL 1643 1644 You can log in to the administrator account with the following information: 1645 1646 Username: USERNAME 1647 Password: PASSWORD 1648 Log in here: BLOG_URLwp-login.php 1649 1650 We hope you enjoy your new site. Thanks! 1651 1652 --The Team @ SITE_NAME' 1653 ); 1654 } 1655 1656 $url = get_blogaddress_by_id( $blog_id ); 1657 1658 $welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email ); 1659 $welcome_email = str_replace( 'BLOG_TITLE', $title, $welcome_email ); 1660 $welcome_email = str_replace( 'BLOG_URL', $url, $welcome_email ); 1661 $welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email ); 1662 $welcome_email = str_replace( 'PASSWORD', $password, $welcome_email ); 1663 1664 /** 1665 * Filters the content of the welcome email sent to the site administrator after site activation. 1666 * 1667 * Content should be formatted for transmission via wp_mail(). 1668 * 1669 * @since MU (3.0.0) 1670 * 1671 * @param string $welcome_email Message body of the email. 1672 * @param int $blog_id Site ID. 1673 * @param int $user_id User ID of the site administrator. 1674 * @param string $password User password, or "N/A" if the user account is not new. 1675 * @param string $title Site title. 1676 * @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id. 1677 */ 1678 $welcome_email = apply_filters( 'update_welcome_email', $welcome_email, $blog_id, $user_id, $password, $title, $meta ); 1679 1680 $admin_email = get_site_option( 'admin_email' ); 1681 1682 if ( '' === $admin_email ) { 1683 $admin_email = 'support@' . wp_parse_url( network_home_url(), PHP_URL_HOST ); 1684 } 1685 1686 $from_name = ( '' !== get_site_option( 'site_name' ) ) ? esc_html( get_site_option( 'site_name' ) ) : 'WordPress'; 1687 $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n"; 1688 $message = $welcome_email; 1689 1690 if ( empty( $current_network->site_name ) ) { 1691 $current_network->site_name = 'WordPress'; 1692 } 1693 1694 /* translators: New site notification email subject. 1: Network title, 2: New site title. */ 1695 $subject = __( 'New %1$s Site: %2$s' ); 1696 1697 /** 1698 * Filters the subject of the welcome email sent to the site administrator after site activation. 1699 * 1700 * @since MU (3.0.0) 1701 * 1702 * @param string $subject Subject of the email. 1703 */ 1704 $subject = apply_filters( 'update_welcome_subject', sprintf( $subject, $current_network->site_name, wp_unslash( $title ) ) ); 1705 1706 wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 1707 1708 if ( $switched_locale ) { 1709 restore_previous_locale(); 1710 } 1711 1712 return true; 1713 } 1714 1715 /** 1716 * Notifies the Multisite network administrator that a new site was created. 1717 * 1718 * Filter {@see 'send_new_site_email'} to disable or bypass. 1719 * 1720 * Filter {@see 'new_site_email'} to filter the contents. 1721 * 1722 * @since 5.6.0 1723 * 1724 * @param int $site_id Site ID of the new site. 1725 * @param int $user_id User ID of the administrator of the new site. 1726 * @return bool Whether the email notification was sent. 1727 */ 1728 function wpmu_new_site_admin_notification( $site_id, $user_id ) { 1729 $site = get_site( $site_id ); 1730 $user = get_userdata( $user_id ); 1731 $email = get_site_option( 'admin_email' ); 1732 1733 if ( ! $site || ! $user || ! $email ) { 1734 return false; 1735 } 1736 1737 /** 1738 * Filters whether to send an email to the Multisite network administrator when a new site is created. 1739 * 1740 * Return false to disable sending the email. 1741 * 1742 * @since 5.6.0 1743 * 1744 * @param bool $send Whether to send the email. 1745 * @param WP_Site $site Site object of the new site. 1746 * @param WP_User $user User object of the administrator of the new site. 1747 */ 1748 if ( ! apply_filters( 'send_new_site_email', true, $site, $user ) ) { 1749 return false; 1750 } 1751 1752 $switched_locale = false; 1753 $network_admin = get_user_by( 'email', $email ); 1754 1755 if ( $network_admin ) { 1756 // If the network admin email address corresponds to a user, switch to their locale. 1757 $switched_locale = switch_to_user_locale( $network_admin->ID ); 1758 } else { 1759 // Otherwise switch to the locale of the current site. 1760 $switched_locale = switch_to_locale( get_locale() ); 1761 } 1762 1763 $subject = sprintf( 1764 /* translators: New site notification email subject. %s: Network title. */ 1765 __( '[%s] New Site Created' ), 1766 get_network()->site_name 1767 ); 1768 1769 $message = sprintf( 1770 /* translators: New site notification email. 1: User login, 2: Site URL, 3: Site title. */ 1771 __( 1772 'New site created by %1$s 1773 1774 Address: %2$s 1775 Name: %3$s' 1776 ), 1777 $user->user_login, 1778 get_site_url( $site->id ), 1779 get_blog_option( $site->id, 'blogname' ) 1780 ); 1781 1782 $header = sprintf( 1783 'From: "%1$s" <%2$s>', 1784 _x( 'Site Admin', 'email "From" field' ), 1785 $email 1786 ); 1787 1788 $new_site_email = array( 1789 'to' => $email, 1790 'subject' => $subject, 1791 'message' => $message, 1792 'headers' => $header, 1793 ); 1794 1795 /** 1796 * Filters the content of the email sent to the Multisite network administrator when a new site is created. 1797 * 1798 * Content should be formatted for transmission via wp_mail(). 1799 * 1800 * @since 5.6.0 1801 * 1802 * @param array $new_site_email { 1803 * Used to build wp_mail(). 1804 * 1805 * @type string $to The email address of the recipient. 1806 * @type string $subject The subject of the email. 1807 * @type string $message The content of the email. 1808 * @type string $headers Headers. 1809 * } 1810 * @param WP_Site $site Site object of the new site. 1811 * @param WP_User $user User object of the administrator of the new site. 1812 */ 1813 $new_site_email = apply_filters( 'new_site_email', $new_site_email, $site, $user ); 1814 1815 wp_mail( 1816 $new_site_email['to'], 1817 wp_specialchars_decode( $new_site_email['subject'] ), 1818 $new_site_email['message'], 1819 $new_site_email['headers'] 1820 ); 1821 1822 if ( $switched_locale ) { 1823 restore_previous_locale(); 1824 } 1825 1826 return true; 1827 } 1828 1829 /** 1830 * Notifies a user that their account activation has been successful. 1831 * 1832 * Filter {@see 'wpmu_welcome_user_notification'} to disable or bypass. 1833 * 1834 * Filter {@see 'update_welcome_user_email'} and {@see 'update_welcome_user_subject'} to 1835 * modify the content and subject line of the notification email. 1836 * 1837 * @since MU (3.0.0) 1838 * 1839 * @param int $user_id User ID. 1840 * @param string $password User password. 1841 * @param array $meta Optional. Signup meta data. Default empty array. 1842 * @return bool 1843 */ 1844 function wpmu_welcome_user_notification( $user_id, $password, $meta = array() ) { 1845 $current_network = get_network(); 1846 1847 /** 1848 * Filters whether to bypass the welcome email after user activation. 1849 * 1850 * Returning false disables the welcome email. 1851 * 1852 * @since MU (3.0.0) 1853 * 1854 * @param int $user_id User ID. 1855 * @param string $password User password. 1856 * @param array $meta Signup meta data. Default empty array. 1857 */ 1858 if ( ! apply_filters( 'wpmu_welcome_user_notification', $user_id, $password, $meta ) ) { 1859 return false; 1860 } 1861 1862 $welcome_email = get_site_option( 'welcome_user_email' ); 1863 1864 $user = get_userdata( $user_id ); 1865 1866 $switched_locale = switch_to_user_locale( $user_id ); 1867 1868 /** 1869 * Filters the content of the welcome email after user activation. 1870 * 1871 * Content should be formatted for transmission via wp_mail(). 1872 * 1873 * @since MU (3.0.0) 1874 * 1875 * @param string $welcome_email The message body of the account activation success email. 1876 * @param int $user_id User ID. 1877 * @param string $password User password. 1878 * @param array $meta Signup meta data. Default empty array. 1879 */ 1880 $welcome_email = apply_filters( 'update_welcome_user_email', $welcome_email, $user_id, $password, $meta ); 1881 $welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email ); 1882 $welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email ); 1883 $welcome_email = str_replace( 'PASSWORD', $password, $welcome_email ); 1884 $welcome_email = str_replace( 'LOGINLINK', wp_login_url(), $welcome_email ); 1885 1886 $admin_email = get_site_option( 'admin_email' ); 1887 1888 if ( '' === $admin_email ) { 1889 $admin_email = 'support@' . wp_parse_url( network_home_url(), PHP_URL_HOST ); 1890 } 1891 1892 $from_name = ( '' !== get_site_option( 'site_name' ) ) ? esc_html( get_site_option( 'site_name' ) ) : 'WordPress'; 1893 $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n"; 1894 $message = $welcome_email; 1895 1896 if ( empty( $current_network->site_name ) ) { 1897 $current_network->site_name = 'WordPress'; 1898 } 1899 1900 /* translators: New user notification email subject. 1: Network title, 2: New user login. */ 1901 $subject = __( 'New %1$s User: %2$s' ); 1902 1903 /** 1904 * Filters the subject of the welcome email after user activation. 1905 * 1906 * @since MU (3.0.0) 1907 * 1908 * @param string $subject Subject of the email. 1909 */ 1910 $subject = apply_filters( 'update_welcome_user_subject', sprintf( $subject, $current_network->site_name, $user->user_login ) ); 1911 1912 wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 1913 1914 if ( $switched_locale ) { 1915 restore_previous_locale(); 1916 } 1917 1918 return true; 1919 } 1920 1921 /** 1922 * Gets the current network. 1923 * 1924 * Returns an object containing the 'id', 'domain', 'path', and 'site_name' 1925 * properties of the network being viewed. 1926 * 1927 * @see wpmu_current_site() 1928 * 1929 * @since MU (3.0.0) 1930 * 1931 * @global WP_Network $current_site The current network. 1932 * 1933 * @return WP_Network The current network. 1934 */ 1935 function get_current_site() { 1936 global $current_site; 1937 return $current_site; 1938 } 1939 1940 /** 1941 * Gets a user's most recent post. 1942 * 1943 * Walks through each of a user's blogs to find the post with 1944 * the most recent post_date_gmt. 1945 * 1946 * @since MU (3.0.0) 1947 * 1948 * @global wpdb $wpdb WordPress database abstraction object. 1949 * 1950 * @param int $user_id User ID. 1951 * @return array Contains the blog_id, post_id, post_date_gmt, and post_gmt_ts. 1952 */ 1953 function get_most_recent_post_of_user( $user_id ) { 1954 global $wpdb; 1955 1956 $user_blogs = get_blogs_of_user( (int) $user_id ); 1957 $most_recent_post = array(); 1958 1959 /* 1960 * Walk through each blog and get the most recent post 1961 * published by $user_id. 1962 */ 1963 foreach ( (array) $user_blogs as $blog ) { 1964 $prefix = $wpdb->get_blog_prefix( $blog->userblog_id ); 1965 $recent_post = $wpdb->get_row( $wpdb->prepare( "SELECT ID, post_date_gmt FROM {$prefix}posts WHERE post_author = %d AND post_type = 'post' AND post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1", $user_id ), ARRAY_A ); 1966 1967 // Make sure we found a post. 1968 if ( isset( $recent_post['ID'] ) ) { 1969 $post_gmt_ts = strtotime( $recent_post['post_date_gmt'] ); 1970 1971 /* 1972 * If this is the first post checked 1973 * or if this post is newer than the current recent post, 1974 * make it the new most recent post. 1975 */ 1976 if ( ! isset( $most_recent_post['post_gmt_ts'] ) || ( $post_gmt_ts > $most_recent_post['post_gmt_ts'] ) ) { 1977 $most_recent_post = array( 1978 'blog_id' => $blog->userblog_id, 1979 'post_id' => $recent_post['ID'], 1980 'post_date_gmt' => $recent_post['post_date_gmt'], 1981 'post_gmt_ts' => $post_gmt_ts, 1982 ); 1983 } 1984 } 1985 } 1986 1987 return $most_recent_post; 1988 } 1989 1990 // 1991 // Misc functions. 1992 // 1993 1994 /** 1995 * Checks an array of MIME types against a list of allowed types. 1996 * 1997 * WordPress ships with a set of allowed upload filetypes, 1998 * which is defined in wp-includes/functions.php in 1999 * get_allowed_mime_types(). This function is used to filter 2000 * that list against the filetypes allowed provided by Multisite 2001 * Super Admins at wp-admin/network/settings.php. 2002 * 2003 * @since MU (3.0.0) 2004 * 2005 * @param array $mimes 2006 * @return array 2007 */ 2008 function check_upload_mimes( $mimes ) { 2009 $site_exts = explode( ' ', get_site_option( 'upload_filetypes', 'jpg jpeg png gif' ) ); 2010 $site_mimes = array(); 2011 foreach ( $site_exts as $ext ) { 2012 foreach ( $mimes as $ext_pattern => $mime ) { 2013 if ( '' !== $ext && str_contains( $ext_pattern, $ext ) ) { 2014 $site_mimes[ $ext_pattern ] = $mime; 2015 } 2016 } 2017 } 2018 return $site_mimes; 2019 } 2020 2021 /** 2022 * Updates a blog's post count. 2023 * 2024 * WordPress MS stores a blog's post count as an option so as 2025 * to avoid extraneous COUNTs when a blog's details are fetched 2026 * with get_site(). This function is called when posts are published 2027 * or unpublished to make sure the count stays current. 2028 * 2029 * @since MU (3.0.0) 2030 * 2031 * @global wpdb $wpdb WordPress database abstraction object. 2032 * 2033 * @param string $deprecated Not used. 2034 */ 2035 function update_posts_count( $deprecated = '' ) { 2036 global $wpdb; 2037 update_option( 'post_count', (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_status = 'publish' and post_type = 'post'" ), true ); 2038 } 2039 2040 /** 2041 * Logs the user email, IP, and registration date of a new site. 2042 * 2043 * @since MU (3.0.0) 2044 * @since 5.1.0 Parameters now support input from the {@see 'wp_initialize_site'} action. 2045 * 2046 * @global wpdb $wpdb WordPress database abstraction object. 2047 * 2048 * @param WP_Site|int $blog_id The new site's object or ID. 2049 * @param int|array $user_id User ID, or array of arguments including 'user_id'. 2050 */ 2051 function wpmu_log_new_registrations( $blog_id, $user_id ) { 2052 global $wpdb; 2053 2054 if ( is_object( $blog_id ) ) { 2055 $blog_id = $blog_id->blog_id; 2056 } 2057 2058 if ( is_array( $user_id ) ) { 2059 $user_id = ! empty( $user_id['user_id'] ) ? $user_id['user_id'] : 0; 2060 } 2061 2062 $user = get_userdata( (int) $user_id ); 2063 if ( $user ) { 2064 $wpdb->insert( 2065 $wpdb->registration_log, 2066 array( 2067 'email' => $user->user_email, 2068 'IP' => preg_replace( '/[^0-9., ]/', '', wp_unslash( $_SERVER['REMOTE_ADDR'] ) ), 2069 'blog_id' => $blog_id, 2070 'date_registered' => current_time( 'mysql' ), 2071 ) 2072 ); 2073 } 2074 } 2075 2076 /** 2077 * Ensures that the current site's domain is listed in the allowed redirect host list. 2078 * 2079 * @see wp_validate_redirect() 2080 * @since MU (3.0.0) 2081 * 2082 * @param array|string $deprecated Not used. 2083 * @return string[] { 2084 * An array containing the current site's domain. 2085 * 2086 * @type string $0 The current site's domain. 2087 * } 2088 */ 2089 function redirect_this_site( $deprecated = '' ) { 2090 return array( get_network()->domain ); 2091 } 2092 2093 /** 2094 * Checks whether an upload is too big. 2095 * 2096 * @since MU (3.0.0) 2097 * 2098 * @param array $upload An array of information about the newly-uploaded file. 2099 * @return string|array If the upload is under the size limit, $upload is returned. Otherwise returns an error message. 2100 */ 2101 function upload_is_file_too_big( $upload ) { 2102 if ( ! is_array( $upload ) || defined( 'WP_IMPORTING' ) || get_site_option( 'upload_space_check_disabled' ) ) { 2103 return $upload; 2104 } 2105 2106 if ( strlen( $upload['bits'] ) > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) { 2107 /* translators: %s: Maximum allowed file size in kilobytes. */ 2108 return sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ) . '<br />', get_site_option( 'fileupload_maxk', 1500 ) ); 2109 } 2110 2111 return $upload; 2112 } 2113 2114 /** 2115 * Adds a nonce field to the signup page. 2116 * 2117 * @since MU (3.0.0) 2118 */ 2119 function signup_nonce_fields() { 2120 $id = mt_rand(); 2121 echo "<input type='hidden' name='signup_form_id' value='{$id}' />"; 2122 wp_nonce_field( 'signup_form_' . $id, '_signup_form', false ); 2123 } 2124 2125 /** 2126 * Processes the signup nonce created in signup_nonce_fields(). 2127 * 2128 * @since MU (3.0.0) 2129 * 2130 * @param array $result 2131 * @return array 2132 */ 2133 function signup_nonce_check( $result ) { 2134 if ( ! strpos( $_SERVER['PHP_SELF'], 'wp-signup.php' ) ) { 2135 return $result; 2136 } 2137 2138 if ( ! wp_verify_nonce( $_POST['_signup_form'], 'signup_form_' . $_POST['signup_form_id'] ) ) { 2139 $result['errors']->add( 'invalid_nonce', __( 'Unable to submit this form, please try again.' ) ); 2140 } 2141 2142 return $result; 2143 } 2144 2145 /** 2146 * Corrects 404 redirects when NOBLOGREDIRECT is defined. 2147 * 2148 * @since MU (3.0.0) 2149 */ 2150 function maybe_redirect_404() { 2151 if ( is_main_site() && is_404() && defined( 'NOBLOGREDIRECT' ) ) { 2152 /** 2153 * Filters the redirect URL for 404s on the main site. 2154 * 2155 * The filter is only evaluated if the NOBLOGREDIRECT constant is defined. 2156 * 2157 * @since 3.0.0 2158 * 2159 * @param string $no_blog_redirect The redirect URL defined in NOBLOGREDIRECT. 2160 */ 2161 $destination = apply_filters( 'blog_redirect_404', NOBLOGREDIRECT ); 2162 2163 if ( $destination ) { 2164 if ( '%siteurl%' === $destination ) { 2165 $destination = network_home_url(); 2166 } 2167 2168 wp_redirect( $destination ); 2169 exit; 2170 } 2171 } 2172 } 2173 2174 /** 2175 * Adds a new user to a blog by visiting /newbloguser/{key}/. 2176 * 2177 * This will only work when the user's details are saved as an option 2178 * keyed as 'new_user_{key}', where '{key}' is a hash generated for the user to be 2179 * added, as when a user is invited through the regular WP Add User interface. 2180 * 2181 * @since MU (3.0.0) 2182 */ 2183 function maybe_add_existing_user_to_blog() { 2184 if ( ! str_contains( $_SERVER['REQUEST_URI'], '/newbloguser/' ) ) { 2185 return; 2186 } 2187 2188 $parts = explode( '/', $_SERVER['REQUEST_URI'] ); 2189 $key = array_pop( $parts ); 2190 2191 if ( '' === $key ) { 2192 $key = array_pop( $parts ); 2193 } 2194 2195 $details = get_option( 'new_user_' . $key ); 2196 if ( ! empty( $details ) ) { 2197 delete_option( 'new_user_' . $key ); 2198 } 2199 2200 if ( empty( $details ) || is_wp_error( add_existing_user_to_blog( $details ) ) ) { 2201 wp_die( 2202 sprintf( 2203 /* translators: %s: Home URL. */ 2204 __( 'An error occurred adding you to this site. Go to the <a href="%s">homepage</a>.' ), 2205 home_url() 2206 ) 2207 ); 2208 } 2209 2210 wp_die( 2211 sprintf( 2212 /* translators: 1: Home URL, 2: Admin URL. */ 2213 __( 'You have been added to this site. Please visit the <a href="%1$s">homepage</a> or <a href="%2$s">log in</a> using your username and password.' ), 2214 home_url(), 2215 admin_url() 2216 ), 2217 __( 'WordPress › Success' ), 2218 array( 'response' => 200 ) 2219 ); 2220 } 2221 2222 /** 2223 * Adds a user to a blog based on details from maybe_add_existing_user_to_blog(). 2224 * 2225 * @since MU (3.0.0) 2226 * 2227 * @param array|false $details { 2228 * User details. Must at least contain values for the keys listed below. 2229 * 2230 * @type int $user_id The ID of the user being added to the current blog. 2231 * @type string $role The role to be assigned to the user. 2232 * } 2233 * @return true|WP_Error|void True on success or a WP_Error object if the user doesn't exist 2234 * or could not be added. Void if $details array was not provided. 2235 */ 2236 function add_existing_user_to_blog( $details = false ) { 2237 if ( is_array( $details ) ) { 2238 $blog_id = get_current_blog_id(); 2239 $result = add_user_to_blog( $blog_id, $details['user_id'], $details['role'] ); 2240 2241 /** 2242 * Fires immediately after an existing user is added to a site. 2243 * 2244 * @since MU (3.0.0) 2245 * 2246 * @param int $user_id User ID. 2247 * @param true|WP_Error $result True on success or a WP_Error object if the user doesn't exist 2248 * or could not be added. 2249 */ 2250 do_action( 'added_existing_user', $details['user_id'], $result ); 2251 2252 return $result; 2253 } 2254 } 2255 2256 /** 2257 * Adds a newly created user to the appropriate blog 2258 * 2259 * To add a user in general, use add_user_to_blog(). This function 2260 * is specifically hooked into the {@see 'wpmu_activate_user'} action. 2261 * 2262 * @since MU (3.0.0) 2263 * 2264 * @see add_user_to_blog() 2265 * 2266 * @param int $user_id User ID. 2267 * @param string $password User password. Ignored. 2268 * @param array $meta Signup meta data. 2269 */ 2270 function add_new_user_to_blog( $user_id, $password, $meta ) { 2271 if ( ! empty( $meta['add_to_blog'] ) ) { 2272 $blog_id = $meta['add_to_blog']; 2273 $role = $meta['new_role']; 2274 remove_user_from_blog( $user_id, get_network()->site_id ); // Remove user from main blog. 2275 2276 $result = add_user_to_blog( $blog_id, $user_id, $role ); 2277 2278 if ( ! is_wp_error( $result ) ) { 2279 update_user_meta( $user_id, 'primary_blog', $blog_id ); 2280 } 2281 } 2282 } 2283 2284 /** 2285 * Corrects From host on outgoing mail to match the site domain. 2286 * 2287 * @since MU (3.0.0) 2288 * 2289 * @param PHPMailer\PHPMailer\PHPMailer $phpmailer The PHPMailer instance (passed by reference). 2290 */ 2291 function fix_phpmailer_messageid( $phpmailer ) { 2292 $phpmailer->Hostname = get_network()->domain; 2293 } 2294 2295 /** 2296 * Determines whether a user is marked as a spammer, based on user login. 2297 * 2298 * @since MU (3.0.0) 2299 * 2300 * @param string|WP_User $user Optional. Defaults to current user. WP_User object, 2301 * or user login name as a string. 2302 * @return bool 2303 */ 2304 function is_user_spammy( $user = null ) { 2305 if ( ! ( $user instanceof WP_User ) ) { 2306 if ( $user ) { 2307 $user = get_user_by( 'login', $user ); 2308 } else { 2309 $user = wp_get_current_user(); 2310 } 2311 } 2312 2313 return $user && isset( $user->spam ) && '1' === $user->spam; 2314 } 2315 2316 /** 2317 * Updates this blog's 'public' setting in the global blogs table. 2318 * 2319 * Public blogs have a setting of 1, private blogs are 0. 2320 * 2321 * @since MU (3.0.0) 2322 * 2323 * @param int $old_value The old public value. 2324 * @param int $value The new public value. 2325 */ 2326 function update_blog_public( $old_value, $value ) { 2327 update_blog_status( get_current_blog_id(), 'public', (int) $value ); 2328 } 2329 2330 /** 2331 * Determines whether users can self-register, based on Network settings. 2332 * 2333 * @since MU (3.0.0) 2334 * 2335 * @return bool 2336 */ 2337 function users_can_register_signup_filter() { 2338 $registration = get_site_option( 'registration' ); 2339 return ( 'all' === $registration || 'user' === $registration ); 2340 } 2341 2342 /** 2343 * Ensures that the welcome message is not empty. Currently unused. 2344 * 2345 * @since MU (3.0.0) 2346 * 2347 * @param string $text 2348 * @return string 2349 */ 2350 function welcome_user_msg_filter( $text ) { 2351 if ( ! $text ) { 2352 remove_filter( 'site_option_welcome_user_email', 'welcome_user_msg_filter' ); 2353 2354 /* translators: Do not translate USERNAME, PASSWORD, LOGINLINK, SITE_NAME: those are placeholders. */ 2355 $text = __( 2356 'Howdy USERNAME, 2357 2358 Your new account is set up. 2359 2360 You can log in with the following information: 2361 Username: USERNAME 2362 Password: PASSWORD 2363 LOGINLINK 2364 2365 Thanks! 2366 2367 --The Team @ SITE_NAME' 2368 ); 2369 update_site_option( 'welcome_user_email', $text ); 2370 } 2371 return $text; 2372 } 2373 2374 /** 2375 * Determines whether to force SSL on content. 2376 * 2377 * @since 2.8.5 2378 * 2379 * @param bool $force 2380 * @return bool True if forced, false if not forced. 2381 */ 2382 function force_ssl_content( $force = '' ) { 2383 static $forced_content = false; 2384 2385 if ( ! $force ) { 2386 $old_forced = $forced_content; 2387 $forced_content = $force; 2388 return $old_forced; 2389 } 2390 2391 return $forced_content; 2392 } 2393 2394 /** 2395 * Formats a URL to use https. 2396 * 2397 * Useful as a filter. 2398 * 2399 * @since 2.8.5 2400 * 2401 * @param string $url URL. 2402 * @return string URL with https as the scheme. 2403 */ 2404 function filter_SSL( $url ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid 2405 if ( ! is_string( $url ) ) { 2406 return get_bloginfo( 'url' ); // Return home site URL with proper scheme. 2407 } 2408 2409 if ( force_ssl_content() && is_ssl() ) { 2410 $url = set_url_scheme( $url, 'https' ); 2411 } 2412 2413 return $url; 2414 } 2415 2416 /** 2417 * Schedules update of the network-wide counts for the current network. 2418 * 2419 * @since 3.1.0 2420 */ 2421 function wp_schedule_update_network_counts() { 2422 if ( ! is_main_site() ) { 2423 return; 2424 } 2425 2426 if ( ! wp_next_scheduled( 'update_network_counts' ) && ! wp_installing() ) { 2427 wp_schedule_event( time(), 'twicedaily', 'update_network_counts' ); 2428 } 2429 } 2430 2431 /** 2432 * Updates the network-wide counts for the current network. 2433 * 2434 * @since 3.1.0 2435 * @since 4.8.0 The `$network_id` parameter has been added. 2436 * 2437 * @param int|null $network_id ID of the network. Default is the current network. 2438 */ 2439 function wp_update_network_counts( $network_id = null ) { 2440 wp_update_network_user_counts( $network_id ); 2441 wp_update_network_site_counts( $network_id ); 2442 } 2443 2444 /** 2445 * Updates the count of sites for the current network. 2446 * 2447 * If enabled through the {@see 'enable_live_network_counts'} filter, update the sites count 2448 * on a network when a site is created or its status is updated. 2449 * 2450 * @since 3.7.0 2451 * @since 4.8.0 The `$network_id` parameter has been added. 2452 * 2453 * @param int|null $network_id ID of the network. Default is the current network. 2454 */ 2455 function wp_maybe_update_network_site_counts( $network_id = null ) { 2456 $is_small_network = ! wp_is_large_network( 'sites', $network_id ); 2457 2458 /** 2459 * Filters whether to update network site or user counts when a new site is created. 2460 * 2461 * @since 3.7.0 2462 * 2463 * @see wp_is_large_network() 2464 * 2465 * @param bool $small_network Whether the network is considered small. 2466 * @param string $context Context. Either 'users' or 'sites'. 2467 */ 2468 if ( ! apply_filters( 'enable_live_network_counts', $is_small_network, 'sites' ) ) { 2469 return; 2470 } 2471 2472 wp_update_network_site_counts( $network_id ); 2473 } 2474 2475 /** 2476 * Updates the network-wide users count. 2477 * 2478 * If enabled through the {@see 'enable_live_network_counts'} filter, update the users count 2479 * on a network when a user is created or its status is updated. 2480 * 2481 * @since 3.7.0 2482 * @since 4.8.0 The `$network_id` parameter has been added. 2483 * 2484 * @param int|null $network_id ID of the network. Default is the current network. 2485 */ 2486 function wp_maybe_update_network_user_counts( $network_id = null ) { 2487 $is_small_network = ! wp_is_large_network( 'users', $network_id ); 2488 2489 /** This filter is documented in wp-includes/ms-functions.php */ 2490 if ( ! apply_filters( 'enable_live_network_counts', $is_small_network, 'users' ) ) { 2491 return; 2492 } 2493 2494 wp_update_network_user_counts( $network_id ); 2495 } 2496 2497 /** 2498 * Updates the network-wide site count. 2499 * 2500 * @since 3.7.0 2501 * @since 4.8.0 The `$network_id` parameter has been added. 2502 * 2503 * @param int|null $network_id ID of the network. Default is the current network. 2504 */ 2505 function wp_update_network_site_counts( $network_id = null ) { 2506 $network_id = (int) $network_id; 2507 if ( ! $network_id ) { 2508 $network_id = get_current_network_id(); 2509 } 2510 2511 $count = get_sites( 2512 array( 2513 'network_id' => $network_id, 2514 'spam' => 0, 2515 'deleted' => 0, 2516 'archived' => 0, 2517 'count' => true, 2518 'update_site_meta_cache' => false, 2519 ) 2520 ); 2521 2522 update_network_option( $network_id, 'blog_count', $count ); 2523 } 2524 2525 /** 2526 * Updates the network-wide user count. 2527 * 2528 * @since 3.7.0 2529 * @since 4.8.0 The `$network_id` parameter has been added. 2530 * @since 6.0.0 This function is now a wrapper for wp_update_user_counts(). 2531 * 2532 * @param int|null $network_id ID of the network. Default is the current network. 2533 */ 2534 function wp_update_network_user_counts( $network_id = null ) { 2535 wp_update_user_counts( $network_id ); 2536 } 2537 2538 /** 2539 * Returns the space used by the current site. 2540 * 2541 * @since 3.5.0 2542 * 2543 * @return int Used space in megabytes. 2544 */ 2545 function get_space_used() { 2546 /** 2547 * Filters the amount of storage space used by the current site, in megabytes. 2548 * 2549 * @since 3.5.0 2550 * 2551 * @param int|false $space_used The amount of used space, in megabytes. Default false. 2552 */ 2553 $space_used = apply_filters( 'pre_get_space_used', false ); 2554 2555 if ( false === $space_used ) { 2556 $upload_dir = wp_upload_dir(); 2557 $space_used = get_dirsize( $upload_dir['basedir'] ) / MB_IN_BYTES; 2558 } 2559 2560 return $space_used; 2561 } 2562 2563 /** 2564 * Returns the upload quota for the current blog. 2565 * 2566 * @since MU (3.0.0) 2567 * 2568 * @return int Quota in megabytes. 2569 */ 2570 function get_space_allowed() { 2571 $space_allowed = get_option( 'blog_upload_space' ); 2572 2573 if ( ! is_numeric( $space_allowed ) ) { 2574 $space_allowed = get_site_option( 'blog_upload_space' ); 2575 } 2576 2577 if ( ! is_numeric( $space_allowed ) ) { 2578 $space_allowed = 100; 2579 } 2580 2581 /** 2582 * Filters the upload quota for the current site. 2583 * 2584 * @since 3.7.0 2585 * 2586 * @param int $space_allowed Upload quota in megabytes for the current blog. 2587 */ 2588 return apply_filters( 'get_space_allowed', $space_allowed ); 2589 } 2590 2591 /** 2592 * Determines if there is any upload space left in the current blog's quota. 2593 * 2594 * @since 3.0.0 2595 * 2596 * @return int of upload space available in bytes. 2597 */ 2598 function get_upload_space_available() { 2599 $allowed = get_space_allowed(); 2600 if ( $allowed < 0 ) { 2601 $allowed = 0; 2602 } 2603 $space_allowed = $allowed * MB_IN_BYTES; 2604 if ( get_site_option( 'upload_space_check_disabled' ) ) { 2605 return $space_allowed; 2606 } 2607 2608 $space_used = get_space_used() * MB_IN_BYTES; 2609 2610 if ( ( $space_allowed - $space_used ) <= 0 ) { 2611 return 0; 2612 } 2613 2614 return $space_allowed - $space_used; 2615 } 2616 2617 /** 2618 * Determines if there is any upload space left in the current blog's quota. 2619 * 2620 * @since 3.0.0 2621 * @return bool True if space is available, false otherwise. 2622 */ 2623 function is_upload_space_available() { 2624 if ( get_site_option( 'upload_space_check_disabled' ) ) { 2625 return true; 2626 } 2627 2628 return (bool) get_upload_space_available(); 2629 } 2630 2631 /** 2632 * Filters the maximum upload file size allowed, in bytes. 2633 * 2634 * @since 3.0.0 2635 * 2636 * @param int $size Upload size limit in bytes. 2637 * @return int Upload size limit in bytes. 2638 */ 2639 function upload_size_limit_filter( $size ) { 2640 $fileupload_maxk = (int) get_site_option( 'fileupload_maxk', 1500 ); 2641 $max_fileupload_in_bytes = KB_IN_BYTES * $fileupload_maxk; 2642 2643 if ( get_site_option( 'upload_space_check_disabled' ) ) { 2644 return min( $size, $max_fileupload_in_bytes ); 2645 } 2646 2647 return min( $size, $max_fileupload_in_bytes, get_upload_space_available() ); 2648 } 2649 2650 /** 2651 * Determines whether or not we have a large network. 2652 * 2653 * The default criteria for a large network is either more than 10,000 users or more than 10,000 sites. 2654 * Plugins can alter this criteria using the {@see 'wp_is_large_network'} filter. 2655 * 2656 * @since 3.3.0 2657 * @since 4.8.0 The `$network_id` parameter has been added. 2658 * 2659 * @param string $using 'sites' or 'users'. Default is 'sites'. 2660 * @param int|null $network_id ID of the network. Default is the current network. 2661 * @return bool True if the network meets the criteria for large. False otherwise. 2662 */ 2663 function wp_is_large_network( $using = 'sites', $network_id = null ) { 2664 $network_id = (int) $network_id; 2665 if ( ! $network_id ) { 2666 $network_id = get_current_network_id(); 2667 } 2668 2669 if ( 'users' === $using ) { 2670 $count = get_user_count( $network_id ); 2671 2672 $is_large_network = wp_is_large_user_count( $network_id ); 2673 2674 /** 2675 * Filters whether the network is considered large. 2676 * 2677 * @since 3.3.0 2678 * @since 4.8.0 The `$network_id` parameter has been added. 2679 * 2680 * @param bool $is_large_network Whether the network has more than 10000 users or sites. 2681 * @param string $component The component to count. Accepts 'users', or 'sites'. 2682 * @param int $count The count of items for the component. 2683 * @param int $network_id The ID of the network being checked. 2684 */ 2685 return apply_filters( 'wp_is_large_network', $is_large_network, 'users', $count, $network_id ); 2686 } 2687 2688 $count = get_blog_count( $network_id ); 2689 2690 /** This filter is documented in wp-includes/ms-functions.php */ 2691 return apply_filters( 'wp_is_large_network', $count > 10000, 'sites', $count, $network_id ); 2692 } 2693 2694 /** 2695 * Retrieves a list of reserved site on a sub-directory Multisite installation. 2696 * 2697 * @since 4.4.0 2698 * 2699 * @return string[] Array of reserved names. 2700 */ 2701 function get_subdirectory_reserved_names() { 2702 $names = array( 2703 'page', 2704 'comments', 2705 'blog', 2706 'files', 2707 'feed', 2708 'wp-admin', 2709 'wp-content', 2710 'wp-includes', 2711 'wp-json', 2712 'embed', 2713 ); 2714 2715 /** 2716 * Filters reserved site names on a sub-directory Multisite installation. 2717 * 2718 * @since 3.0.0 2719 * @since 4.4.0 'wp-admin', 'wp-content', 'wp-includes', 'wp-json', and 'embed' were added 2720 * to the reserved names list. 2721 * 2722 * @param string[] $subdirectory_reserved_names Array of reserved names. 2723 */ 2724 return apply_filters( 'subdirectory_reserved_names', $names ); 2725 } 2726 2727 /** 2728 * Sends a confirmation request email when a change of network admin email address is attempted. 2729 * 2730 * The new network admin address will not become active until confirmed. 2731 * 2732 * @since 4.9.0 2733 * 2734 * @param string $old_value The old network admin email address. 2735 * @param string $value The proposed new network admin email address. 2736 */ 2737 function update_network_option_new_admin_email( $old_value, $value ) { 2738 if ( get_site_option( 'admin_email' ) === $value || ! is_email( $value ) ) { 2739 return; 2740 } 2741 2742 $hash = md5( $value . time() . mt_rand() ); 2743 $new_admin_email = array( 2744 'hash' => $hash, 2745 'newemail' => $value, 2746 ); 2747 update_site_option( 'network_admin_hash', $new_admin_email ); 2748 2749 $switched_locale = switch_to_user_locale( get_current_user_id() ); 2750 2751 /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ 2752 $email_text = __( 2753 'Howdy ###USERNAME###, 2754 2755 You recently requested to have the network admin email address on 2756 your network changed. 2757 2758 If this is correct, please click on the following link to change it: 2759 ###ADMIN_URL### 2760 2761 You can safely ignore and delete this email if you do not want to 2762 take this action. 2763 2764 This email has been sent to ###EMAIL### 2765 2766 Regards, 2767 All at ###SITENAME### 2768 ###SITEURL###' 2769 ); 2770 2771 /** 2772 * Filters the text of the email sent when a change of network admin email address is attempted. 2773 * 2774 * The following strings have a special meaning and will get replaced dynamically: 2775 * ###USERNAME### The current user's username. 2776 * ###ADMIN_URL### The link to click on to confirm the email change. 2777 * ###EMAIL### The proposed new network admin email address. 2778 * ###SITENAME### The name of the network. 2779 * ###SITEURL### The URL to the network. 2780 * 2781 * @since 4.9.0 2782 * 2783 * @param string $email_text Text in the email. 2784 * @param array $new_admin_email { 2785 * Data relating to the new network admin email address. 2786 * 2787 * @type string $hash The secure hash used in the confirmation link URL. 2788 * @type string $newemail The proposed new network admin email address. 2789 * } 2790 */ 2791 $content = apply_filters( 'new_network_admin_email_content', $email_text, $new_admin_email ); 2792 2793 $current_user = wp_get_current_user(); 2794 $content = str_replace( '###USERNAME###', $current_user->user_login, $content ); 2795 $content = str_replace( '###ADMIN_URL###', esc_url( network_admin_url( 'settings.php?network_admin_hash=' . $hash ) ), $content ); 2796 $content = str_replace( '###EMAIL###', $value, $content ); 2797 $content = str_replace( '###SITENAME###', wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ), $content ); 2798 $content = str_replace( '###SITEURL###', network_home_url(), $content ); 2799 2800 wp_mail( 2801 $value, 2802 sprintf( 2803 /* translators: Email change notification email subject. %s: Network title. */ 2804 __( '[%s] Network Admin Email Change Request' ), 2805 wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ) 2806 ), 2807 $content 2808 ); 2809 2810 if ( $switched_locale ) { 2811 restore_previous_locale(); 2812 } 2813 } 2814 2815 /** 2816 * Sends an email to the old network admin email address when the network admin email address changes. 2817 * 2818 * @since 4.9.0 2819 * 2820 * @param string $option_name The relevant database option name. 2821 * @param string $new_email The new network admin email address. 2822 * @param string $old_email The old network admin email address. 2823 * @param int $network_id ID of the network. 2824 */ 2825 function wp_network_admin_email_change_notification( $option_name, $new_email, $old_email, $network_id ) { 2826 $send = true; 2827 2828 // Don't send the notification to the default 'admin_email' value. 2829 if ( 'you@example.com' === $old_email ) { 2830 $send = false; 2831 } 2832 2833 /** 2834 * Filters whether to send the network admin email change notification email. 2835 * 2836 * @since 4.9.0 2837 * 2838 * @param bool $send Whether to send the email notification. 2839 * @param string $old_email The old network admin email address. 2840 * @param string $new_email The new network admin email address. 2841 * @param int $network_id ID of the network. 2842 */ 2843 $send = apply_filters( 'send_network_admin_email_change_email', $send, $old_email, $new_email, $network_id ); 2844 2845 if ( ! $send ) { 2846 return; 2847 } 2848 2849 /* translators: Do not translate OLD_EMAIL, NEW_EMAIL, SITENAME, SITEURL: those are placeholders. */ 2850 $email_change_text = __( 2851 'Hi, 2852 2853 This notice confirms that the network admin email address was changed on ###SITENAME###. 2854 2855 The new network admin email address is ###NEW_EMAIL###. 2856 2857 This email has been sent to ###OLD_EMAIL### 2858 2859 Regards, 2860 All at ###SITENAME### 2861 ###SITEURL###' 2862 ); 2863 2864 $email_change_email = array( 2865 'to' => $old_email, 2866 /* translators: Network admin email change notification email subject. %s: Network title. */ 2867 'subject' => __( '[%s] Network Admin Email Changed' ), 2868 'message' => $email_change_text, 2869 'headers' => '', 2870 ); 2871 // Get network name. 2872 $network_name = wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ); 2873 2874 /** 2875 * Filters the contents of the email notification sent when the network admin email address is changed. 2876 * 2877 * @since 4.9.0 2878 * 2879 * @param array $email_change_email { 2880 * Used to build wp_mail(). 2881 * 2882 * @type string $to The intended recipient. 2883 * @type string $subject The subject of the email. 2884 * @type string $message The content of the email. 2885 * The following strings have a special meaning and will get replaced dynamically: 2886 * - ###OLD_EMAIL### The old network admin email address. 2887 * - ###NEW_EMAIL### The new network admin email address. 2888 * - ###SITENAME### The name of the network. 2889 * - ###SITEURL### The URL to the site. 2890 * @type string $headers Headers. 2891 * } 2892 * @param string $old_email The old network admin email address. 2893 * @param string $new_email The new network admin email address. 2894 * @param int $network_id ID of the network. 2895 */ 2896 $email_change_email = apply_filters( 'network_admin_email_change_email', $email_change_email, $old_email, $new_email, $network_id ); 2897 2898 $email_change_email['message'] = str_replace( '###OLD_EMAIL###', $old_email, $email_change_email['message'] ); 2899 $email_change_email['message'] = str_replace( '###NEW_EMAIL###', $new_email, $email_change_email['message'] ); 2900 $email_change_email['message'] = str_replace( '###SITENAME###', $network_name, $email_change_email['message'] ); 2901 $email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] ); 2902 2903 wp_mail( 2904 $email_change_email['to'], 2905 sprintf( 2906 $email_change_email['subject'], 2907 $network_name 2908 ), 2909 $email_change_email['message'], 2910 $email_change_email['headers'] 2911 ); 2912 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Tue Jan 21 08:20:01 2025 | Cross-referenced by PHPXref |