Annonces à venir proposées, et dates d'événement au lieu des dates de publication
Retour du commanditaire après le premier envoi réel (juillet 2026) : des annonces à venir n'étaient pas proposées à la coche, et les dates affichées étaient les dates de publication. - Fenêtre « à venir » de 12 mois (FUTURE_HORIZON_MONTHS), démarrant à la fin du mois de la newsletter ou à aujourd'hui si ce mois est passé, en remplacement du plafond « début de fenêtre <= fin du mois ». Idem pour les séances (SEANCE_WINDOW_MARGIN_DAYS de 5 jours supprimée). Ces items sont regroupés dans un bloc « À venir », décochés par défaut. - event_date_label() centralise les libellés du thème (« Le X de H1 à H2 », « Du X au Y », « Jusqu'au X », « X à H ») sur la convention date_de_debut > datetime > post_date. Utilisée par l'export et par la pastille de la liste à cocher, qui affichent donc la même chose. - Tri par date d'événement (sql_event_date_order) et non par date de publication. - Fenêtres de fin « +35 j » et « +3 mois » recalées sur la date d'événement : un événement annoncé plus de 35 jours à l'avance sortait de la fenêtre avant d'avoir eu lieu et manquait dans la newsletter de son propre mois. - merge_selected_items() : une sélection déjà enregistrée est réinjectée dans la liste même si ses items sont sortis de la fenêtre — sans ça, rouvrir puis réenregistrer une ancienne newsletter l'amputait silencieusement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w7RzAHv4r1Yahnm2NwDDG
This commit is contained in:
@@ -53,6 +53,9 @@ class Thalim_NL_Admin_Page {
|
||||
// Query posts for current month
|
||||
$query = new Thalim_NL_Post_Query();
|
||||
$month_data = $query->get_posts_for_month($year_month);
|
||||
if ($existing) {
|
||||
$month_data = $query->merge_selected_items($month_data, $existing_sections);
|
||||
}
|
||||
|
||||
// Past newsletters
|
||||
$past_newsletters = get_posts([
|
||||
@@ -304,12 +307,12 @@ class Thalim_NL_Admin_Page {
|
||||
</a>
|
||||
</div>
|
||||
<?php foreach ($sem['seances'] as $seance): ?>
|
||||
<label class="thalim-nl-post-row thalim-nl-seance-row">
|
||||
<label class="thalim-nl-post-row thalim-nl-seance-row<?php echo !empty($seance['is_future']) ? ' is-future' : ''; ?>">
|
||||
<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)); ?>
|
||||
<?php checked($this->is_item_checked($seance, $check_all, $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>
|
||||
@@ -318,23 +321,33 @@ class Thalim_NL_Admin_Page {
|
||||
</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
|
||||
// Les annonces dont la date d'événement dépasse le mois sont
|
||||
// regroupées à part et décochées par défaut : elles restent
|
||||
// disponibles à la coche sans encombrer la sélection du mois.
|
||||
$posts_du_mois = [];
|
||||
$posts_a_venir = [];
|
||||
foreach ($posts as $post) {
|
||||
if (!empty($post['is_future'])) {
|
||||
$posts_a_venir[] = $post;
|
||||
} else {
|
||||
$posts_du_mois[] = $post;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?php foreach ($posts_du_mois as $post): ?>
|
||||
<?php echo $this->render_post_row((int) $cat_id, $post, $check_all, $checked_in_section); ?>
|
||||
<?php endforeach; ?>
|
||||
<?php if (!empty($posts_a_venir)): ?>
|
||||
<div class="thalim-nl-future">
|
||||
<p class="thalim-nl-future-title">
|
||||
À venir <span>(au-delà du mois — à cocher au besoin)</span>
|
||||
</p>
|
||||
<?php foreach ($posts_a_venir as $post): ?>
|
||||
<?php echo $this->render_post_row((int) $cat_id, $post, $check_all, $checked_in_section); ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</details>
|
||||
@@ -350,17 +363,59 @@ class Thalim_NL_Admin_Page {
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Un item est-il coché à l'ouverture ?
|
||||
* - newsletter déjà enregistrée : la sélection sauvegardée fait foi ;
|
||||
* - mois neuf : tout est coché sauf ce qui dépasse le mois (`is_future`).
|
||||
*/
|
||||
private function is_item_checked(array $item, bool $check_all, array $checked_in_section): bool {
|
||||
if ($check_all) {
|
||||
return empty($item['is_future']);
|
||||
}
|
||||
// Normalisation : la sélection vient d'un json_decode, tolérer les chaînes.
|
||||
return in_array((int) $item['id'], array_map('intval', $checked_in_section), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Une ligne d'annonce cochable (hors séances, qui ont leur propre gabarit).
|
||||
*/
|
||||
private function render_post_row(int $cat_id, array $post, bool $check_all, array $checked_in_section): string {
|
||||
ob_start();
|
||||
?>
|
||||
<label class="thalim-nl-post-row<?php echo !empty($post['is_future']) ? ' is-future' : ''; ?>">
|
||||
<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 $cat_id; ?>][]"
|
||||
value="<?php echo (int) $post['id']; ?>"
|
||||
<?php checked($this->is_item_checked($post, $check_all, $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
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Small date hint shown next to each post title in the checklist.
|
||||
*/
|
||||
private function format_post_date_hint(array $post): string {
|
||||
$candidates = [$post['date_debut'], $post['datetime'], $post['post_date']];
|
||||
foreach ($candidates as $raw) {
|
||||
if ($raw && !str_starts_with($raw, '0000-00-00')) {
|
||||
$ts = strtotime($raw);
|
||||
if ($ts) {
|
||||
return date_i18n('j M Y', $ts);
|
||||
}
|
||||
// Même libellé que l'export HTML (« Du X au Y », « Jusqu'au X »…) :
|
||||
// ce que voit le rédacteur dans la liste est ce qui partira dans le mail.
|
||||
$label = Thalim_NL_Post_Query::event_date_label((int) $post['id'], 'j M Y');
|
||||
if ($label !== '') {
|
||||
return $label;
|
||||
}
|
||||
$raw = $post['post_date'] ?? '';
|
||||
if ($raw && !str_starts_with($raw, '0000-00-00')) {
|
||||
$ts = strtotime($raw);
|
||||
if ($ts) {
|
||||
return date_i18n('j M Y', $ts);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
@@ -605,6 +660,10 @@ class Thalim_NL_Admin_Page {
|
||||
$unsubscribe_url = get_post_meta($existing->ID, '_newsletter_unsubscribe_url', true) ?: '';
|
||||
}
|
||||
|
||||
if ($existing) {
|
||||
$month_data = $query->merge_selected_items($month_data, $existing_sections);
|
||||
}
|
||||
|
||||
$html = $this->render_sections_html($month_data, $existing ? $existing_sections : null);
|
||||
|
||||
wp_send_json_success([
|
||||
|
||||
Reference in New Issue
Block a user