Comprobar si se está mostrando una página de archivo de taxonomía personalizada

22 nov 2015, 08:41:21
Vistas: 33.4K
Votos: 6

Tengo un tipo de entrada personalizada llamado 'advert' y una taxonomía personalizada relacionada llamada 'advert_category', creados por un plugin de terceros. Ejecuto en un plugin una declaración if que debe establecer (como espero) un diseño de tema específico para anuncios individuales (example.com/advert/un-anuncio-individual.html) y para páginas de archivo de taxonomía personalizada (example.com/advert-category/servicios/), pero la segunda condición is_tax( 'advert_category' ) no funciona. ¿Qué está mal aquí?

Mi código:

function my_advert_single_template( ) {
    global $post;
    global $wpgo_global_column_layout;

    if ( $post->post_type == 'advert' || is_tax( 'advert_category' ) ) {
        $wpgo_global_column_layout = "2-col-l";
    }
}
add_filter( 'single_template', 'my_advert_single_template' );

Así es como están registrados el tipo de entrada personalizada y la taxonomía personalizada:

// registrar tipo de entrada y taxonomía para permitir la inserción de datos predeterminados
register_post_type( 'advert' ); 
register_taxonomy( 'advert_category', 'advert' );

$hid = wp_insert_post(array(
    'post_type' => 'page',
    'post_status' => 'publish',
    'post_title' => 'Adverts',
    'comment_status' => 'closed',
    'ping_status' => 'closed',
    'post_content' => "[adverts_list]"
));

$aid = wp_insert_post(array(
    'post_type' => 'page',
    'post_status' => 'publish',
    'post_title' => 'Add',
    'post_parent' => $hid,
    'comment_status' => 'closed',
    'ping_status' => 'closed',
    'post_content' => "[adverts_add]"
));

$mid = wp_insert_post(array(
    'post_type' => 'page',
    'post_status' => 'publish',
    'post_title' => 'Manage',
    'post_parent' => $hid,
    'comment_status' => 'closed',
    'ping_status' => 'closed',
    'post_content' => "[adverts_manage]"
));

wp_insert_term(
    'Default',
    'advert_category'
);
2
Comentarios

Estás usando tu filtro incorrectamente. Esta es información muy importante que debería haber estado en tu publicación original. No estoy siendo grosero, pero es realmente frustrante si damos vueltas en círculos solo para descubrir que información muy importante fue omitida

Pieter Goosen Pieter Goosen
22 nov 2015 09:09:34

Por favor, mueve la solución en la que trabajaste a una respuesta separada. :) Eso está más en línea con la mecánica del sitio.

Rarst Rarst
22 nov 2015 14:40:13
Todas las respuestas a la pregunta 2
5
10

Tienes muchos problemas aquí:

  • pre_get_posts no es el hook correcto para establecer plantillas. pre_get_posts se usa para alterar las variables de consulta justo antes de que se construya el SQL para ejecutar la consulta principal.

  • Un filtro debe siempre devolver algo. No hacer esto puede causar comportamientos inesperados, y olvidarse de esto puede hacerte perder horas depurando el problema.

  • Usar variables globales para controlar características del tema o almacenar cualquier tipo de datos es una mala práctica y no es seguro. WordPress ya tiene un gran desorden con las variables globales, especialmente en convenciones de nombres. Solo fíjate cómo los principiantes (que no conocen WordPress) usan variables como $post y $posts como variables locales. Estas son variables globales nativas de WordPress, y usarlas como variables locales rompe sus valores.

    Debido a esto, algo en la página falla, no hay errores, y te quedas atascado intentando depurar algo que has roto sin saberlo. Las variables globales son puro mal y deberías evitarlas. Imagina que usas la variable $wpgo_global_column_layout para los argumentos de una consulta personalizada, romperás el valor de la plantilla que necesita establecerse. Tu plantilla no se carga porque el valor de $wpgo_global_column_layout no se reconoce como un nombre de plantilla válido, y no sabes por qué tu plantilla no se carga aunque tu código es 100% correcto.

  • is_tax() es la comprobación incorrecta para ver si un post tiene un término específico. is_tax() simplemente verifica si estás en un archivo de taxonomía. Deberías usar has_term(), que hace exactamente eso: comprobar si un post tiene un término específico.

  • Si necesitas establecer una plantilla para una página de taxonomía, single_template es el hook incorrecto. Deberías usar el hook taxonomy_template o el filtro más genérico template_include.

  • En la línea $post->post_type == 'advert' || is_tax( 'advert_category' ), sospecho que estás usando el operador incorrecto. Deberías usar el operador AND. No voy a explicar esto aquí porque ya lo hice aquí. Ten en cuenta que, con la configuración actual, cada vez que veas un post del tipo advert, tu condición devolverá verdadero y se ejecutará, independientemente de si la segunda condición (is_tax( 'advert_category' )) falla o no.

  • Si necesitas seleccionar un término según su relación padre/hijo, simplemente debes verificar la propiedad $parent del objeto término. Un valor de 0 significa que el término es padre, cualquier otro valor significa que es hijo/nieto/bisnieto/etc.

