# thalim-hal-importer Plugin WordPress qui importe les publications du laboratoire THALIM depuis l'archive ouverte [HAL](https://hal.science/) (structure `254015`) et les transforme en posts WordPress avec tous les champs Pods renseignés. - **Version :** 2.0.0 - **Auteur :** THALIM Dev - **Licence :** GPL v2 or later ## Installation ```bash cd wp-content/plugins git clone gitea@figureslibres.io:valentin_le_moign/thalim-plugin-hal-importer.git thalim-hal-importer ``` Puis activer depuis l'admin WordPress. Dans le cadre du projet THALIM, le clonage est automatisé par `bootstrap.sh` du repo [`thalim-stack`](https://figureslibres.io/valentin_le_moign/thalim-stack). ## Utilisation Deux points d'entrée selon le rôle : - **Admin / éditeur** (cap `edit_others_posts`) : **Outils → HAL Import** — UI complète, voit toutes les publications de la structure THALIM, peut filtrer par n'importe quel auteur. - **Contributeur** (cap `edit_posts` sans `edit_others_posts`) : menu top-level **Importer depuis HAL** — UI réduite scopée sur son propre idHAL (cf. § Mode contributeur). ### Aperçu live + import - Filtres : plage de dates (`producedDate_s`) et auteur (idHAL d'un membre THALIM) - Liste les publications HAL correspondantes avec statut coloré : - **vert** : déjà importée (présence du meta `hal_id` côté WP). Le statut WP est précisé (« Publié » ou « En attente »). Pour les pending, un bouton **Modifier** ouvre la page d'édition du post. - **jaune** : prête à être importée (au moins un auteur HAL matche un user WordPress) - **rouge** : aucun auteur THALIM identifié → ignorée - Colonne **Action** : - Bouton **Importer** par ligne jaune : crée le post correspondant en `pending` - Bouton global **Importer N publication(s)** au-dessus du tableau : import en masse de toutes les lignes jaunes du tableau courant - Après chaque import, le cache du tableau est muté en place (la ligne devient verte, les stats sont ajustées) sans nouvel appel HAL - Cache des aperçus en transient (5 min, clé hashée sur les filtres), rafraîchissable manuellement ### Mode contributeur Quand un contributeur ouvre la page : - **Précondition idHAL** : si le user n'a pas renseigné son `identifiant_hal` sur son profil, ou si son idHAL est invalide (absent du référentiel `ref/author`), la page se bloque sur une notice avec un lien vers son profil. - **Scoping côté serveur** : le filtre auteur est forcé à l'idHAL du contributeur, indépendamment de tout `$_POST['hal_author_id']` reçu. La cache key des aperçus est préfixée par `u|` pour éviter toute collision avec le cache admin. - **UI réduite** : dropdown auteur masqué, panneau de validation des idHAL des autres membres masqué. - **Notice persistante** rappelant que l'axe thématique est obligatoire avant publication, qu'une image à la une est attendue, etc. - **Sécurité import unitaire** : `handle_import_single()` vérifie que l'idHAL du contributeur figure bien dans `authIdHal_s` du doc HAL ciblé — un POST forgé sur un `hal_id` d'une autre publi est rejeté. - **post_author forcé** : l'importer reçoit `force_post_author = get_current_user_id()` (6e param de `import()`) pour que le contributeur soit l'auteur WP du post même s'il est 2e co-auteur dans `authIdHal_s`. - Le statut `pending` natif de l'importer aligne nativement avec la restriction WP "contributeur = pas de publication directe" — un éditeur ou admin valide ensuite le post. ### Validation des idHAL des membres Le panneau dépliable « Utilisateurs WordPress avec identifiant HAL » liste tous les users dont le meta `identifiant_hal` est rempli et vérifie chaque idHAL contre le référentiel auteur HAL (`ref/author`). Les idHAL absents du référentiel sont colorés en rouge et comptés dans l'en-tête du panneau. Résultat mis en cache 24h (transient invalidé naturellement quand la liste des users change). ### Features désactivées (code conservé, feature flag à `false`) - **Card Configuration + bouton Test API** : `Thalim_HAL_Admin_Page::CONFIG_PANEL_ENABLED` - **Import en masse via CSV (legacy SPIP)** : `Thalim_HAL_Admin_Page::CSV_IMPORT_ENABLED`. Permettait l'upload d'un CSV de `hal_id` + d'un fichier de contexte SPIP (axes/tags/programmes/owner par publication), traités par batchs de 100 avec rapport CSV final. Le code vit dans `includes/trait-admin-page-csv-legacy.php`. Basculer le flag à `true` dans `class-admin-page.php` pour réactiver. ## Mapping des types HAL → catégories WordPress `DOC_TYPE_MAP` dans `includes/class-importer.php` : | Type HAL | Description | Catégorie WP | | ------------- | ---------------------------- | ------------ | | `ART` | Article | `16` | | `COUV` | Chapitre d'ouvrage | `16` | | `OUV` | Ouvrage | `15` | | `COMM` | Communication | `13` | | `ISSUE` | Direction de numéro | `16` | | `PROCEEDINGS` | Direction d'ouvrage / actes | `15` | | `THESE` | Thèse | `14` | | `HDR` | HDR | `14` | | `SON` | Son | `19` | | `VIDEO` | Vidéo | `19` | | `NOTICE` | Notice / recension | `16` | | `BLOG` | Blog / tribune | `19` | | `TRAD` | Traduction | `15` | | `REPORT` | Rapport | `4` | | `UNDEFINED` | Non défini | `4` | | `POSTER` | Poster | `4` | | `OTHER` | Autre | `4` | `COMM`, `THESE`, `HDR`, `SON`, `VIDEO` sont traités comme événements et utilisent le champ Pods `date_de_debut`. Les autres utilisent `datetime`. `TRAD` reçoit en plus `fonction_auteur = « Traduction // Translation »` (au même titre que `COUV` et `ISSUE`). ## Champs HAL → champs WP À l'import, chaque publication remplit : - **Identification** : `hal_id`, `hal_url` (URI HAL), `lien_externe_1` (PDF si dispo) avec titre `Document HAL // HAL Document` - **Titre** : `post_title` (issu de HAL) - **Catégorie** : triple écriture (term assignment + meta `categorie` + meta `_pods_categorie`) - **Auteurs HAL → membres** : matching via `authIdHal_s` ↔ user meta `identifiant_hal`. Stockage en triple-pattern Pods (`membres` add_post_meta + `_pods_membres`) - **Date** : `date_de_debut` ou `datetime` selon le type, optionnellement backdaté sur `producedDate_s` - **Métadonnées** : `journal`, `editeur`, `sous-titre` (book/conference title), `lieu` (city/country pour PROCEEDINGS), `reference_bibliographique` (`citationFull_s`) - **Fonction** : `fonction_auteur` (varie selon doc type : « Auteur du chapitre // Chapter author », « Direction de numéro // Editor-in-Chief », etc.) - **Axes thématiques** : cascade `spip_context` → co-auteurs THALIM → owner. Source effective stockée dans `$importer->last_axes_source` - **Programmes de recherche** et **étiquettes** : depuis `spip_context` (import CSV uniquement) ## Dédoublonnage L'import vérifie le meta `hal_id` avant chaque insertion : une publication ne peut pas être importée deux fois. `get_imported_post($hal_id)` renvoie l'id et le `post_status` du post correspondant — utilisé dans l'aperçu pour distinguer Publié / En attente. ## Prérequis - WordPress 6.0+ - PHP 8.2+ (constantes dans les traits) - Plugin **Pods** (le pod `post` et le champ user `identifiant_hal`) - IDs de catégorie WordPress conformes au mapping (8/13/14/15/16/19) — codés en dur dans `DOC_TYPE_MAP` ## Structure ``` . ├── thalim-hal-importer.php # point d'entrée, constantes, bootstrap └── includes/ ├── class-hal-api.php # client API HAL (fetch_publications, fetch_by_hal_ids, validate_hal_ids) ├── class-admin-page.php # UI Tools > HAL Import (aperçu + import unitaire/masse) ├── class-importer.php # mapping HAL → posts WP (triple-storage, axes cascade) ├── trait-admin-page-config.php # card Configuration + Test API (désactivé) └── trait-admin-page-csv-legacy.php # import bulk CSV legacy SPIP (désactivé) ``` ## API HAL - Recherche publications : `https://api.archives-ouvertes.fr/search/` (structure THALIM `254015`) - Référentiel auteurs : `https://api.archives-ouvertes.fr/ref/author/` (validation des idHAL) - Documentation :