Files
thalim-theme/inc/event-dates.php

149 lines
6.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Tri et filtre par date d'événement (date_de_debut / datetime / post_date)
* + helpers de listes : groupes d'axes pour les filtres, posts épinglés.
*
* Activation sur un WP_Query / Timber::get_posts :
* 'thalim_event_date_order' => true
* 'thalim_event_date_filter' => ['from' => 'Y-m-d', 'to' => 'Y-m-d']
*/
// Event date ordering: COALESCE(date_de_debut, datetime, post_date)
// Activated by adding 'thalim_event_date_order' => true to WP_Query args.
add_filter('posts_join', function ($join, $query) {
if (!$query->get('thalim_event_date_order') && !$query->get('thalim_event_date_filter')) return $join;
global $wpdb;
$join .= " LEFT JOIN {$wpdb->postmeta} AS thalim_ed"
. " ON (thalim_ed.post_id = {$wpdb->posts}.ID"
. " AND thalim_ed.meta_key = 'date_de_debut') ";
$join .= " LEFT JOIN {$wpdb->postmeta} AS thalim_dt"
. " ON (thalim_dt.post_id = {$wpdb->posts}.ID"
. " AND thalim_dt.meta_key = 'datetime') ";
return $join;
}, 10, 2);
add_filter('posts_orderby', function ($orderby, $query) {
if (!$query->get('thalim_event_date_order')) return $orderby;
global $wpdb;
$valid = "IS NOT NULL AND %s != '' AND %s NOT LIKE '0000-00-00%%'";
return "CASE"
. " WHEN thalim_ed.meta_value " . sprintf($valid, 'thalim_ed.meta_value', 'thalim_ed.meta_value') . " THEN thalim_ed.meta_value"
. " WHEN thalim_dt.meta_value " . sprintf($valid, 'thalim_dt.meta_value', 'thalim_dt.meta_value') . " THEN thalim_dt.meta_value"
. " ELSE {$wpdb->posts}.post_date"
. " END DESC, {$wpdb->posts}.ID DESC"; // tiebreaker déterministe: sans lui, les dates ex-æquo paginent de façon instable entre les requêtes séparées (initial vs AJAX)
}, 10, 2);
// Event date range filter: uses same CASE logic as ordering so date_de_debut/datetime take priority over post_date.
// Activated by adding 'thalim_event_date_filter' => ['from' => $date_from, 'to' => $date_to] to WP_Query args.
add_filter('posts_where', function ($where, $query) {
$filter = $query->get('thalim_event_date_filter');
if (empty($filter) || (!isset($filter['from']) && !isset($filter['to']))) return $where;
global $wpdb;
$effective = "CASE"
. " WHEN thalim_ed.meta_value IS NOT NULL AND thalim_ed.meta_value != '' AND thalim_ed.meta_value NOT LIKE '0000-00-00%' THEN thalim_ed.meta_value"
. " WHEN thalim_dt.meta_value IS NOT NULL AND thalim_dt.meta_value != '' AND thalim_dt.meta_value NOT LIKE '0000-00-00%' THEN thalim_dt.meta_value"
. " ELSE {$wpdb->posts}.post_date"
. " END";
if (!empty($filter['from'])) {
$from = $wpdb->prepare('%s', $filter['from']);
$where .= " AND ({$effective}) >= {$from}";
}
if (!empty($filter['to'])) {
$to = $wpdb->prepare('%s', $filter['to'] . ' 23:59:59');
$where .= " AND ({$effective}) <= {$to}";
}
return $where;
}, 10, 2);
// Return the IDs of posts currently pinned ("épinglé dans la catégorie") in a given category.
// A pin is active if epingler_dans_la_categorie == 1 AND date_de_fin_depinglage is empty/0000-00-00/future.
// Shared by category.php (pull them out of the main flow) and the AJAX handler (exclude them from
// pagination) so both sides stay in sync — a mismatch shifts the page boundary and dupes posts.
function thalim_get_active_pinned_ids( $category_id ) {
if ( ! $category_id ) return [];
$today = date( 'Y-m-d' );
$pinned_query = new WP_Query([
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'fields' => 'ids',
'no_found_rows' => true,
'tax_query' => [[
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => [ $category_id ],
'include_children' => false,
]],
'meta_query' => [[
'key' => 'epingler_dans_la_categorie',
'value' => '1',
]],
]);
$pinned_ids = [];
foreach ( $pinned_query->posts as $pid ) {
$fin = get_post_meta( $pid, 'date_de_fin_depinglage', true );
if ( empty( $fin ) || $fin === '0000-00-00' || $fin >= $today ) {
$pinned_ids[] = $pid;
}
}
return $pinned_ids;
}
// ── Axes thématiques groupés pour les filtres ──────────────────
// Retourne un tableau de groupes triés par période (plus récent en premier,
// "passés" toujours en dernier). Chaque terme contient id, name, ordre.
function thalim_get_axes_filter_groups() {
$terms = get_terms( [ 'taxonomy' => 'axe_thematique', 'hide_empty' => false ] );
$axes_map = [];
foreach ( $terms as $term ) {
$debut = trim( get_term_meta( $term->term_id, 'annee_debut', true ) );
$fin = trim( get_term_meta( $term->term_id, 'annee_fin', true ) );
if ( $debut && $fin ) {
$key = $debut . '-' . $fin;
$label = $debut . ' ' . $fin;
} else {
$key = 'passes';
$label = 'Axes antérieurs';
}
if ( ! isset( $axes_map[ $key ] ) ) {
$axes_map[ $key ] = [ 'label' => $label, 'debut' => intval( $debut ), 'terms' => [] ];
}
$ordre = trim( get_term_meta( $term->term_id, 'ordre_daffichage', true ) );
$axes_map[ $key ]['terms'][] = [
'id' => $term->term_id,
'name' => $term->name,
'ordre' => $ordre !== '' ? intval( $ordre ) : null,
'href' => get_term_link( $term ),
];
}
// Tri des groupes : plus récent en premier, passés toujours en dernier
uasort( $axes_map, function ( $a, $b ) {
if ( $a['label'] === 'Axes antérieurs' ) return 1;
if ( $b['label'] === 'Axes antérieurs' ) return -1;
return $b['debut'] - $a['debut'];
} );
// Tri des termes dans chaque groupe : ordre_daffichage d'abord, puis alphabétique
foreach ( $axes_map as &$group ) {
usort( $group['terms'], function ( $a, $b ) {
$a_has = $a['ordre'] !== null;
$b_has = $b['ordre'] !== null;
if ( $a_has && $b_has ) return $a['ordre'] - $b['ordre'];
if ( $a_has ) return -1;
if ( $b_has ) return 1;
return strcmp( $a['name'], $b['name'] );
} );
}
unset( $group );
return array_values( $axes_map );
}