Subversion Repositories eFlore/Applications.cel

Rev

Rev 2536 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// declare(encoding='UTF-8');
/**
 * Traitement des codes INSEE et des codes pays de la base de données CEL
 * Permet d'affecter des codes INSEE et des codes pays aux obs possédant des coordonnées mais pas de commune ou de pays.
 *
 * Utilisation :
 * - Pour ? : <code>/opt/lamp/bin/php cli.php code_zone_geo -a tout</code>
 * - Pour ? : <code>/opt/lamp/bin/php cli.php code_zone_geo -a colonne</code>
 * - Pour ? : <code>/opt/lamp/bin/php cli.php code_zone_geo -a payssanscorrespondance</code>
 * - Pour ? : <code>/opt/lamp/bin/php cli.php code_zone_geo -a codeinseesanscorrespondance</code>
 *
 * @category   CEL
 * @package    Scripts
 * @subpackage Zones Geo
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
 */
include_once dirname(__FILE__).'/bibliotheque/Dao.php';

class CodeZoneGeo extends Script {

        protected $tableauTaxon;
        protected $dao;
        protected $observations;
        
        protected $url_service_geo_tpl;
        protected $url_service_pays_tpl;

        protected $mode_verbeux = false;

        // Paramêtres autorisées lors de l'appel au script en ligne de commande
        protected $parametres_autorises = array(
                '-n' => array(true, true, 'Nom du fichier ou du dossier à traiter'));

        public function executer() {
                
                $this->url_service_geo_tpl = Config::get('urlZoneGeoTpl');
                $this->url_service_pays_tpl = Config::get('urlPaysTpl');

                $this->dao = new Dao();
                // Récupération de paramétres
                // Lancement de l'action demandée
                $cmd = $this->getParametre('a');
                $this->mode_verbeux = $this->getParametre('v');

                switch ($cmd) {
                        case 'tout' :
                                // à effectuer manuellement au premier lancement du script
                                $this->creerColonne();
                                $this->calculerToutSansCorrespondanceDepuisLeDebut();
                                break;
                        case 'colonne' :
                                $this->creerColonne();
                                break;
                        case 'codeinseesanscorrespondance' :
                                $this->calculerCodesInseeSansCorrespondance();
                                break;
                        case 'codeinseesanscorrespondancedepuisledebut' :
                                $this->calculerCodesInseeSansCorrespondanceDepuisLeDebut();
                                break;
                        case 'payssanscorrespondance' :
                                $this->calculerPaysSansCorrespondance();
                                break;  
                        case 'payssanscorrespondancedepuisledebut' :
                                $this->calculerPaysSansCorrespondanceDepuisLeDebut();
                                break;
                        case 'toutsanscorrespondance' :
                                // devrait être être l'option utilisée dans le cron quotidien (avec l'option -v 0)
                                $this->calculerToutSansCorrespondance();
                                break;
                        case 'toutsanscorrespondancedepuisledebut' :
                                $this->calculerToutSansCorrespondanceDepuisLeDebut();
                                break;
                        default :
                                $this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
                }
        }

        protected function creerColonne() {
                $this->dao->creerColonneCodeInseeCalcule();
        }

        protected function calculerCodesInseeSansCorrespondance() {
                $liste_coordonnees = $this->dao->rechercherCoordonneesFrancaisesSansCorrespondances();
                $this->traiterCoordonnees($liste_coordonnees);
        }
        
        protected function calculerCodesInseeSansCorrespondanceDepuisLeDebut() {
                $liste_coordonnees = $this->dao->rechercherCoordonneesFrancaisesSansCorrespondanceDepuisLeDebut();
                $this->traiterCoordonnees($liste_coordonnees);
        }
        
        protected function calculerPaysSansCorrespondance() {
                $liste_coordonnees = $this->dao->rechercherPaysSansCorrespondance();
                $this->traiterCoordonnees($liste_coordonnees);
        }
        
        protected function calculerPaysSansCorrespondanceDepuisLeDebut() {
                $liste_coordonnees = $this->dao->rechercherPaysSansCorrespondanceDepuisLeDebut();
                $this->traiterCoordonnees($liste_coordonnees);
        }
        
