[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> ms-functions.php (source)

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


Generated: Thu Sep 19 01:00:03 2019 Cross-referenced by PHPXref 0.7.1