Ticket #16470: 16470.3.patch
File 16470.3.patch, 14.4 KB (added by , 6 years ago) |
---|
-
src/wp-admin/includes/admin-filters.php
diff --git src/wp-admin/includes/admin-filters.php src/wp-admin/includes/admin-filters.php index 141e8aa08e..24b42c16fe 100644
add_action( 'install_themes_pre_theme-information', 'install_theme_information' 99 99 add_action( 'admin_init', 'default_password_nag_handler' ); 100 100 101 101 add_action( 'admin_notices', 'default_password_nag' ); 102 add_action( 'admin_notices', 'new_user_email_admin_notice' ); 102 103 103 104 add_action( 'profile_update', 'default_password_nag_edit_user', 10, 2 ); 104 105 106 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' ); 107 105 108 // Update hooks. 106 109 add_action( 'load-plugins.php', 'wp_plugin_update_rows', 20 ); // After wp_update_plugins() is called. 107 110 add_action( 'load-themes.php', 'wp_theme_update_rows', 20 ); // After wp_update_themes() is called. -
src/wp-admin/includes/ms-admin-filters.php
diff --git src/wp-admin/includes/ms-admin-filters.php src/wp-admin/includes/ms-admin-filters.php index fb4f678a3a..619ef0963b 100644
11 11 add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' ); 12 12 13 13 // User Hooks 14 add_action( 'admin_notices', 'new_user_email_admin_notice' );15 14 add_action( 'user_admin_notices', 'new_user_email_admin_notice' ); 16 15 17 16 add_action( 'admin_page_access_denied', '_access_denied_splash', 99 ); 18 17 19 18 add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 ); 20 19 21 add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );22 23 20 add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 ); 24 21 25 22 // Site Hooks. -
src/wp-admin/includes/ms.php
diff --git src/wp-admin/includes/ms.php src/wp-admin/includes/ms.php index 866db3f698..6a1b397875 100644
All at ###SITENAME### 336 336 } 337 337 338 338 /** 339 * Sends an email when an email address change is requested.340 *341 * @since 3.0.0342 *343 * @global WP_Error $errors WP_Error object.344 * @global wpdb $wpdb WordPress database object.345 */346 function send_confirmation_on_profile_email() {347 global $errors, $wpdb;348 $current_user = wp_get_current_user();349 if ( ! is_object($errors) )350 $errors = new WP_Error();351 352 if ( $current_user->ID != $_POST['user_id'] )353 return false;354 355 if ( $current_user->user_email != $_POST['email'] ) {356 if ( !is_email( $_POST['email'] ) ) {357 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn’t correct." ), array( 'form-field' => 'email' ) );358 return;359 }360 361 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) {362 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 'form-field' => 'email' ) );363 delete_user_meta( $current_user->ID, '_new_email' );364 return;365 }366 367 $hash = md5( $_POST['email'] . time() . mt_rand() );368 $new_user_email = array(369 'hash' => $hash,370 'newemail' => $_POST['email']371 );372 update_user_meta( $current_user->ID, '_new_email', $new_user_email );373 374 $switched_locale = switch_to_locale( get_user_locale() );375 376 /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */377 $email_text = __( 'Howdy ###USERNAME###,378 379 You recently requested to have the email address on your account changed.380 381 If this is correct, please click on the following link to change it:382 ###ADMIN_URL###383 384 You can safely ignore and delete this email if you do not want to385 take this action.386 387 This email has been sent to ###EMAIL###388 389 Regards,390 All at ###SITENAME###391 ###SITEURL###' );392 393 /**394 * Filters the email text sent when a user changes emails.395 *396 * The following strings have a special meaning and will get replaced dynamically:397 * ###USERNAME### The current user's username.398 * ###ADMIN_URL### The link to click on to confirm the email change.399 * ###EMAIL### The new email.400 * ###SITENAME### The name of the site.401 * ###SITEURL### The URL to the site.402 *403 * @since MU404 *405 * @param string $email_text Text in the email.406 * @param string $new_user_email New user email that the current user has changed to.407 */408 $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email );409 410 $content = str_replace( '###USERNAME###', $current_user->user_login, $content );411 $content = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'profile.php?newuseremail=' . $hash ) ), $content );412 $content = str_replace( '###EMAIL###', $_POST['email'], $content);413 $content = str_replace( '###SITENAME###', wp_specialchars_decode( get_site_option( 'site_name' ), ENT_QUOTES ), $content );414 $content = str_replace( '###SITEURL###', network_home_url(), $content );415 416 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content );417 $_POST['email'] = $current_user->user_email;418 419 if ( $switched_locale ) {420 restore_previous_locale();421 }422 }423 }424 425 /**426 * Adds an admin notice alerting the user to check for confirmation email427 * after email address change.428 *429 * @since 3.0.0430 *431 * @global string $pagenow432 */433 function new_user_email_admin_notice() {434 global $pagenow;435 if ( 'profile.php' === $pagenow && isset( $_GET['updated'] ) && $email = get_user_meta( get_current_user_id(), '_new_email', true ) ) {436 /* translators: %s: New email address */437 echo '<div class="notice notice-info"><p>' . sprintf( __( 'Your email address has not been updated yet. Please check your inbox at %s for a confirmation email.' ), '<code>' . esc_html( $email['newemail'] ) . '</code>' ) . '</p></div>';438 }439 }440 441 /**442 339 * Check whether a site has used its allotted upload space. 443 340 * 444 341 * @since MU -
src/wp-admin/user-edit.php
diff --git src/wp-admin/user-edit.php src/wp-admin/user-edit.php index 80cef618e5..e034163da4 100644
if ( is_multisite() 88 88 } 89 89 90 90 // Execute confirmed email change. See send_confirmation_on_profile_email(). 91 if ( is_multisite() &&IS_PROFILE_PAGE && isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) {91 if ( IS_PROFILE_PAGE && isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) { 92 92 $new_email = get_user_meta( $current_user->ID, '_new_email', true ); 93 93 if ( $new_email && hash_equals( $new_email[ 'hash' ], $_GET[ 'newuseremail' ] ) ) { 94 94 $user = new stdClass; 95 95 $user->ID = $current_user->ID; 96 96 $user->user_email = esc_html( trim( $new_email[ 'newemail' ] ) ); 97 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->signups} WHERE user_login = %s", $current_user->user_login ) ) ) {97 if ( is_multisite() && $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->signups} WHERE user_login = %s", $current_user->user_login ) ) ) { 98 98 $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->signups} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) ); 99 99 } 100 100 wp_update_user( $user ); … … if ( is_multisite() && IS_PROFILE_PAGE && isset( $_GET[ 'newuseremail' ] ) && $c 104 104 } else { 105 105 wp_redirect( add_query_arg( array( 'error' => 'new-email' ), self_admin_url( 'profile.php' ) ) ); 106 106 } 107 } elseif ( is_multisite() && IS_PROFILE_PAGE && !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' === $_GET['dismiss'] ) {107 } elseif ( IS_PROFILE_PAGE && ! empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' === $_GET['dismiss'] ) { 108 108 check_admin_referer( 'dismiss-' . $current_user->ID . '_new_email' ); 109 109 delete_user_meta( $current_user->ID, '_new_email' ); 110 110 wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) ); -
src/wp-includes/user.php
diff --git src/wp-includes/user.php src/wp-includes/user.php index 41a83d2422..d27bbda392 100644
function _wp_get_current_user() { 2590 2590 2591 2591 return $current_user; 2592 2592 } 2593 2594 /** 2595 * Sends an email when an email address change is requested. 2596 * 2597 * @since 3.0.0 2598 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. 2599 * 2600 * @global WP_Error $errors WP_Error object. 2601 * @global wpdb $wpdb WordPress database object. 2602 */ 2603 function send_confirmation_on_profile_email() { 2604 global $errors, $wpdb; 2605 2606 $current_user = wp_get_current_user(); 2607 if ( ! is_object( $errors ) ) { 2608 $errors = new WP_Error(); 2609 } 2610 2611 if ( $current_user->ID != $_POST['user_id'] ) { 2612 return false; 2613 } 2614 2615 if ( $current_user->user_email != $_POST['email'] ) { 2616 if ( ! is_email( $_POST['email'] ) ) { 2617 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn’t correct." ), array( 2618 'form-field' => 'email', 2619 ) ); 2620 2621 return; 2622 } 2623 2624 if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_email FROM {$wpdb->users} WHERE user_email=%s", $_POST['email'] ) ) ) { 2625 $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 2626 'form-field' => 'email', 2627 ) ); 2628 delete_user_meta( $current_user->ID, '_new_email' ); 2629 2630 return; 2631 } 2632 2633 $hash = md5( $_POST['email'] . time() . mt_rand() ); 2634 $new_user_email = array( 2635 'hash' => $hash, 2636 'newemail' => $_POST['email'], 2637 ); 2638 update_user_meta( $current_user->ID, '_new_email', $new_user_email ); 2639 2640 /* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ 2641 $email_text = __( 'Howdy ###USERNAME###, 2642 2643 You recently requested to have the email address on your account changed. 2644 2645 If this is correct, please click on the following link to change it: 2646 ###ADMIN_URL### 2647 2648 You can safely ignore and delete this email if you do not want to 2649 take this action. 2650 2651 This email has been sent to ###EMAIL### 2652 2653 Regards, 2654 All at ###SITENAME### 2655 ###SITEURL###' ); 2656 2657 /** 2658 * Filters the email text sent when a user changes emails. 2659 * 2660 * The following strings have a special meaning and will get replaced dynamically: 2661 * ###USERNAME### The current user's username. 2662 * ###ADMIN_URL### The link to click on to confirm the email change. 2663 * ###EMAIL### The new email. 2664 * ###SITENAME### The name of the site. 2665 * ###SITEURL### The URL to the site. 2666 * 2667 * @since MU 2668 * @since 4.9.0 This filter is no longer Multisite specific. 2669 * 2670 * @param string $email_text Text in the email. 2671 * @param string $new_user_email New user email that the current user has changed to. 2672 */ 2673 $content = apply_filters( 'new_user_email_content', $email_text, $new_user_email ); 2674 2675 $content = str_replace( '###USERNAME###', $current_user->user_login, $content ); 2676 $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail=' . $hash ) ), $content ); 2677 $content = str_replace( '###EMAIL###', $_POST['email'], $content ); 2678 $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content ); 2679 $content = str_replace( '###SITEURL###', network_home_url(), $content ); 2680 2681 wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), wp_specialchars_decode( get_option( 'blogname' ) ) ), $content ); 2682 2683 $_POST['email'] = $current_user->user_email; 2684 } 2685 } 2686 2687 /** 2688 * Adds an admin notice alerting the user to check for confirmation email 2689 * after email address change. 2690 * 2691 * @since 3.0.0 2692 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific. 2693 * 2694 * @global string $pagenow 2695 */ 2696 function new_user_email_admin_notice() { 2697 global $pagenow; 2698 if ( 'profile.php' === $pagenow && isset( $_GET['updated'] ) && $email = get_user_meta( get_current_user_id(), '_new_email', true ) ) { 2699 /* translators: %s: New email address */ 2700 echo '<div class="notice notice-info"><p>' . sprintf( __( 'Your email address has not been updated yet. Please check your inbox at %s for a confirmation email.' ), '<code>' . esc_html( $email['newemail'] ) . '</code>' ) . '</p></div>'; 2701 } 2702 } -
tests/phpunit/tests/user.php
diff --git tests/phpunit/tests/user.php tests/phpunit/tests/user.php index b2b87d19d2..94a4bde5ce 100644
class Tests_User extends WP_UnitTestCase { 1204 1204 function action_check_passwords_blank_pw( $user_login, &$pass1 ) { 1205 1205 $pass1 = ''; 1206 1206 } 1207 1208 /** 1209 * @ticket 16470 1210 */ 1211 function test_send_confirmation_on_profile_email() { 1212 reset_phpmailer_instance(); 1213 $was_confirmation_email_sent = false; 1214 1215 $user = $this->factory()->user->create_and_get( array( 1216 'user_email' => 'before@example.com', 1217 ) ); 1218 1219 $_POST['email'] = 'after@example.com'; 1220 $_POST['user_id'] = $user->ID; 1221 1222 wp_set_current_user( $user->ID ); 1223 1224 do_action( 'personal_options_update' ); 1225 1226 if ( ! empty( $GLOBALS['phpmailer']->mock_sent ) ) { 1227 $was_confirmation_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[0] ) && 'after@example.com' == $GLOBALS['phpmailer']->mock_sent[0]['to'][0][0] ); 1228 } 1229 1230 // A confirmation email is sent. 1231 $this->assertTrue( $was_confirmation_email_sent ); 1232 1233 // The new email address gets put into user_meta. 1234 $new_email_meta = get_user_meta( $user->ID, '_new_email', true ); 1235 $this->assertEquals( 'after@example.com', $new_email_meta['newemail'] ); 1236 1237 // The email address of the user doesn't change. $_POST['email'] should be the email address pre-update. 1238 $this->assertEquals( $_POST['email'], $user->user_email ); 1239 } 1240 1241 /** 1242 * @ticket 16470 1243 */ 1244 function test_remove_send_confirmation_on_profile_email() { 1245 remove_action( 'personal_options_update', 'send_confirmation_on_profile_email' ); 1246 1247 reset_phpmailer_instance(); 1248 $was_confirmation_email_sent = false; 1249 1250 $user = $this->factory()->user->create_and_get( array( 1251 'user_email' => 'before@example.com', 1252 ) ); 1253 1254 $_POST['email'] = 'after@example.com'; 1255 $_POST['user_id'] = $user->ID; 1256 1257 wp_set_current_user( $user->ID ); 1258 1259 do_action( 'personal_options_update' ); 1260 1261 if ( ! empty( $GLOBALS['phpmailer']->mock_sent ) ) { 1262 $was_confirmation_email_sent = ( isset( $GLOBALS['phpmailer']->mock_sent[0] ) && 'after@example.com' == $GLOBALS['phpmailer']->mock_sent[0]['to'][0][0] ); 1263 } 1264 1265 // No confirmation email is sent. 1266 $this->assertFalse( $was_confirmation_email_sent ); 1267 1268 // No usermeta is created. 1269 $new_email_meta = get_user_meta( $user->ID, '_new_email', true ); 1270 $this->assertEmpty( $new_email_meta ); 1271 1272 // $_POST['email'] should be the email address posted from the form. 1273 $this->assertEquals( $_POST['email'], 'after@example.com' ); 1274 } 1207 1275 }