WordPress.org

Make WordPress Core

Opened 4 years ago

Last modified 9 months ago

#39370 new defect (bug)

wp_insert_user() appends suffix to nicename when updating already existing user

Reported by: alfhen Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 4.6.1
Component: Users Keywords: reporter-feedback has-patch needs-testing needs-unit-tests
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)

39370.patch (636 bytes) - added by alfhen 4 years ago.
Patch with the mentioned fix
39370.1.diff (1.4 KB) - added by azaozz 9 months ago.

Download all attachments as: .zip

Change History (8)

@alfhen
4 years ago

Patch with the mentioned fix

#1 @chanthaboune
12 months ago

  • Milestone changed from Awaiting Review to 5.4

#2 @donmhico
10 months 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.


9 months ago

#4 @davidbaumwald
9 months 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 @azaozz
9 months 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.

Last edited 9 months ago by azaozz (previous) (diff)

@azaozz
9 months ago

#6 @azaozz
9 months 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.

Would be great if this can be tested with existing code/plugins that allow changing of $user_login.

Last edited 9 months ago by azaozz (previous) (diff)
Note: See TracTickets for help on using tickets.