358 lines
12 KiB
PHP
358 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ESI_CRVI_AGENDA\controllers;
|
|
|
|
use ESI_CRVI_AGENDA\models\CRVI_Local_Model;
|
|
use ESI_CRVI_AGENDA\helpers\Api_Helper;
|
|
|
|
class CRVI_Local_Controller {
|
|
public static function register_cpt() {
|
|
register_post_type('local', [
|
|
'label' => 'Locaux',
|
|
'labels' => [
|
|
'name' => 'Locaux',
|
|
'singular_name' => 'Local',
|
|
'add_new' => 'Ajouter un local',
|
|
'add_new_item' => 'Ajouter un nouveau local',
|
|
'edit_item' => 'Modifier le local',
|
|
'new_item' => 'Nouveau local',
|
|
'view_item' => 'Voir le local',
|
|
'search_items' => 'Rechercher un local',
|
|
'not_found' => 'Aucun local trouvé',
|
|
'not_found_in_trash' => 'Aucun local dans la corbeille',
|
|
],
|
|
'public' => true,
|
|
'show_in_menu' => true,
|
|
'menu_position' => 23,
|
|
'menu_icon' => 'dashicons-building',
|
|
'supports' => ['title'],
|
|
'has_archive' => false,
|
|
'show_in_rest' => true,
|
|
]);
|
|
}
|
|
|
|
public static function register_routes() {
|
|
register_rest_route('crvi/v1', '/locaux', [
|
|
[
|
|
'methods' => 'GET',
|
|
'callback' => [self::class, 'get_items'],
|
|
'permission_callback' => '__return_true',
|
|
],
|
|
[
|
|
'methods' => 'POST',
|
|
'callback' => [self::class, 'create_item'],
|
|
'permission_callback' => [self::class, 'can_edit'],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('crvi/v1', '/locaux/disponibles', [
|
|
[
|
|
'methods' => 'GET',
|
|
'callback' => [self::class, 'filtrer_disponibles'],
|
|
'permission_callback' => '__return_true',
|
|
'args' => [
|
|
'date_debut' => [
|
|
'required' => false,
|
|
'type' => 'string',
|
|
'description' => 'Date de début (YYYY-MM-DD)',
|
|
],
|
|
'date_fin' => [
|
|
'required' => false,
|
|
'type' => 'string',
|
|
'description' => 'Date de fin (YYYY-MM-DD)',
|
|
],
|
|
'heure_debut' => [
|
|
'required' => false,
|
|
'type' => 'string',
|
|
'description' => 'Heure de début (HH:MM)',
|
|
],
|
|
'heure_fin' => [
|
|
'required' => false,
|
|
'type' => 'string',
|
|
'description' => 'Heure de fin (HH:MM)',
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('crvi/v1', '/locaux/import', [
|
|
[
|
|
'methods' => 'POST',
|
|
'callback' => [self::class, 'import_csv'],
|
|
'permission_callback' => [self::class, 'can_edit'],
|
|
'args' => [
|
|
'file' => [
|
|
'required' => true,
|
|
'description' => 'Fichier CSV à importer',
|
|
'type' => 'file',
|
|
],
|
|
],
|
|
],
|
|
]);
|
|
|
|
register_rest_route('crvi/v1', '/locaux/(?P<id>\\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'],
|
|
],
|
|
]);
|
|
}
|
|
|
|
public static function get_items($request) {
|
|
$items = CRVI_Local_Model::all();
|
|
return Api_Helper::json_success($items);
|
|
}
|
|
|
|
public static function get_item($request) {
|
|
$id = (int) $request['id'];
|
|
$item = CRVI_Local_Model::load($id);
|
|
if (!$item) {
|
|
return Api_Helper::json_error('Local introuvable', 404);
|
|
}
|
|
return Api_Helper::json_success($item);
|
|
}
|
|
|
|
/**
|
|
* Filtre les locaux disponibles selon les critères fournis
|
|
* @param WP_REST_Request $request
|
|
* @return WP_REST_Response
|
|
*/
|
|
public static function filtrer_disponibles($request) {
|
|
$date_debut = $request->get_param('date_debut');
|
|
$date_fin = $request->get_param('date_fin');
|
|
$heure_debut = $request->get_param('heure_debut');
|
|
$heure_fin = $request->get_param('heure_fin');
|
|
|
|
// Récupérer tous les locaux
|
|
$tous_locaux = CRVI_Local_Model::all();
|
|
|
|
// Si aucun critère de temps n'est fourni, retourner tous les locaux
|
|
if (empty($date_debut) && empty($date_fin) && empty($heure_debut) && empty($heure_fin)) {
|
|
return Api_Helper::json_success($tous_locaux);
|
|
}
|
|
|
|
// Filtrer les locaux disponibles selon les critères
|
|
$locaux_disponibles = [];
|
|
|
|
foreach ($tous_locaux as $local) {
|
|
$disponible = true;
|
|
|
|
// Vérifier la disponibilité selon les critères fournis
|
|
if ($date_debut && $date_fin) {
|
|
// Vérifier s'il y a des conflits d'événements dans cette période
|
|
$conflits = self::verifier_conflits_local($local['id'], $date_debut, $date_fin, $heure_debut, $heure_fin);
|
|
if (!empty($conflits)) {
|
|
$disponible = false;
|
|
}
|
|
}
|
|
|
|
if ($disponible) {
|
|
$locaux_disponibles[] = $local;
|
|
}
|
|
}
|
|
|
|
return Api_Helper::json_success($locaux_disponibles);
|
|
}
|
|
|
|
/**
|
|
* Vérifie s'il y a des conflits d'événements pour un local donné
|
|
* @param int $local_id
|
|
* @param string $date_debut
|
|
* @param string $date_fin
|
|
* @param string $heure_debut
|
|
* @param string $heure_fin
|
|
* @return array
|
|
*/
|
|
private static function verifier_conflits_local($local_id, $date_debut, $date_fin, $heure_debut = null, $heure_fin = null) {
|
|
global $wpdb;
|
|
|
|
$table_events = $wpdb->prefix . 'crvi_agenda';
|
|
|
|
$where_conditions = ['local_id = %d'];
|
|
$where_values = [$local_id];
|
|
|
|
// Ajouter les conditions de date
|
|
if ($date_debut && $date_fin) {
|
|
$where_conditions[] = '(
|
|
(date_rdv BETWEEN %s AND %s) OR
|
|
(date_fin BETWEEN %s AND %s) OR
|
|
(%s BETWEEN date_rdv AND date_fin) OR
|
|
(%s BETWEEN date_rdv AND date_fin)
|
|
)';
|
|
$where_values = array_merge($where_values, [$date_debut, $date_fin, $date_debut, $date_fin, $date_debut, $date_fin]);
|
|
}
|
|
|
|
// Ajouter les conditions d'heure si fournies
|
|
if ($heure_debut && $heure_fin) {
|
|
$where_conditions[] = '(
|
|
(heure_rdv BETWEEN %s AND %s) OR
|
|
(heure_fin BETWEEN %s AND %s) OR
|
|
(%s BETWEEN heure_rdv AND heure_fin) OR
|
|
(%s BETWEEN heure_rdv AND heure_fin)
|
|
)';
|
|
$where_values = array_merge($where_values, [$heure_debut, $heure_fin, $heure_debut, $heure_fin, $heure_debut, $heure_fin]);
|
|
}
|
|
|
|
$where_clause = implode(' AND ', $where_conditions);
|
|
$query = $wpdb->prepare(
|
|
"SELECT * FROM {$table_events} WHERE {$where_clause}",
|
|
$where_values
|
|
);
|
|
|
|
return $wpdb->get_results($query, ARRAY_A);
|
|
}
|
|
|
|
public static function create($request) {
|
|
|
|
$data = $request->get_json_params();
|
|
|
|
|
|
$model = new CRVI_Local_Model();
|
|
|
|
$validation = self::validate_local_data($data);
|
|
if (is_wp_error($validation)) {
|
|
return Api_Helper::json_error($validation->get_error_message(), 400);
|
|
}
|
|
|
|
$result = $model->create($data);
|
|
if (is_wp_error($result)) {
|
|
return $result;
|
|
}
|
|
|
|
return Api_Helper::json_success([
|
|
'id' => $result,
|
|
'nom' => $data['nom'],
|
|
'message' => 'Local créé avec succès'
|
|
]);
|
|
}
|
|
|
|
public static function update_item($request) {
|
|
$id = (int) $request['id'];
|
|
$model = new CRVI_Local_Model();
|
|
$result = $model->update($id, $request->get_json_params());
|
|
if (is_wp_error($result)) {
|
|
return $result;
|
|
}
|
|
return Api_Helper::json_success(['id' => $id]);
|
|
}
|
|
|
|
public static function delete_item($request) {
|
|
$id = (int) $request['id'];
|
|
$model = new CRVI_Local_Model();
|
|
$result = $model->delete($id);
|
|
if (is_wp_error($result)) {
|
|
return $result;
|
|
}
|
|
return Api_Helper::json_success(['id' => $id, 'deleted' => true]);
|
|
}
|
|
|
|
/**
|
|
* Import CSV de locaux via REST
|
|
* @param WP_REST_Request $request
|
|
* @return array
|
|
*/
|
|
public static function import_csv($request) {
|
|
if (!current_user_can('edit_posts')) {
|
|
return Api_Helper::json_error('Non autorisé', 403);
|
|
}
|
|
$file = $request->get_file_params()['file'] ?? null;
|
|
if (!$file || !is_uploaded_file($file['tmp_name'])) {
|
|
return Api_Helper::json_error('Fichier CSV manquant ou invalide', 400);
|
|
}
|
|
$handle = fopen($file['tmp_name'], 'r');
|
|
if (!$handle) {
|
|
return Api_Helper::json_error('Impossible d\'ouvrir le fichier', 400);
|
|
}
|
|
$header = fgetcsv($handle, 0, ',');
|
|
$results = [];
|
|
$row_num = 1;
|
|
while (($row = fgetcsv($handle, 0, ',')) !== false) {
|
|
$row_num++;
|
|
$data = array_combine($header, $row);
|
|
$model = new CRVI_Local_Model();
|
|
$result = $model->create($data);
|
|
$results[] = [
|
|
'ligne' => $row_num,
|
|
'data' => $data,
|
|
'resultat' => $result
|
|
];
|
|
}
|
|
fclose($handle);
|
|
return Api_Helper::json_success(['import' => $results]);
|
|
}
|
|
|
|
// 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');
|
|
}
|
|
|
|
// 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_local');
|
|
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);
|
|
|
|
$data = array_combine(
|
|
array_map(function($k) { return sanitize_title($k); }, array_keys($data)),
|
|
array_map('trim', array_values($data))
|
|
);
|
|
|
|
$model = new CRVI_Local_Model();
|
|
$result = $model->create($data);
|
|
|
|
if (is_numeric($result)) {
|
|
$created++;
|
|
} elseif (is_wp_error($result) && $result->get_error_code() === '409') {
|
|
// Nom déjà utilisé - on pourrait mettre à jour au lieu d'ignorer
|
|
$errors++;
|
|
} else {
|
|
$errors++;
|
|
}
|
|
}
|
|
fclose($handle);
|
|
$msg = "Créés: $created, Erreurs: $errors";
|
|
wp_redirect(admin_url('admin.php?page=crvi_agenda&import=success&msg=' . urlencode($msg)));
|
|
exit;
|
|
}
|
|
|
|
public static function validate_local_data($data) {
|
|
if (empty($data['nom'])) {
|
|
return new \WP_Error('missing_nom', 'Le nom du local est obligatoire');
|
|
}
|
|
if (!empty($data['capacite']) && !is_numeric($data['capacite'])) {
|
|
return new \WP_Error('invalid_capacite', 'La capacité doit être un nombre');
|
|
}
|
|
return true;
|
|
}
|
|
} |