En WordPress dentro de cada usuario, podemos grabar por defecto una serie de datos en su perfil: nombre, apellidos, URL, email, etc. algunos de estos datos de base se guardan en la tabla de metadatos de usuarios, como el nombre o los apellidos; y otros como el email o la URL asociada se guardan en la tabla de usuarios (la wp_users si usamos el prefijo estándar).
Al estar la URL en la tabla de usuarios, no tenemos la flexibilidad de cualquier metadato. Los metadatos están definidos como datos de tipo LONGTEXT así que en un metadato podemos meter datos increíblemente grandes, hasta 4GB (cosa no del todo recomendable), pero en este caso al estar definido como un campo de la tabla usuarios nos tenemos que ceñir al tamaño máximo definido al crear la tabla: 100 caracteres.
Pues justo el otro día necesitaba guardar URL de usuarios de más de 100 caracteres, porque es un directorio de agentes inmobiliarios y usaban ese campo para poder relacionar una URL personal de cada uno y en algunos casos eran URLs realmente largas y esta limitación hacía que fallara la actualización de usuarios.
Alterar la tabla de usuarios
Lo primero que debemos hacer es usando phpMyAdmin o cualquier otro cliente de MySQL, alterar la tabla de usuarios para que el campo user_url pueda soportar más caracteres, por ejemplo un VARHCAR de 256 caracteres en lugar del VARCHAR de 100 original.
Esto es algo que no debe hacerse, pero literalmente aquí no tenemos otra posibilidad y encima la parte positiva es que hasta que en una actualización del núcleo de WordPress no haya un ALTER TABLE que toque esta parte, realmente improbable, este cambio será indefinido.
Sortear la limitación que impone el núcleo
La limitación de la base de datos, va de la mano con una limitación que viene incluida en el núcleo y que se asegura de que el valor no tenga más de 100 caracteres, para evitar pérdida de información cuando sea más grande el valor.
Como a priori, la tabla no puede cambiarse, no existe un filtro sencillo para hacerlo. Así que hay que usar dos hooks diferentes.
El primero:
add_filter( 'pre_user_url', function( $user_url ){ if ( mb_strlen( $user_url ) > 100 ) { set_transient( 'usr_too_long_bypass', $user_url, 10 ); } return mb_substr( $user_url, 0, 99 ); } );
Esta primera función hace dos cosas:
- si la URL tiene más de 100 caracteres, guarda el valor de la URL original en un transient de tipo temporal (solo va a existir 10 segundos para asegurarnos de que no choca con otra ejecución en paralelo)
- devuelve la URL con un máximo de 99 caracteres, recortándola, para evitar problemas en los chequeos posteriores
El segundo, que recupera el dato cuando hace falta:
add_filter( 'wp_pre_insert_user_data', function( $data ){ $usr_too_long_bypass = get_transient( 'usr_too_long_bypass' ); if( empty( $usr_too_long_bypass ) ) return $data; $data['user_url'] = $usr_too_long_bypass; return $data; } );
Este básicamente justo antes de hacer la inserción en la base de datos, comprueba si existe ese transient temporal y si existe, es el que guarda en el array que se va a guardar.