Opened 7 years ago
Closed 3 years ago
#39829 closed enhancement (duplicate)
Missing Filter before user is created within "wp_insert_user" function
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 4.7.2 |
Component: | Users | Keywords: | |
Focuses: | Cc: |
Description
The "wp_insert_post" function has a filter called "wp_insert_post_data" that filters the post data right before the post is created.
For me the "wp_insert_user" function should have as well a filter right before the user is created in the database.
Unfortunately it doesn't exists. There is a action called "user_register" that lets me do something once the user is created, but it doesn't let me modify the actual data the "wp_insert_user" function returns.
Background:
I use the "wp_insert_post_data" filter to assign a random unique ID to each new post. This is helpful if you have a custom post type with sensitive data, where you don't want to make public how many exists or get created per day. (If the post ID is only auto increated each day, you could get this information by quering once in the morning and once in the night).
But it's impossible to assign a random unique ID to a newly created user. Or actually, it is not possible, I can hook into the "user_register" action and udpate all database tables with a new user id. But I can not use that new information as the "wp_insert_user" function will still return the old ID.
Change History (5)
#2
@
7 years ago
Hey @SergeyBiryukov, thanks for the fast reply. I have seen the other filters, but there is still no filter for the user ID
.
As I explained: Within the wp_insert_post_data
function you have the ability to filter through all the $data
array. That means that you can modify the $data[ID]
and assign a different one before the post gets actually inserted into the database.
Example:
/**
* Filter to use random 6 digit number as post ID
**/
function create_random_unique_id( $data, $postarr ) {
// Check if we are updating an existing post or importing with a suggested post ID
if ( ! empty( $postarr['ID'] ) || ! isset( $postarr['import_id'] ) ) {
return $data;
} else {
// Get Wordpress Database
global $wpdb;
// Create random 6 digit number
$random = substr( rand() * 900000 + 100000, 0, 6 );
// Check if ID is unique in database
while ( $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE ID = %d", $random ) ) ) {
// Generate new random ID
$random = substr( rand() * 900000 + 100000, 0, 8 );
}
// Assign new post id random number
$data['ID'] = $random;
return $data;
}
}
add_action( 'wp_insert_post_data', 'create_random_unique_id', 10, 2 );
The wp_insert_user
function seems to work different, as it inserts the user first into the database based on the nickname (and not like the post based on the ID) and than works with the ID returned by the database going forward. Meaning that I can't hook in anywhere to change the ID of the to be created user. The only thing I can do is updating the database after the user is created with the user_register
action. Here is an example for that:
function create_random_unique_user_id( $user_id ) {
// Get global Wordpress Database Object
global $wpdb;
// Get newly created user ID
$user_object = get_user_by( 'id', $user_id );
// Create random 6 digit number
$random = substr( rand() * 900000 + 100000, 0, 6 );
// Check if ID is unique in database
while ( $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE ID = %d", $random ) ) ) {
// Generate new random ID
$random = substr( rand() * 900000 + 100000, 0, 8 );
}
// Update all tables with new user ID
$wpdb->update( $wpdb->users, array( 'ID' => $random ), array( 'ID' => $user_id ) );
$wpdb->update( $wpdb->posts, array( 'ID' => $random ), array( 'post_author' => $user_id ) );
$wpdb->update( $wpdb->usermeta, array( 'ID' => $random ), array( 'user_id' => $user_id ) );
$wpdb->update( $wpdb->comments, array( 'ID' => $random ), array( 'user_id' => $user_id ) );
$wpdb->update( $wpdb->links, array( 'ID' => $random ), array( 'link_owner' => $user_id ) );
}
add_action( 'user_register', 'create_random_unique_user_id', 10, 1 );
But this is problematic as the user_id
returned by wp_insert_user
is still the old one. As such other functions who depend on the return value of wp_insert_user
fail.
I just wondered why there are filters available for every other field of the user, but no one for the ID. Especially if its possible within the "wp_insert_post_data" function. These two should work similar.
#4
@
7 years ago
I also am +1 on a filter before the user is created OR updated, just after the $data
var is set.
Something like this?
$data = wp_unslash( $compacted ); /** * Filters a user's data values and keys before the user is created or updated. * * Does not include contact methods. These are added using `wp_get_user_contact_methods( $user )`. * * @since 4.8 * * @param array $data { * Default data values and keys for the user. * * @type string $user_pass The user's password. * @type string $user_email The user's email. * @type string $user_url The user's url. * @type string $user_nicename The user's nicename. * @type string $display_name The user's display name. * @type string $user_registered The user's registration date. * } * @param array $where { * Values and keys used for identifying the user being inserted or updated. * * @type int $ID The user's ID. * @type string $user_login The user's login. * } * @param array $meta { * Default meta values and keys for the user. * * @type string $nickname The user's nickname. Default is the user's username. * @type string $first_name The user's first name. * @type string $last_name The user's last name. * @type string $description The user's description. * @type bool $rich_editing Whether to enable the rich-editor for the user. False if not empty. * @type bool $comment_shortcuts Whether to enable keyboard shortcuts for the user. Default false. * @type string $admin_color The color scheme for a user's admin screen. Default 'fresh'. * @type int|bool $use_ssl Whether to force SSL on the user's admin area. 0|false if SSL is * not forced. * @type bool $show_admin_bar_front Whether to show the admin bar on the front end for the user. * Default true. * } * @param bool $update Whether the user is being updated rather than created. */ $data = apply_filters( 'insert_user_data', $data, compact( 'ID', 'user_login' ), $meta, $update );
I think we should follow up with an additional ticket at some point that fixes the text of the insert_user_meta
filter does not describe as "before the user is created or updated" -- it should actually be "after the user has been created or updated". Right now, the hook description is problematic and misinforming to developers.
Hi @jaschaio, welcome to WordPress Trac! Thanks for the ticket.
wp_insert_user()
does not return user data though, just user ID on success or aWP_Error
object on failure.There are filters for individual fields and metadata, any reason they don't work for your use case?
pre_user_login
pre_user_nicename
pre_user_url
pre_user_email
pre_user_nickname
pre_user_first_name
pre_user_last_name
pre_user_display_name
pre_user_description
insert_user_meta