Incluir y excluir taxonomías en archivos y feeds con 'pre_get_posts' en WordPress
¿Qué estoy intentando hacer?
Mi blog utiliza una taxonomía personalizada llamada edition
con términos como us-canada
(6), eu
(7) e india
(8) -- slug del término (ID).
Quiero asegurarme de que los posts no asignados a ninguna 'edition' específica se muestren bajo todos los términos (es decir, si un post no está asignado a usa, europa o india, aparecerá en las páginas de archivo de todos estos términos).
¿Qué he intentado?
Aquí está el código de ejemplo relacionado con uno de los términos, que debería darte una idea de lo que estoy intentando hacer exactamente, y lo que podría estar haciendo mal.
add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive($query) {
if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query',
array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => array( 1, 2, 4, 5 )
),
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 7, 8 ),
'operator' => 'NOT IN'
)
)
);
}
return $query;
}
¿Qué está mal? El código mencionado no funciona (otros que he probado: código-1, código-2), no cambia nada. Tampoco hay ningún error de depuración.
Entonces, ¿qué podría estar haciendo mal?
ADEMÁS, para asegurarme de que los cambios también se apliquen a los feeds de estos términos, reemplacé la línea relevante en el código mencionado con esto:
function better_editions_archive($query) {
if ( ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) || ( $query->is_feed() && $query->is_tax( 'edition', 6 ) ) ) {
Pero eso comienza a redirigir los feeds de los términos de vuelta a los archivos de los términos. Es decir, con la función en su lugar, example.com/edition/usa/feed/
redirige de vuelta a example.com/edition/usa/
.
De nuevo, no tengo idea de qué podría estar haciendo mal.
ACTUALIZACIÓN: ¿Qué ha funcionado para mí? (Pero...)
add_filter( 'pre_get_posts', 'better_editions_archive' );
function better_editions_archive( $query ) {
if ( $query->is_tax( 'edition', 6 ) && $query->is_main_query() ) {
$args = array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => array( 1, 2, 4, 5 )
),
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 7, 8 ),
'operator' => 'NOT IN'
)
)
);
$query->query_vars = $args;
}
return $query;
}
Funciona, pero el problema es que tuve una extensa discusión con un desarrollador de WordPress experto, y me dijo esto (puedes seguir la conversación completa aquí, pero es muy larga):
Y luego estás asignando este array como
query_vars
. Ahora bien,query_vars
es un objeto bastante grande. Y básicamente estás sobrescribiendo los datos que hay ahí y solo agregando tus personalizados. Esto significa que 'desconfiguras' todo lo que se agrega por defecto.
Básicamente me aconsejó no usar esta solución, y en su lugar usar el método $query->set();
.
Pero como puedes ver más arriba, no pude hacer que el otro funcionara. Así que estoy aquí para ver si alguien puede decirme qué estoy haciendo mal, en un lenguaje menos técnico.

Lo intentaré de nuevo.
Lo siguiente debería modificar la consulta principal, de modo que incluya en su bucle cualquier publicación que no pertenezca a ningún término de la taxonomía personalizada Edition.
add_filter('pre_get_posts','mejorar_archivo_ediciones');
function mejorar_archivo_ediciones( $query ) {
if ( $query->is_tax( 'edition' ) && $query->is_main_query() ) {
$terms = get_terms( 'edition', array( 'fields' => 'ids' ) );
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query', array(
'relation' => 'OR',
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => $terms,
'operator' => 'NOT IN'
)
) );
}
return $query;
}

Acabo de intentar eso. No cambió nada. Tampoco hay errores de depuración/sugerencias. Gracias por intentarlo. :)

Como método de depuración, puedes probar print_r($query) en tu primer código de ejemplo. En alguna parte del resultado debería aparecer el SQL generado. Añádelo aquí, podría ser útil.

¿Sí, la última versión de WordPress (¡siempre!)? Y para el debug, ¿quieres que reemplace return $query;
con print_r($query);
? ¿Es eso lo que quieres que haga?

Si es así, esto es lo que obtuve: http://paste.kde.org/694496/ -- ¿Eso dice algo? (No lo entendí).

¡Oh Dios mío, eso funcionó! Y sin más cambios también está modificando los feeds de los términos de taxonomía personalizados, tal como lo hace con los archivos de los términos (que, por supuesto, es lo que quiero). ¿Así es como funciona o estoy soñando? ¿No necesitamos agregar algo como ( is_feed() && is_.... )
?

Nota para mí: La respuesta de @vancoder es básicamente una versión mejorada (y automatizada) de esto:
add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive($query) {
if ( $query->is_tax( 'edition') && $query->is_main_query() ) {
$query->set( 'post_type', array( 'post' ) );
$query->set( 'tax_query',
array(
array(
'taxonomy' => 'edition',
'field' => 'id',
'terms' => array( 6, 7, 8 ),
'operator' => 'NOT IN'
)
)
);
}
return $query;
}
(Lo que hace el código) Si es el archivo para cualquier término que pertenezca a la taxonomía personalizada 'edition
', entonces...
El código no interfiere con la función por defecto de las páginas de archivo de los términos, es decir, los posts asignados a un término de la taxonomía personalizada '
edition
' se mostrarán (como es habitual) en el archivo del término correspondiente.Pero si un post no está asignado a ninguno de los términos dados de la taxonomía personalizada (ver
'terms' => array( 6, 7, 8 )
y'operator' => 'NOT IN'
), entonces muestra dichos posts en las páginas de archivo de todos los términos de la taxonomía personalizada.El código también afecta a los feeds de dichos términos, y por lo tanto, los feeds reflejan el contenido de las páginas de archivo, que es justo lo que necesito. En caso de que no quieras que los feeds se vean afectados, es decir, si quieres que los cambios solo se apliquen a las páginas de archivo, reemplaza el IF con esto:
if ( $query->is_tax( 'edition') && $query->is_main_query() && ! $query->is_feed() ) {
