From 1dd1b9931ed39cf4b0834974eed52527e17ef7e3 Mon Sep 17 00:00:00 2001 From: David Baumwald Date: Wed, 13 Aug 2025 13:09:14 -0400 Subject: [PATCH 1/4] Refreshing the patch --- src/wp-includes/user.php | 8 +++++ tests/phpunit/tests/user.php | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index eab8fa7e00565..9cdfd59597227 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -2501,6 +2501,11 @@ function wp_insert_user( $userdata ) { $user = new WP_User( $user_id ); + if ( ! $update ) { + /** This action is documented in wp-includes/pluggable.php */ + do_action( 'wp_set_password', $userdata['user_pass'], $user_id, $userdata ); + } + /** * Filters a user's meta values and keys immediately after the user is created or updated * and before any user meta is inserted or updated. @@ -2684,6 +2689,9 @@ function wp_update_user( $userdata ) { $plaintext_pass = $userdata['user_pass']; $userdata['user_pass'] = wp_hash_password( $userdata['user_pass'] ); + /** This action is documented in wp-includes/pluggable.php */ + do_action( 'wp_set_password', $plaintext_pass, $user_id, $user_obj ); + /** * Filters whether to send the password change email. * diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index df9f74b7e806a..958c0e7a72de3 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -2353,4 +2353,67 @@ function ( $meta_id, $object_id, $meta_key ) use ( &$db_update_count ) { // Verify there are no updates to 'use_ssl' user meta. $this->assertSame( 1, $db_update_count ); } + + /** + * Tests that `wp_set_password` action is triggered correctly during `wp_insert_user()`. + * + * @ticket 22114 + */ + public function test_set_password_action_fires_during_wp_insert_user() { + $mock_action = new MockAction(); + + add_action( 'wp_set_password', array( $mock_action, 'action' ), 10, 3 ); + + $userdata = array( + 'user_login' => 'testuser_' . wp_rand(), + 'user_pass' => 'initialpassword', + 'user_email' => 'testuser@example.com', + ); + + $user_id = wp_insert_user( $userdata ); + + // Assert that `wp_set_password` was triggered once during user creation. + $this->assertSame( 1, $mock_action->get_call_count(), 'wp_set_password was not triggered during user creation.' ); + + $args = $mock_action->get_args(); + + $this->assertSame( $userdata['user_pass'], $args[0][0], 'Wrong password argument in action.' ); + $this->assertSame( $user_id, $args[0][1], 'Wrong user ID in action.' ); + } + + /** + * Tests that `wp_set_password` action is triggered correctly during `wp_update_user()`. + * + * @ticket 22114 + */ + public function test_set_password_action_on_user_update() { + $mock_action = new MockAction(); + + add_action( 'wp_set_password', array( $mock_action, 'action' ), 10, 3 ); + + $user_id = $this->factory()->user->create( + array( + 'role' => 'subscriber', + 'user_login' => 'testuser_update', + 'user_email' => 'testuser_update@example.com', + 'user_pass' => 'initialpassword', + ) + ); + + $updated_password = 'newpassword123'; + + $userdata = array( + 'ID' => $user_id, + 'user_pass' => 'password', + ); + + wp_update_user( $userdata ); + + $this->assertSame( 1, $mock_action->get_call_count(), 'wp_set_password was not triggered during password update.' ); + + $args = $mock_action->get_args(); + + $this->assertSame( $updated_password, $args[0][0], 'Invalid password in wp_set_password action.' ); + $this->assertSame( $user_id, $args[0][1], 'Invalid user ID in wp_set_password action.' ); + } } From b8111eb28ce9929f77cf1edcc9a0311336da0912 Mon Sep 17 00:00:00 2001 From: David Baumwald Date: Wed, 13 Aug 2025 13:20:52 -0400 Subject: [PATCH 2/4] Reset the MockAction before running the update --- tests/phpunit/tests/user.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index 958c0e7a72de3..b46ec1bdc7160 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -2400,6 +2400,8 @@ public function test_set_password_action_on_user_update() { ) ); + $mock_action->reset(); + $updated_password = 'newpassword123'; $userdata = array( From fd3f61b5a44aa730faa33c7e5247e4aba4cebddd Mon Sep 17 00:00:00 2001 From: David Baumwald Date: Wed, 13 Aug 2025 13:31:35 -0400 Subject: [PATCH 3/4] Fix pass ref --- tests/phpunit/tests/user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index b46ec1bdc7160..535004ee560a8 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -2406,7 +2406,7 @@ public function test_set_password_action_on_user_update() { $userdata = array( 'ID' => $user_id, - 'user_pass' => 'password', + 'user_pass' => $updated_password, ); wp_update_user( $userdata ); From 45e3a93541c9339b9d78c9a58f5a5f8f9fa98bfb Mon Sep 17 00:00:00 2001 From: David Baumwald Date: Thu, 14 Aug 2025 08:21:22 -0400 Subject: [PATCH 4/4] On initial user creation, pass an empty WP_User obj for the old user data --- src/wp-includes/user.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 9cdfd59597227..26bfe2be1638b 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -2502,6 +2502,9 @@ function wp_insert_user( $userdata ) { $user = new WP_User( $user_id ); if ( ! $update ) { + // On initial creation, there is no existing user data, but `wp_set_password` expects a `WP_User` object. + $old_user_data = new WP_User(); + /** This action is documented in wp-includes/pluggable.php */ do_action( 'wp_set_password', $userdata['user_pass'], $user_id, $userdata ); }