Crvi/app/models/Event_Permission_Model.php
2026-01-20 07:54:37 +01:00

725 lines
33 KiB
PHP

<?php
declare(strict_types=1);
namespace ESI_CRVI_AGENDA\models;
/**
* Modèle pour la table crvi_event_permission
*
* Cette table stocke les DISPONIBILITÉS de l'intervenant pour un événement :
* - Jours de la semaine disponibles (lundi, mardi, etc. - PAS des dates spécifiques)
* - Plages horaires disponibles
* - Indisponibilités ponctuelles (dates spécifiques où l'intervenant n'est pas disponible)
*
* OPTIMISATION : Permet de vérifier rapidement les disponibilités sans charger l'intervenant
*/
class Event_Permission_Model extends Main_Model {
public $id;
public $event_id;
public $jours_permis; // JSON array ["lundi", "mardi"] - JOURS DE LA SEMAINE de l'intervenant
public $plages_horaires; // JSON array [{"debut":"09:00","fin":"17:00"}] - Heures disponibles (intervenant)
public $indisponibilites; // JSON array - Indisponibilités ponctuelles de l'intervenant
public $traducteur_jours_permis; // JSON array - Jours de la semaine du traducteur (si présent)
public $traducteur_indisponibilites; // JSON array - Indisponibilités ponctuelles du traducteur (si présent)
public $local_indisponibilites; // JSON array - Indisponibilités ponctuelles du local
public $locaux_autories; // JSON array [1,2,3] (IDs de locaux)
public $departements_autories; // JSON array [1,2,3] (IDs de départements)
public $types_intervention_autories; // JSON array [1,2,3]
public $traducteurs_disponibles_par_langue; // JSON object {"fr": [1,2,3], "en": [4,5]} - IDs des traducteurs disponibles par langue
public $date_creation;
public $date_modification;
public $cree_par;
public $modifie_par;
/**
* Crée la table crvi_event_permission
*
* Stocke les disponibilités de l'intervenant pour chaque événement :
* - Jours de la semaine (lundi, mardi, etc.)
* - Plages horaires (heures disponibles)
* - Indisponibilités ponctuelles (dates spécifiques)
*/
public static function create_table() {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$table_name = $wpdb->prefix . 'crvi_event_permission';
$charset_collate = $wpdb->get_charset_collate();
// Vérifier si la table existe déjà
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name) {
return; // La table existe déjà
}
$sql = "CREATE TABLE $table_name (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
event_id BIGINT(20) UNSIGNED NOT NULL,
jours_permis TEXT DEFAULT NULL,
plages_horaires TEXT DEFAULT NULL,
indisponibilites TEXT DEFAULT NULL,
-- Disponibilités traducteur (si présent)
traducteur_jours_permis TEXT DEFAULT NULL,
traducteur_indisponibilites TEXT DEFAULT NULL,
-- Disponibilités local
local_indisponibilites TEXT DEFAULT NULL,
locaux_autories TEXT DEFAULT NULL,
departements_autories TEXT DEFAULT NULL,
types_intervention_autories TEXT DEFAULT NULL,
traducteurs_disponibles_par_langue TEXT DEFAULT NULL COMMENT 'Présets traducteurs disponibles par langue (JSON)',
date_creation DATETIME NOT NULL,
date_modification DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
cree_par BIGINT(20) UNSIGNED DEFAULT NULL,
modifie_par BIGINT(20) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY event_id (event_id),
KEY event_id_index (event_id)
) $charset_collate;";
// Si la table existe déjà, ajouter les nouvelles colonnes si nécessaire
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") === $table_name) {
// Ajouter les colonnes pour traducteur et local si elles n'existent pas
$columns_to_add = [
'traducteur_jours_permis' => 'ALTER TABLE ' . $table_name . ' ADD COLUMN traducteur_jours_permis TEXT DEFAULT NULL',
'traducteur_indisponibilites' => 'ALTER TABLE ' . $table_name . ' ADD COLUMN traducteur_indisponibilites TEXT DEFAULT NULL',
'local_indisponibilites' => 'ALTER TABLE ' . $table_name . ' ADD COLUMN local_indisponibilites TEXT DEFAULT NULL',
'traducteurs_disponibles_par_langue' => 'ALTER TABLE ' . $table_name . ' ADD COLUMN traducteurs_disponibles_par_langue TEXT DEFAULT NULL',
];
foreach ($columns_to_add as $column => $sql_add) {
$column_exists = $wpdb->get_results($wpdb->prepare(
"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
DB_NAME, $table_name, $column
));
if (empty($column_exists)) {
$wpdb->query($sql_add);
}
}
return; // Table existe, colonnes ajoutées si nécessaire
}
dbDelta($sql);
}
/**
* Crée les disponibilités à partir de l'intervenant, traducteur et local lors de la création d'un événement
*
* Stocke :
* - Les jours de la semaine disponibles (intervenant, traducteur)
* - Les plages horaires disponibles (intervenant)
* - Les indisponibilités ponctuelles (intervenant, traducteur, local)
* - Les traducteurs disponibles par langue (preset pour optimisation)
*
* @param int $event_id ID de l'événement
* @param int $intervenant_id ID de l'intervenant
* @param array|null $plages_horaires Plages horaires spécifiques (optionnel, pour les permanences)
* @param int|null $traducteur_id ID du traducteur (optionnel)
* @param int|null $local_id ID du local (optionnel)
* @param string|null $langue_slug Slug de la langue de l'événement (pour précalculer traducteurs disponibles)
* @param string|null $date_rdv Date de l'événement (pour précalculer traducteurs disponibles)
* @return bool|WP_Error
*/
public static function create_from_intervenant($event_id, $intervenant_id, $plages_horaires = null, $traducteur_id = null, $local_id = null, $langue_slug = null, $date_rdv = null) {
global $wpdb;
$intervenant = CRVI_Intervenant_Model::load($intervenant_id);
if (!$intervenant) {
return new \WP_Error('intervenant_not_found', 'Intervenant introuvable', ['status' => 404]);
}
// Extraire les jours de la semaine disponibles de l'intervenant (lundi, mardi, etc. - PAS des dates)
$jours_disponibles = get_field('jours_de_disponibilite', 'user_' . $intervenant_id);
$jours_permis = is_array($jours_disponibles) ? json_encode($jours_disponibles) : json_encode([]);
// Extraire les indisponibilités ponctuelles de l'intervenant
$indisponibilites_acf = get_field('indisponibilitee_ponctuelle', 'user_' . $intervenant_id);
$indisponibilites = is_array($indisponibilites_acf) ? json_encode($indisponibilites_acf) : json_encode([]);
// Extraire les départements et types d'intervention
$departements_autories = !empty($intervenant->departements_ids)
? json_encode($intervenant->departements_ids)
: json_encode([]);
$types_intervention_autories = !empty($intervenant->types_intervention_ids)
? json_encode($intervenant->types_intervention_ids)
: json_encode([]);
// Plages horaires : si fournies, les utiliser, sinon null
$plages_horaires_json = null;
if ($plages_horaires !== null && is_array($plages_horaires)) {
$plages_horaires_json = json_encode($plages_horaires);
}
// Traducteur : jours et indisponibilités (si présent)
$traducteur_jours_permis = null;
$traducteur_indisponibilites = null;
if ($traducteur_id) {
$traducteur = CRVI_Traducteur_Model::load($traducteur_id);
if ($traducteur) {
// Jours de disponibilité du traducteur
$traducteur_jours = get_field('jours_de_disponibilite', $traducteur_id);
$traducteur_jours_permis = is_array($traducteur_jours) ? json_encode($traducteur_jours) : json_encode([]);
// Indisponibilités ponctuelles du traducteur
$traducteur_indispo_acf = get_field('indisponibilitee_ponctuelle', $traducteur_id);
$traducteur_indisponibilites = is_array($traducteur_indispo_acf) ? json_encode($traducteur_indispo_acf) : json_encode([]);
}
}
// Local : indisponibilités (si présent)
$local_indisponibilites = null;
if ($local_id) {
$local = CRVI_Local_Model::load($local_id);
if ($local) {
// Indisponibilités ponctuelles du local (si le champ existe)
$local_indispo_acf = get_field('indisponibilitee_ponctuelle', $local_id);
$local_indisponibilites = is_array($local_indispo_acf) ? json_encode($local_indispo_acf) : json_encode([]);
}
}
// Précalculer les traducteurs disponibles par langue (preset pour optimisation)
$traducteurs_disponibles_par_langue = null;
if ($langue_slug && $date_rdv) {
$traducteurs_disponibles_par_langue = self::precalculate_traducteurs_par_langue($date_rdv, $langue_slug);
}
// Créer l'entrée de permission
$table_name = $wpdb->prefix . 'crvi_event_permission';
$result = $wpdb->insert($table_name, [
'event_id' => $event_id,
'jours_permis' => $jours_permis,
'plages_horaires' => $plages_horaires_json,
'indisponibilites' => $indisponibilites,
'traducteur_jours_permis' => $traducteur_jours_permis,
'traducteur_indisponibilites' => $traducteur_indisponibilites,
'local_indisponibilites' => $local_indisponibilites,
'departements_autories' => $departements_autories,
'types_intervention_autories' => $types_intervention_autories,
'traducteurs_disponibles_par_langue' => $traducteurs_disponibles_par_langue,
'date_creation' => current_time('mysql'),
'cree_par' => get_current_user_id(),
], [
'%d', // event_id
'%s', // jours_permis
'%s', // plages_horaires
'%s', // indisponibilites
'%s', // traducteur_jours_permis
'%s', // traducteur_indisponibilites
'%s', // local_indisponibilites
'%s', // departements_autories
'%s', // types_intervention_autories
'%s', // traducteurs_disponibles_par_langue
'%s', // date_creation
'%d', // cree_par
]);
return $result !== false;
}
/**
* Précalcule les IDs des traducteurs disponibles par langue pour une date donnée
*
* Retourne un tableau JSON avec les IDs des traducteurs disponibles pour chaque langue :
* {"fr": [1,2,3], "en": [4,5], "es": [2,6]}
*
* @param string $date_rdv Date au format Y-m-d
* @param string|null $langue_slug Slug de la langue principale (si null, calcule pour toutes les langues)
* @return string|null JSON string ou null
*/
private static function precalculate_traducteurs_par_langue($date_rdv, $langue_slug = null) {
// Récupérer toutes les langues ou seulement celle demandée
$langues_to_check = [];
if ($langue_slug) {
$term = get_term_by('slug', $langue_slug, 'langue');
if ($term) {
$langues_to_check[] = [
'slug' => $langue_slug,
'term_id' => $term->term_id,
];
}
} else {
// Récupérer toutes les langues
$terms = get_terms([
'taxonomy' => 'langue',
'hide_empty' => false,
]);
foreach ($terms as $term) {
$langues_to_check[] = [
'slug' => $term->slug,
'term_id' => $term->term_id,
];
}
}
if (empty($langues_to_check)) {
return null;
}
// Pour chaque langue, récupérer les traducteurs disponibles
$result = [];
foreach ($langues_to_check as $langue_info) {
$traducteurs_disponibles = CRVI_Traducteur_Model::filtrer_disponibles(
$date_rdv,
$langue_info['slug']
);
// Extraire les IDs des traducteurs disponibles
$ids = [];
foreach ($traducteurs_disponibles as $traducteur) {
if (isset($traducteur->id)) {
$ids[] = (int)$traducteur->id;
}
}
if (!empty($ids)) {
$result[$langue_info['slug']] = $ids;
}
}
return !empty($result) ? json_encode($result) : null;
}
/**
* Crée les disponibilités pour une permanence à partir des jours et heures sélectionnés dans le formulaire
*
* Stocke directement les jours et plages horaires sélectionnés dans le formulaire de création de permanences,
* sans charger les disponibilités générales de l'intervenant.
*
* @param int $event_id ID de l'événement (permanence)
* @param int $intervenant_id ID de l'intervenant
* @param array $jours_permis Jours de la semaine sélectionnés (ex: ["lundi", "mardi"])
* @param array $plages_horaires Plages horaires sélectionnées (ex: [{"debut":"11:00","fin":"15:00"}])
* @return bool|WP_Error
*/
public static function create_for_permanence($event_id, $intervenant_id, $jours_permis = [], $plages_horaires = []) {
global $wpdb;
// Vérifier que l'intervenant existe
$intervenant = CRVI_Intervenant_Model::load($intervenant_id);
if (!$intervenant) {
return new \WP_Error('intervenant_not_found', 'Intervenant introuvable', ['status' => 404]);
}
// Convertir les jours et plages horaires en JSON
$jours_permis_json = is_array($jours_permis) ? json_encode($jours_permis) : json_encode([]);
$plages_horaires_json = is_array($plages_horaires) ? json_encode($plages_horaires) : json_encode([]);
// Charger les indisponibilités ponctuelles de l'intervenant (pour les vérifications)
$indisponibilites_acf = get_field('indisponibilitee_ponctuelle', 'user_' . $intervenant_id);
$indisponibilites = is_array($indisponibilites_acf) ? json_encode($indisponibilites_acf) : json_encode([]);
// Extraire les départements et types d'intervention
$departements_autories = !empty($intervenant->departements_ids)
? json_encode($intervenant->departements_ids)
: json_encode([]);
$types_intervention_autories = !empty($intervenant->types_intervention_ids)
? json_encode($intervenant->types_intervention_ids)
: json_encode([]);
// Créer l'entrée de permission avec les jours et heures sélectionnés
$table_name = $wpdb->prefix . 'crvi_event_permission';
$result = $wpdb->insert($table_name, [
'event_id' => $event_id,
'jours_permis' => $jours_permis_json,
'plages_horaires' => $plages_horaires_json,
'indisponibilites' => $indisponibilites,
'traducteur_jours_permis' => null,
'traducteur_indisponibilites' => null,
'local_indisponibilites' => null,
'departements_autories' => $departements_autories,
'types_intervention_autories' => $types_intervention_autories,
'date_creation' => current_time('mysql'),
'cree_par' => get_current_user_id(),
], [
'%d', // event_id
'%s', // jours_permis
'%s', // plages_horaires
'%s', // indisponibilites
'%s', // traducteur_jours_permis
'%s', // traducteur_indisponibilites
'%s', // local_indisponibilites
'%s', // departements_autories
'%s', // types_intervention_autories
'%s', // date_creation
'%d', // cree_par
]);
return $result !== false;
}
/**
* Vérifie rapidement si une date/heure est disponible selon les disponibilités stockées
*
* Vérifie :
* - Si le jour de la semaine de la date correspond aux jours disponibles
* - Si l'heure est dans les plages horaires autorisées
* - Si la date n'est pas dans une période d'indisponibilité
*
* OPTIMISÉ : Une seule requête SQL, pas de chargement de modèle Intervenant
*
* @param int $event_id ID de l'événement
* @param string $date Date au format Y-m-d
* @param string $heure Heure au format H:i (optionnel, pour vérifier les plages horaires)
* @return bool|null true=disponible, false=non disponible, null=pas de disponibilité définie (fallback requis)
*/
public static function is_date_heure_authorized($event_id, $date, $heure = null) {
global $wpdb;
$table_name = $wpdb->prefix . 'crvi_event_permission';
// Requête optimisée : une seule requête SQL pour toutes les disponibilités
// Récupère intervenant, traducteur et local en une seule fois (si présents dans la table)
$permission = $wpdb->get_row($wpdb->prepare(
"SELECT jours_permis, plages_horaires, indisponibilites,
traducteur_jours_permis, traducteur_indisponibilites,
local_indisponibilites
FROM $table_name
WHERE event_id = %d",
$event_id
), ARRAY_A);
if (!$permission) {
// Pas de permission définie, fallback vers l'intervenant
return null;
}
// Vérifier le jour de la semaine (lundi, mardi, etc. - pas une date spécifique)
$timestamp = strtotime($date);
if ($timestamp === false) {
return false;
}
$jour_semaine = (int)date('w', $timestamp); // 0=dimanche, 1=lundi, etc.
// Mapping jours français vers numériques (jours de la semaine)
$jours_mapping = [
'dimanche' => 0,
'lundi' => 1,
'mardi' => 2,
'mercredi' => 3,
'jeudi' => 4,
'vendredi' => 5,
'samedi' => 6,
];
// Vérifier si ce jour de la semaine est disponible
$jours_permis_json = $permission['jours_permis'] ?? '[]';
$jours_permis = json_decode($jours_permis_json, true) ?? [];
if (!empty($jours_permis)) {
$jours_permis_numeriques = [];
foreach ($jours_permis as $jour) {
$jour_lower = strtolower($jour);
if (isset($jours_mapping[$jour_lower])) {
$jours_permis_numeriques[] = $jours_mapping[$jour_lower];
}
}
// Vérifier si le jour de la semaine de la date est dans les jours disponibles
if (!in_array($jour_semaine, $jours_permis_numeriques, true)) {
return false; // Ce jour de la semaine n'est pas disponible
}
}
// Vérifier les indisponibilités ponctuelles
$indisponibilites_json = $permission['indisponibilites'] ?? '[]';
$indisponibilites = json_decode($indisponibilites_json, true) ?? [];
foreach ($indisponibilites as $indispo) {
$debut_str = $indispo['debut'] ?? $indispo['date_debut'] ?? '';
$fin_str = $indispo['fin'] ?? $indispo['date_fin'] ?? '';
if (empty($debut_str) || empty($fin_str)) {
continue;
}
// Convertir les dates ACF (format d/m/Y) en timestamp
$debut_timestamp = self::parse_acf_date($debut_str);
$fin_timestamp = self::parse_acf_date($fin_str);
if ($debut_timestamp && $fin_timestamp && $timestamp >= $debut_timestamp && $timestamp <= $fin_timestamp) {
return false; // Date dans une période d'indisponibilité
}
}
// Vérifier les plages horaires si une heure est fournie
if ($heure !== null && !empty($permission['plages_horaires'])) {
$plages_json = $permission['plages_horaires'];
$plages = json_decode($plages_json, true) ?? [];
if (!empty($plages)) {
$heure_timestamp = strtotime($heure);
$heure_autorisee = false;
foreach ($plages as $plage) {
$debut_plage = strtotime($plage['debut'] ?? '');
$fin_plage = strtotime($plage['fin'] ?? '');
if ($debut_plage && $fin_plage && $heure_timestamp >= $debut_plage && $heure_timestamp <= $fin_plage) {
$heure_autorisee = true;
break;
}
}
if (!$heure_autorisee) {
return false; // Heure non dans les plages autorisées
}
}
}
// Vérifier les disponibilités du traducteur (si présent dans les permissions stockées)
// OPTIMISATION : Si les données sont dans la table, on les utilise, sinon on laisse fallback
if (!empty($permission['traducteur_jours_permis']) || !empty($permission['traducteur_indisponibilites'])) {
// Vérifier le jour de la semaine pour le traducteur
$traducteur_jours_json = $permission['traducteur_jours_permis'] ?? '[]';
$traducteur_jours = json_decode($traducteur_jours_json, true) ?? [];
if (!empty($traducteur_jours)) {
$traducteur_jours_numeriques = [];
foreach ($traducteur_jours as $jour) {
$jour_lower = strtolower($jour);
if (isset($jours_mapping[$jour_lower])) {
$traducteur_jours_numeriques[] = $jours_mapping[$jour_lower];
}
}
if (!in_array($jour_semaine, $traducteur_jours_numeriques, true)) {
return false; // Ce jour de la semaine n'est pas disponible pour le traducteur
}
}
// Vérifier les indisponibilités ponctuelles du traducteur
$traducteur_indispo_json = $permission['traducteur_indisponibilites'] ?? '[]';
$traducteur_indispo = json_decode($traducteur_indispo_json, true) ?? [];
foreach ($traducteur_indispo as $indispo) {
$debut_str = $indispo['debut'] ?? $indispo['date_debut'] ?? '';
$fin_str = $indispo['fin'] ?? $indispo['date_fin'] ?? '';
if (empty($debut_str) || empty($fin_str)) {
continue;
}
$debut_timestamp = self::parse_acf_date($debut_str);
$fin_timestamp = self::parse_acf_date($fin_str);
if ($debut_timestamp && $fin_timestamp && $timestamp >= $debut_timestamp && $timestamp <= $fin_timestamp) {
return false; // Date dans une période d'indisponibilité du traducteur
}
}
}
// Si traducteur pas dans la table, on laisse le fallback dans update_event() le gérer
// Vérifier les disponibilités du local (si présent dans les permissions stockées)
// OPTIMISATION : Si les données sont dans la table, on les utilise, sinon on laisse fallback
if (!empty($permission['local_indisponibilites'])) {
$local_indispo_json = $permission['local_indisponibilites'] ?? '[]';
$local_indispo = json_decode($local_indispo_json, true) ?? [];
foreach ($local_indispo as $indispo) {
$debut_str = $indispo['debut'] ?? $indispo['date_debut'] ?? '';
$fin_str = $indispo['fin'] ?? $indispo['date_fin'] ?? '';
if (empty($debut_str) || empty($fin_str)) {
continue;
}
$debut_timestamp = self::parse_acf_date($debut_str);
$fin_timestamp = self::parse_acf_date($fin_str);
if ($debut_timestamp && $fin_timestamp && $timestamp >= $debut_timestamp && $timestamp <= $fin_timestamp) {
return false; // Date dans une période d'indisponibilité du local
}
}
}
// Si local pas dans la table, on laisse le fallback dans update_event() le gérer
return true; // Autorisé (intervenant, traducteur et local disponibles)
}
/**
* Parse une date ACF (format d/m/Y ou Y-m-d)
* @param string $date_str
* @return int|false Timestamp ou false
*/
private static function parse_acf_date($date_str) {
// Essayer le format ACF (d/m/Y)
$date = \DateTime::createFromFormat('d/m/Y', $date_str);
if ($date) {
return $date->getTimestamp();
}
// Essayer le format standard (Y-m-d)
$date = \DateTime::createFromFormat('Y-m-d', $date_str);
if ($date) {
return $date->getTimestamp();
}
// Fallback : strtotime
$timestamp = strtotime($date_str);
return $timestamp !== false ? $timestamp : false;
}
/**
* Met à jour les disponibilités d'un événement (ex: après modification de l'intervenant, traducteur ou local)
*
* Met à jour :
* - Les jours de la semaine disponibles (intervenant, traducteur)
* - Les indisponibilités ponctuelles (intervenant, traducteur, local)
* - Les départements/types d'intervention
* - Les traducteurs disponibles par langue (preset)
*
* Les plages horaires existantes sont conservées par défaut (utile pour les permanences)
*
* @param int $event_id
* @param int|null $intervenant_id Si null, utilise l'intervenant de l'événement
* @param bool $preserve_plages_horaires Si true, conserve les plages horaires existantes (défaut: true)
* @param int|null $traducteur_id ID du traducteur (si changé)
* @param int|null $local_id ID du local (si changé)
* @param string|null $langue_slug Slug de la langue de l'événement (pour précalculer traducteurs disponibles)
* @param string|null $date_rdv Date de l'événement (pour précalculer traducteurs disponibles)
* @return bool
*/
public static function update_from_intervenant($event_id, $intervenant_id = null, $preserve_plages_horaires = true, $traducteur_id = null, $local_id = null, $langue_slug = null, $date_rdv = null) {
global $wpdb;
// Si pas d'intervenant fourni, le récupérer depuis l'événement
if ($intervenant_id === null) {
$event = CRVI_Event_Model::load($event_id);
if (!$event || !$event->id_intervenant) {
return false;
}
$intervenant_id = $event->id_intervenant;
}
// Si traducteur/local non fournis, les récupérer depuis l'événement
if ($traducteur_id === null || $local_id === null) {
if (!$event) {
$event = CRVI_Event_Model::load($event_id);
}
if ($event) {
if ($traducteur_id === null) {
$traducteur_id = $event->id_traducteur ?? null;
}
if ($local_id === null) {
$local_id = $event->id_local ?? null;
}
}
}
$table_name = $wpdb->prefix . 'crvi_event_permission';
// Vérifier si la permission existe déjà
$existing = $wpdb->get_row($wpdb->prepare(
"SELECT id, plages_horaires, traducteur_jours_permis, traducteur_indisponibilites, local_indisponibilites
FROM $table_name WHERE event_id = %d",
$event_id
), ARRAY_A);
$intervenant = CRVI_Intervenant_Model::load($intervenant_id);
if (!$intervenant) {
return false;
}
// Récupérer les nouvelles données depuis l'intervenant
$jours_disponibles = get_field('jours_de_disponibilite', 'user_' . $intervenant_id);
$jours_permis = is_array($jours_disponibles) ? json_encode($jours_disponibles) : json_encode([]);
$indisponibilites_acf = get_field('indisponibilitee_ponctuelle', 'user_' . $intervenant_id);
$indisponibilites = is_array($indisponibilites_acf) ? json_encode($indisponibilites_acf) : json_encode([]);
$departements_autories = !empty($intervenant->departements_ids)
? json_encode($intervenant->departements_ids)
: json_encode([]);
$types_intervention_autories = !empty($intervenant->types_intervention_ids)
? json_encode($intervenant->types_intervention_ids)
: json_encode([]);
// Récupérer les disponibilités du traducteur si présent
$traducteur_jours_permis = null;
$traducteur_indisponibilites = null;
if ($traducteur_id) {
$traducteur = CRVI_Traducteur_Model::load($traducteur_id);
if ($traducteur) {
$traducteur_jours = get_field('jours_de_disponibilite', $traducteur_id);
$traducteur_jours_permis = is_array($traducteur_jours) ? json_encode($traducteur_jours) : json_encode([]);
$traducteur_indispo_acf = get_field('indisponibilitee_ponctuelle', $traducteur_id);
$traducteur_indisponibilites = is_array($traducteur_indispo_acf) ? json_encode($traducteur_indispo_acf) : json_encode([]);
}
}
// Récupérer les indisponibilités du local si présent
$local_indisponibilites = null;
if ($local_id) {
$local = CRVI_Local_Model::load($local_id);
if ($local) {
$local_indispo_acf = get_field('indisponibilitee_ponctuelle', $local_id);
$local_indisponibilites = is_array($local_indispo_acf) ? json_encode($local_indispo_acf) : json_encode([]);
}
}
// Précalculer les traducteurs disponibles par langue si langue et date fournies
$traducteurs_disponibles_par_langue = null;
if ($langue_slug && $date_rdv) {
$traducteurs_disponibles_par_langue = self::precalculate_traducteurs_par_langue($date_rdv, $langue_slug);
}
if ($existing) {
// Mettre à jour l'existant
$update_data = [
'jours_permis' => $jours_permis,
'indisponibilites' => $indisponibilites,
'traducteur_jours_permis' => $traducteur_jours_permis,
'traducteur_indisponibilites' => $traducteur_indisponibilites,
'local_indisponibilites' => $local_indisponibilites,
'departements_autories' => $departements_autories,
'types_intervention_autories' => $types_intervention_autories,
'traducteurs_disponibles_par_langue' => $traducteurs_disponibles_par_langue,
'date_modification' => current_time('mysql'),
'modifie_par' => get_current_user_id(),
];
// Conserver les plages horaires existantes si demandé
if ($preserve_plages_horaires && !empty($existing['plages_horaires'])) {
$update_data['plages_horaires'] = $existing['plages_horaires'];
$formats = ['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d']; // Avec plages_horaires
} else {
$formats = ['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d']; // Sans plages_horaires
}
$result = $wpdb->update(
$table_name,
$update_data,
['event_id' => $event_id],
$formats,
['%d'] // Format pour WHERE
);
return $result !== false;
} else {
// Créer une nouvelle entrée
return self::create_from_intervenant($event_id, $intervenant_id, null, $traducteur_id, $local_id, $langue_slug, $date_rdv) !== false;
}
}
/**
* Supprime les permissions d'un événement (lors de la suppression de l'événement)
* @param int $event_id
* @return bool
*/
public static function delete_by_event_id($event_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'crvi_event_permission';
return $wpdb->delete($table_name, ['event_id' => $event_id], ['%d']) !== false;
}
}