'Bénéficiaires', 'labels' => [ 'name' => 'Bénéficiaires', 'singular_name' => 'Bénéficiaire', 'add_new' => 'Ajouter un bénéficiaire', 'add_new_item' => 'Ajouter un nouveau bénéficiaire', 'edit_item' => 'Modifier le bénéficiaire', 'new_item' => 'Nouveau bénéficiaire', 'view_item' => 'Voir le bénéficiaire', 'search_items' => 'Rechercher un bénéficiaire', 'not_found' => 'Aucun bénéficiaire trouvé', 'not_found_in_trash' => 'Aucun bénéficiaire dans la corbeille', ], 'public' => true, 'show_in_menu' => true, 'menu_position' => 21, 'menu_icon' => 'dashicons-groups', 'supports' => ['title'], 'has_archive' => false, 'show_in_rest' => true, ]); // Déclaration de la taxonomie 'langue' (si pas déjà déclarée) self::register_taxonomy(); // Association de la taxonomie 'langue' au CPT 'beneficiaire' \register_taxonomy_for_object_type('langue', 'beneficiaire'); } public static function register_taxonomy() { \register_taxonomy('langue_beneficiaire', ['beneficiaire'], [ 'label' => 'Langues', 'labels' => [ 'name' => 'Langues', 'singular_name' => 'Langue', 'search_items' => 'Rechercher des langues', 'all_items' => 'Toutes les langues', 'edit_item' => 'Modifier la langue', 'update_item' => 'Mettre à jour la langue', 'add_new_item' => 'Ajouter une nouvelle langue', 'new_item_name' => 'Nom de la nouvelle langue', 'menu_name' => 'Langues', ], 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => true, 'show_tagcloud' => false, 'show_in_quick_edit' => true, 'show_admin_column' => true, 'hierarchical' => false, // comme une étiquette 'show_in_rest' => true, 'rewrite' => [ 'slug' => 'langue' ], ]); } public static function register_routes() { register_rest_route('crvi/v1', '/beneficiaires', [ [ 'methods' => 'GET', 'callback' => [self::class, 'get_items'], 'permission_callback' => '__return_true', ], [ 'methods' => 'POST', 'callback' => [self::class, 'create_item'], 'permission_callback' => [self::class, 'can_edit'], ], ]); // Endpoint pour rechercher des bénéficiaires par nom/prénom register_rest_route('crvi/v1', '/beneficiaires/search', [ [ 'methods' => 'GET', 'callback' => [self::class, 'search_beneficiaires'], 'permission_callback' => '__return_true', ], ]); register_rest_route('crvi/v1', '/beneficiaires/(?P\\d+)', [ [ 'methods' => 'GET', 'callback' => [self::class, 'get_item'], 'permission_callback' => '__return_true', ], [ 'methods' => 'PUT,PATCH', 'callback' => [self::class, 'update_item'], 'permission_callback' => [self::class, 'can_edit'], ], [ 'methods' => 'DELETE', 'callback' => [self::class, 'delete_item'], 'permission_callback' => [self::class, 'can_delete'], ], ]); // Endpoint pour récupérer les absences d'un bénéficiaire register_rest_route('crvi/v1', '/beneficiaires/(?P\\d+)/absences', [ [ 'methods' => 'GET', 'callback' => [self::class, 'get_absences'], 'permission_callback' => '__return_true', ], ]); // Endpoint pour mettre à jour le statut liste rouge d'un bénéficiaire register_rest_route('crvi/v1', '/beneficiaires/(?P\\d+)/liste-rouge', [ [ 'methods' => 'PUT,PATCH', 'callback' => [self::class, 'update_liste_rouge'], 'permission_callback' => [self::class, 'can_edit'], ], ]); } public static function get_items($request) { $model = new CRVI_Beneficiaire_Model(); $items = $model->get_all_beneficiaires($request->get_params()); return Api_Helper::json_success($items); } /** * Recherche de bénéficiaires par nom ou prénom * GET /wp-json/crvi/v1/beneficiaires/search?search=durand */ public static function search_beneficiaires($request) { $search = $request->get_param('search'); if (empty($search) || strlen($search) < 3) { return Api_Helper::json_success([]); } // Rechercher les bénéficiaires par nom ou prénom $args = [ 'post_type' => 'beneficiaire', 'posts_per_page' => 20, 'post_status' => 'publish', 'meta_query' => [ 'relation' => 'OR', [ 'key' => 'nom', 'value' => $search, 'compare' => 'LIKE' ], [ 'key' => 'prenom', 'value' => $search, 'compare' => 'LIKE' ] ] ]; $query = new \WP_Query($args); $results = []; if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); $post_id = get_the_ID(); $nom = get_post_meta($post_id, 'nom', true); $prenom = get_post_meta($post_id, 'prenom', true); $results[] = [ 'id' => $post_id, 'nom' => $nom, 'prenom' => $prenom, 'nom_complet' => trim($prenom . ' ' . $nom) ]; } wp_reset_postdata(); } return Api_Helper::json_success($results); } public static function get_item($request) { $id = (int) $request['id']; $item = CRVI_Beneficiaire_Model::load($id); if (!$item) { return Api_Helper::json_error('Bénéficiaire introuvable', 404); } // Convertir l'objet en tableau pour pouvoir ajouter des champs $data = (array) $item; // Ajouter le champ ACF personne_en_liste_rouge if (function_exists('get_field')) { $personne_en_liste_rouge = get_field('field_69495826ac495', $id); $data['personne_en_liste_rouge'] = $personne_en_liste_rouge; } return Api_Helper::json_success($data); } public static function create_item($request) { $data = $request->get_json_params(); $validation = self::validate_beneficiaire_data($data); if (is_wp_error($validation)) { return Api_Helper::json_error($validation->get_error_message(), 400); } $model = new CRVI_Beneficiaire_Model(); $result = $model->create($data); if (is_wp_error($result)) { return $result; } return Api_Helper::json_success([ 'id' => $result, 'nom' => $data['nom'], 'prenom' => $data['prenom'] ?? '', 'message' => 'Bénéficiaire créé avec succès' ]); } public static function update_item($request) { $id = (int) $request['id']; $model = new CRVI_Beneficiaire_Model(); $result = $model->update($id, $request->get_json_params()); if (is_wp_error($result)) { return $result; } } public static function delete_item($request) { $id = (int) $request['id']; $model = new CRVI_Beneficiaire_Model(); $result = $model->delete($id); if (is_wp_error($result)) { return $result; } return Api_Helper::json_success(['id' => $id, 'deleted' => true]); } /** * Récupère les absences d'un bénéficiaire * @param \WP_REST_Request $request * @return \WP_REST_Response */ public static function get_absences($request) { $id = (int) $request['id']; if (!$id) { return Api_Helper::json_error('ID du bénéficiaire requis', 400); } $model = new CRVI_Beneficiaire_Model(); $absences = $model->get_absences($id); if (is_wp_error($absences)) { return $absences; } return Api_Helper::json_success($absences); } /** * Met à jour le statut liste rouge d'un bénéficiaire * @param \WP_REST_Request $request * @return \WP_REST_Response */ public static function update_liste_rouge($request) { $id = (int) $request['id']; if (!$id) { return Api_Helper::json_error('ID du bénéficiaire requis', 400); } // Vérifier que le bénéficiaire existe $beneficiaire = get_post($id); if (!$beneficiaire || $beneficiaire->post_type !== 'beneficiaire') { return Api_Helper::json_error('Bénéficiaire introuvable', 404); } $data = $request->get_json_params(); $is_liste_rouge = isset($data['liste_rouge']) ? (bool) $data['liste_rouge'] : false; // Mettre à jour le champ ACF personne_en_liste_rouge if (!function_exists('update_field')) { return Api_Helper::json_error('ACF n\'est pas disponible', 500); } // Le champ checkbox ACF retourne un tableau avec "oui" si coché $field_value = $is_liste_rouge ? ['oui'] : []; $result = update_field('field_69495826ac495', $field_value, $id); if ($result === false) { return Api_Helper::json_error('Erreur lors de la mise à jour du statut liste rouge', 500); } return Api_Helper::json_success([ 'id' => $id, 'liste_rouge' => $is_liste_rouge, 'message' => $is_liste_rouge ? 'Bénéficiaire ajouté à la liste rouge' : 'Bénéficiaire retiré de la liste rouge' ]); } // Permissions personnalisées public static function can_edit() { return current_user_can('edit_posts'); } public static function can_delete() { return current_user_can('delete_posts'); } public static function import_csv() { if (!current_user_can('manage_options')) { wp_die('Non autorisé'); } if (empty($_FILES['import_csv']['tmp_name'])) { wp_redirect(admin_url('admin.php?page=crvi_agenda&import=error&msg=Fichier manquant')); exit; } $file = $_FILES['import_csv']['tmp_name']; $handle = fopen($file, 'r'); if (!$handle) { wp_redirect(admin_url('admin.php?page=crvi_agenda&import=error&msg=Impossible d\'ouvrir le fichier')); exit; } $header = fgetcsv($handle, 0, ','); $created = $updated = $errors = 0; while (($row = fgetcsv($handle, 0, ',')) !== false) { $data = array_combine($header, $row); $result = CRVI_Beneficiaire_Model::create($data, true); if ($result === 'created') $created++; elseif ($result === 'updated') $updated++; else $errors++; } fclose($handle); $msg = "Créés: $created, Modifiés: $updated, Erreurs: $errors"; wp_redirect(admin_url('admin.php?page=crvi_agenda&import=success&msg=' . urlencode($msg))); exit; } // Handler pour l'import CSV via formulaire admin public static function import_csv_admin() { if (!current_user_can('edit_posts')) { wp_die('Non autorisé'); } check_admin_referer('crvi_import_beneficiaire'); if (empty($_FILES['import_csv']['tmp_name'])) { wp_redirect(admin_url('admin.php?page=crvi_agenda&import=error&msg=Fichier manquant')); exit; } $file = $_FILES['import_csv']['tmp_name']; $handle = fopen($file, 'r'); if (!$handle) { wp_redirect(admin_url('admin.php?page=crvi_agenda&import=error&msg=Impossible d\'ouvrir le fichier')); exit; } $header = fgetcsv($handle, 0, ','); $created = $updated = $errors = 0; while (($row = fgetcsv($handle, 0, ',')) !== false) { $data = array_combine($header, $row); //sanitize data $data = array_combine( array_map(function($k) { return sanitize_title($k); }, array_keys($data)), array_map('trim', array_values($data)) ); $result = CRVI_Beneficiaire_Model::create($data, false); if ($result === 'created') $created++; elseif ($result === 'updated') $updated++; else $errors++; } fclose($handle); $msg = "Créés: $created, Modifiés: $updated, Erreurs: $errors"; wp_redirect(admin_url('admin.php?page=crvi_agenda&import=success&msg=' . urlencode($msg))); exit; } /** * Validation des données de bénéficiaire */ public static function validate_beneficiaire_data($data) { if (empty($data['nom'])) { return new \WP_Error('missing_nom', 'Le nom est obligatoire'); } if (!empty($data['email']) && !is_email($data['email'])) { return new \WP_Error('invalid_email', 'L\'email n\'est pas valide'); } return true; } }