valentin_le_moignandClaude Opus 5 3cf09ea74f 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
2026-08-27 17:48:08 +02:00
2026-05-12 23:34:00 +02:00

thalim-newsletter

Plugin WordPress qui compose les newsletters mensuelles du laboratoire THALIM à partir du contenu déjà publié sur le site, et les exporte en HTML prêt pour un envoi email.

  • Version : 1.0.0
  • Auteur : THALIM Dev
  • Licence : GPL v2 or later

Installation

cd wp-content/plugins
git clone gitea@figureslibres.io:valentin_le_moign/thalim-plugin-newsletter.git thalim-newsletter

Puis activer depuis l'admin WordPress. Dans le cadre du projet THALIM, le clonage est automatisé par bootstrap.sh du repo thalim-stack.

Utilisation

Une fois activé, le plugin ajoute une page d'administration : Outils → Newsletter (capacité requise : edit_others_posts).

Le workflow :

  1. Sélection d'un mois (sélecteur année-mois)
  2. Chargement AJAX (thalim_nl_load_month) des contenus éligibles, regroupés par catégorie parente
  3. Cases à cocher pour inclure ou exclure chaque publication / séance. Pour un mois sans newsletter existante, tout est coché par défaut sauf le bloc « À venir » (voir plus bas). À l'ouverture d'une newsletter déjà enregistrée, c'est la sélection sauvegardée qui est restaurée — y compris les items qui ne seraient plus dans la fenêtre du mois, réintégrés par merge_selected_items() pour qu'un réenregistrement ne les perde pas
  4. Réordonnancement par glisser-déposer : chaque item porte une poignée (). Pour les catégories normales, on réordonne les annonces dans leur liste. Pour les séminaires, la poignée est sur le titre du séminaire : on réordonne les séminaires entre eux (les séances, elles, restent toujours triées par ordre chronologique). L'ordre choisi est repris tel quel dans le rendu HTML après sauvegarde — l'ordre de soumission des cases suit l'ordre du DOM, et l'export rend chaque section dans l'ordre stocké
  5. Champs intro, conclusion, URL d'inscription, URL de désinscription
  6. Sauvegarde : crée un post WordPress dans la catégorie Newsletter (20) avec le HTML email complet en post_content
  7. Bouton Exporter en HTML (thalim_nl_export_html) → téléchargement du fichier newsletter-THALIM-{mois}.html

Une liste des newsletters déjà sauvegardées permet de revenir éditer un mois passé.

Les catégories Vie du labo (intranet) (9), Séance de séminaire (12), Newsletter (20) et Non classé (31) sont exclues de l'UI (EXCLUDED_CATS dans includes/class-post-query.php). Les séances (cat 12) restent listées, mais imbriquées sous leur séminaire — voir plus bas.

Éligibilité : date d'événement, pas date de publication

Partout où il est question de « la date » d'un contenu, c'est la date de l'événement annoncé qui fait foi, dans l'ordre de priorité du thème : date_de_debut > datetime > post_date. Cet ordre gouverne l'éligibilité, le tri à l'intérieur de chaque section, et la date affichée dans le mail.

Un contenu est proposé pour le mois M s'il remplit l'une des deux conditions :

  1. Contenu du mois — sa date d'événement est antérieure ou égale à la fin de M, et sa fenêtre de fin (ci-dessous) ne s'est pas achevée avant le début de M ;
  2. Contenu à venir — sa date d'événement tombe entre la fin de M (ou aujourd'hui si M est déjà passé) et FUTURE_HORIZON_MONTHS (12 mois). Ces items sont regroupés dans un bloc « À venir », décochés par défaut.

La fenêtre de fin, qui détermine combien de temps un contenu reste proposé après son événement, dépend de la catégorie (SPECIAL_WINDOW_TYPES dans includes/class-post-query.php) :

Catégorie Fin de fenêtre
Appels (8), Soutenances (14) date_de_fin (date limite / date de soutenance)
Colloques (10), Communications (13) date_de_fin, sinon date_de_debut
Ouvrages (15), Articles (16) date d'événement + 3 mois
Toutes les autres date d'événement + 35 jours

Un appel à contribution reste donc proposé dans toutes les newsletters jusqu'à sa date limite, et un événement annoncé six mois à l'avance apparaît à la fois dans le bloc « À venir » des newsletters intermédiaires et dans la liste principale de la newsletter de son propre mois.

Cas particulier : Séminaires (11) → sélection par séance

