Opened 9 years ago
Last modified 5 months ago
#39370 new defect (bug)
wp_insert_user() appends suffix to nicename when updating already existing user
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Future Release | Priority: | normal |
| Severity: | normal | Version: | 4.6.1 |
| Component: | Users | Keywords: | reporter-feedback has-patch needs-unit-tests needs-test-info |
| Focuses: | Cc: |
Description
wp_insert_user() appends suffix to nicename when updating already existing user, even though the user_nicename prop is set to exactly the same value as it currently has.
Steps to reproduce:
- Asuming you have a user in your wordpress database with the ID 1 and user_nicename set to 'test-nicename'.
- If you then make an update using wp_insert_user() of that user and in the update set the user_nicename to 'test-nicename', then wordpress will update the user, but append -2 as a suffix to the nicename.
This happens because of a check located on line 1597 - 1609 in wp-includes/user.php
<?php $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login)); if ( $user_nicename_check) { $suffix = 2; while ($user_nicename_check) { // user_nicename allows 50 chars. Subtract one for a hyphen, plus the length of the suffix. $base_length = 49 - mb_strlen( $suffix ); $alt_user_nicename = mb_substr( $user_nicename, 0, $base_length ) . "-$suffix"; $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $alt_user_nicename, $user_login)); $suffix++; } $user_nicename = $alt_user_nicename; }
This code is there to make sure that there are no duplicate nicenames in the wp_users table, which is fine. However it does not take into account updating the nicename of a user with the same value as it currently has.
The way to solve it is very easy, only simply changes the if() statement to check the id fethced in $user_nicename_check against the ID of the user currently being updated, like so:
<?php $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $user_nicename, $user_login)); if ( $user_nicename_check && $ID != $user_nicename_check) { $suffix = 2; while ($user_nicename_check) { // user_nicename allows 50 chars. Subtract one for a hyphen, plus the length of the suffix. $base_length = 49 - mb_strlen( $suffix ); $alt_user_nicename = mb_substr( $user_nicename, 0, $base_length ) . "-$suffix"; $user_nicename_check = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1" , $alt_user_nicename, $user_login)); $suffix++; } $user_nicename = $alt_user_nicename; }
This makes prevents the code from appending the suffix when the $user_nicename_check ID matches the ID of the user currently being updated
Attachments (2)
Change History (10)
#2
@
6 years ago
- Keywords reporter-feedback added
Hello @alfhen,
Welcome in WordPress trac! I know that this ticket is quite old now but I'm having difficulties to reproduce the problem.
Using wp_insert_user() without ID param and with user_nicename that already exists will create a new user with suffixed user_nicename.
Using wp_insert_user() with ID and with user_nicename that's the same as the current user's user_nicename will update the user info properly. user_nicename isn't suffixed.
In short, I can't seem to find a way to use wp_insert_user() that updates the an existing user that also suffixed the user_nicename. If you can give the exact wp_insert_user() code you use to produce the problem, it will definitely help.
Thank you!
This ticket was mentioned in Slack in #core by david.baumwald. View the logs.
6 years ago
#4
@
6 years ago
- Milestone changed from 5.4 to Future Release
With 5.4 Beta 3 landing tomorrow, this is being moved to Future Release. If any maintainer or committer feels this can be resolved in time or wishes to assume ownership during a specific cycle, feel free to update the milestone accordingly.
#5
@
6 years ago
As far as I see this can happen when the $user_login has been changed. This cannot happen in core by default ($user_login is not changeable), but can be added/enabled by a plugin.
Then the DB query will "find" a user ID as the updated $user_login hasn't been saved yet. So using the $user_login to confirm if it is the same user doesn't work. Would be better to use the user ID for that.
#6
@
6 years ago
- Keywords has-patch needs-testing needs-unit-tests added
In 39370.1.diff: Instead of the user login use the user ID when checking whether a user nicename belongs to the same user.
This ticket was mentioned in PR #9055 on WordPress/wordpress-develop by @SirLouen.
5 months ago
#7
Refreshing patch for testing.
Trac ticket: https://core.trac.wordpress.org/ticket/39370
#8
@
5 months ago
- Keywords needs-test-info added; needs-testing removed
Bug Reproduction Report
Description
❌ This report can't validate that the issue can be reproduced.
Environment
- WordPress: 6.9-alpha-60093-src
- PHP: 8.2.28
- Server: nginx/1.27.5
- Database: mysqli (Server: 8.4.5 / Client: mysqlnd 8.2.28)
- Browser: Chrome 137.0.0.0
- OS: Windows 10/11
- Theme: Twenty Twenty 2.9
- MU Plugins: None activated
- Plugins:
- Change Username 1.0.2
- Test Reports 1.2.0
Testing Instructions
- Use the code provided in supplemental artifacts somewhere you can execute it. For example, you can create a standalone file loading
wp-load.phpand hard-code a user id and a username and pass both to the function. - Execute the code twice. First time it will set the username you selected correctly.
- ❌ Second time, the nicename is preserved identically
Actual Results
- ❌ Issue can't be reproduced
Additional Notes
- The idea of @azaozz to using a plugin for changing the username was good on paper… but obviously, if they wanted to have a functional plugin, they would not be using this route. For example, this plugin, directly do the edits through SQL. For this reason, I built a little plugin to mimic this job.
- Maybe this has been solved at some point? Please review the code proposed and the steps and see if I'm missing something to report back.
- I refreshed the patch thinking that I could easily reproduce this bug, but I couldn't. In case someone gives new testing instructions, perhaps that patch could sort the potential problem.
Supplemental Artifacts
Testing base code:
function change_username( $user_id, $new_username ) {
$user_data = array(
'ID' => $user_id,
'user_login' => $new_username,
);
return wp_insert_user( $user_data );
}
$user_id = 1
$new_username = 'test-nicename'
change_username( $user_id, $new_username );
Patch with the mentioned fix