116 lines
4.6 KiB
PHP
116 lines
4.6 KiB
PHP
<?php
|
|
/**
|
|
* Background resolver + cache for alternate idHAL forms.
|
|
*
|
|
* Problem: a member's WP `identifiant_hal` stores ONE idHAL form, but HAL may
|
|
* tag their publications under other valid forms of the same person. Matching
|
|
* on the single stored form silently drops those links.
|
|
*
|
|
* Fix: resolve every member's full set of valid idHAL forms (via HAL ref/author)
|
|
* and cache them in usermeta `_hal_id_forms`. Matching then uses the cached
|
|
* forms — with ZERO network calls in the UI / import path.
|
|
*
|
|
* All resolution happens in the background via WP-Cron, in small batches, so the
|
|
* admin interface and the import flow stay as fast as before.
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class Thalim_HAL_Forms_Cache {
|
|
|
|
const META_FORMS = '_hal_id_forms'; // usermeta: JSON array of forms
|
|
const META_SOURCE = '_hal_id_forms_src'; // usermeta: the identifiant_hal the cache was built from
|
|
const CRON_HOOK = 'thalim_hal_refresh_forms';
|
|
const BATCH_SIZE = 15; // members resolved per cron tick
|
|
|
|
/** Wire the background hooks. Called once at plugins_loaded. */
|
|
public static function init() {
|
|
add_action(self::CRON_HOOK, [__CLASS__, 'run_batch']);
|
|
|
|
// Ensure the recurring event exists (hourly).
|
|
if (!wp_next_scheduled(self::CRON_HOOK)) {
|
|
wp_schedule_event(time() + 60, 'hourly', self::CRON_HOOK);
|
|
}
|
|
|
|
// When a profile's identifiant_hal changes, invalidate its cache so the
|
|
// next background tick re-resolves it (no synchronous API call here).
|
|
add_action('updated_user_meta', [__CLASS__, 'on_user_meta_change'], 10, 4);
|
|
add_action('added_user_meta', [__CLASS__, 'on_user_meta_change'], 10, 4);
|
|
}
|
|
|
|
/** Remove the scheduled event (plugin deactivation). */
|
|
public static function clear_schedule() {
|
|
$ts = wp_next_scheduled(self::CRON_HOOK);
|
|
if ($ts) wp_unschedule_event($ts, self::CRON_HOOK);
|
|
}
|
|
|
|
/** Invalidate a user's cache when their identifiant_hal is edited. */
|
|
public static function on_user_meta_change($meta_id, $user_id, $meta_key, $_meta_value) {
|
|
if ($meta_key === 'identifiant_hal') {
|
|
delete_user_meta($user_id, self::META_SOURCE); // marks the cache stale
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read cached alternate forms for a user's identifiant_hal.
|
|
* Always returns at least the stored form itself (graceful degradation:
|
|
* behaves exactly like the old code until the background job has run).
|
|
*
|
|
* @return string[] lowercased idHAL forms.
|
|
*/
|
|
public static function forms_for_user($user_id, $identifiant_hal) {
|
|
$base = strtolower(trim((string) $identifiant_hal));
|
|
if ($base === '') return [];
|
|
|
|
$src = get_user_meta($user_id, self::META_SOURCE, true);
|
|
if ($src === $base) {
|
|
$cached = json_decode((string) get_user_meta($user_id, self::META_FORMS, true), true);
|
|
if (is_array($cached) && $cached) {
|
|
$cached[] = $base;
|
|
return array_values(array_unique(array_map('strtolower', $cached)));
|
|
}
|
|
}
|
|
// Not resolved yet (or stale) -> fall back to the single stored form.
|
|
return [$base];
|
|
}
|
|
|
|
/**
|
|
* Cron worker: resolve forms for a batch of members whose cache is missing
|
|
* or stale. Runs in the background; safe to be interrupted (idempotent).
|
|
*/
|
|
public static function run_batch() {
|
|
$users = get_users([
|
|
'meta_key' => 'identifiant_hal',
|
|
'meta_compare' => 'EXISTS',
|
|
'fields' => ['ID'],
|
|
'number' => 500,
|
|
]);
|
|
|
|
// Select those needing (re)resolution: stored form != cached source.
|
|
$todo = [];
|
|
foreach ($users as $u) {
|
|
$idhal = strtolower(trim((string) get_user_meta($u->ID, 'identifiant_hal', true)));
|
|
if ($idhal === '') continue;
|
|
$src = get_user_meta($u->ID, self::META_SOURCE, true);
|
|
if ($src !== $idhal) {
|
|
$todo[$idhal][] = (int) $u->ID; // group users sharing a slug
|
|
}
|
|
if (count($todo) >= self::BATCH_SIZE) break;
|
|
}
|
|
if (empty($todo)) return;
|
|
|
|
$api = new Thalim_HAL_API();
|
|
$expanded = $api->expand_hal_id_forms(array_keys($todo));
|
|
|
|
foreach ($todo as $idhal => $user_ids) {
|
|
$forms = $expanded[$idhal] ?? [$idhal];
|
|
foreach ($user_ids as $uid) {
|
|
update_user_meta($uid, self::META_FORMS, wp_json_encode(array_values($forms)));
|
|
update_user_meta($uid, self::META_SOURCE, $idhal);
|
|
}
|
|
}
|
|
}
|
|
}
|