@@ -20,6 +20,10 @@ function bootstrap() {
2020
2121 add_action ( 'after_signup_user ' , __NAMESPACE__ . '\\altis_signup_user_notification ' , 10 , 4 );
2222 add_action ( 'wpmu_activate_user ' , __NAMESPACE__ . '\\altis_welcome_user_notification ' , 10 , 3 );
23+
24+ // Redirect to password reset after activation (priority 20, after welcome emails at 10).
25+ add_action ( 'wpmu_activate_user ' , __NAMESPACE__ . '\\redirect_to_password_reset ' , 20 , 3 );
26+ add_action ( 'wpmu_activate_blog ' , __NAMESPACE__ . '\\redirect_blog_user_to_password_reset ' , 20 , 5 );
2327}
2428
2529/**
@@ -374,7 +378,7 @@ function altis_welcome_notification( $blog_id, $user_id, $password, $title, $met
374378 $ welcome_email = str_replace ( 'BLOG_TITLE ' , $ title , $ welcome_email );
375379 $ welcome_email = str_replace ( 'BLOG_URL ' , $ url , $ welcome_email );
376380 $ welcome_email = str_replace ( 'USERNAME ' , $ user ->user_login , $ welcome_email );
377- $ welcome_email = str_replace ( 'PASSWORD ' , $ password , $ welcome_email );
381+ $ welcome_email = str_replace ( 'PASSWORD ' , __ ( ' Please set your password by visiting the login page. ' ) , $ welcome_email );
378382
379383 /**
380384 * Filters the content of the welcome email sent to the site administrator after site activation.
@@ -483,7 +487,7 @@ function altis_welcome_user_notification( $user_id, $password, $meta = [] ) {
483487 $ welcome_email = apply_filters ( 'update_welcome_user_email ' , $ welcome_email , $ user_id , $ password , $ meta );
484488 $ welcome_email = str_replace ( 'SITE_NAME ' , $ current_network ->site_name , $ welcome_email );
485489 $ welcome_email = str_replace ( 'USERNAME ' , $ user ->user_login , $ welcome_email );
486- $ welcome_email = str_replace ( 'PASSWORD ' , $ password , $ welcome_email );
490+ $ welcome_email = str_replace ( 'PASSWORD ' , __ ( ' Please set your password by visiting the login page. ' ) , $ welcome_email );
487491 $ welcome_email = str_replace ( 'LOGINLINK ' , wp_login_url (), $ welcome_email );
488492
489493 $ admin_email = get_site_option ( 'admin_email ' );
@@ -522,3 +526,85 @@ function altis_welcome_user_notification( $user_id, $password, $meta = [] ) {
522526
523527 return true ;
524528}
529+
530+ /**
531+ * Redirect a user to the password reset page after account activation.
532+ *
533+ * Fires on `wpmu_activate_user` at priority 20, after the welcome email
534+ * has been sent at priority 10. This prevents the plaintext password from
535+ * being displayed on the wp-activate.php page.
536+ *
537+ * @param int $user_id User ID.
538+ * @param string $password User password.
539+ * @param array $meta Signup meta data.
540+ */
541+ function redirect_to_password_reset ( $ user_id , $ password , $ meta ) {
542+ $ user = get_userdata ( $ user_id );
543+ if ( ! $ user ) {
544+ return ;
545+ }
546+
547+ $ reset_key = get_password_reset_key ( $ user );
548+ if ( is_wp_error ( $ reset_key ) ) {
549+ return ;
550+ }
551+
552+ $ login_url = network_site_url ( 'wp-login.php ' , 'login ' );
553+ $ redirect_url = add_query_arg ( [
554+ 'action ' => 'rp ' ,
555+ 'key ' => $ reset_key ,
556+ 'login ' => rawurlencode ( $ user ->user_login ),
557+ ], $ login_url );
558+
559+ // Invalidate the wp-user-signups cache so the admin list table reflects
560+ // the updated activation status. Core's wpmu_activate_signup() updates
561+ // the DB directly but doesn't clean the plugin's object cache.
562+ wp_cache_set ( 'last_changed ' , microtime (), 'signups ' );
563+
564+ wp_safe_redirect ( $ redirect_url );
565+ exit ;
566+ }
567+
568+ /**
569+ * Redirect a blog signup user to the password reset page after activation.
570+ *
571+ * Fires on `wpmu_activate_blog` at priority 20, after the welcome email
572+ * has been sent at priority 10. This prevents the plaintext password from
573+ * being displayed on the wp-activate.php page.
574+ *
575+ * @param int $blog_id Blog ID.
576+ * @param int $user_id User ID.
577+ * @param string $password User password.
578+ * @param string $title Site title.
579+ * @param array $meta Signup meta data.
580+ */
581+ function redirect_blog_user_to_password_reset ( $ blog_id , $ user_id , $ password , $ title , $ meta ) {
582+ $ user = get_userdata ( $ user_id );
583+ if ( ! $ user ) {
584+ return ;
585+ }
586+
587+ $ reset_key = get_password_reset_key ( $ user );
588+ if ( is_wp_error ( $ reset_key ) ) {
589+ return ;
590+ }
591+
592+ // Use the network login URL rather than the new blog's login URL.
593+ // The password reset key works network-wide, and wp_safe_redirect()
594+ // may reject cross-host redirects to the new blog's subdomain.
595+ $ login_url = network_site_url ( 'wp-login.php ' , 'login ' );
596+
597+ $ redirect_url = add_query_arg ( [
598+ 'action ' => 'rp ' ,
599+ 'key ' => $ reset_key ,
600+ 'login ' => rawurlencode ( $ user ->user_login ),
601+ ], $ login_url );
602+
603+ // Invalidate the wp-user-signups cache so the admin list table reflects
604+ // the updated activation status. Core's wpmu_activate_signup() updates
605+ // the DB directly but doesn't clean the plugin's object cache.
606+ wp_cache_set ( 'last_changed ' , microtime (), 'signups ' );
607+
608+ wp_safe_redirect ( $ redirect_url );
609+ exit ;
610+ }
0 commit comments