Skip to main content

Import des offres d'emploi

Source de données

L'import interroge l'API HRMaps via une requête POST :

ParamètreValeur
URLhttps://niort-freres.hrmaps.cloud/api/AdepApi/GetJobOfferList/0
MéthodePOST
Format retourJSON (tableau d'offres)

Déclenchement

Import automatique (WP-Cron)

L'import est planifié toutes les heures via WP-Cron :

if (!wp_next_scheduled('import_jobs_event')) {
wp_schedule_event(time(), 'hourly', 'import_jobs_event');
}
add_action('import_jobs_event', 'import_jobs_from_api');
Dépendance au trafic

WP-Cron ne se déclenche que lorsque le site reçoit une visite. En production avec peu de trafic, configurer un vrai cron système :

* * * * * curl -s https://groupeniort.fr/wp-cron.php?doing_wp_cron > /dev/null

Import manuel (Admin WP)

Un bouton d'import manuel est accessible dans l'administration :

WordPress Admin → Offres d'emploi → Importation API → "Importer Maintenant"

Il appelle directement import_jobs_from_api() sans passer par le cron.


Logique d'import

Étape 1 — Filtrage des offres archivées

Avant tout traitement, les offres marquées comme archivées sont ignorées :

if (!empty($job['IsArchived']) && $job['IsArchived'] === true) {
continue;
}

Étape 2 — Vérification des doublons

L'unicité est assurée par le champ _position_id (ID HRMaps). Si une offre avec le même PositionID existe déjà en base, elle est ignorée :

$existing_job = get_posts([
'post_type' => 'job_offer',
'meta_query' => [[
'key' => '_position_id',
'value' => $job['PositionID'],
]],
]);

if (empty($existing_job)) {
// Création du nouveau post
}

Étape 3 — Création du post WordPress

Les nouvelles offres sont créées comme Custom Post Type job_offer :

$post_id = wp_insert_post([
'post_title' => $job['PositionTitle'],
'post_content' => wp_kses_post($job['PositionFormattedDescription']['Content']),
'post_type' => 'job_offer',
'post_status' => 'publish',
]);

Le contenu HTML de la description est assaini via wp_kses_post() avant insertion.

Étape 4 — Cas particulier DPAN

Si l'organisation est DPAN et qu'aucune localisation n'est fournie par l'API, une adresse par défaut est appliquée :

if ($job['OrganizationName'] === 'DPAN' && empty($city) && empty($postal_code) && empty($address)) {
$city = 'Rouen';
$postal_code = '76000';
$address = '154 Avenue du mont Riboudet';
}

Suppression des offres obsolètes

Après chaque import, les offres présentes en base mais absentes de la réponse API sont supprimées définitivement :

// Construction de la liste des IDs reçus
foreach ($data as $offer) {
$new_job_ids[] = $offer['PositionID'];
}

// Suppression des offres qui ne sont plus dans l'API
foreach ($existing_jobs as $job) {
$existing_job_id = get_post_meta($job->ID, '_position_id', true);

if (!in_array($existing_job_id, $new_job_ids)) {
wp_delete_post($job->ID, true); // true = suppression définitive (sans corbeille)
}
}
Suppression définitive

Le second argument true de wp_delete_post() bypasse la corbeille. Les offres supprimées ne sont pas récupérables depuis l'admin WordPress.


Schéma récapitulatif

Requête POST → GetJobOfferList


Pour chaque offre reçue :

├─ IsArchived === true ──────────────────► Ignorée

├─ _position_id déjà en base ───────────► Ignorée (pas de doublon)

└─ Nouvelle offre
├─ Org = DPAN sans localisation ─► Adresse Rouen par défaut
└─ wp_insert_post() + metas ─────► Post publié

Après la boucle :
└─ Posts WP absents de l'API ────────────► wp_delete_post() définitif