db = $db; } /** * Vérifie si la table existe */ public function tableExists(): bool { try { $sql = "SHOW TABLES LIKE 'x_departements_contours'"; $stmt = $this->db->query($sql); return $stmt->rowCount() > 0; } catch (Exception $e) { return false; } } /** * Vérifie si la table est vide */ private function isTableEmpty(): bool { try { $sql = "SELECT COUNT(*) as count FROM x_departements_contours"; $stmt = $this->db->query($sql); $result = $stmt->fetch(); return $result['count'] == 0; } catch (Exception $e) { return true; } } /** * Importe les départements depuis un fichier GeoJSON */ public function importFromFile(string $filePath): array { $this->log[] = "Début de l'import depuis le fichier : $filePath"; $this->log[] = ""; // Vérifier que le fichier existe if (!file_exists($filePath)) { $this->log[] = "✗ Fichier non trouvé : $filePath"; return $this->log; } // Vérifier que la table existe if (!$this->tableExists()) { $this->log[] = "✗ La table x_departements_contours n'existe pas"; return $this->log; } // Vérifier que la table est vide if (!$this->isTableEmpty()) { $this->log[] = "✗ La table x_departements_contours contient déjà des données"; return $this->log; } // Lire le fichier GeoJSON $this->log[] = "Lecture du fichier GeoJSON..."; $jsonContent = file_get_contents($filePath); if ($jsonContent === false) { $this->log[] = "✗ Impossible de lire le fichier"; return $this->log; } // Parser le JSON $geojson = json_decode($jsonContent, true); if (json_last_error() !== JSON_ERROR_NONE) { $this->log[] = "✗ Erreur JSON : " . json_last_error_msg(); return $this->log; } if (!isset($geojson['features']) || !is_array($geojson['features'])) { $this->log[] = "✗ Format GeoJSON invalide : pas de features"; return $this->log; } $this->log[] = "✓ Fichier chargé : " . count($geojson['features']) . " départements trouvés"; $this->log[] = ""; // Préparer la requête d'insertion $sql = "INSERT INTO x_departements_contours (code_dept, nom_dept, contour, bbox_min_lat, bbox_max_lat, bbox_min_lng, bbox_max_lng) VALUES (:code, :nom, ST_GeomFromText(:polygon, 4326), :min_lat, :max_lat, :min_lng, :max_lng)"; $stmt = $this->db->prepare($sql); $success = 0; $errors = 0; // Démarrer une transaction $this->db->beginTransaction(); try { foreach ($geojson['features'] as $feature) { // Extraire les informations $code = $feature['properties']['code'] ?? null; $nom = $feature['properties']['nom'] ?? null; $geometry = $feature['geometry'] ?? null; if (!$code || !$nom || !$geometry) { $this->log[] = "✗ Données manquantes pour un département"; $errors++; continue; } // Convertir la géométrie en WKT $wktData = $this->geometryToWkt($geometry); if (!$wktData) { $this->log[] = "✗ Conversion échouée pour $code ($nom)"; $errors++; continue; } try { $stmt->execute([ 'code' => $code, 'nom' => $nom, 'polygon' => $wktData['wkt'], 'min_lat' => $wktData['bbox']['min_lat'], 'max_lat' => $wktData['bbox']['max_lat'], 'min_lng' => $wktData['bbox']['min_lng'], 'max_lng' => $wktData['bbox']['max_lng'] ]); $this->log[] = "✓ $code - $nom importé"; $success++; } catch (Exception $e) { $this->log[] = "✗ Erreur SQL pour $code ($nom) : " . $e->getMessage(); $errors++; } } // Valider ou annuler la transaction if ($success > 0) { $this->db->commit(); $this->log[] = ""; $this->log[] = "✓ Transaction validée"; } else { $this->db->rollBack(); $this->log[] = ""; $this->log[] = "✗ Transaction annulée (aucun import réussi)"; } } catch (Exception $e) { $this->db->rollBack(); $this->log[] = ""; $this->log[] = "✗ Erreur fatale : " . $e->getMessage(); $this->log[] = "✗ Transaction annulée"; } $this->log[] = ""; $this->log[] = "Import terminé : $success réussis, $errors erreurs"; return $this->log; } /** * Convertit une géométrie GeoJSON en WKT */ private function geometryToWkt(array $geometry): ?array { $type = $geometry['type'] ?? null; $coordinates = $geometry['coordinates'] ?? null; if (!$type || !$coordinates) { return null; } $wkt = null; $allPoints = []; switch ($type) { case 'Polygon': // Un seul polygone $ring = $coordinates[0]; // Anneau extérieur $points = []; foreach ($ring as $point) { $points[] = $point[0] . ' ' . $point[1]; $allPoints[] = $point; } $wkt = 'POLYGON((' . implode(',', $points) . '))'; break; case 'MultiPolygon': // Plusieurs polygones $polygons = []; foreach ($coordinates as $polygon) { $ring = $polygon[0]; // Anneau extérieur du polygone $points = []; foreach ($ring as $point) { $points[] = $point[0] . ' ' . $point[1]; $allPoints[] = $point; } $polygons[] = '((' . implode(',', $points) . '))'; } $wkt = 'MULTIPOLYGON(' . implode(',', $polygons) . ')'; break; default: return null; } if (!$wkt || empty($allPoints)) { return null; } // Calculer la bounding box $lats = array_map(function($p) { return $p[1]; }, $allPoints); $lngs = array_map(function($p) { return $p[0]; }, $allPoints); return [ 'wkt' => $wkt, 'bbox' => [ 'min_lat' => min($lats), 'max_lat' => max($lats), 'min_lng' => min($lngs), 'max_lng' => max($lngs) ] ]; } } // Si le script est exécuté directement if (php_sapi_name() === 'cli' && basename(__FILE__) === basename($_SERVER['PHP_SELF'] ?? __FILE__)) { require_once __DIR__ . '/../src/Config/AppConfig.php'; require_once __DIR__ . '/../src/Core/Database.php'; // Chemin vers le fichier GeoJSON $filePath = __DIR__ . '/../docs/contour-des-departements.geojson'; // Vérifier les arguments if ($argc > 1) { $filePath = $argv[1]; } echo "Import des contours départementaux depuis un fichier\n"; echo "==================================================\n\n"; echo "Fichier : $filePath\n\n"; $appConfig = AppConfig::getInstance(); Database::init($appConfig->getDatabaseConfig()); $db = Database::getInstance(); $importer = new DepartementContoursFileImporter($db); $log = $importer->importFromFile($filePath); foreach ($log as $line) { echo $line . "\n"; } }