Sélection par séance, réordonnancement et exclusion vie du labo
This commit is contained in:
@@ -118,7 +118,7 @@ class Thalim_NL_Admin_Page {
|
||||
</div>
|
||||
|
||||
<div id="thalim-nl-sections-wrap">
|
||||
<?php echo $this->render_sections_html($month_data, $existing_sections); ?>
|
||||
<?php echo $this->render_sections_html($month_data, $existing ? $existing_sections : null); ?>
|
||||
</div>
|
||||
|
||||
<div class="thalim-nl-conclusion">
|
||||
@@ -213,9 +213,18 @@ class Thalim_NL_Admin_Page {
|
||||
// Sections HTML (shared between initial render and AJAX)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function render_sections_html(array $month_data, array $checked_ids = []): string {
|
||||
/**
|
||||
* @param array $month_data Posts grouped by category for the month.
|
||||
* @param array|null $checked_ids Saved selection (cat_id => [post_id,...]) for an
|
||||
* existing newsletter. Pass null for a fresh month:
|
||||
* every item is then checked by default.
|
||||
*/
|
||||
public function render_sections_html(array $month_data, ?array $checked_ids = null): string {
|
||||
$groups = Thalim_NL_Post_Query::get_eligible_categories();
|
||||
|
||||
// No saved newsletter yet → everything checked by default.
|
||||
$check_all = ($checked_ids === null);
|
||||
|
||||
ob_start();
|
||||
$has_content = false;
|
||||
|
||||
@@ -249,8 +258,17 @@ class Thalim_NL_Admin_Page {
|
||||
continue;
|
||||
}
|
||||
$count = count($posts);
|
||||
$checked_in_section = (array) ($checked_ids[$cat_id] ?? $checked_ids[(string) $cat_id] ?? []);
|
||||
$has_checked = !empty($checked_in_section);
|
||||
$checked_in_section = $check_all
|
||||
? []
|
||||
: (array) ($checked_ids[$cat_id] ?? $checked_ids[(string) $cat_id] ?? []);
|
||||
$has_checked = $check_all || !empty($checked_in_section);
|
||||
|
||||
// Restore the saved drag-and-drop order ($checked_in_section is
|
||||
// stored in submit order). For seminars this also reorders the
|
||||
// seminar groups, since grouping below follows first appearance.
|
||||
if (!$check_all) {
|
||||
$posts = $this->reorder_posts_by_saved($posts, $checked_in_section);
|
||||
}
|
||||
?>
|
||||
<details class="thalim-nl-section" <?php if ($has_checked) echo 'open'; ?>>
|
||||
<summary class="thalim-nl-section-summary">
|
||||
@@ -258,49 +276,67 @@ class Thalim_NL_Admin_Page {
|
||||
<span class="thalim-nl-count">(<?php echo $count; ?>)</span>
|
||||
</summary>
|
||||
<div class="thalim-nl-section-body">
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<label class="thalim-nl-post-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $post['id']; ?>"
|
||||
<?php checked(in_array((int) $post['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($post['title']); ?></span>
|
||||
<a href="<?php echo esc_url($post['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_post_date_hint($post)); ?></span>
|
||||
</label>
|
||||
<?php if (!empty($post['seances'])): ?>
|
||||
<ul class="thalim-nl-seances-list">
|
||||
<?php foreach ($post['seances'] as $seance): ?>
|
||||
<li class="thalim-nl-seance-item">
|
||||
<span class="thalim-nl-seance-title"><?php echo esc_html($seance['title']); ?></span>
|
||||
<span class="thalim-nl-seance-meta">
|
||||
<?php
|
||||
$parts = [];
|
||||
if ($seance['date_debut']) {
|
||||
$ts = strtotime($seance['date_debut']);
|
||||
$parts[] = $ts ? date_i18n('j M Y', $ts) : '';
|
||||
}
|
||||
if ($seance['heure_de_debut']) {
|
||||
$time = $seance['heure_de_debut'];
|
||||
if ($seance['heure_de_fin']) $time .= '–' . $seance['heure_de_fin'];
|
||||
$parts[] = $time;
|
||||
}
|
||||
if ($seance['lieu']) {
|
||||
$parts[] = $seance['lieu'];
|
||||
}
|
||||
echo esc_html(implode(' · ', array_filter($parts)));
|
||||
?>
|
||||
</span>
|
||||
</li>
|
||||
<?php if ((int) $cat_id === THALIM_NL_CAT_SEMINAIRES): ?>
|
||||
<?php
|
||||
// Seminars: posts are séance items carrying their parent
|
||||
// seminar. Group them under a (non-selectable) seminar
|
||||
// header; each séance is an individual checkbox.
|
||||
$by_seminar = [];
|
||||
foreach ($posts as $seance) {
|
||||
$sem_id = (int) $seance['seminar_id'];
|
||||
if (!isset($by_seminar[$sem_id])) {
|
||||
$by_seminar[$sem_id] = [
|
||||
'title' => $seance['seminar_title'],
|
||||
'permalink' => $seance['seminar_permalink'],
|
||||
'seances' => [],
|
||||
];
|
||||
}
|
||||
$by_seminar[$sem_id]['seances'][] = $seance;
|
||||
}
|
||||
?>
|
||||
<?php foreach ($by_seminar as $sem): ?>
|
||||
<div class="thalim-nl-seminar-group">
|
||||
<div class="thalim-nl-seminar-title">
|
||||
<span class="thalim-nl-drag-handle dashicons dashicons-menu" title="Glisser pour réordonner les séminaires" aria-hidden="true"></span>
|
||||
<span class="thalim-nl-seminar-name"><?php echo esc_html($sem['title']); ?></span>
|
||||
<a href="<?php echo esc_url($sem['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
</div>
|
||||
<?php foreach ($sem['seances'] as $seance): ?>
|
||||
<label class="thalim-nl-post-row thalim-nl-seance-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $seance['id']; ?>"
|
||||
<?php checked($check_all || in_array((int) $seance['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($seance['title']); ?></span>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_seance_hint($seance)); ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<label class="thalim-nl-post-row">
|
||||
<span class="thalim-nl-drag-handle dashicons dashicons-menu" title="Glisser pour réordonner" aria-hidden="true"></span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $post['id']; ?>"
|
||||
<?php checked($check_all || in_array((int) $post['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($post['title']); ?></span>
|
||||
<a href="<?php echo esc_url($post['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_post_date_hint($post)); ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</details>
|
||||
<?php endforeach; ?>
|
||||
@@ -331,6 +367,53 @@ class Thalim_NL_Admin_Page {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder $posts so items whose 'id' appears in $order come first, in
|
||||
* $order's sequence; the rest keep their query order, appended after.
|
||||
* Restores the editor's saved drag-and-drop order in the admin UI.
|
||||
*/
|
||||
private function reorder_posts_by_saved(array $posts, array $order): array {
|
||||
if (empty($order)) {
|
||||
return $posts;
|
||||
}
|
||||
$rank = array_flip(array_map('intval', array_values($order)));
|
||||
$keyed = [];
|
||||
foreach ($posts as $idx => $post) {
|
||||
$keyed[] = [
|
||||
'post' => $post,
|
||||
'rank' => $rank[(int) $post['id']] ?? PHP_INT_MAX,
|
||||
'idx' => $idx,
|
||||
];
|
||||
}
|
||||
// Sort by saved rank, then original index (stable for un-ranked items).
|
||||
usort($keyed, fn($a, $b) => [$a['rank'], $a['idx']] <=> [$b['rank'], $b['idx']]);
|
||||
return array_map(fn($x) => $x['post'], $keyed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Date · heure · lieu hint shown next to each séance checkbox.
|
||||
*/
|
||||
private function format_seance_hint(array $seance): string {
|
||||
$parts = [];
|
||||
if (!empty($seance['date_debut']) && !str_starts_with($seance['date_debut'], '0000-00-00')) {
|
||||
$ts = strtotime($seance['date_debut']);
|
||||
if ($ts) {
|
||||
$parts[] = date_i18n('j M Y', $ts);
|
||||
}
|
||||
}
|
||||
if (!empty($seance['heure_de_debut'])) {
|
||||
$time = $seance['heure_de_debut'];
|
||||
if (!empty($seance['heure_de_fin'])) {
|
||||
$time .= '–' . $seance['heure_de_fin'];
|
||||
}
|
||||
$parts[] = $time;
|
||||
}
|
||||
if (!empty($seance['lieu'])) {
|
||||
$parts[] = $seance['lieu'];
|
||||
}
|
||||
return implode(' · ', $parts);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Save
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -490,7 +573,7 @@ class Thalim_NL_Admin_Page {
|
||||
$unsubscribe_url = get_post_meta($existing->ID, '_newsletter_unsubscribe_url', true) ?: '';
|
||||
}
|
||||
|
||||
$html = $this->render_sections_html($month_data, $existing_sections);
|
||||
$html = $this->render_sections_html($month_data, $existing ? $existing_sections : null);
|
||||
|
||||
wp_send_json_success([
|
||||
'html' => $html,
|
||||
|
||||
@@ -44,10 +44,6 @@ class Thalim_NL_HTML_Exporter {
|
||||
/**
|
||||
* Generate a complete email-ready HTML document from a saved newsletter post.
|
||||
*/
|
||||
/** Month window timestamps — set by generate(), used by format_seminar_line() */
|
||||
private int $month_start = 0;
|
||||
private int $month_end = 0;
|
||||
|
||||
public function generate(WP_Post $post): string {
|
||||
$sections_json = get_post_meta($post->ID, '_newsletter_sections', true);
|
||||
$sections = json_decode($sections_json, true) ?: [];
|
||||
@@ -57,13 +53,6 @@ class Thalim_NL_HTML_Exporter {
|
||||
$subscribe_url = get_post_meta($post->ID, '_newsletter_subscribe_url', true) ?: '';
|
||||
$unsubscribe_url = get_post_meta($post->ID, '_newsletter_unsubscribe_url', true) ?: '';
|
||||
|
||||
// Compute month window from stored newsletter month
|
||||
$year_month = get_post_meta($post->ID, '_newsletter_month', true) ?: '';
|
||||
if ($year_month) {
|
||||
$this->month_start = strtotime($year_month . '-01 00:00:00') ?: 0;
|
||||
$this->month_end = strtotime('last day of ' . $year_month . ' 23:59:59') ?: 0;
|
||||
}
|
||||
|
||||
// Build ordered section blocks following the category hierarchy
|
||||
$groups = Thalim_NL_Post_Query::get_eligible_categories();
|
||||
$section_blocks = [];
|
||||
@@ -83,10 +72,16 @@ class Thalim_NL_HTML_Exporter {
|
||||
continue;
|
||||
}
|
||||
$items = [];
|
||||
foreach ($post_ids as $pid) {
|
||||
$line = $this->format_post_line((int) $pid, $cat_id);
|
||||
if ($line) {
|
||||
$items[] = $line;
|
||||
if ((int) $cat_id === THALIM_NL_CAT_SEMINAIRES) {
|
||||
// Selected items are séance IDs: group them by parent seminar,
|
||||
// rendering each seminar's title once above its séances.
|
||||
$items = $this->format_seminar_blocks(array_map('intval', $post_ids));
|
||||
} else {
|
||||
foreach ($post_ids as $pid) {
|
||||
$line = $this->format_post_line((int) $pid, $cat_id);
|
||||
if ($line) {
|
||||
$items[] = $line;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($items)) {
|
||||
@@ -305,11 +300,6 @@ body { margin: 0 !important; padding: 0 !important; }
|
||||
* Optional image on the left, title in serif, meta below in sans-serif.
|
||||
*/
|
||||
public function format_post_line(int $post_id, int $cat_id): string {
|
||||
// Seminars: special rendering with séances
|
||||
if ($cat_id === THALIM_NL_CAT_SEMINAIRES) {
|
||||
return $this->format_seminar_line($post_id);
|
||||
}
|
||||
|
||||
$post = get_post($post_id);
|
||||
if (!$post) {
|
||||
return '';
|
||||
@@ -394,11 +384,45 @@ body { margin: 0 !important; padding: 0 !important; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a seminar post: title (no dates) + list of séances with date, time, location.
|
||||
* Each séance links to the seminar page.
|
||||
* Render the seminar section from a flat list of selected séance IDs.
|
||||
* Séances are grouped by their parent seminar (first-appearance order),
|
||||
* and each seminar is rendered as one block with its title shown once.
|
||||
*
|
||||
* @return string[] One HTML block per seminar.
|
||||
*/
|
||||
private function format_seminar_line(int $post_id): string {
|
||||
$post = get_post($post_id);
|
||||
private function format_seminar_blocks(array $seance_ids): array {
|
||||
// Group séance IDs by parent seminar, preserving order of first appearance.
|
||||
$by_seminar = [];
|
||||
foreach ($seance_ids as $sid) {
|
||||
$sid = (int) $sid;
|
||||
$s_post = get_post($sid);
|
||||
if (!$s_post || $s_post->post_status !== 'publish') {
|
||||
continue;
|
||||
}
|
||||
$sem_id = Thalim_NL_Post_Query::get_seminar_id_for_seance($sid);
|
||||
if (!$sem_id) {
|
||||
continue;
|
||||
}
|
||||
$by_seminar[$sem_id][] = $sid;
|
||||
}
|
||||
|
||||
$blocks = [];
|
||||
foreach ($by_seminar as $sem_id => $sids) {
|
||||
$block = $this->format_seminar_block((int) $sem_id, $sids);
|
||||
if ($block) {
|
||||
$blocks[] = $block;
|
||||
}
|
||||
}
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format one seminar block: title (no dates) shown once + the given
|
||||
* séances with date, time, location. Each séance links to its anchor
|
||||
* on the seminar page.
|
||||
*/
|
||||
private function format_seminar_block(int $seminar_id, array $seance_ids): string {
|
||||
$post = get_post($seminar_id);
|
||||
if (!$post) {
|
||||
return '';
|
||||
}
|
||||
@@ -406,12 +430,12 @@ body { margin: 0 !important; padding: 0 !important; }
|
||||
$font_serif = "Gelasio, Georgia, 'Times New Roman', serif";
|
||||
$font_sans = "Arial, Helvetica, sans-serif";
|
||||
|
||||
$url = get_permalink($post_id);
|
||||
$title = get_the_title($post_id);
|
||||
$url = get_permalink($seminar_id);
|
||||
$title = get_the_title($seminar_id);
|
||||
|
||||
// Image
|
||||
// Image (first image from the seminar's documents_joints)
|
||||
$image_url = '';
|
||||
$doc_ids = get_post_meta($post_id, 'documents_joints', false);
|
||||
$doc_ids = get_post_meta($seminar_id, 'documents_joints', false);
|
||||
foreach ($doc_ids as $doc_id) {
|
||||
$mime = get_post_mime_type($doc_id);
|
||||
if ($mime && str_starts_with($mime, 'image/')) {
|
||||
@@ -423,28 +447,19 @@ body { margin: 0 !important; padding: 0 !important; }
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch séances within the newsletter month window
|
||||
$seance_ids = get_post_meta($post_id, 'seances', false);
|
||||
// Build the selected séances. Within a seminar, séances always display
|
||||
// in chronological order (seminars themselves are reorderable, séances
|
||||
// are not).
|
||||
$seances = [];
|
||||
foreach ($seance_ids as $sid) {
|
||||
$sid = (int) $sid;
|
||||
$s_post = get_post($sid);
|
||||
if (!$s_post || $s_post->post_status !== 'publish') continue;
|
||||
|
||||
$raw_debut = get_post_meta($sid, 'date_de_debut', true) ?: '';
|
||||
$ts = $raw_debut ? strtotime($raw_debut) : false;
|
||||
|
||||
// Filter: only séances within the month window
|
||||
if ($this->month_start && $this->month_end) {
|
||||
if (!$ts || $ts < $this->month_start || $ts > $this->month_end) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$seances[] = [
|
||||
'id' => $sid,
|
||||
'title' => get_the_title($sid),
|
||||
'date_debut' => $raw_debut,
|
||||
'date_debut' => get_post_meta($sid, 'date_de_debut', true) ?: '',
|
||||
'date_fin' => get_post_meta($sid, 'date_de_fin', true) ?: '',
|
||||
'heure_de_debut' => substr(get_post_meta($sid, 'heure_de_debut', true) ?: '', 0, 5),
|
||||
'heure_de_fin' => substr(get_post_meta($sid, 'heure_de_fin', true) ?: '', 0, 5),
|
||||
|
||||
@@ -21,7 +21,6 @@ class Thalim_NL_Post_Query {
|
||||
private const SPECIAL_WINDOW_TYPES = [
|
||||
THALIM_NL_CAT_APPELS => 'datetime_to_fin',
|
||||
THALIM_NL_CAT_COLLOQUES => 'debut_minus35_to_fin',
|
||||
THALIM_NL_CAT_SEMINAIRES => 'debut_minus35_to_fin',
|
||||
THALIM_NL_CAT_COMMS => 'debut_minus35_to_fin',
|
||||
THALIM_NL_CAT_SOUTENANCES => 'datetime_to_fin',
|
||||
THALIM_NL_CAT_OUVRAGES => 'datetime_plus3m',
|
||||
@@ -30,8 +29,17 @@ class Thalim_NL_Post_Query {
|
||||
|
||||
private const DEFAULT_WINDOW_TYPE = 'datetime_plus35d';
|
||||
|
||||
/**
|
||||
* Séminaires (cat 11) are not selected as whole posts: instead, each of
|
||||
* their séances (cat 12) is individually selectable. A séance is eligible
|
||||
* when its date_de_debut falls within the newsletter month, extended by
|
||||
* this margin (in days) past the end of the month.
|
||||
*/
|
||||
private const SEANCE_WINDOW_MARGIN_DAYS = 5;
|
||||
|
||||
/** Categories to exclude from the newsletter UI */
|
||||
private const EXCLUDED_CATS = [
|
||||
9, // Vie du labo (intranet)
|
||||
12, // Séance de séminaire
|
||||
20, // Newsletter
|
||||
31, // Non classé
|
||||
@@ -119,6 +127,15 @@ class Thalim_NL_Post_Query {
|
||||
|
||||
$result = [];
|
||||
foreach (self::get_all_eligible_cat_ids() as $cat_id) {
|
||||
// Seminars: list individually-selectable séances grouped by seminar.
|
||||
if ($cat_id === THALIM_NL_CAT_SEMINAIRES) {
|
||||
$seances = $this->query_seminar_seances($month_start, $month_end);
|
||||
if (!empty($seances)) {
|
||||
$result[$cat_id] = $seances;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$window_type = self::get_window_type($cat_id);
|
||||
$posts = $this->query_category($cat_id, $window_type, $month_start, $month_end);
|
||||
if (!empty($posts)) {
|
||||
@@ -128,6 +145,100 @@ class Thalim_NL_Post_Query {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the flat list of selectable séances for the seminar category.
|
||||
*
|
||||
* We walk every published seminar (cat 11), read its `seances` meta
|
||||
* (array of séance post IDs), and keep the séances whose date_de_debut
|
||||
* falls within [month_start, month_end + SEANCE_WINDOW_MARGIN_DAYS].
|
||||
* Each returned item carries its parent seminar (id/title/permalink) so
|
||||
* the UI and the exporter can group séances under their seminar.
|
||||
*
|
||||
* @return array Flat list of séance items (see shape below).
|
||||
*/
|
||||
private function query_seminar_seances(int $month_start, int $month_end): array {
|
||||
global $wpdb;
|
||||
|
||||
$window_end = $month_end + (self::SEANCE_WINDOW_MARGIN_DAYS * DAY_IN_SECONDS);
|
||||
|
||||
$seminar_ids = $wpdb->get_col($wpdb->prepare(
|
||||
"SELECT DISTINCT p.ID
|
||||
FROM {$wpdb->posts} p
|
||||
INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id = p.ID
|
||||
INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
|
||||
AND tt.taxonomy = 'category' AND tt.term_id = %d
|
||||
WHERE p.post_type = 'post' AND p.post_status = 'publish'",
|
||||
THALIM_NL_CAT_SEMINAIRES
|
||||
));
|
||||
|
||||
$items = [];
|
||||
foreach ($seminar_ids as $seminar_id) {
|
||||
$seminar_id = (int) $seminar_id;
|
||||
$seminar_title = get_the_title($seminar_id);
|
||||
$seminar_permalink = get_permalink($seminar_id);
|
||||
|
||||
foreach (get_post_meta($seminar_id, 'seances', false) as $sid) {
|
||||
$sid = (int) $sid;
|
||||
$s_post = get_post($sid);
|
||||
if (!$s_post || $s_post->post_status !== 'publish') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$raw_debut = get_post_meta($sid, 'date_de_debut', true) ?: '';
|
||||
$ts = $raw_debut ? strtotime($raw_debut) : false;
|
||||
if (!$ts || $ts < $month_start || $ts > $window_end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$items[] = [
|
||||
'id' => $sid,
|
||||
'title' => get_the_title($sid),
|
||||
// Links straight to the séance anchor on the seminar page.
|
||||
'permalink' => $seminar_permalink . '#seance-' . $sid,
|
||||
'datetime' => '',
|
||||
'date_debut' => $raw_debut,
|
||||
'date_fin' => get_post_meta($sid, 'date_de_fin', true) ?: '',
|
||||
'post_date' => $s_post->post_date,
|
||||
'heure_de_debut' => substr(get_post_meta($sid, 'heure_de_debut', true) ?: '', 0, 5),
|
||||
'heure_de_fin' => substr(get_post_meta($sid, 'heure_de_fin', true) ?: '', 0, 5),
|
||||
'lieu' => get_post_meta($sid, 'lieu', true) ?: '',
|
||||
'membres' => $this->get_post_membres($sid),
|
||||
'autrepersonnes' => get_post_meta($sid, 'autrepersonnes', true) ?: '',
|
||||
'seminar_id' => $seminar_id,
|
||||
'seminar_title' => $seminar_title,
|
||||
'seminar_permalink' => $seminar_permalink,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by séance date: seminars naturally order by their earliest séance
|
||||
// when grouped by first appearance (see render / export grouping).
|
||||
usort($items, fn($a, $b) => strcmp($a['date_debut'], $b['date_debut']));
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the parent seminar (cat 11) that lists a given séance in its
|
||||
* `seances` meta. Mirrors the reverse lookup used by the theme's
|
||||
* #seance-{ID} redirect. Returns 0 when none is found.
|
||||
*/
|
||||
public static function get_seminar_id_for_seance(int $seance_id): int {
|
||||
global $wpdb;
|
||||
|
||||
$parent_id = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT pm.post_id
|
||||
FROM {$wpdb->postmeta} pm
|
||||
JOIN {$wpdb->posts} p ON p.ID = pm.post_id
|
||||
WHERE pm.meta_key = 'seances' AND pm.meta_value = %s
|
||||
AND p.post_status = 'publish'
|
||||
LIMIT 1",
|
||||
(string) $seance_id
|
||||
));
|
||||
|
||||
return (int) $parent_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query a single category with the appropriate window expression.
|
||||
*/
|
||||
@@ -190,7 +301,7 @@ class Thalim_NL_Post_Query {
|
||||
|
||||
$posts = [];
|
||||
foreach ($rows as $row) {
|
||||
$posts[] = $this->build_post_data((int) $row->ID, $row->post_title, $row->post_date, $month_start, $month_end);
|
||||
$posts[] = $this->build_post_data((int) $row->ID, $row->post_title, $row->post_date);
|
||||
}
|
||||
return $posts;
|
||||
}
|
||||
@@ -289,8 +400,8 @@ class Thalim_NL_Post_Query {
|
||||
// Post data builder
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private function build_post_data(int $post_id, string $post_title, string $post_date, int $month_start = 0, int $month_end = 0): array {
|
||||
$data = [
|
||||
private function build_post_data(int $post_id, string $post_title, string $post_date): array {
|
||||
return [
|
||||
'id' => $post_id,
|
||||
'title' => $post_title,
|
||||
'permalink' => get_permalink($post_id),
|
||||
@@ -300,57 +411,7 @@ class Thalim_NL_Post_Query {
|
||||
'post_date' => $post_date,
|
||||
'membres' => $this->get_post_membres($post_id),
|
||||
'autrepersonnes' => get_post_meta($post_id, 'autrepersonnes', true) ?: '',
|
||||
'seances' => [],
|
||||
];
|
||||
|
||||
// For seminars, fetch séances within the month window
|
||||
if ($month_start && $month_end && has_category(THALIM_NL_CAT_SEMINAIRES, $post_id)) {
|
||||
$data['seances'] = $this->get_seances_in_window($post_id, $month_start, $month_end);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch séances linked to a seminar that fall within the given time window.
|
||||
*/
|
||||
private function get_seances_in_window(int $seminar_id, int $month_start, int $month_end): array {
|
||||
$seance_ids = get_post_meta($seminar_id, 'seances', false);
|
||||
if (empty($seance_ids)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$seances = [];
|
||||
foreach ($seance_ids as $sid) {
|
||||
$sid = (int) $sid;
|
||||
$post = get_post($sid);
|
||||
if (!$post || $post->post_status !== 'publish') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$raw_debut = get_post_meta($sid, 'date_de_debut', true) ?: '';
|
||||
$ts = $raw_debut ? strtotime($raw_debut) : false;
|
||||
if (!$ts || $ts < $month_start || $ts > $month_end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$seances[] = [
|
||||
'id' => $sid,
|
||||
'title' => get_the_title($sid),
|
||||
'date_debut' => $raw_debut,
|
||||
'date_fin' => get_post_meta($sid, 'date_de_fin', true) ?: '',
|
||||
'heure_de_debut' => substr(get_post_meta($sid, 'heure_de_debut', true) ?: '', 0, 5),
|
||||
'heure_de_fin' => substr(get_post_meta($sid, 'heure_de_fin', true) ?: '', 0, 5),
|
||||
'lieu' => get_post_meta($sid, 'lieu', true) ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
// Sort by date_de_debut ascending
|
||||
usort($seances, function ($a, $b) {
|
||||
return strcmp($a['date_debut'], $b['date_debut']);
|
||||
});
|
||||
|
||||
return $seances;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user