Vamos a dejar de lado las variables globales malas y establecer las plantillas correctamente. No sé exactamente cómo tu tema establece plantillas a través de $wpgo_global_column_layout, pero lo siguiente debería funcionar con prioridad. He comentado el código para que sea fácil de seguir.

PARA PÁGINAS INDIVIDUALES:

add_filter( 'single_template', function ( $template )
{
    // Elimina todos los filtros del filtro actual
    remove_all_filters( current_filter(), PHP_INT_MAX );
    
    /**
     * Obtiene el objeto del post actual. Usamos get_queried_object
     * porque es más seguro que usar $post
     *
     * @see https://wordpress.stackexchange.com/q/167706/31545
     */
    $current_post = get_queried_object();
    
    // Verifica si el post actual pertenece al tipo 'advert', si no, salimos
    if ( $current_post->post_type !== 'advert' )
        return $template;
    
    // Obtiene los términos del post
    $terms = get_the_terms( 
        $current_post, // Objeto del post actual
        'advert_category' // Nombre de la taxonomía
    );
    
    // Si $terms está vacío o devuelve un objeto WP_Error, salimos
    if ( !$terms || is_wp_error( $terms ) )
        return $template;
    
    /**
     * Obtiene el primer término y verifica si es de nivel superior o no.
     * Carga la plantilla según el valor de parent
     *
     * NOTA: Esto solo funciona correctamente si el post tiene un solo término
     */
    if ( $terms[0]->parent == 0 ) {
        $part = 'single-parent.php'; // Establece la plantilla para términos padre
    } else {
        $part = 'single-child.php'; // Establece la plantilla para términos hijo
    }
    
    // Verifica si la plantilla existe, si no, salimos
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // Hemos llegado a este punto, establecemos nuestra plantilla personalizada
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

PARA PÁGINAS DE TAXONOMÍA:

add_filter( 'taxonomy_template', function ( $template )
{
    // Elimina todos los filtros del filtro actual
    remove_all_filters( current_filter(), PHP_INT_MAX );

    // Obtiene el objeto del término actual. Usamos get_queried_object
    $current_term = get_queried_object();
    
    // Si el término actual no pertenece a 'advert_category', salimos
    if ( $current_term->taxonomy !== 'advert_category' )
        return $template;
    
    // Verifica si el término es de nivel superior o no y establece la plantilla
    if ( $current_term->parent == 0 ) {
        $part = 'taxonomy-parent.php'; // Plantilla para términos padre
    } else {
        $part = 'taxonomy-child.php'; // Plantilla para términos hijo
    }
    
    // Verifica si la plantilla existe, si no, salimos
    $locate_template = locate_template( $part );
    if ( !$locate_template ) 
        return $template;
    
    // Hemos llegado a este punto, establecemos nuestra plantilla personalizada
    return $template = $locate_template;
}, PHP_INT_MAX + 1 );

Solo una nota, todo el código no ha sido probado, así que asegúrate de probarlo localmente primero con el modo de depuración activado. También modifica y adapta el código según tus necesidades.

22 nov 2015 08:49:44
Comentarios

No funciona :(. Según FunctionReference/has term: "Comprueba si la publicación actual tiene alguno de los términos dados", entonces, ¿esto solo funcionará en publicaciones individuales?

Iurie Iurie
22 nov 2015 08:55:45

Eso funciona en páginas individuales, ¿cuál es el problema? Decir no funciona es muy vago

Pieter Goosen Pieter Goosen
22 nov 2015 08:57:08

Me refiero a que la página 'example.com/advert-category/services/' no cambia la plantilla.

Iurie Iurie
22 nov 2015 09:00:07

Revisa mi actualización. Espero que sea lo que estabas buscando

Pieter Goosen Pieter Goosen
22 nov 2015 18:44:43

Pieter, como siempre, ¡una excelente respuesta! ¡Muchas gracias!

Iurie Iurie
22 nov 2015 21:27:20
2

Tienes dos problemas en tu función:

  • Falta un argumento en el filtro "single_template" y por lo tanto el filtro no está devolviendo lo que debería.
  • También estás llamando a has_term() sin especificar la taxonomía en la que estás intentando buscar.

Revisa esto:

function my_advert_single_template( $single_template ) {
    global $post;
    global $wpgo_global_column_layout;

    if ( $post->post_type == 'advert' || has_term( 'util-categorie', 'advert_category' ) ) {
        $wpgo_global_column_layout = "2-col-l";
    }

    return $single_template;
}
add_filter( 'single_template', 'my_advert_single_template' );
22 nov 2015 10:27:25
Comentarios

Corregí algunos errores en mi código antiguo (era una variante de prueba, lo siento, parece que aún no estaba despierto). Y probé tu función, pero no funciona para páginas de taxonomías personalizadas, solo para publicaciones individuales. Encontré una solución (mira la actualización).

Iurie Iurie
22 nov 2015 10:45:56

¡No hay problema! Me alegra que lo hayas resuelto.

Luis Sanz Luis Sanz
23 nov 2015 13:04:41