: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( strlen( $user_name ) > 60 ) {
$errors->add( 'user_name', __( 'Username may not be longer than 60 characters.' ) );
if ( preg_match( '/^[0-9]*$/', $user_name ) ) {
$errors->add( 'user_name', __( 'Sorry, usernames must have letters too!' ) );
$limited_email_domains = get_site_option( 'limited_email_domains' );
if ( is_array( $limited_email_domains ) && ! empty( $limited_email_domains ) ) {
$limited_email_domains = array_map( 'strtolower', $limited_email_domains );
$emaildomain = strtolower( substr( $user_email, 1 + strpos( $user_email, '@' ) ) );
if ( ! in_array( $emaildomain, $limited_email_domains, true ) ) {
$errors->add( 'user_email', __( 'Sorry, that email address is not allowed!' ) );
// Check if the username has been used already.
if ( username_exists( $user_name ) ) {
$errors->add( 'user_name', __( 'Sorry, that username already exists!' ) );
// Check if the email address has been used already.
if ( email_exists( $user_email ) ) {
/* translators: %s: Link to the login page. */
__( '<strong>Error:</strong> This email address is already registered. <a href="%s">Log in</a> with this address or choose another one.' ),
// Has someone already signed up for this username?
$signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name ) );
if ( $signup instanceof stdClass ) {
$registered_at = mysql2date( 'U', $signup->registered );
$diff = $now - $registered_at;
// If registered more than two days ago, cancel registration and let this signup go through.
if ( $diff > 2 * DAY_IN_SECONDS ) {
$wpdb->delete( $wpdb->signups, array( 'user_login' => $user_name ) );
$errors->add( 'user_name', __( 'That username is currently reserved but may be available in a couple of days.' ) );
$signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email ) );
if ( $signup instanceof stdClass ) {
$diff = time() - mysql2date( 'U', $signup->registered );
// If registered more than two days ago, cancel registration and let this signup go through.
if ( $diff > 2 * DAY_IN_SECONDS ) {
$wpdb->delete( $wpdb->signups, array( 'user_email' => $user_email ) );
$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.' ) );
'user_name' => $user_name,
'orig_username' => $orig_username,
'user_email' => $user_email,
* Filters the validated user registration details.
* This does not allow you to override the username or email of the user during
* registration. The values are solely used for validation and error handling.
* The array of user name, email, and the error messages.
* @type string $user_name Sanitized and unique username.
* @type string $orig_username Original username.
* @type string $user_email User email address.
* @type WP_Error $errors WP_Error object containing any errors found.
return apply_filters( 'wpmu_validate_user_signup', $result );
* Processes new site registrations.
* Checks the data provided by the user during blog signup. Verifies
* the validity and uniqueness of blog paths and domains.
* This function prevents the current user from registering a new site
* with a blogname equivalent to another user's login name. Passing the
* $user parameter to the function, where $user is the other user, is
* effectively an override of this limitation.
* Filter {@see 'wpmu_validate_blog_signup'} if you want to modify
* the way that WordPress validates new site signups.
* @global wpdb $wpdb WordPress database abstraction object.
* @param string $blogname The site name provided by the user. Must be unique.
* @param string $blog_title The site title provided by the user.
* @param WP_User|string $user Optional. The user object to check against the new site name.
* Array of domain, path, site name, site title, user and error messages.
* @type string $domain Domain for the site.
* @type string $path Path for the site. Used in subdirectory installations.
* @type string $blogname The unique site name (slug).
* @type string $blog_title Blog title.
* @type string|WP_User $user By default, an empty string. A user object if provided.
* @type WP_Error $errors WP_Error containing any errors found.
function wpmu_validate_blog_signup( $blogname, $blog_title, $user = '' ) {
$current_network = get_network();
$base = $current_network->path;
$blog_title = strip_tags( $blog_title );
$errors = new WP_Error();
$illegal_names = get_site_option( 'illegal_names' );
if ( false == $illegal_names ) {
$illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' );
add_site_option( 'illegal_names', $illegal_names );
* On sub dir installations, some names are so illegal, only a filter can
if ( ! is_subdomain_install() ) {
$illegal_names = array_merge( $illegal_names, get_subdirectory_reserved_names() );
if ( empty( $blogname ) ) {
$errors->add( 'blogname', __( 'Please enter a site name.' ) );
if ( preg_match( '/[^a-z0-9]+/', $blogname ) ) {
$errors->add( 'blogname', __( 'Site names can only contain lowercase letters (a-z) and numbers.' ) );
if ( in_array( $blogname, $illegal_names, true ) ) {
$errors->add( 'blogname', __( 'That name is not allowed.' ) );
* Filters the minimum site name length required when validating a site signup.
* @param int $length The minimum site name length. Default 4.
$minimum_site_name_length = apply_filters( 'minimum_site_name_length', 4 );
if ( strlen( $blogname ) < $minimum_site_name_length ) {
/* translators: %s: Minimum site name length. */
$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 ) ) );
// Do not allow users to create a site that conflicts with a page on the main blog.
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 ) ) ) {
$errors->add( 'blogname', __( 'Sorry, you may not use that site name.' ) );
if ( preg_match( '/^[0-9]*$/', $blogname ) ) {
$errors->add( 'blogname', __( 'Sorry, site names must have letters too!' ) );
* Filters the new site name during registration.
* The name is the site's subdomain or the site's subdirectory
* path depending on the network settings.
* @param string $blogname Site name.
$blogname = apply_filters( 'newblogname', $blogname );
$blog_title = wp_unslash( $blog_title );
if ( empty( $blog_title ) ) {
$errors->add( 'blog_title', __( 'Please enter a site title.' ) );
// Check if the domain/path has been used already.
if ( is_subdomain_install() ) {
$mydomain = $blogname . '.' . preg_replace( '|^www\.|', '', $domain );
$path = $base . $blogname . '/';
if ( domain_exists( $mydomain, $path, $current_network->id ) ) {
$errors->add( 'blogname', __( 'Sorry, that site already exists!' ) );
* Do not allow users to create a site that matches an existing user's login name,
* unless it's the user's own username.
if ( username_exists( $blogname ) ) {
if ( ! is_object( $user ) || ( is_object( $user ) && ( $user->user_login != $blogname ) ) ) {
$errors->add( 'blogname', __( 'Sorry, that site is reserved!' ) );
* Has someone already signed up for this domain?
$signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->signups WHERE domain = %s AND path = %s", $mydomain, $path ) );
if ( $signup instanceof stdClass ) {
$diff = time() - mysql2date( 'U', $signup->registered );
// If registered more than two days ago, cancel registration and let this signup go through.
if ( $diff > 2 * DAY_IN_SECONDS ) {
$errors->add( 'blogname', __( 'That site is currently reserved but may be available in a couple days.' ) );
'blog_title' => $blog_title,
* Filters site details and error messages following registration.
* Array of domain, path, site name, site title, user and error messages.
* @type string $domain Domain for the site.
* @type string $path Path for the site. Used in subdirectory installations.
* @type string $blogname The unique site name (slug).
* @type string $blog_title Site title.
* @type string|WP_User $user By default, an empty string. A user object if provided.
* @type WP_Error $errors WP_Error containing any errors found.
return apply_filters( 'wpmu_validate_blog_signup', $result );
* Records site signup information for future activation.
* @global wpdb $wpdb WordPress database abstraction object.
* @param string $domain The requested domain.
* @param string $path The requested path.
* @param string $title The requested site title.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id.
function wpmu_signup_blog( $domain, $path, $title, $user, $user_email, $meta = array() ) {
$key = substr( md5( time() . wp_rand() . $domain ), 0, 16 );
* Filters the metadata for a site signup.
* The metadata will be serialized prior to storing it in the database.
* @param array $meta Signup meta data. Default empty array.
* @param string $domain The requested domain.
* @param string $path The requested path.
* @param string $title The requested site title.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param string $key The user's activation key.
$meta = apply_filters( 'signup_site_meta', $meta, $domain, $path, $title, $user, $user_email, $key );
'user_email' => $user_email,
'registered' => current_time( 'mysql', true ),
'activation_key' => $key,
'meta' => serialize( $meta ),
* Fires after site signup information has been written to the database.
* @param string $domain The requested domain.
* @param string $path The requested path.
* @param string $title The requested site title.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param string $key The user's activation key.
* @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id.
do_action( 'after_signup_site', $domain, $path, $title, $user, $user_email, $key, $meta );
* Records user signup information for future activation.
* This function is used when user registration is open but
* new site registration is not.
* @global wpdb $wpdb WordPress database abstraction object.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param array $meta Optional. Signup meta data. Default empty array.
function wpmu_signup_user( $user, $user_email, $meta = array() ) {
$user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) );
$user_email = sanitize_email( $user_email );
$key = substr( md5( time() . wp_rand() . $user_email ), 0, 16 );
* Filters the metadata for a user signup.
* The metadata will be serialized prior to storing it in the database.
* @param array $meta Signup meta data. Default empty array.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param string $key The user's activation key.
$meta = apply_filters( 'signup_user_meta', $meta, $user, $user_email, $key );
'user_email' => $user_email,
'registered' => current_time( 'mysql', true ),
'activation_key' => $key,
'meta' => serialize( $meta ),
* Fires after a user's signup information has been written to the database.
* @param string $user The user's requested login name.
* @param string $user_email The user's email address.
* @param string $key The user's activation key.
* @param array $meta Signup meta data. Default empty array.
do_action( 'after_signup_user', $user, $user_email, $key, $meta );
* Sends a confirmation request email to a user when they sign up for a new site. The new site will not become active
* until the confirmation link is clicked.
* This is the notification function used when site registration
* Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or
* replace it with your own notification behavior.
* Filter {@see 'wpmu_signup_blog_notification_email'} and
* {@see 'wpmu_signup_blog_notification_subject'} to change the content
* and subject line of the email sent to newly registered users.
* @param string $domain The new blog domain.
* @param string $path The new blog path.
* @param string $title The site title.
* @param string $user_login The user's login name.
* @param string $user_email The user's email address.
* @param string $key The activation key created in wpmu_signup_blog().
* @param array $meta Optional. Signup meta data. By default, contains the requested privacy setting and lang_id.
function wpmu_signup_blog_notification( $domain, $path, $title, $user_login, $user_email, $key, $meta = array() ) {
* Filters whether to bypass the new site email notification.
* @param string|false $domain Site domain, or false to prevent the email from sending.
* @param string $path Site path.
* @param string $title Site title.
* @param string $user_login User login name.
* @param string $user_email User email address.
* @param string $key Activation key created in wpmu_signup_blog().
* @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id.
if ( ! apply_filters( 'wpmu_signup_blog_notification', $domain, $path, $title, $user_login, $user_email, $key, $meta ) ) {
// Send email with activation link.
if ( ! is_subdomain_install() || get_current_network_id() != 1 ) {
$activate_url = network_site_url( "wp-activate.php?key=$key" );
$activate_url = "http://{$domain}{$path}wp-activate.php?key=$key"; // @todo Use *_url() API.
$activate_url = esc_url( $activate_url );
$admin_email = get_site_option( 'admin_email' );
if ( '' === $admin_email ) {
$admin_email = 'support@' . wp_parse_url( network_home_url(), PHP_URL_HOST );
$from_name = ( '' !== get_site_option( 'site_name' ) ) ? esc_html( get_site_option( 'site_name' ) ) : 'WordPress';
$message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
$user = get_user_by( 'login', $user_login );
$switched_locale = $user && switch_to_user_locale( $user->ID );
* Filters the message content of the new blog notification email.
* Content should be formatted for transmission via wp_mail().
* @param string $content Content of the notification email.
* @param string $domain Site domain.
* @param string $path Site path.
* @param string $title Site title.
* @param string $user_login User login name.
* @param string $user_email User email address.
* @param string $key Activation key created in wpmu_signup_blog().
* @param array $meta Signup meta data. By default, contains the requested privacy setting and lang_id.
'wpmu_signup_blog_notification_email',
/* translators: New site notification email. 1: Activation URL, 2: New site URL. */
__( "To activate your site, please click the following link:\n\n%1\$s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%2\$s" ),
esc_url( "http://{$domain}{$path}" ),
* Filters the subject of the new blog notification email.