// ===== SHORTCODE BLOG FILTRABLE (paramétrable) =====
function journal_shortcode_blog_filtrable_relevanssi( $atts = array() ) {

    // 🔹 Paramètres du shortcode
    $atts = shortcode_atts(
        array(
            'post_type'  => 'post',                  // type de contenu (par défaut : articles)
            'taxonomies' => 'category,sources',      // taxonomies à afficher/filtrer
            'per_page'   => 10,                      // nb d’articles par page
        ),
        $atts,
        'blog_filtrable_relevanssi'
    );

    $post_type   = sanitize_text_field( $atts['post_type'] );
    $per_page    = max( 1, intval( $atts['per_page'] ) );
    $taxonomies  = array();

    // Liste des taxonomies à gérer, en tableau
    foreach ( explode( ',', $atts['taxonomies'] ) as $tx ) {
        $tx = trim( $tx );
        if ( $tx !== '' ) {
            $taxonomies[] = $tx;
        }
    }

    // 🔹 Terme de recherche
    $search_term = isset($_GET['bfrr_s']) ? sanitize_text_field($_GET['bfrr_s']) : '';

    // 🔹 Construction du tax_query global
    $tax_query = array();

    if ( isset($_GET['tax_query']) && is_array($_GET['tax_query']) ) {
        foreach ( $_GET['tax_query'] as $taxonomy => $terms ) {
            $terms = array_filter( array_map( 'intval', (array) $terms ) );
            if ( ! empty( $terms ) ) {
                $tax_query[] = array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'term_id',
                    'terms'    => $terms,
                    'operator' => 'IN',
                );
            }
        }
    }

    if ( count( $tax_query ) > 1 ) {
        $tax_query = array_merge( array( 'relation' => 'AND' ), $tax_query );
    }

    // --- Préparation du texte "Filtre appliqué" ---
    $filtre_applique = array();

    // Texte pour CHAQUE taxonomie déclarée dans $taxonomies
    foreach ( $taxonomies as $tx ) {
        if ( isset( $_GET['tax_query'][ $tx ] ) && is_array( $_GET['tax_query'][ $tx ] ) ) {
            $ids = array_filter( array_map( 'intval', $_GET['tax_query'][ $tx ] ) );
            if ( ! empty( $ids ) ) {
                $terms_tx = get_terms( array(
                    'taxonomy' => $tx,
                    'include'  => $ids,
                ) );
                if ( ! is_wp_error( $terms_tx ) && ! empty( $terms_tx ) ) {
                    $noms = wp_list_pluck( $terms_tx, 'name' );
                    // Label lisible : on met le nom de la taxonomie en première lettre majuscule
                    $label = ucfirst( $tx );
                    $filtre_applique[] = $label . ' : ' . implode( ', ', $noms );
                }
            }
        }
    }

    // Texte global
    if ( empty( $filtre_applique ) && empty( $search_term ) ) {
        $filtre_applique_texte = 'Aucun filtre : tous les articles';
    } else {
        $parts = array();
        if ( ! empty( $search_term ) ) {
            $parts[] = 'Texte : « ' . $search_term . ' »';
        }
        if ( ! empty( $filtre_applique ) ) {
            $parts = array_merge( $parts, $filtre_applique );
        }
        $filtre_applique_texte = 'Filtre appliqué : ' . implode( ' | ', $parts );
    }

    ob_start();

    // 🔹 FORMULAIRE
    $page_obj   = get_post(); // page actuelle
    if ( ! $page_obj ) {
        return ''; // sécurité
    }

    $form_action = get_permalink( $page_obj->ID );
    $form_action = strtok( $form_action, '?' ); // enlever query string

    echo '<form method="get" action="' . esc_url( $form_action ) . '" class="journal-arbre-form">';

    // Champ texte
    echo '<p><input type="text" name="bfrr_s" placeholder="Recherche texte (optionnel)" value="' . esc_attr( $search_term ) . '" style="width:100%; padding:6px;"></p>';

    // Arbres pour chaque taxonomie déclarée
    foreach ( $taxonomies as $tx ) {
        // On essaie de récupérer un label poli
        $tax_obj = get_taxonomy( $tx );
        $title   = $tax_obj && ! empty( $tax_obj->labels->name ) ? $tax_obj->labels->name : ucfirst( $tx );

        echo journal_afficher_arbre_taxonomie( $tx, $title );
    }

    // Bouton Rechercher (le bouton Vider est injecté par le JS en footer)
    echo '<p><input type="submit" value="Rechercher"></p>';

    echo '</form>';

    // 🔹 REQUÊTE FILTRÉE
    $paged = max(
        1,
        get_query_var( 'paged' )
            ? get_query_var( 'paged' )
            : ( isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 1 )
    );

    $args = array(
        'post_type'           => $post_type,
        'post_status'         => 'publish',
        'ignore_sticky_posts' => true,
        's'                   => $search_term,
        'paged'               => $paged,
        'posts_per_page'      => $per_page,
    );

    if ( ! empty( $tax_query ) ) {
        $args['tax_query'] = $tax_query;
    }

    $query = new WP_Query( $args );

    // Intégration Relevanssi si actif et si recherche texte
    if ( function_exists( 'relevanssi_do_query' ) && ! empty( $search_term ) ) {
        relevanssi_do_query( $query );
    }

    echo '<div class="journal-resultats">';

    // 🔹 Affichage du filtre appliqué
    echo '<p class="journal-filtre-applique">' . esc_html( $filtre_applique_texte ) . '</p>';

    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();

            echo '<article class="journal-resultat-article">';
            echo '<h3 class="journal-resultat-titre"><a href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></h3>';
            echo '<div class="journal-resultat-extrait">' . wp_kses_post( wp_trim_words( get_the_excerpt(), 30, '...' ) ) . '</div>';
            echo '</article>';
        }

        echo paginate_links( array(
            'total'   => $query->max_num_pages,
            'current' => $paged,
        ) );
    } else {
        echo '<p>Aucun article trouvé.</p>';
    }

    echo '</div>';

    wp_reset_postdata();

    // Script pour ouvrir/fermer les branches de l’arbre (inchangé)
    ?>
    <script>
    document.addEventListener("DOMContentLoaded", function() {
        document.querySelectorAll(".toggle-node").forEach(function(node) {
            node.addEventListener("click", function() {
                const subtree = this.parentNode.querySelector(".sub-tree");
                if (!subtree) return;
                if (subtree.style.display === 'none') {
                    subtree.style.display = 'block';
                    this.textContent = 'â–¼';
                } else {
                    subtree.style.display = 'none';
                    this.textContent = 'â–º';
                }
            });
        });
    });
    </script>
    <?php

    return ob_get_clean();
}
add_shortcode( 'blog_filtrable_relevanssi', 'journal_shortcode_blog_filtrable_relevanssi' );
  • bricoler/prive/blog/code-blog_filtrable_relevanssi
  • Dernière modification : 2025/11/21 23:21
  • de dpt