* @copyright Copyright (C) 2008-2018, Rémi Jean * @author Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @link http://zwiicms.fr/ */ class geoevent extends common { const VERSION = '0.1'; const REALNAME = 'Géo Evénements'; const DATADIRECTORY = self::DATA_DIR . 'geoevent/'; const SORT_ASC = 'SORT_ASC'; const SORT_DSC = 'SORT_DSC'; const SORT_HAND = 'SORT_HAND'; public static $events = []; public static $eventsId = []; public static $eventsCenter = []; public static $actions = [ 'config' => self::GROUP_EDITOR, 'delete' => self::GROUP_EDITOR, 'dirs' => self::GROUP_EDITOR, 'add' => self::GROUP_EDITOR, 'index' => self::GROUP_VISITOR ]; /** * Mise à jour du module * Appelée par les fonctions index et config */ private function update() { //$versionData = $this->getData(['module', $this->getUrl(0), 'config', 'versionData']); } /** * Configuration */ public function config() { // Soumission du formulaire if ( $this->getUser('permission', __CLASS__, __FUNCTION__) === true ) { $events = $this->getData(['module', $this->getUrl(0), 'content']); foreach ($events as $eventId => $eventData) { # code... echo $eventId; } } // Valeurs en sortie $this->addOutput([ 'showBarEditButton' => true, 'showPageContent' => true, 'title' => helper::translate('Configuration'), 'view' => 'edit' ]); } /** * Ajout d'une galerie */ public function add() { // Soumission du formulaire d'ajout d'une galerie if ( $this->getUser('permission', __CLASS__, __FUNCTION__) === true && $this->isPost() ) { if ($this->getInput('eventAddName', null, true)) { $eventId = helper::increment($this->getInput('eventAddName', helper::FILTER_ID, true), (array) $this->getData(['module', $this->getUrl(0), 'content'])); // Le dossier de la galerie est vide $this->setData([ 'module', $this->getUrl(0), 'content', $eventId, [ 'name' => $this->getInput('eventAddName'), 'description' => $this->getInput('eventAddDescription', helper::FILTER_STRING_SHORT, true), 'lat' => $this->getInput('eventAddLat', helper::FILTER_FLOAT, true), 'long' => $this->getInput('eventAddLong', helper::FILTER_FLOAT, true) ] ]); } // Valeurs en sortie $this->addOutput([ 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $eventId, 'notification' => helper::translate('Nouvel événement créé'), 'state' => true ]); } else { // Valeurs en sortie $this->addOutput([ 'title' => helper::translate('Nouvel événement'), 'view' => 'add' ]); } } /** * Suppression */ public function delete() { // La galerie n'existe pas if ( $this->getUser('permission', __CLASS__, __FUNCTION__) !== true || $this->getData(['module', $this->getUrl(0), 'content', $this->getUrl(2)]) === null ) { // Valeurs en sortie $this->addOutput([ 'access' => false ]); } // Suppression else { $this->deleteData(['module', $this->getUrl(0), 'content', $this->getUrl(2)]); // Valeurs en sortie $this->addOutput([ 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/config', 'notification' => helper::translate('Galerie effacée'), 'state' => true ]); } } /** * Accueil (deux affichages en un pour éviter une url à rallonge) */ public function index() { // Mise à jour des données de module $this->update(); // Affichage du template if (self::$events) { // Valeurs en sortie $this->addOutput([ 'showBarEditButton' => true, 'showPageContent' => true, 'view' => 'index', 'vendor' => [ 'leaflet' ], ]); // Calcul du point central // Calculer le centre géographique $totalLat = 0; $totalLong = 0; $count = count(self::$events); foreach (self::$events as $coordinate) { $totalLat += $coordinate["lat"]; $totalLong += $coordinate["long"]; } $centerLat = $totalLat / $count; $centerLong = $totalLong / $count; // Calculer la distance maximale au centre pour déterminer le niveau de zoom $maxDistance = 0; foreach (self::$events as $coordinate) { if ( is_numeric($centerLat) && is_numeric($centerLong) && $coordinate["lat"] && $coordinate["long"] ) { $distance = $this->haversineGreatCircleDistance($centerLat, $centerLong, $coordinate["lat"], $coordinate["long"]); if ($distance > $maxDistance) { $maxDistance = $distance; } } } $zoomLevel = $this->getZoomLevel($maxDistance); self::$eventsCenter = array( 'lat' => $centerLat, 'long' => $centerLong, 'zoom' => $zoomLevel ); } } // Fonction pour convertir les coordonnées GPS au format décimal private function gps_decimal($coordinate, $hemisphere) { // Extrait les degrés, minutes et secondes $degrees = count($coordinate) > 0 ? $this->gps2Num($coordinate[0]) : 0; $minutes = count($coordinate) > 1 ? $this->gps2Num($coordinate[1]) : 0; $seconds = count($coordinate) > 2 ? $this->gps2Num($coordinate[2]) : 0; // Convertit les degrés, minutes et secondes en décimal $decimal = $degrees + ($minutes / 60) + ($seconds / 3600); // Si l'hémisphère est au Sud ou à l'Ouest, les coordonnées sont négatives $decimal *= ($hemisphere == 'S' || $hemisphere == 'W') ? -1 : 1; return $decimal; } // Fonction pour convertir les coordonnées GPS en nombre private function gps2Num($coordPart) { $parts = explode('/', $coordPart); if (count($parts) <= 0) return 0; if (count($parts) == 1) return $parts[0]; return floatval($parts[0]) / floatval($parts[1]); } // Fonction pour calculer la distance entre deux points géographiques private function haversineGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371) { $latFrom = deg2rad($latitudeFrom); $lonFrom = deg2rad($longitudeFrom); $latTo = deg2rad($latitudeTo); $lonTo = deg2rad($longitudeTo); $latDelta = $latTo - $latFrom; $lonDelta = $lonTo - $lonFrom; $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) + cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2))); return $angle * $earthRadius; } // Déterminer le niveau de zoom // Cette fonction est une approximation pour le calcul du zoom private function getZoomLevel($maxDistance) { $maxZoom = 21; // Le zoom maximal pour Leaflet $earthCircumference = 40075; // La circonférence de la Terre en km for ($zoom = $maxZoom; $zoom >= 0; $zoom--) { if ($maxDistance < ($earthCircumference / pow(2, $zoom))) { return $zoom; } } return 0; } }