633 lines
22 KiB
PHP
633 lines
22 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers;
|
|
|
|
require_once __DIR__ . '/../Services/LogService.php';
|
|
require_once __DIR__ . '/../Services/ApiService.php';
|
|
|
|
use PDO;
|
|
use PDOException;
|
|
use Database;
|
|
use AppConfig;
|
|
use Request;
|
|
use Response;
|
|
use Session;
|
|
use LogService;
|
|
use ApiService;
|
|
use Exception;
|
|
|
|
class EntiteController {
|
|
private PDO $db;
|
|
private AppConfig $appConfig;
|
|
|
|
public function __construct() {
|
|
$this->db = Database::getInstance();
|
|
$this->appConfig = AppConfig::getInstance();
|
|
}
|
|
|
|
/**
|
|
* Crée une nouvelle entité (amicale) si elle n'existe pas déjà avec le code postal spécifié
|
|
*
|
|
* @param string $name Nom de l'amicale
|
|
* @param string $postalCode Code postal
|
|
* @param string $cityName Nom de la ville
|
|
* @return array|false Tableau contenant l'ID de l'entité créée ou false en cas d'erreur
|
|
* @throws Exception Si une entité existe déjà avec ce code postal
|
|
*/
|
|
public function createEntite(string $name, string $postalCode, string $cityName): array|false {
|
|
try {
|
|
// Vérification que le code postal n'existe pas déjà
|
|
$stmt = $this->db->prepare('SELECT id FROM entites WHERE code_postal = ?');
|
|
$stmt->execute([$postalCode]);
|
|
|
|
if ($stmt->fetch()) {
|
|
throw new Exception('Une amicale existe déjà sur ce code postal');
|
|
}
|
|
|
|
// Chiffrement du nom
|
|
$encryptedName = ApiService::encryptData($name);
|
|
|
|
// Insertion de la nouvelle entité
|
|
$stmt = $this->db->prepare('
|
|
INSERT INTO entites (
|
|
encrypted_name,
|
|
code_postal,
|
|
ville,
|
|
fk_type,
|
|
created_at,
|
|
chk_active
|
|
) VALUES (?, ?, ?, 1, NOW(), 1)
|
|
');
|
|
|
|
$stmt->execute([
|
|
$encryptedName,
|
|
$postalCode,
|
|
$cityName
|
|
]);
|
|
|
|
$entiteId = $this->db->lastInsertId();
|
|
|
|
if (!$entiteId) {
|
|
throw new Exception('Erreur lors de la création de l\'entité');
|
|
}
|
|
|
|
LogService::log('Création d\'une nouvelle entité GeoSector', [
|
|
'level' => 'info',
|
|
'entiteId' => $entiteId,
|
|
'name' => $name,
|
|
'postalCode' => $postalCode,
|
|
'cityName' => $cityName
|
|
]);
|
|
|
|
return [
|
|
'id' => $entiteId,
|
|
'name' => $name,
|
|
'postalCode' => $postalCode,
|
|
'cityName' => $cityName
|
|
];
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la création de l\'entité GeoSector', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'name' => $name,
|
|
'postalCode' => $postalCode,
|
|
'cityName' => $cityName
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère une entité par son ID
|
|
*
|
|
* @param int $id ID de l'entité
|
|
* @return array|false Données de l'entité ou false si non trouvée
|
|
*/
|
|
public function getEntiteById(int $id): array|false {
|
|
try {
|
|
$stmt = $this->db->prepare('
|
|
SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active
|
|
FROM entites
|
|
WHERE id = ? AND chk_active = 1
|
|
');
|
|
|
|
$stmt->execute([$id]);
|
|
$entite = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$entite) {
|
|
return false;
|
|
}
|
|
|
|
// Déchiffrement du nom
|
|
$entite['name'] = ApiService::decryptData($entite['encrypted_name']);
|
|
unset($entite['encrypted_name']);
|
|
|
|
return $entite;
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la récupération de l\'entité GeoSector', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'id' => $id
|
|
]);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère une entité par son code postal
|
|
*
|
|
* @param string $postalCode Code postal
|
|
* @return array|false Données de l'entité ou false si non trouvée
|
|
*/
|
|
public function getEntiteByPostalCode(string $postalCode): array|false {
|
|
try {
|
|
$stmt = $this->db->prepare('
|
|
SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active
|
|
FROM entites
|
|
WHERE code_postal = ? AND chk_active = 1
|
|
');
|
|
|
|
$stmt->execute([$postalCode]);
|
|
$entite = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$entite) {
|
|
return false;
|
|
}
|
|
|
|
// Déchiffrement du nom
|
|
$entite['name'] = ApiService::decryptData($entite['encrypted_name']);
|
|
unset($entite['encrypted_name']);
|
|
|
|
return $entite;
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la récupération de l\'entité GeoSector par code postal', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'postalCode' => $postalCode
|
|
]);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vérifie si une entité existe avec le code postal spécifié, et en crée une nouvelle si nécessaire
|
|
*
|
|
* @param string $name Nom de l'amicale
|
|
* @param string $postalCode Code postal
|
|
* @return int ID de l'entité créée ou existante
|
|
* @throws Exception Si une entité existe déjà avec ce code postal
|
|
*/
|
|
public function getOrCreateEntiteByPostalCode(string $name, string $postalCode): int {
|
|
try {
|
|
// Vérification que le code postal n'existe pas déjà
|
|
$stmt = $this->db->prepare('SELECT COUNT(*) as count FROM entites WHERE code_postal = ?');
|
|
$stmt->execute([$postalCode]);
|
|
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($result && $result['count'] > 0) {
|
|
throw new Exception('Une amicale est déjà inscrite à ce code postal');
|
|
}
|
|
|
|
// Chiffrement du nom
|
|
$encryptedName = ApiService::encryptData($name);
|
|
|
|
// Insertion de la nouvelle entité
|
|
$stmt = $this->db->prepare('
|
|
INSERT INTO entites (
|
|
encrypted_name,
|
|
code_postal,
|
|
ville,
|
|
fk_type,
|
|
created_at,
|
|
chk_active
|
|
) VALUES (?, ?, "", 1, NOW(), 1)
|
|
');
|
|
|
|
$stmt->execute([
|
|
$encryptedName,
|
|
$postalCode
|
|
]);
|
|
|
|
$entiteId = (int)$this->db->lastInsertId();
|
|
|
|
if (!$entiteId) {
|
|
throw new Exception('Erreur lors de la création de l\'entité');
|
|
}
|
|
|
|
LogService::log('Création d\'une nouvelle entité GeoSector via getOrCreateEntiteByPostalCode', [
|
|
'level' => 'info',
|
|
'entiteId' => $entiteId,
|
|
'name' => $name,
|
|
'postalCode' => $postalCode
|
|
]);
|
|
|
|
return $entiteId;
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la vérification/création de l\'entité GeoSector', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'name' => $name,
|
|
'postalCode' => $postalCode
|
|
]);
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère toutes les entités actives
|
|
*
|
|
* @return array Liste des entités
|
|
*/
|
|
public function getEntites(): void {
|
|
try {
|
|
$stmt = $this->db->prepare('
|
|
SELECT id, encrypted_name, code_postal, ville, fk_type, chk_active
|
|
FROM entites
|
|
WHERE chk_active = 1
|
|
ORDER BY code_postal ASC
|
|
');
|
|
|
|
$stmt->execute();
|
|
$entites = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$result = [];
|
|
foreach ($entites as $entite) {
|
|
// Déchiffrement du nom pour chaque entité
|
|
$entite['name'] = ApiService::decryptData($entite['encrypted_name']);
|
|
unset($entite['encrypted_name']);
|
|
$result[] = $entite;
|
|
}
|
|
|
|
Response::json([
|
|
'status' => 'success',
|
|
'entites' => $result
|
|
], 200);
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la récupération des entités GeoSector', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage()
|
|
]);
|
|
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Erreur lors de la récupération des entités'
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recherche les coordonnées GPS d'une caserne de pompiers à partir d'une adresse
|
|
*
|
|
* @param string $address Adresse complète (adresse + code postal + ville)
|
|
* @param string $postalCode Code postal
|
|
* @param string $city Ville
|
|
* @return array|null Tableau contenant les coordonnées GPS [lat, lng] ou null si non trouvé
|
|
*/
|
|
private function findFireStationCoordinates(string $address, string $postalCode, string $city): ?array {
|
|
try {
|
|
// Construire l'adresse complète
|
|
$fullAddress = urlencode($address . ' ' . $postalCode . ' ' . $city);
|
|
|
|
// Mots-clés pour rechercher une caserne de pompiers
|
|
$keywords = ['pompiers', 'sapeurs-pompiers', 'sdis', 'caserne', 'centre de secours'];
|
|
|
|
foreach ($keywords as $keyword) {
|
|
// Construire l'URL de recherche
|
|
$searchUrl = "https://api-adresse.data.gouv.fr/search/?q=" . urlencode($keyword) . "&postcode=$postalCode&limit=1";
|
|
|
|
// Effectuer la requête
|
|
$response = file_get_contents($searchUrl);
|
|
|
|
if ($response) {
|
|
$data = json_decode($response, true);
|
|
|
|
// Vérifier si des résultats ont été trouvés
|
|
if (isset($data['features']) && count($data['features']) > 0) {
|
|
$feature = $data['features'][0];
|
|
|
|
// Vérifier si les coordonnées sont disponibles
|
|
if (isset($feature['geometry']['coordinates'])) {
|
|
$coordinates = $feature['geometry']['coordinates'];
|
|
|
|
// Les coordonnées sont au format [longitude, latitude]
|
|
return [
|
|
'lat' => $coordinates[1],
|
|
'lng' => $coordinates[0]
|
|
];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Si aucune caserne n'a été trouvée, essayer avec l'adresse de la mairie
|
|
$searchUrl = "https://api-adresse.data.gouv.fr/search/?q=mairie&postcode=$postalCode&limit=1";
|
|
$response = file_get_contents($searchUrl);
|
|
|
|
if ($response) {
|
|
$data = json_decode($response, true);
|
|
|
|
if (isset($data['features']) && count($data['features']) > 0) {
|
|
$feature = $data['features'][0];
|
|
|
|
if (isset($feature['geometry']['coordinates'])) {
|
|
$coordinates = $feature['geometry']['coordinates'];
|
|
|
|
return [
|
|
'lat' => $coordinates[1],
|
|
'lng' => $coordinates[0]
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Si toujours rien, essayer avec l'adresse complète
|
|
$searchUrl = "https://api-adresse.data.gouv.fr/search/?q=$fullAddress&limit=1";
|
|
$response = file_get_contents($searchUrl);
|
|
|
|
if ($response) {
|
|
$data = json_decode($response, true);
|
|
|
|
if (isset($data['features']) && count($data['features']) > 0) {
|
|
$feature = $data['features'][0];
|
|
|
|
if (isset($feature['geometry']['coordinates'])) {
|
|
$coordinates = $feature['geometry']['coordinates'];
|
|
|
|
return [
|
|
'lat' => $coordinates[1],
|
|
'lng' => $coordinates[0]
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Aucune coordonnée trouvée
|
|
return null;
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la recherche des coordonnées GPS', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'address' => $address,
|
|
'postalCode' => $postalCode,
|
|
'city' => $city
|
|
]);
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Met à jour une entité existante avec les données fournies
|
|
* Seuls les administrateurs (rôle > 2) peuvent modifier certains champs
|
|
*
|
|
* @return void
|
|
*/
|
|
public function updateEntite(): void {
|
|
try {
|
|
// Vérifier l'authentification et les droits d'accès
|
|
$userId = Session::getUserId();
|
|
if (!$userId) {
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Vous devez être connecté pour effectuer cette action'
|
|
], 401);
|
|
return;
|
|
}
|
|
|
|
// Récupérer le rôle de l'utilisateur
|
|
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
|
|
$stmt->execute([$userId]);
|
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$user) {
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Utilisateur non trouvé'
|
|
], 404);
|
|
return;
|
|
}
|
|
|
|
$userRole = (int)$user['fk_role'];
|
|
$isAdmin = $userRole > 2;
|
|
|
|
// Récupérer les données de la requête
|
|
$data = Request::getJson();
|
|
|
|
if (!isset($data['id']) || empty($data['id'])) {
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'ID de l\'entité requis'
|
|
], 400);
|
|
return;
|
|
}
|
|
|
|
$entiteId = (int)$data['id'];
|
|
|
|
// Récupérer les données actuelles de l'entité pour vérifier si l'adresse a changé
|
|
$stmt = $this->db->prepare('SELECT adresse1, adresse2, code_postal, ville FROM entites WHERE id = ?');
|
|
$stmt->execute([$entiteId]);
|
|
$currentEntite = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$currentEntite) {
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Entité non trouvée'
|
|
], 404);
|
|
return;
|
|
}
|
|
|
|
// Vérifier si l'adresse a changé
|
|
$addressChanged = false;
|
|
$newAdresse1 = $data['adresse1'] ?? $currentEntite['adresse1'];
|
|
$newAdresse2 = $data['adresse2'] ?? $currentEntite['adresse2'];
|
|
$newCodePostal = $data['code_postal'] ?? $currentEntite['code_postal'];
|
|
$newVille = $data['ville'] ?? $currentEntite['ville'];
|
|
|
|
// Vérifier si l'adresse a changé
|
|
if (
|
|
$newAdresse1 !== $currentEntite['adresse1'] ||
|
|
$newAdresse2 !== $currentEntite['adresse2'] ||
|
|
$newCodePostal !== $currentEntite['code_postal'] ||
|
|
$newVille !== $currentEntite['ville']
|
|
) {
|
|
$addressChanged = true;
|
|
}
|
|
|
|
// Si l'adresse a changé, recalculer les coordonnées GPS
|
|
if ($addressChanged) {
|
|
// Construire l'adresse complète
|
|
$fullAddress = $newAdresse1;
|
|
if (!empty($newAdresse2)) {
|
|
$fullAddress .= ' ' . $newAdresse2;
|
|
}
|
|
|
|
// Rechercher les coordonnées GPS de la caserne de pompiers
|
|
$coordinates = $this->findFireStationCoordinates($fullAddress, $newCodePostal, $newVille);
|
|
|
|
// Si des coordonnées ont été trouvées, les ajouter aux champs à mettre à jour
|
|
if ($coordinates) {
|
|
$data['gps_lat'] = $coordinates['lat'];
|
|
$data['gps_lng'] = $coordinates['lng'];
|
|
|
|
LogService::log('Coordonnées GPS mises à jour suite à un changement d\'adresse', [
|
|
'level' => 'info',
|
|
'entiteId' => $entiteId,
|
|
'lat' => $coordinates['lat'],
|
|
'lng' => $coordinates['lng']
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Préparer les champs à mettre à jour
|
|
$updateFields = [];
|
|
$params = [];
|
|
|
|
// Champs modifiables par tous les utilisateurs
|
|
if (isset($data['name']) && !empty($data['name'])) {
|
|
$updateFields[] = 'encrypted_name = ?';
|
|
$params[] = ApiService::encryptData($data['name']);
|
|
}
|
|
|
|
if (isset($data['adresse1'])) {
|
|
$updateFields[] = 'adresse1 = ?';
|
|
$params[] = $data['adresse1'];
|
|
}
|
|
|
|
if (isset($data['adresse2'])) {
|
|
$updateFields[] = 'adresse2 = ?';
|
|
$params[] = $data['adresse2'];
|
|
}
|
|
|
|
if (isset($data['code_postal']) && !empty($data['code_postal'])) {
|
|
$updateFields[] = 'code_postal = ?';
|
|
$params[] = $data['code_postal'];
|
|
}
|
|
|
|
if (isset($data['ville'])) {
|
|
$updateFields[] = 'ville = ?';
|
|
$params[] = $data['ville'];
|
|
}
|
|
|
|
if (isset($data['fk_region'])) {
|
|
$updateFields[] = 'fk_region = ?';
|
|
$params[] = $data['fk_region'];
|
|
}
|
|
|
|
if (isset($data['phone'])) {
|
|
$updateFields[] = 'encrypted_phone = ?';
|
|
$params[] = ApiService::encryptData($data['phone']);
|
|
}
|
|
|
|
if (isset($data['mobile'])) {
|
|
$updateFields[] = 'encrypted_mobile = ?';
|
|
$params[] = ApiService::encryptData($data['mobile']);
|
|
}
|
|
|
|
if (isset($data['email']) && !empty($data['email'])) {
|
|
$updateFields[] = 'encrypted_email = ?';
|
|
$params[] = ApiService::encryptSearchableData($data['email']);
|
|
}
|
|
|
|
if (isset($data['chk_copie_mail_recu'])) {
|
|
$updateFields[] = 'chk_copie_mail_recu = ?';
|
|
$params[] = $data['chk_copie_mail_recu'] ? 1 : 0;
|
|
}
|
|
|
|
if (isset($data['chk_accept_sms'])) {
|
|
$updateFields[] = 'chk_accept_sms = ?';
|
|
$params[] = $data['chk_accept_sms'] ? 1 : 0;
|
|
}
|
|
|
|
// Champs modifiables uniquement par les administrateurs
|
|
if ($isAdmin) {
|
|
if (isset($data['gps_lat'])) {
|
|
$updateFields[] = 'gps_lat = ?';
|
|
$params[] = $data['gps_lat'];
|
|
}
|
|
|
|
if (isset($data['gps_lng'])) {
|
|
$updateFields[] = 'gps_lng = ?';
|
|
$params[] = $data['gps_lng'];
|
|
}
|
|
|
|
if (isset($data['stripe_id'])) {
|
|
$updateFields[] = 'encrypted_stripe_id = ?';
|
|
$params[] = ApiService::encryptData($data['stripe_id']);
|
|
}
|
|
|
|
if (isset($data['chk_demo'])) {
|
|
$updateFields[] = 'chk_demo = ?';
|
|
$params[] = $data['chk_demo'] ? 1 : 0;
|
|
}
|
|
|
|
if (isset($data['chk_active'])) {
|
|
$updateFields[] = 'chk_active = ?';
|
|
$params[] = $data['chk_active'] ? 1 : 0;
|
|
}
|
|
|
|
if (isset($data['chk_stripe'])) {
|
|
$updateFields[] = 'chk_stripe = ?';
|
|
$params[] = $data['chk_stripe'] ? 1 : 0;
|
|
}
|
|
}
|
|
|
|
// Si aucun champ à mettre à jour, retourner une erreur
|
|
if (empty($updateFields)) {
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Aucune donnée à mettre à jour'
|
|
], 400);
|
|
return;
|
|
}
|
|
|
|
// Ajouter la date de mise à jour
|
|
$updateFields[] = 'updated_at = NOW()';
|
|
|
|
// Construire la requête SQL
|
|
$sql = 'UPDATE entites SET ' . implode(', ', $updateFields) . ' WHERE id = ?';
|
|
$params[] = $entiteId;
|
|
|
|
// Exécuter la requête
|
|
$stmt = $this->db->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
// Vérifier si la mise à jour a réussi
|
|
if ($stmt->rowCount() === 0) {
|
|
Response::json([
|
|
'status' => 'warning',
|
|
'message' => 'Aucune modification effectuée'
|
|
], 200);
|
|
return;
|
|
}
|
|
|
|
LogService::log('Mise à jour d\'une entité GeoSector', [
|
|
'level' => 'info',
|
|
'userId' => $userId,
|
|
'entiteId' => $entiteId,
|
|
'isAdmin' => $isAdmin
|
|
]);
|
|
|
|
Response::json([
|
|
'status' => 'success',
|
|
'message' => 'Entité mise à jour avec succès'
|
|
], 200);
|
|
} catch (Exception $e) {
|
|
LogService::log('Erreur lors de la mise à jour de l\'entité GeoSector', [
|
|
'level' => 'error',
|
|
'error' => $e->getMessage()
|
|
]);
|
|
|
|
Response::json([
|
|
'status' => 'error',
|
|
'message' => 'Erreur lors de la mise à jour de l\'entité'
|
|
], 500);
|
|
}
|
|
}
|
|
}
|