¿Cómo cambiar programáticamente el nombre de usuario (user_login)?
Como se indica en el título, ¿cómo cambiar programáticamente el nombre de usuario?
Quería usar la función wp_insert_user, pero parece que al actualizar el usuario actual, no cambia su nombre de usuario. ¿Debería usar $wpdb->update para eso? Si es así, ¿cómo se vería el código para cambiar el nombre de usuario? ¿Qué consecuencias tendría cambiar el nombre de usuario, dado que la API de WordPress no permite cambiar nombres de usuario?
Estaba seguro de que wp_update_user() debería hacer esto.
Incluso recibe user_login como parámetro, pero parece que lo ignora cuando lo estableces.
Así que este código parece correcto, pero no funciona como desearías :( :
wp_update_user(
['ID' => $user_id, 'user_login' => $new_login]
);
Tienes que ejecutar una consulta SQL personalizada para actualizar user_login:
global $wpdb;
$wpdb->update(
$wpdb->users,
['user_login' => $new_user_login],
['ID' => $user_id]
);
Funciona correctamente y no creo que tenga consecuencias graves, porque WordPress usa los ID de usuario para asignar publicaciones/comentarios (y demás) al usuario.
El único problema que se me ocurre es que si este usuario está actualmente conectado, se cerrará su sesión después de cambiar el user_login.
En realidad no, revisa las notas de esta función (así como el código): Ten en cuenta que no podemos cambiar los nombres de usuario a través de esta función, de hecho los nombres de usuario no se pueden cambiar desde el panel de administración ya que WordPress no permite que se actualicen los nombres de usuario.
Mateusz Hajdziony
¡Gracias, funciona genial! No hay problema con los usuarios conectados, ya que solo permito el cambio de nombre de usuario para usuarios desconectados (activación de cuenta por correo electrónico).
Mateusz Hajdziony
@pogoking Algo que podrías considerar es que los enlaces permanentes de usuario o autor podrían romperse después de permitir que los usuarios cambien sus nombres de usuario si los enlaces permanentes "bonitos" están habilitados, por lo que podrías necesitar tomar medidas para compensar eso.
Ahmad M
@AhmadM Gracias Ahmad, pero como mencioné antes - los usuarios antes de la activación de su cuenta no aparecerán listados en ningún lugar, así que los enlaces permanentes no son un problema. ¡Gracias por la advertencia de todos modos!
Mateusz Hajdziony
@Mauro Bueno, si ejecutas este código dentro de una función, entonces sí - por supuesto. También tienes que declarar $user_id y $new_login, pero es obvio y no está relacionado con WP, ¿verdad?
Krzysiek Dróżdż
Publicación antigua, pero estoy pensando en hacer esto mismo, valdría la pena verificar que no haya otro usuario con el mismo user_login registrado en tu sitio, ya que el formulario de inicio de sesión obviamente usa este valor para encontrar cuentas y coincidir con los hashes de contraseñas.
haxxxton
@haxxxton Tuve el mismo pensamiento, ! username_exists( sanitize_user( $new_user_login ) ); hará exactamente eso.
amarinediary
Sugeriría agregar ya sea update_user_caches(get_user_by('id', $user_id)) o clean_user_cache($user_id) después de esa actualización si estás usando wp_object_cache. He descubierto por las malas que modificar directamente los registros de usuario en WP puede llevar a comportamientos muy inesperados de otra manera.
Dan B
Además de la respuesta de Krzysiek Dróżdż.
Si no deseas cerrar la sesión de los usuarios después de cambiar user_login, necesitas hacer lo siguiente para mantener al usuario conectado con los nuevos datos:
clean_user_cache($user->ID); // Limpiar caché del usuario
wp_clear_auth_cookie(); // Eliminar cookie de autenticación actual
wp_set_current_user($user->ID); // Establecer usuario actual
wp_set_auth_cookie($user->ID, true); // Crear nueva cookie de autenticación
update_user_caches($user); // Actualizar cachés del usuario
Debes usar el filtro para modificar el $data cuando se actualice el usuario, no puedes actuar con el action al que normalmente te engancharías en una actualización de usuario.
También debes implementar varias de las medidas de seguridad y validación que WordPress aplica en su código dentro de tu nueva función.
Lo que puedes hacer:
- Engancharte al filtro
wp_pre_insert_user_data. Asegúrate de hacerlo solo con los permisos correctos:add_filter( 'wp_pre_insert_user_data', 'prefix_change_user_login', 10, 4 ); - Ahora crea una función
prefix_change_user_logindonde obtengas el$data, eluser_logindel$_POSTy lo pases por una serie de validaciones y saneamientos (ver https://github.com/WordPress/wordpress-develop/blob/bb27ffce6c3b10738008f9a054782945a0744960/src/wp-includes/user.php#L2076-L2498 para más detalles) - Además, por supuesto, tendrás que permitir la edición real del campo de inicio de sesión del usuario en la pantalla de Editar Usuario del Administrador de WP, o pasar ese valor de alguna otra manera a tu código.
Un ejemplo de dicha función:
/**
* Actualiza el nombre de inicio de sesión del usuario
*
* @since x.x.x
* @param array $data {
* Valores y claves para el usuario.
*
* @type string $user_login El inicio de sesión del usuario. Solo incluido si $update == false
* @type string $user_pass La contraseña del usuario.
* @type string $user_email El email del usuario.
* @type string $user_url La URL del usuario.
* @type string $user_nicename El nombre "bonito" del usuario. Por defecto una versión segura para URL del inicio de sesión
* @type string $display_name El nombre para mostrar del usuario.
* @type string $user_registered Timestamp MySQL que describe el momento en que el usuario se registró. Por defecto
* el timestamp UTC actual.
* }
* @param bool $update Si el usuario se está actualizando en lugar de crearse.
* @param int|null $user_id ID del usuario a actualizar, o NULL si el usuario se está creando.
* @param array $userdata El array crudo de datos pasado a wp_insert_user().
*/
function prefix_change_user_login( $data, $update, $user_id, $userdata ){
// ¡¡¡NO OLVIDES AÑADIR AQUÍ LA VALIDACIÓN CORRECTA DE NONCE Y REFERER!!!!
$sanitized_user_login = sanitize_user( wp_unslash( $_POST['user_login'] ), true );// En nuestro caso obtenemos el nuevo inicio de sesión del valor POST del formulario en el Admin de WP. ¡Si esto es diferente en tu caso, adáptalo!
/**
* Filtra un nombre de usuario después de ser saneado.
*
* Este filtro se llama antes de que el usuario sea creado o actualizado.
*
* @since 2.0.3
*
* @param string $sanitized_user_login Nombre de usuario después de ser saneado.
*/
$pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login );
$illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );
// Elimina cualquier carácter no imprimible del string de inicio de sesión para ver si terminamos con un nombre vacío.
$user_login = trim( $pre_user_login );
if ( empty( $user_login )
|| mb_strlen( $user_login ) > 60
|| username_exists( $user_login )
|| in_array( strtolower( $user_login ), array_map( 'strtolower', $illegal_logins ), true )
) {
return $data;
}
$data['user_login'] = $user_login;
$user_nicename = sanitize_title( mb_substr( $user_login, 0, 50 ) );// ¿Quién sabe qué habían fumado los desarrolladores de WP cuando decidieron hacer el nicename 10 caracteres más corto que el nombre de inicio de sesión?
global $wpdb;
$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 permite 50 chars. Resta uno por el guión, más la longitud del sufijo.
$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;
}
$data['user_nicename'] = $user_nicename;
return $data;
}
Esto te permitirá actualizar el nombre de inicio de sesión del usuario, y también actualizará el "nicename" del usuario (usado en archivos por ejemplo).
Por supuesto, esto aún requiere que "habilites" la edición en el área de Administración de WP, pero eso no debería ser muy difícil.
Nota que si ocurre algún error en el código anterior (el nombre de usuario ya existe, etc.) NO se muestra ningún error, en su lugar, el usuario simplemente se actualiza y vuelve al estado anterior.
Nota que, aunque este código está probado, depende de ti lo que hagas con él, y hay RAZONES por las que wp no permite actualizar el inicio de sesión del usuario.