        protected function calculerToutSansCorrespondance() {
                $this->affecterPaysFranceAuxCommunes();
                $liste_coordonnees = $this->dao->rechercherToutSansCorrespondance();
                $this->traiterCoordonnees($liste_coordonnees);
        }

        protected function calculerToutSansCorrespondanceDepuisLeDebut() {
                $this->affecterPaysFranceAuxCommunes();
                $liste_coordonnees = $this->dao->rechercherSansCorrespondanceDepuisLeDebut();
                $this->traiterCoordonnees($liste_coordonnees);
        }
        
        protected function affecterPaysFranceAuxCommunes() {
                if ($this->mode_verbeux) {
                        echo "-------------------------------------------------------------------\n";
                        echo "  Affectation du pays France aux communes ayant un code INSEE mais pas de pays ... ";
                }
                
                $maj = $this->dao->affecterPaysFranceAuxCommunesRenseignees();
                
                if ($this->mode_verbeux) {
                        echo "OK \n";
                        echo "  ".$maj." commune".($maj > 1 ? 's' : '')." affectée".($maj > 1 ? 's' : '')."\n";
                        echo "-------------------------------------------------------------------\n";
                }
        }

        private function traiterCoordonnees($liste_coordonnees) {
                $debut = microtime(true);
                $nb_coordonnees_modifiees = 0;
                $nb_coordonnees_ignorees = 0;
                $total = count($liste_coordonnees);

                if ($this->mode_verbeux) {
                        echo "-------------------------------------------------------------------\n";
                        echo "  Calcul des codes INSEE, du code pays et modification (".count($liste_coordonnees)." coordonnées en tout) ... \n";
                        echo "  Enrichissement des champs zone geo et ce_zone_geo vides ... \n";
                        echo "-------------------------------------------------------------------\n";
                }

                foreach ($liste_coordonnees as $coordonnees) {
                        $infos_coord = $this->obtenirInfosPourCoordonnees($coordonnees);
                        if ($infos_coord != null) {
                                // Le type renvoyé permet de connaitre ce qu'on peut modifier
                                if($infos_coord['type'] == 'france') {
                                        // Cas d'une commune française
                                        $coordonnee_a_traiter = array(
                                                'latitude' => $coordonnees['latitude'],
                                                'longitude' => $coordonnees['longitude'],
                                                'code_insee' => $infos_coord['code_insee'],
                                                'nom' => $infos_coord['nom']
                                        );
                                        $this->dao->modifierCodeInseeEtZoneGeo($coordonnee_a_traiter);
                                } else if($infos_coord['type'] == 'pays') {
                                        // Cas d'un lieu à l'étranger
                                        $coordonnee_a_traiter = array(
                                                        'latitude' => $coordonnees['latitude'],
                                                        'longitude' => $coordonnees['longitude'],
                                                        'code_pays' => $infos_coord['code_pays'],
                                                        'nom' => $infos_coord['nom']
                                        );
                                        $this->dao->modifierPays($coordonnee_a_traiter);
                                }
                                $nb_coordonnees_modifiees++;
                        } else {
                                $nb_coordonnees_ignorees++;
                        }
                        if ($this->mode_verbeux) {
                                $this->afficherAvancement('  Coordonnées traitées ', $nb_coordonnees_modifiees);
                        }
                }

                $fin = microtime(true);
                if ($this->mode_verbeux) {
                        echo "\n";
                        echo "-------------------------------------------------------------------\n";
                        echo "  Fin de la mise à jour des codes INSEE calculés, du pays et de l'enrichissement, \n";
                        echo "  ".($fin - $debut)." secondes écoulées \n";
                        echo "  ".$nb_coordonnees_modifiees." code insee calculés et modifiés \n";
                        echo "  ".$nb_coordonnees_ignorees." coordonnées ignorées \n";
                        echo "-------------------------------------------------------------------\n";
                        echo "\n";
                }
        }

        private function obtenirInfosPourCoordonnees($coordonnees) {
                $infos_coord = null;
                // Test facile qui permet d'abord de tenter une localisation bien plus rapide si les coordonnées 
                // sont dans la bounding box approximative de la France
                if($this->testerCoordonneesWgsFrance($coordonnees['latitude'], $coordonnees['longitude'])) {
                        $infos_coord = $this->chercherInfosCommune('osm', $coordonnees['latitude'], $coordonnees['longitude']);
                        if ($infos_coord == null) {
                                // Sinon recherche par pays
                                $infos_coord = $this->chercherInfosPays($coordonnees['latitude'], $coordonnees['longitude']);
                        }
                } else {
                        // Recherche par pays immédiate si en dehors de la bouding box française
                        $infos_coord = $this->chercherInfosPays($coordonnees['latitude'], $coordonnees['longitude']);
                }
                return $infos_coord;
        }

