225 lines
8.7 KiB
PHP
225 lines
8.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Build card display data for a single post.
|
|
* Resolves Pods relationship fields (stored as multiple meta rows) into
|
|
* ready-to-display values so Twig templates don't need to call PHP functions.
|
|
*
|
|
* Returns an associative array with resolved card fields.
|
|
*/
|
|
function thalim_get_card_data($post_id) {
|
|
$data = [
|
|
'card_image' => null,
|
|
'card_membres' => [],
|
|
'parent_slug' => '',
|
|
'card_category_name' => '',
|
|
'card_category_url' => '',
|
|
'card_type' => '',
|
|
'card_event_date' => '',
|
|
'card_event_date_iso' => '',
|
|
'card_link' => '',
|
|
];
|
|
|
|
// Category-based date formatting:
|
|
// - Séminaire (hors séances): "Du X au Y" from first/last linked séance dates
|
|
// - Ouvrage: year only — includes the post.date fallback (overrides Twig default d/m/Y)
|
|
// - Default: date_de_debut > datetime > (empty → Twig falls back to post.date('d/m/Y'))
|
|
$seance_cat = thalim_cat_id('seance');
|
|
$cat_ids = wp_get_post_categories($post_id);
|
|
$is_seminaire = in_array(thalim_cat_id('seminaires'), $cat_ids, true) && !in_array($seance_cat, $cat_ids, true);
|
|
$is_ouvrage = in_array(thalim_cat_id('ouvrages'), $cat_ids, true);
|
|
|
|
if ($is_seminaire) {
|
|
// Aggregate timestamps from linked séances (Pods `seances` meta = array of post IDs)
|
|
$seance_ts = [];
|
|
foreach (get_post_meta($post_id, 'seances', false) as $sid) {
|
|
foreach (['date_de_debut', 'datetime'] as $key) {
|
|
$raw = get_post_meta($sid, $key, true) ?: '';
|
|
if ($raw && !str_starts_with($raw, '0000-00-00')) {
|
|
$ts = strtotime($raw);
|
|
if ($ts) { $seance_ts[] = $ts; break; }
|
|
}
|
|
}
|
|
}
|
|
if (!empty($seance_ts)) {
|
|
sort($seance_ts);
|
|
$first = reset($seance_ts);
|
|
$last = end($seance_ts);
|
|
$fmt = 'd/m/Y'; // aligné sur le format standard des cards
|
|
if ($first === $last) {
|
|
$data['card_event_date'] = date_i18n($fmt, $first);
|
|
} else {
|
|
$lang = thalim_current_language();
|
|
$prefix = $lang === 'en' ? 'From ' : 'Du ';
|
|
$infix = $lang === 'en' ? ' to ' : ' au ';
|
|
$data['card_event_date'] = $prefix . date_i18n($fmt, $first) . $infix . date_i18n($fmt, $last);
|
|
}
|
|
$data['card_event_date_iso'] = date('Y-m-d', $first);
|
|
}
|
|
// else: leave empty → Twig falls back to post.date('d/m/Y')
|
|
} else {
|
|
// Default + ouvrage handling
|
|
$display_fmt = $is_ouvrage ? 'Y' : 'd/m/Y';
|
|
foreach (['date_de_debut', 'datetime'] as $date_key) {
|
|
$event_raw = get_post_meta($post_id, $date_key, true) ?: '';
|
|
$formatted = thalim_format_date($event_raw, 'fr', $display_fmt);
|
|
if ($formatted) {
|
|
$data['card_event_date'] = $formatted;
|
|
$data['card_event_date_iso'] = date('Y-m-d', strtotime($event_raw));
|
|
break;
|
|
}
|
|
}
|
|
// Ouvrage fallback: if no custom date, use post.date but show year only
|
|
// (overrides the Twig's default post.date('d/m/Y') fallback)
|
|
if ($is_ouvrage && !$data['card_event_date']) {
|
|
$post = get_post($post_id);
|
|
if ($post) {
|
|
$formatted = thalim_format_date($post->post_date, 'fr', 'Y');
|
|
if ($formatted) {
|
|
$data['card_event_date'] = $formatted;
|
|
$data['card_event_date_iso'] = date('Y-m-d', strtotime($post->post_date));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Resolve top-level parent category slug for color theming and direct category name for display
|
|
$categories = wp_get_post_categories($post_id, ['fields' => 'all']);
|
|
$excluded_ids = array_filter([ $seance_cat, thalim_cat_id('non-classe') ]);
|
|
$is_seance = false;
|
|
foreach ($categories as $cat) {
|
|
if ($cat->term_id === $seance_cat) { $is_seance = true; }
|
|
}
|
|
foreach ($categories as $cat) {
|
|
if (in_array($cat->term_id, $excluded_ids)) continue;
|
|
$ancestor_ids = get_ancestors($cat->term_id, 'category');
|
|
if (!empty($ancestor_ids)) {
|
|
$root = get_category(end($ancestor_ids));
|
|
} else {
|
|
$root = $cat;
|
|
}
|
|
$data['parent_slug'] = thalim_category_color_slug($root->term_id, $root->slug);
|
|
$data['card_category_name'] = thalim_cat_name($cat);
|
|
$data['card_category_url'] = get_category_link($cat->term_id);
|
|
break;
|
|
}
|
|
|
|
// Séances de séminaire: link to parent séminaire with hash, derive color from parent's categories
|
|
if ($is_seance) {
|
|
// Always show the category label for séances even though the séance
|
|
// category is excluded from color resolution
|
|
if (!$data['card_category_name']) {
|
|
$seance_term = get_category($seance_cat);
|
|
if ($seance_term) {
|
|
$data['card_category_name'] = thalim_cat_name($seance_term);
|
|
$data['card_category_url'] = get_category_link($seance_cat);
|
|
}
|
|
}
|
|
$parent_id = thalim_get_seance_parent_id($post_id);
|
|
if ($parent_id) {
|
|
$data['card_link'] = get_permalink($parent_id) . '#seance-' . $post_id;
|
|
// Derive color from parent séminaire's categories if not already set
|
|
if (!$data['parent_slug']) {
|
|
foreach (wp_get_post_categories($parent_id, ['fields' => 'all']) as $cat) {
|
|
if (in_array($cat->term_id, $excluded_ids)) continue;
|
|
$ancestor_ids = get_ancestors($cat->term_id, 'category');
|
|
$root = !empty($ancestor_ids) ? get_category(end($ancestor_ids)) : $cat;
|
|
$data['parent_slug'] = thalim_category_color_slug($root->term_id, $root->slug);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Type label (first non-empty type_* field)
|
|
$type_fields = [
|
|
'type_colloque_journee_d_etude',
|
|
'type_soutenance',
|
|
'type_evenement_culturel',
|
|
'type_media',
|
|
'type_captation',
|
|
'type_revue_collection',
|
|
'type_autre',
|
|
];
|
|
foreach ($type_fields as $field) {
|
|
$val = get_post_meta($post_id, $field, true);
|
|
if ($val) {
|
|
$data['card_type'] = $val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// First image from documents_joints
|
|
$doc_ids = get_post_meta($post_id, 'documents_joints', false);
|
|
foreach ($doc_ids as $doc_id) {
|
|
$mime = get_post_mime_type($doc_id);
|
|
if ($mime && str_starts_with($mime, 'image/')) {
|
|
$src = wp_get_attachment_image_url($doc_id, 'medium');
|
|
if ($src) {
|
|
$data['card_image'] = $src;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Members (user IDs → display names + profile URLs)
|
|
// Falls back to autre_membres if membres is empty
|
|
$membre_ids = get_post_meta($post_id, 'membres', false);
|
|
if (empty($membre_ids)) {
|
|
$membre_ids = get_post_meta($post_id, 'autre_membres', false);
|
|
}
|
|
foreach ($membre_ids as $uid) {
|
|
$user = get_userdata($uid);
|
|
if ($user) {
|
|
$data['card_membres'][] = [
|
|
'name' => $user->display_name,
|
|
'url' => get_author_posts_url($uid),
|
|
];
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Build card data map for a collection of posts.
|
|
* Returns an array keyed by post ID.
|
|
*
|
|
* Précharge en lot les caches meta/termes des posts et les utilisateurs
|
|
* référencés (membres/autre_membres) pour éviter les requêtes N+1 de
|
|
* thalim_get_card_data() (une grille de 12 cartes passait par des dizaines
|
|
* de get_post_meta/get_userdata individuels).
|
|
*/
|
|
function thalim_get_cards_data($posts) {
|
|
$ids = [];
|
|
foreach ($posts as $post) {
|
|
$ids[] = $post->ID;
|
|
}
|
|
|
|
if ($ids) {
|
|
// Meta + termes en 2 requêtes pour tout le lot
|
|
update_meta_cache('post', $ids);
|
|
update_object_term_cache($ids, 'post');
|
|
|
|
// Utilisateurs référencés par les cartes (lecture servie par le cache meta)
|
|
$user_ids = [];
|
|
foreach ($ids as $pid) {
|
|
foreach (['membres', 'autre_membres'] as $key) {
|
|
foreach (get_post_meta($pid, $key, false) as $uid) {
|
|
$user_ids[] = (int) $uid;
|
|
}
|
|
}
|
|
}
|
|
$user_ids = array_values(array_unique(array_filter($user_ids)));
|
|
if ($user_ids) {
|
|
cache_users($user_ids);
|
|
}
|
|
}
|
|
|
|
$cards = [];
|
|
foreach ($posts as $post) {
|
|
$cards[$post->ID] = thalim_get_card_data($post->ID);
|
|
}
|
|
return $cards;
|
|
}
|