parent) { $parent_cat = get_category($category->parent); $context['parent_slug'] = thalim_category_color_slug($parent_cat->term_id, $parent_cat->slug); $context['active_rubrique'] = $parent_cat->term_id; } else { $context['parent_slug'] = thalim_category_color_slug($category->term_id, $category->slug); $context['active_rubrique'] = $category->term_id; } // Read filter query params $active_axe = isset($_GET['axe']) ? intval($_GET['axe']) : 0; $active_date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : ''; $active_date_to = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : ''; $context['active_axe'] = $active_axe; $context['active_date_from'] = $active_date_from; $context['active_date_to'] = $active_date_to; // Build query param string to preserve across filter links $filter_query = http_build_query(array_filter([ 'axe' => $active_axe ?: null, 'date_from' => $active_date_from ?: null, 'date_to' => $active_date_to ?: null, ])); $context['filter_query'] = $filter_query; // Build extra query args for axe/date filtering $extra_query_args = []; if ($active_axe) { $extra_query_args['meta_query'] = [[ 'key' => 'axes_thematiques', 'value' => $active_axe, 'type' => 'NUMERIC', ]]; } if ($active_date_from || $active_date_to) { $extra_query_args['thalim_event_date_filter'] = ['from' => $active_date_from, 'to' => $active_date_to]; } // Build parent categories for filter bar (with links) $all_cats = get_categories([ 'taxonomy' => 'category', 'hide_empty' => false, 'exclude' => $excluded_ids, ]); // Liens de filtre : navigation vers la page de catégorie, en conservant axe/dates $make_cat_link = function ($cat) use ($filter_query) { $link = get_category_link($cat->term_id); return $filter_query ? $link . '?' . $filter_query : $link; }; $context['filter_parents'] = thalim_archive_filter_parents($all_cats, $make_cat_link); // Children of active rubrique for catégorie filter (with links) $active_rubrique_id = $context['active_rubrique']; $is_direct = (bool) get_query_var('thalim_direct_posts'); $filter_categories = thalim_archive_filter_children($all_cats, $active_rubrique_id, $make_cat_link); // Add "Autres" entry if the active rubrique has posts directly assigned to it $has_direct_posts = $is_direct ?: thalim_rubrique_has_direct_posts($active_rubrique_id); if ($has_direct_posts && !empty($filter_categories)) { $autres_link = trailingslashit(get_category_link($active_rubrique_id)) . 'autres/'; if ($filter_query) $autres_link .= '?' . $filter_query; $filter_categories[] = thalim_archive_autres_entry($autres_link); } $context['filter_categories'] = $filter_categories; $context['active_category_id'] = $is_direct ? 'autres' : $category->term_id; // Axes thématiques for filter dropdown $axes_groups = thalim_get_axes_filter_groups(); $current_axes = $axes_groups[0]['terms'] ?? []; $context['filter_axes'] = $current_axes; $context['axe_stay_on_page'] = true; // Fetch posts for initial display $children = get_categories([ 'parent' => $category->term_id, 'taxonomy' => 'category', 'hide_empty' => true, 'exclude' => $excluded_ids, ]); // Ordre personnalisé des sous-catégories (slug => position). // Les termes absents du tableau sont placés en dernier (position 999). $subcategory_order = [ // Publications et productions 'ouvrages' => 0, 'articles' => 1, 'revues-et-collections' => 2, 'multimedia' => 3, // Manifestations scientifiques 'seminaires' => 0, 'colloques-et-journees-detudes' => 1, 'communications' => 2, 'soutenances' => 3, ]; usort($children, function($a, $b) use ($subcategory_order) { $pos_a = $subcategory_order[$a->slug] ?? 999; $pos_b = $subcategory_order[$b->slug] ?? 999; return $pos_a - $pos_b; }); $context['category_id'] = $category->term_id; $context['agenda_include_children'] = ( ! $is_direct && ! empty( $children ) ) ? 1 : 0; // Helper: move pinned posts to the front (same logic as homepage diaporamas) $sort_with_pinned = function ( $posts ) { $today = date( 'Y-m-d' ); $pinned = []; $normal = []; foreach ( $posts as $post ) { $epingle = get_post_meta( $post->ID, 'epingler_dans_la_categorie', true ); $fin = get_post_meta( $post->ID, 'date_de_fin_depinglage', true ); $active = $epingle == '1' && ( empty( $fin ) || $fin === '0000-00-00' || $fin >= $today ); if ( $active ) { $pinned[] = $post; } else { $normal[] = $post; } } return array_merge( $pinned, $normal ); }; if (!$is_direct && !empty($children)) { $context['is_parent'] = true; $context['subcategories'] = []; foreach ($children as $child) { $query_args = array_merge([ 'post_type' => 'post', 'tax_query' => [[ 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => [$child->term_id], 'include_children' => false, ]], 'posts_per_page' => 3, 'orderby' => 'date', 'order' => 'DESC', 'thalim_event_date_order' => true, ], $extra_query_args); $posts = $sort_with_pinned( Timber::get_posts($query_args) ); $context['cards'] += thalim_get_cards_data($posts); $context['subcategories'][] = [ 'term' => Timber::get_term($child), 'posts' => $posts, ]; } // Fetch posts directly in the parent category (no child category assigned) if ($has_direct_posts) { $direct_query_args = array_merge([ 'post_type' => 'post', 'tax_query' => [[ 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => [$category->term_id], 'include_children' => false, ]], 'posts_per_page' => 3, 'orderby' => 'date', 'order' => 'DESC', 'thalim_event_date_order' => true, ], $extra_query_args); $direct_posts = $sort_with_pinned( Timber::get_posts($direct_query_args) ); if (!empty($direct_posts)) { $context['cards'] += thalim_get_cards_data($direct_posts); $context['direct_posts'] = $direct_posts; $autres_link = trailingslashit(get_category_link($category->term_id)) . 'autres/'; if ($filter_query) $autres_link .= '?' . $filter_query; $context['autres_link'] = $autres_link; } } } else { $context['is_parent'] = false; $context['is_direct'] = $is_direct; // Épinglés sortis du flux principal (et exclus de la pagination AJAX par thalim_load_more_posts), // affichés dans un bloc dédié en tête. Garde l'initial et l'AJAX sur le même univers : sinon la // fenêtre de pagination se décale et le post de la couture est dupliqué. $pinned_ids = thalim_get_active_pinned_ids( $category->term_id ); $query_args = array_merge([ 'post_type' => 'post', 'tax_query' => [[ 'taxonomy' => 'category', 'field' => 'term_id', 'terms' => [$category->term_id], 'include_children' => false, ]], 'posts_per_page' => 12, 'orderby' => 'date', 'order' => 'DESC', 'thalim_event_date_order' => true, ], $extra_query_args); if ( $pinned_ids ) { $query_args['post__not_in'] = $pinned_ids; } $posts = Timber::get_posts($query_args); // Pinned posts, respecting the active axe/date filters (so a pin outside the filter doesn't show). $pinned_posts = $pinned_ids ? Timber::get_posts( array_merge([ 'post_type' => 'post', 'post_status' => 'publish', 'post__in' => $pinned_ids, 'orderby' => 'post__in', 'posts_per_page' => -1, ], $extra_query_args ) ) : []; $context['cards'] = thalim_get_cards_data($pinned_posts) + thalim_get_cards_data($posts); $context['pinned_posts'] = $pinned_posts; $context['posts'] = $posts; } // View mode toggle (?view=agenda) $view_mode = ( isset( $_GET['view'] ) && $_GET['view'] === 'agenda' ) ? 'agenda' : 'grid'; $context['view_mode'] = $view_mode; // Toggle URL (used as href fallback on the button) $toggle_base = get_category_link( $category->term_id ); $toggle_params = array_filter([ 'axe' => $active_axe ?: null, 'date_from' => $active_date_from ?: null, 'date_to' => $active_date_to ?: null, ]); if ( $view_mode === 'grid' ) { $toggle_params['view'] = 'agenda'; } // When toggling back to grid we omit ?view entirely $context['agenda_toggle_url'] = add_query_arg( $toggle_params, $toggle_base ); // Custom Pods presentation fields $cat_lang = thalim_current_language(); $pres_fr = get_term_meta( $category->term_id, 'presentation', true ) ?: ''; $pres_en = get_term_meta( $category->term_id, 'presentation_en', true ) ?: ''; $context['term_presentation'] = wpautop( wp_kses_post( ( $cat_lang === 'en' && $pres_en ) ? $pres_en : $pres_fr ) ); Timber::render('category.twig', $context);