        private function chercherInfosCommune($projet, $latitude, $longitude) {
                
                $noms_params = array('{projet}', '{latitude}', '{longitude}');
                $valeurs_params = array($projet, $latitude, $longitude);
                
                $url_service = str_replace($noms_params, $valeurs_params, $this->url_service_geo_tpl);
                $url_service = str_replace(',', '.', $url_service);

                $ch = curl_init($url_service);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                $reponse = curl_exec($ch);

                $infos_coord = $this->traiterReponseServiceCommune($reponse);
                curl_close($ch);

                return $infos_coord;
        }
        
        private function chercherInfosPays($latitude, $longitude) {
                $noms_params = array('{latitude}', '{longitude}');
                $valeurs_params = array($latitude, $longitude);
                $url_service = str_replace($noms_params, $valeurs_params, $this->url_service_pays_tpl);
                $url_service = str_replace(',', '.', $url_service);

                $ch = curl_init($url_service);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                $reponse = curl_exec($ch);
                
                $res = json_decode($reponse, true);
                $retour = null;
                
                if(!empty($res)) {
                        // Cas où l'on a recherché des coordonnées en France
                        // On en profite pour remplir plus de données
                        // que le simple pays si elles sont présentes
                        if(isset($res[8]) && isset($res[8]['codeInsee'])) {
                                $retour = array(
                                        'code_insee' => $res[8]['codeInsee'],
                                        'nom' => $res[8]['intitule'],
                                        'type' => 'france'
                                );
                        } else {
                                // Cas de la recherche en dehors de France
                                // La zone de plus haut niveau est toujours un pays 
                                // (car le niveau de zone est limité à 2)
                                $infos_pays = $res[min(array_keys($res))];
                                // La zone de niveau le plus bas est la "localité"
                                // la plus précise qu'on a pu trouver
                                $infos_localite = $res[max(array_keys($res))];
        
                                // Cas où l'on a trouvé un code pays
                                if(!empty($infos_pays['codeIso31661'])) {
                                        $retour = array(
                                                'code_pays' => $infos_pays['codeIso31661'], 
                                                'nom' => ''
                                        );
                                } elseif(!empty($infos_pays['codeIso31662'])) {
                                        // Quelquefois la zone de plus haut niveau est une région ou une province
                                        // heureusement son code est de forme XX-YY ou XX est le code iso du pays !
                                        $retour = array(
                                                'code_pays' => substr($infos_pays['codeIso31662'], 0, 2), 
                                                'nom' => ''
                                        );
                                }
                                
                                // Pas de sens de prendre un nom de localité si on a pas de pays
                                if(!empty($retour['code_pays'])) {
                                        // Type sert à savoir quelle fonction de mise à jour on appellera
                                        $retour['type'] = 'pays';
                                        $retour['nom'] = $infos_localite['intitule'];
                                }
                        }
                }
                return $retour;
        }

        private function traiterReponseServiceCommune($reponse) {
                $retour = null;
                $reponse = json_decode($reponse);
                // cas du service lion 1906 qui peut renvoyer plusieurs communes (on prend la première)
                if (is_array($reponse)) {
                        $reponse = $reponse[0];
                }
                if (isset($reponse->codeINSEE)) {
                        // Type sert à savoir quelle fonction de mise à jour on appellera
                        $retour = array('code_insee' => $reponse->codeINSEE,
                                                        'nom' => $reponse->nom,
                                                        'type' => 'france');
                }
                return $retour;
        }
        
        private function testerCoordonneesWgsFrance($latitude, $longitude) {
                $coord_france = false;
                if ($latitude != '' && $longitude != '') {
                        if ($latitude < 51.071667 && $latitude > 41.316667) {
                                if ($longitude < 9.513333 && $longitude > -5.140278) {
                                        $coord_france = true;
                                }
                        }
                }
                return $coord_france;
        }
}