Permítame explicarle el procesamiento de WordPress de una solicitud y un método para cambiar el comportamiento de WordPress para lograr sus objetivos en consecuencia.
Analizar la solicitud
Cuando WordPress recibe una solicitud, comienza un proceso de disección de la solicitud y la transformación en una página. El núcleo de este proceso comienza cuando se llama al método de consulta principal de WordPress WP::main()
. Esta función analiza la consulta, como se identificó correctamente, en parse_request()
(en includes/class-wp.php
). Allí, WordPress intenta hacer coincidir la URL con una de las reglas de reescritura . Cuando la URL coincide, crea una cadena de consulta de las partes de la URL y codifica estas partes (todo entre dos barras) usando urlencode()
, para evitar que los caracteres especiales como &
ensucien la cadena de consulta. Es posible que estos caracteres codificados le hayan hecho pensar que el problema residía allí, pero en realidad se convierten en sus caracteres "reales" correspondientes al analizar la cadena de consulta.
Ejecutando la consulta asociada con la solicitud
Después de que WordPress haya analizado la URL, configura la clase de consulta principal, WP_Query
, que se realiza en el mismo método main()
de la clase WP
. La base de WP_Query
se puede encontrar en su método get_posts()
, donde todos los argumentos de consulta se analizan y sanean y la consulta SQL real se construye (y, finalmente, se ejecuta).
En este método, en la línea 2730, se ejecuta el siguiente código:
$q['name'] = sanitize_title_for_query( $q['name'] );
Esto desinfecta la publicación para recuperarla de la tabla de publicaciones. La información de depuración de salida dentro del bucle muestra que aquí es donde reside el problema: su nombre de publicación, my-permalink~
, se transforma en my-permalink
, que luego se usa para recuperar la publicación de la base de datos.
La función de desinfección del título de la entrada
La función sanitize_title_for_query
llama a sanitize_title
con los parámetros adecuados, que procede a desinfectar el título. Ahora, el núcleo de esta función es aplicar el filtro sanitize_title
:
$title = apply_filters( 'sanitize_title', $title, $raw_title, $context );
Este filtro tiene, en WordPress nativo, una única función asociada: sanitize_title_with_dashes
. He escrito una amplia descripción de lo que hace esta función, que se puede encontrar aquí . En esta función, la línea que está causando tu problema es
$title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
Esta línea elimina todos los caracteres excepto los caracteres alfanuméricos, espacios, guiones y guiones bajos.
Resolviendo tu problema
Entonces, básicamente hay una sola manera de resolver su problema: eliminar la función sanitize_title_with_dashes
del filtro y reemplazarla con su propia función. En realidad, esto no es tan difícil de hacer, pero :
- Cuando WordPress cambia el proceso interno de desinfección de títulos, esto tendrá efectos importantes en su sitio web.
- Es posible que otros complementos que se enganchen en este filtro no manejen correctamente la nueva funcionalidad.
-
Lo más importante : WordPress usa el resultado de la función sanitize_title
directamente en la consulta SQL en esta línea:
$where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
Si alguna vez consideras cambiar el filtro, ¡asegúrate de escapar correctamente del título antes de que se use en la consulta!
Conclusión: la solución de su problema no es necesaria en lo que respecta a la seguridad, pero si desea hacerlo, reemplace sanitize_title_with_dashes
con su propia funcionalidad y preste atención al escape de SQL.
NB: todos los nombres de archivos y números de línea se corresponden con los archivos de WordPress 4.4.2.