From 594079c5d108822fcb785bcf02bd797f275961b8 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Tue, 7 Sep 2021 21:30:07 +0000 Subject: [PATCH] Users: Introduce a `meta_input` argument for `wp_insert_user()`. This allows custom user meta values to be provided when creating or updating a user in the same way custom post meta can be provided to `wp_insert_post()` when creating or updating a post. Also introduces the `insert_custom_user_meta` to filter these values. Props desrosj, donmhico Fixes #41950 git-svn-id: https://develop.svn.wordpress.org/trunk@51738 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/user.php | 29 ++++++++++++++- tests/phpunit/tests/user.php | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 94598e8493..55bd546568 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -1711,9 +1711,10 @@ function validate_username( $username ) { * @since 2.0.0 * @since 3.6.0 The `aim`, `jabber`, and `yim` fields were removed as default user contact * methods for new installations. See wp_get_user_contact_methods(). - * @since 4.7.0 The user's locale can be passed to `$userdata`. + * @since 4.7.0 The `locale` field can be passed to `$userdata`. * @since 5.3.0 The `user_activation_key` field can be passed to `$userdata`. * @since 5.3.0 The `spam` field can be passed to `$userdata` (Multisite only). + * @since 5.9.0 The `meta_input` field can be passed to `$userdata` to allow addition of user meta data. * * @global wpdb $wpdb WordPress database abstraction object. * @@ -1758,6 +1759,8 @@ function validate_username( $username ) { * as a string literal, not boolean. Default 'true'. * @type string $role User's role. * @type string $locale User's locale. Default empty. + * @type array $meta_input Array of custom user meta values keyed by meta key. + * Default empty. * } * @return int|WP_Error The newly created user's ID or a WP_Error object if the user could not * be created. @@ -2058,6 +2061,8 @@ function wp_insert_user( $userdata ) { * * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`. * + * For custom meta fields, see the {@see 'insert_custom_user_meta'} filter. + * * @since 4.4.0 * @since 5.8.0 The $userdata parameter was added. * @@ -2084,6 +2089,28 @@ function wp_insert_user( $userdata ) { */ $meta = apply_filters( 'insert_user_meta', $meta, $user, $update, $userdata ); + $custom_meta = array(); + if ( array_key_exists( 'meta_input', $userdata ) && is_array( $userdata['meta_input'] ) && ! empty( $userdata['meta_input'] ) ) { + $custom_meta = $userdata['meta_input']; + } + + /** + * Filters a user's custom meta values and keys immediately after the user is created or updated + * and before any user meta is inserted or updated. + * + * For non-custom meta fields, see the {@see 'insert_user_meta'} filter. + * + * @since 5.9.0 + * + * @param array $custom_meta Array of custom user meta values keyed by meta key. + * @param WP_User $user User object. + * @param bool $update Whether the user is being updated rather than created. + * @param array $userdata The raw array of data passed to wp_insert_user(). + */ + $custom_meta = apply_filters( 'insert_custom_user_meta', $custom_meta, $user, $update, $userdata ); + + $meta = array_merge( $meta, $custom_meta ); + // Update user meta. foreach ( $meta as $key => $value ) { update_user_meta( $user_id, $key, $value ); diff --git a/tests/phpunit/tests/user.php b/tests/phpunit/tests/user.php index 5f94848e05..c7a04779cd 100644 --- a/tests/phpunit/tests/user.php +++ b/tests/phpunit/tests/user.php @@ -1845,6 +1845,78 @@ class Tests_User extends WP_UnitTestCase { $this->assertSame( 'January 29, 2020 09:13 AM', $actual['data'][1]['data'][3]['value'] ); } + /** + * Test `$user_data['meta_input']` args in `wp_insert_user( $user_data )`. + * + * @ticket 41950 + */ + public function test_wp_insert_user_with_meta() { + $user_data = array( + 'user_login' => 'test_user', + 'user_pass' => 'test_password', + 'user_email' => 'user@example.com', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_value', + 'custom_meta' => 'custom_value', + ), + ); + $create_user = wp_insert_user( $user_data ); + + $this->assertSame( 'test_meta_value', get_user_meta( $create_user, 'test_meta_key', true ) ); + $this->assertSame( 'custom_value', get_user_meta( $create_user, 'custom_meta', true ) ); + + // Update the user meta thru wp_insert_user. + $update_data = array( + 'ID' => $create_user, + 'user_login' => 'test_user', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_updated', + 'custom_meta' => 'updated_value', + 'new_meta_k' => 'new_meta_val', + ), + ); + $update_user = wp_insert_user( $update_data ); + + $this->assertSame( 'test_meta_updated', get_user_meta( $update_user, 'test_meta_key', true ) ); + $this->assertSame( 'updated_value', get_user_meta( $update_user, 'custom_meta', true ) ); + $this->assertSame( 'new_meta_val', get_user_meta( $update_user, 'new_meta_k', true ) ); + + // Create new user. + $new_user_data = array( + 'user_login' => 'new_test', + 'user_pass' => 'new_password', + 'user_email' => 'new_user@newexample.com', + 'meta_input' => array( + 'test_meta_key' => 'test_meta_value', + 'custom_meta' => 'new_user_custom_value', + ), + ); + + // Hook filter + add_filter( 'insert_custom_user_meta', array( $this, 'filter_custom_meta' ) ); + + $new_user = wp_insert_user( $new_user_data ); + + // This meta is updated by the filter. + $this->assertSame( 'update_from_filter', get_user_meta( $new_user, 'test_meta_key', true ) ); + $this->assertSame( 'new_user_custom_value', get_user_meta( $new_user, 'custom_meta', true ) ); + // This meta is inserted by the filter. + $this->assertSame( 'new_from_filter', get_user_meta( $new_user, 'new_meta_from_filter', true ) ); + } + + /** + * Hook a filter to alter custom meta when inserting new user. + * This hook is used in `test_wp_insert_user_with_meta()`. + */ + public function filter_custom_meta( $meta_input ) { + // Update some meta inputs + $meta_input['test_meta_key'] = 'update_from_filter'; + // Add a new meta + $meta_input['new_meta_from_filter'] = 'new_from_filter'; + + return $meta_input; + } + /** * Testing the `wp_privacy_additional_user_profile_data` filter works. *