Le séminaire n'est pas sélectionnable en tant que tel. À la place, le plugin liste ses séances (cat 12) individuellement, chacune avec sa propre case à cocher, regroupées sous le titre (non cliquable) de leur séminaire parent.

  • Éligibilité : une séance apparaît si sa date_de_debut tombe dans le mois, ou dans la fenêtre « à venir » (jusqu'à 12 mois). Un séminaire sans séance dans ces fenêtres n'apparaît pas. Les séances à venir sont décochées par défaut et signalées visuellement.
  • Découverte : on parcourt les séminaires publiés (cat 11) et on lit leur meta seances (tableau d'IDs de séances). Le lien parent→séance vit donc sur le séminaire.
  • Sélection stockée : _newsletter_sections[11] contient des IDs de séances, plus des IDs de séminaires.
  • Rendu HTML (class-html-exporter.php) : les séances cochées sont regroupées par séminaire parent (lookup inverse via Thalim_NL_Post_Query::get_seminar_id_for_seance(), même requête que la redirection #seance-{ID} du thème). Le titre du séminaire est affiché une seule fois, suivi de la liste des séances sélectionnées (date · heure · lieu, lien vers #seance-{id}).
  • Ordre : les séminaires sont réordonnables entre eux par glisser-déposer (poignée sur le titre) — leur ordre de premier appartenance dans la sélection stockée donne l'ordre de rendu. Les séances d'un séminaire sont toujours triées par date_de_debut croissante, dans l'UI comme à l'export.

Catégories couvertes

La liste des catégories éligibles n'est pas codée en dur dans le plugin — elle est calculée dynamiquement via Thalim_NL_Post_Query::get_eligible_categories() (toutes les catégories WordPress, groupées par parent). Les constantes en haut de thalim-newsletter.php (THALIM_NL_CAT_APPELS = 8, etc.) ne servent qu'à associer les fenêtres temporelles spéciales aux catégories concernées :

Constante ID Description
THALIM_NL_CAT_APPELS 8 Appels
THALIM_NL_CAT_COLLOQUES 10 Colloques
THALIM_NL_CAT_SEMINAIRES 11 Séminaires
THALIM_NL_CAT_COMMS 13 Communications
THALIM_NL_CAT_SOUTENANCES 14 Soutenances
THALIM_NL_CAT_OUVRAGES 15 Ouvrages
THALIM_NL_CAT_ARTICLES 16 Articles
THALIM_NL_CAT_NEWSLETTER 20 Newsletter (catégorie où sont sauvegardés les digests)

IDs vérifiés en DB le 2026-03-20. À mettre à jour en cas de migration ou de réorganisation des taxonomies.

Dates affichées dans le mail

Le libellé est construit par Thalim_NL_Post_Query::event_date_label(), qui reprend les règles du thème (thalim_get_agenda_card_data()) :

Champs renseignés Rendu
début et fin le même jour, avec horaires Le 9 octobre 2026 de 14:00 à 17:00
début et fin sur plusieurs jours Du 9 octobre 2026 au 11 octobre 2026
début seul (+ heure éventuelle) 9 octobre 2026 à 14:00
fin seule — cas des appels à contribution Jusqu'au 1 septembre 2026
datetime seul 9 octobre 2026
aucune date date de publication, en dernier recours

Les ouvrages (15) font exception : année seule, comme les cartes du site.

La même fonction alimente la pastille de date de la liste à cocher — ce que voit le rédacteur est ce qui partira dans le mail.

Format HTML email

includes/class-html-exporter.php génère un HTML compatible clients mail :

  • Layout table-based, largeur 600 px
  • Styles inline sur tous les éléments
  • Polices : Gelasio (Google Fonts @import, fallback Georgia) pour les titres, Arial/Helvetica pour le corps
  • Media queries pour le rendu mobile
  • Preheader caché (texte d'aperçu dans les boîtes mail)

Le HTML complet est généré à la sauvegarde et stocké tel quel dans post_content — l'export se contente de le renvoyer.

Prérequis

  • WordPress 6.0+
  • PHP 7.4+
  • Plugin Pods (le pod post et son champ catégorie pour la triple écriture)

Structure

.
├── thalim-newsletter.php       # point d'entrée, constantes, bootstrap
├── assets/
│   ├── admin.css                 # styles de la page admin
│   └── admin.js                  # interactions (sélecteur mois, cases, export)
└── includes/
    ├── class-post-query.php      # requêtes SQL custom + fenêtres temporelles par catégorie
    ├── class-html-exporter.php   # génération du HTML email (tables, inline styles)
    └── class-admin-page.php      # UI Tools > Newsletter + handlers AJAX + sauvegarde
S
Description
No description provided
Readme
136 KiB
Languages
PHP 87.4%
JavaScript 6.8%
CSS 5.8%