Accès contributeur scopé sur leurs propres publications
This commit is contained in:
59
README.md
59
README.md
@@ -17,29 +17,46 @@ Puis activer depuis l'admin WordPress. Dans le cadre du projet THALIM, le clonag
|
||||
|
||||
## Utilisation
|
||||
|
||||
Une fois activé, le plugin ajoute une page d'administration : **Outils → HAL Import** (capacité requise : `edit_others_posts`).
|
||||
Deux points d'entrée selon le rôle :
|
||||
|
||||
La page propose deux flux d'import :
|
||||
- **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).
|
||||
|
||||
### 1. Aperçu live + import incrémental
|
||||
### 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)
|
||||
- **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
|
||||
- Bouton **Importer** : crée tous les posts « prêts » en statut `pending` (à publier après relecture)
|
||||
- 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
|
||||
- Bouton **Test API** pour vérifier la connexion
|
||||
|
||||
### 2. Import en masse via CSV (legacy SPIP)
|
||||
### Mode contributeur
|
||||
|
||||
Permet d'importer des publications anciennes par lots de 100 :
|
||||
Quand un contributeur ouvre la page :
|
||||
|
||||
- Upload d'un CSV avec une colonne `hal_id` + d'un fichier de contexte SPIP (axes/tags/programmes/owner par publication)
|
||||
- Traitement par batchs séquentiels (cliquer plusieurs fois)
|
||||
- Rapport CSV téléchargeable en fin de file
|
||||
- Annulation possible à tout moment
|
||||
- **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<user_id>|` 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
|
||||
|
||||
@@ -76,12 +93,12 @@ Permet d'importer des publications anciennes par lots de 100 :
|
||||
|
||||
## Dédoublonnage
|
||||
|
||||
L'import vérifie le meta `hal_id` avant chaque insertion : une publication ne peut pas être importée deux fois. Le `is_imported($hal_id)` est aussi affiché en colonne de statut dans l'aperçu.
|
||||
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 7.4+
|
||||
- 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`
|
||||
|
||||
@@ -89,15 +106,17 @@ L'import vérifie le meta `hal_id` avant chaque insertion : une publication ne p
|
||||
|
||||
```
|
||||
.
|
||||
├── thalim-hal-importer.php # point d'entrée, constantes, bootstrap
|
||||
├── thalim-hal-importer.php # point d'entrée, constantes, bootstrap
|
||||
└── includes/
|
||||
├── class-hal-api.php # client API HAL (fetch_publications, fetch_by_hal_ids)
|
||||
├── class-admin-page.php # UI Tools > HAL Import (aperçu + CSV)
|
||||
└── class-importer.php # mapping HAL → posts WP (triple-storage, axes cascade)
|
||||
├── 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
|
||||
|
||||
- Base : `https://api.archives-ouvertes.fr/search/`
|
||||
- Structure THALIM : `254015`
|
||||
- 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 : <https://api.archives-ouvertes.fr/docs>
|
||||
|
||||
@@ -20,6 +20,7 @@ class Thalim_HAL_Admin_Page {
|
||||
private $api;
|
||||
private $message = null;
|
||||
private $wp_users_by_hal_id = null; // Cache: normalized_hal_id => ['id' => int, 'name' => string]
|
||||
private $contributor_idhal = null; // Set by check_contributor_idhal_gate() — forced filter in contributor mode
|
||||
|
||||
// Document type labels
|
||||
private const DOC_TYPE_LABELS = [
|
||||
@@ -40,23 +41,97 @@ class Thalim_HAL_Admin_Page {
|
||||
}
|
||||
|
||||
public function render() {
|
||||
if (!current_user_can('edit_others_posts')) {
|
||||
if (!current_user_can('edit_posts')) {
|
||||
wp_die('Unauthorized');
|
||||
}
|
||||
|
||||
$is_contributor = $this->is_contributor_mode();
|
||||
|
||||
// Contributor precondition: must have a valid idHAL on their profile
|
||||
if ($is_contributor) {
|
||||
$gate = $this->check_contributor_idhal_gate();
|
||||
if ($gate !== true) {
|
||||
echo '<div class="wrap"><h1>Importer depuis HAL</h1>';
|
||||
echo $gate;
|
||||
echo '</div>';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->handle_actions();
|
||||
echo '<div class="wrap"><h1>THALIM HAL Importer</h1>';
|
||||
|
||||
$title = $is_contributor ? 'Importer mes publications HAL' : 'THALIM HAL Importer';
|
||||
echo '<div class="wrap"><h1>' . esc_html($title) . '</h1>';
|
||||
$this->render_styles();
|
||||
$this->render_message();
|
||||
if (self::CONFIG_PANEL_ENABLED) {
|
||||
if ($is_contributor) {
|
||||
$this->render_contributor_notice();
|
||||
}
|
||||
if (self::CONFIG_PANEL_ENABLED && !$is_contributor) {
|
||||
$this->render_config();
|
||||
}
|
||||
$this->render_preview();
|
||||
if (self::CSV_IMPORT_ENABLED) {
|
||||
if (self::CSV_IMPORT_ENABLED && !$is_contributor) {
|
||||
$this->render_csv_import();
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
private function is_contributor_mode(): bool {
|
||||
return current_user_can('edit_posts') && !current_user_can('edit_others_posts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current contributor can use the page, or an HTML
|
||||
* notice string explaining why not. Also caches the resolved idHAL into
|
||||
* $this->contributor_idhal for downstream forcing.
|
||||
*/
|
||||
private function check_contributor_idhal_gate() {
|
||||
$user_id = get_current_user_id();
|
||||
$idhal = trim((string) get_user_meta($user_id, 'identifiant_hal', true));
|
||||
$profile_url = get_edit_user_link($user_id);
|
||||
|
||||
if ($idhal === '') {
|
||||
return sprintf(
|
||||
'<div class="notice notice-error"><p><strong>Votre identifiant HAL n\'est pas renseigné.</strong></p>'
|
||||
. '<p>Pour utiliser cet outil, ajoutez votre <code>identifiant_hal</code> (idHAL) à votre profil.</p>'
|
||||
. '<p><a href="%s" class="button button-primary">Modifier mon profil</a></p></div>',
|
||||
esc_url($profile_url)
|
||||
);
|
||||
}
|
||||
|
||||
$validity = $this->get_hal_ids_validity([strtolower($idhal)]);
|
||||
$is_valid = $validity[strtolower($idhal)] ?? null;
|
||||
|
||||
if ($is_valid === false) {
|
||||
return sprintf(
|
||||
'<div class="notice notice-error"><p><strong>Votre identifiant HAL (<code>%s</code>) est introuvable dans le référentiel HAL.</strong></p>'
|
||||
. '<p>Vérifiez l\'orthographe sur votre profil. La validation est mise en cache 24h.</p>'
|
||||
. '<p><a href="%s" class="button button-primary">Modifier mon profil</a></p></div>',
|
||||
esc_html($idhal), esc_url($profile_url)
|
||||
);
|
||||
}
|
||||
|
||||
// null = API error → graceful degradation, on laisse passer
|
||||
$this->contributor_idhal = $idhal;
|
||||
return true;
|
||||
}
|
||||
|
||||
private function render_contributor_notice() {
|
||||
?>
|
||||
<div class="notice notice-info" style="border-left-color:#2196f3">
|
||||
<p><strong>À compléter avant publication :</strong></p>
|
||||
<ul style="list-style:disc;padding-left:25px;margin:5px 0">
|
||||
<li><strong>Axe(s) thématique(s)</strong> — obligatoire pour la publication.</li>
|
||||
<li>Autres membres THALIM co-auteurs (champ <em>autre_membres</em>) si applicable.</li>
|
||||
<li>Image à la une (illustration).</li>
|
||||
<li>Programme(s) de recherche associé(s) si pertinent.</li>
|
||||
</ul>
|
||||
<p><small>Les publications sont importées en statut <strong>En attente</strong>. Un éditeur les validera après votre complément.</small></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function handle_actions() {
|
||||
if (!isset($_POST['thalim_hal_action'])) return;
|
||||
if (!wp_verify_nonce($_POST['_wpnonce'] ?? '', 'thalim_hal_action')) {
|
||||
@@ -102,6 +177,12 @@ class Thalim_HAL_Admin_Page {
|
||||
$date_to = sanitize_text_field($_POST['hal_date_to'] ?? '');
|
||||
$author_hal_id = sanitize_text_field($_POST['hal_author_id'] ?? '');
|
||||
|
||||
$is_contributor = $this->is_contributor_mode();
|
||||
if ($is_contributor) {
|
||||
$author_hal_id = $this->contributor_idhal; // force, ignore POST
|
||||
}
|
||||
$force_author = $is_contributor ? get_current_user_id() : null;
|
||||
|
||||
// Reuse the cached preview data — raw_docs are stored alongside processed docs
|
||||
$preview = $this->get_preview_data($date_from, $date_to, $author_hal_id);
|
||||
if (is_wp_error($preview)) {
|
||||
@@ -132,7 +213,7 @@ class Thalim_HAL_Admin_Page {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post_id = $importer->import($doc, $this->wp_users_by_hal_id);
|
||||
$post_id = $importer->import($doc, $this->wp_users_by_hal_id, 'pending', false, [], $force_author);
|
||||
if (is_wp_error($post_id)) {
|
||||
$errors[] = $hal_id . ': ' . $post_id->get_error_message();
|
||||
} else {
|
||||
@@ -160,6 +241,11 @@ class Thalim_HAL_Admin_Page {
|
||||
$date_to = sanitize_text_field($_POST['hal_date_to'] ?? '');
|
||||
$author_hal_id = sanitize_text_field($_POST['hal_author_id'] ?? '');
|
||||
|
||||
$is_contributor = $this->is_contributor_mode();
|
||||
if ($is_contributor) {
|
||||
$author_hal_id = $this->contributor_idhal; // force, ignore POST
|
||||
}
|
||||
|
||||
if (!$hal_id) {
|
||||
$this->message = ['error', 'hal_id manquant.'];
|
||||
return;
|
||||
@@ -180,6 +266,17 @@ class Thalim_HAL_Admin_Page {
|
||||
return;
|
||||
}
|
||||
|
||||
// Critical security check: in contributor mode, the requested hal_id MUST
|
||||
// be a publication where the contributor is an author. Defends against a
|
||||
// forged POST that tries to import another member's publication.
|
||||
if ($is_contributor) {
|
||||
$doc_authors = array_map('strtolower', array_map('trim', $doc['authIdHal_s'] ?? []));
|
||||
if (!in_array(strtolower($this->contributor_idhal), $doc_authors, true)) {
|
||||
$this->message = ['error', "Vous n'êtes pas auteur de la publication $hal_id."];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$importer = new Thalim_HAL_Importer_Logic();
|
||||
if ($importer->is_imported($hal_id)) {
|
||||
$this->message = ['warning', "Publication $hal_id déjà importée."];
|
||||
@@ -192,7 +289,8 @@ class Thalim_HAL_Admin_Page {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = $importer->import($doc, $this->wp_users_by_hal_id);
|
||||
$force_author = $is_contributor ? get_current_user_id() : null;
|
||||
$post_id = $importer->import($doc, $this->wp_users_by_hal_id, 'pending', false, [], $force_author);
|
||||
if (is_wp_error($post_id)) {
|
||||
$this->message = ['error', "Erreur import : " . $post_id->get_error_message()];
|
||||
return;
|
||||
@@ -240,19 +338,29 @@ class Thalim_HAL_Admin_Page {
|
||||
}
|
||||
|
||||
private function render_preview() {
|
||||
$is_contributor = $this->is_contributor_mode();
|
||||
|
||||
// Read filters from POST (after submit) or GET (page reload with state)
|
||||
$date_from = sanitize_text_field($_POST['hal_date_from'] ?? $_GET['hal_date_from'] ?? '');
|
||||
$date_to = sanitize_text_field($_POST['hal_date_to'] ?? $_GET['hal_date_to'] ?? '');
|
||||
$author_hal_id = sanitize_text_field($_POST['hal_author_id'] ?? $_GET['hal_author_id'] ?? '');
|
||||
|
||||
// Users must be loaded before rendering the dropdown
|
||||
// Contributor mode: ignore any POSTed author filter, force their own idHAL.
|
||||
if ($is_contributor) {
|
||||
$author_hal_id = $this->contributor_idhal;
|
||||
}
|
||||
|
||||
// Users must be loaded before rendering the dropdown (admins/editors only)
|
||||
$this->load_wp_users_hal_ids();
|
||||
|
||||
$preview = $this->get_preview_data($date_from, $date_to, $author_hal_id);
|
||||
$ready_count = is_wp_error($preview) ? 0 : $preview['stats']['ready'];
|
||||
$import_label = $is_contributor
|
||||
? sprintf('Importer mes %d publication(s) (En attente)', $ready_count)
|
||||
: sprintf('Importer %d publication(s) (En attente)', $ready_count);
|
||||
?>
|
||||
<div class="card" style="max-width:100%;margin-bottom:20px">
|
||||
<h2>Import Preview</h2>
|
||||
<h2><?php echo $is_contributor ? 'Mes publications HAL' : 'Import Preview'; ?></h2>
|
||||
|
||||
<form method="post" style="margin-bottom:20px;display:flex;align-items:center;gap:15px;flex-wrap:wrap">
|
||||
<?php wp_nonce_field('thalim_hal_action'); ?>
|
||||
@@ -265,17 +373,21 @@ class Thalim_HAL_Admin_Page {
|
||||
<input type="date" name="hal_date_to" value="<?php echo esc_attr($date_to); ?>" style="width:auto">
|
||||
</label>
|
||||
|
||||
<label style="font-weight:600">Auteur
|
||||
<select name="hal_author_id" style="max-width:220px">
|
||||
<option value="">— Tous —</option>
|
||||
<?php foreach ($this->wp_users_by_hal_id as $user): ?>
|
||||
<option value="<?php echo esc_attr($user['hal_id']); ?>"
|
||||
<?php selected($author_hal_id, $user['hal_id']); ?>>
|
||||
<?php echo esc_html($user['name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<?php if (!$is_contributor): ?>
|
||||
<label style="font-weight:600">Auteur
|
||||
<select name="hal_author_id" style="max-width:220px">
|
||||
<option value="">— Tous —</option>
|
||||
<?php foreach ($this->wp_users_by_hal_id as $user): ?>
|
||||
<option value="<?php echo esc_attr($user['hal_id']); ?>"
|
||||
<?php selected($author_hal_id, $user['hal_id']); ?>>
|
||||
<?php echo esc_html($user['name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<?php else: ?>
|
||||
<input type="hidden" name="hal_author_id" value="<?php echo esc_attr($author_hal_id); ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
<button class="button button-secondary" name="thalim_hal_action" value="filter">Filtrer</button>
|
||||
<button class="button button-secondary" name="thalim_hal_action" value="refresh" style="margin-left:5px">Rafraîchir</button>
|
||||
@@ -285,14 +397,14 @@ class Thalim_HAL_Admin_Page {
|
||||
|
||||
<button class="button button-primary" name="thalim_hal_action" value="import_pending"
|
||||
<?php if ($ready_count === 0): ?>disabled title="Aucune publication prête à importer"<?php endif; ?>>
|
||||
Importer <?php echo $ready_count; ?> publication(s) (En attente)
|
||||
<?php echo esc_html($import_label); ?>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<?php if (is_wp_error($preview)): ?>
|
||||
<div class="notice notice-error"><p><?php echo esc_html($preview->get_error_message()); ?></p></div>
|
||||
<?php else: ?>
|
||||
<?php $this->render_wp_users_debug(); ?>
|
||||
<?php if (!$is_contributor) $this->render_wp_users_debug(); ?>
|
||||
<?php $this->render_summary($preview['stats']); ?>
|
||||
<?php $this->render_preview_table($preview['docs'], [
|
||||
'date_from' => $date_from,
|
||||
@@ -486,7 +598,11 @@ class Thalim_HAL_Admin_Page {
|
||||
}
|
||||
|
||||
private function get_preview_cache_key($date_from, $date_to, $author_hal_id) {
|
||||
return 'thalim_hal_preview_' . md5($date_from . '|' . $date_to . '|' . $author_hal_id);
|
||||
// Scope the cache by user ID in contributor mode so two contributors
|
||||
// don't share a cache entry (and don't collide with the admin cache
|
||||
// that might use the same author_hal_id filter).
|
||||
$scope = $this->is_contributor_mode() ? ('u' . get_current_user_id() . '|') : '';
|
||||
return 'thalim_hal_preview_' . md5($scope . $date_from . '|' . $date_to . '|' . $author_hal_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,6 +632,11 @@ class Thalim_HAL_Admin_Page {
|
||||
}
|
||||
|
||||
private function get_preview_data($date_from = '', $date_to = '', $author_hal_id = '') {
|
||||
// Server-side override: in contributor mode, force the author filter
|
||||
// to the contributor's own idHAL regardless of what was POSTed.
|
||||
if ($this->is_contributor_mode() && $this->contributor_idhal) {
|
||||
$author_hal_id = $this->contributor_idhal;
|
||||
}
|
||||
$cache_key = $this->get_preview_cache_key($date_from, $date_to, $author_hal_id);
|
||||
$cached = get_transient($cache_key);
|
||||
if ($cached !== false) return $cached;
|
||||
|
||||
@@ -97,7 +97,8 @@ class Thalim_HAL_Importer_Logic {
|
||||
array $wp_users_by_hal_id = [],
|
||||
string $post_status = 'pending',
|
||||
bool $backdate_post = false,
|
||||
array $spip_context = []
|
||||
array $spip_context = [],
|
||||
?int $force_post_author = null
|
||||
) {
|
||||
$hal_id = $hal_doc['halId_s'] ?? '';
|
||||
$doc_type = $hal_doc['docType_s'] ?? '';
|
||||
@@ -118,7 +119,8 @@ class Thalim_HAL_Importer_Logic {
|
||||
$matched_user_names[] = $user['name'];
|
||||
}
|
||||
}
|
||||
$post_author = !empty($matched_user_ids) ? $matched_user_ids[0] : 1;
|
||||
$post_author = $force_post_author
|
||||
?? (!empty($matched_user_ids) ? $matched_user_ids[0] : 1);
|
||||
|
||||
// --- Create the post ---
|
||||
$post_args = [
|
||||
|
||||
@@ -58,13 +58,31 @@ class Thalim_HAL_Importer {
|
||||
}
|
||||
|
||||
public function add_admin_menu() {
|
||||
add_management_page(
|
||||
'HAL Import',
|
||||
'HAL Import',
|
||||
'edit_others_posts',
|
||||
'thalim-hal-importer',
|
||||
[$this, 'render_admin_page']
|
||||
);
|
||||
// Admins/editors : page sous Outils (UI complète : filtres tous auteurs, debug, etc.)
|
||||
if (current_user_can('edit_others_posts')) {
|
||||
add_management_page(
|
||||
'HAL Import',
|
||||
'HAL Import',
|
||||
'edit_others_posts',
|
||||
'thalim-hal-importer',
|
||||
[$this, 'render_admin_page']
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Contributeurs : menu top-level dédié (Outils est masqué pour eux par le thème).
|
||||
// La classe rend une UI réduite scopée sur leur idHAL en interne.
|
||||
if (current_user_can('edit_posts')) {
|
||||
add_menu_page(
|
||||
'Importer depuis HAL',
|
||||
'Importer depuis HAL',
|
||||
'edit_posts',
|
||||
'thalim-hal-import-mine',
|
||||
[$this, 'render_admin_page'],
|
||||
'dashicons-download',
|
||||
26
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function render_admin_page() {
|
||||
|
||||
Reference in New Issue
Block a user