Subversion Repositories eFlore/Applications.coel

Rev

Rev 1721 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php

/**
 * Exemple lancement:
 * /opt/lampp/bin/php -d memory_limit=3500M cli.php communes -a majCoordonnees
 */

class Communes extends Script {
        
        private $bdd = null;
        private $structures = array();
        private $communes = array();
        private $nonTrouvees = array();
        
        public function __construct($script_nom, $parametres) {
                parent::__construct($script_nom, $parametres);
                $this->bdd = new Bdd();
        }
        
        public function executer() {
                try {
                        $this->initialiserScript();
                        $cmd = $this->getParametre('a');
                        switch ($cmd) {
                                case "majCoordonnees" :
                                        $this->mettreAJourCoordonneesCommunes(); break;
                                default :
                                        $this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
                        }
                } catch (Exception $erreur) {
                        $this->traiterErreur($erreur->getMessage());
                }
        }
        
        private function initialiserScript() {
                $fichierIni = $this->getScriptChemin().'communes.ini';
                if (file_exists($fichierIni)) {
                        Config::charger($fichierIni);
                } else {
                        $erreur = "Veuillez configurer le projet en créant le fichier 'communes.ini' ".
                                "dans le dossier du module de script du projet à partir du fichier 'config.defaut.ini'.";
                        throw new Exception($erreur);
                }
        }
        
        private function mettreAJourCoordonneesCommunes() {
                $this->recupererStructures();
                $departements = $this->determinerDepartementsStructures();
                $this->recupererCommunes($departements);
                $this->chercherCoordonneesVillesStructures();
                $this->mettreAJourDonneesStructures();
                $this->afficherResultatScript();
        }
        
        private function recupererStructures() {
                $this->bdd->requeter("USE ".Config::get("tables.bdd_nom_coel"));
                $requete = sprintf(
            "SELECT cs_id_structure, cs_nom, cs_code_postal, cs_ville FROM %s"
            . " JOIN coel_meta_liste_valeur ON cs_ce_truk_pays = cmlv_id_valeur"
            . " WHERE cmlv_abreviation IN ('FR', 'RE', 'YT', 'GP', 'MQ', 'GF', 'NC')"
            . " AND (cs_latitude IS NULL OR cs_latitude='0' OR Length(Trim(cs_latitude)) = 0)"
            . " AND (cs_longitude IS NULL OR cs_longitude='0' OR Length(Trim(cs_longitude)) = 0)"
            . " ORDER BY cs_ville",
            Config::get("tables.table_structures_coel"));

                $this->structures = $this->bdd->recupererTous($requete);
        }
        
        private function determinerDepartementsStructures() {
                $departements = array();
                foreach ($this->structures as $index => $structure) {
                        $codeDepartement = '';
                        if (strlen($structure['cs_code_postal']) == 5) {
                                if (substr($structure['cs_code_postal'], 0, 2) > "95") {
                                        $codeDepartement = substr($structure['cs_code_postal'], 0, 3);
                                } else {
                                        $codeDepartement = substr($structure['cs_code_postal'], 0, 2);
                                }
                        }
                        $this->structures[$index]['departement'] = $codeDepartement;
                        if (strlen($codeDepartement) > 0 && !in_array($codeDepartement, $departements)) {
                                $departements[] = $codeDepartement;
                        }
                }
                return $departements;
        }
        
        private function recupererCommunes($departements) {
                foreach ($departements as $index => $codeDepartement) {
                        $departements[$index] = "'$codeDepartement'";
                }
                $listeDepartements = implode(',', $departements);
                $this->bdd->requeter("USE ".Config::get("tables.bdd_nom_floradata"));
                $requete = "SELECT code, nom, wgs84_latitude, wgs84_longitude FROM ".Config::get("tables.table_communes")." ".
                "ORDER BY code;";
                $communes = $this->bdd->recupererTous($requete);
                // reorganiser le tableau en series des tableaux contenant les communes par departement
                $communes[0]['recherche'] = self::transformerChainePourRecherche($communes[0]['nom']);
                $communesDepartement = array($communes[0]);
                $numeroDepartement = substr($communes[0]['code'], 0, 2) > '95' ? substr($communes[0]['code'], 0, 3)
                        : substr($communes[0]['code'], 0, 2);
                for ($index = 1; $index < count($communes); $index ++) {
                        $numeroDept = substr($communes[$index]['code'],0,2) > '95' ? substr($communes[$index]['code'],0,3)
                                : substr($communes[$index]['code'],0,2);
                        if ($numeroDept != $numeroDepartement) {
                                $this->communes[$numeroDepartement] = $communesDepartement;
                                $communesDepartement = array();
                                $numeroDepartement = $numeroDept;
                        }
                        $communes[$index]['recherche'] = self::transformerChainePourRecherche($communes[$index]['nom']);
                        $communesDepartement[] = $communes[$index];
                }
                $this->communes[$numeroDepartement] = $communesDepartement;
        }
        
        private static function transformerChainePourRecherche($chaine, $charset='utf-8') {
                $str = htmlentities($chaine, ENT_NOQUOTES, $charset);
                $str = preg_replace('#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
                $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str);
                $str = preg_replace('#&[^;]+;#', '', $str);
                for ($position = 0; $position < strlen($str); $position ++) {
                        if ($str[$position] == "," || $str[$position] == "-" || $str[$position] == "'") {
                                $str[$position] = " ";
                        }
                }
                return strtolower($str);
        }
        
        private function chercherCoordonneesVillesStructures() {
                foreach ($this->structures as $index => $structure) {
                        if (strlen(trim($structure['cs_ville'])) > 0) {
                                if (strlen(trim($structure['departement'])) > 0) {
                                        $this->structures[$index] = $this->retrouverCoordonneesDansDepartement($structure);
                                } else {
                                        $this->structures[$index] = $this->retrouverCoordonneesDansListeCommunes($structure);
                                }
                        } else {
                                $this->nonTrouvees[] = $structure;
                        }
                }
        }
        
        private function retrouverCoordonneesDansDepartement($structure) {
                $villeRecherche = self::transformerChainePourRecherche(($structure['cs_ville']));
                $communeTrouvee = null;
                // comparaison dans un premier temps si les deux chaines de caracteres sont identiques
                // dans un second temps on applique la recherche de sous chaines identiques
                foreach ($this->communes[$structure['departement']] as $commune) {
                        if ($commune['recherche'] == $villeRecherche) {
                                $communeTrouvee = $commune;
                                break;
                        }
                }
                if (is_null($communeTrouvee)) {
                        foreach ($this->communes[$structure['departement']] as $commune) {
                                if (strstr($commune['recherche'], $villeRecherche) !== false) {
                                        $communeTrouvee = $commune;
                                        break;
                                } else if (strstr($villeRecherche, $commune['recherche']) !== false) {
                                        $communeTrouvee = $commune;
                                        break;
                                }
                        }
                }
                if (!is_null($communeTrouvee)) {
                        $structure['cs_ville']  = $communeTrouvee['nom'];
                        $structure['latitude']  = $communeTrouvee['wgs84_latitude'];
                        $structure['longitude'] = $communeTrouvee['wgs84_longitude'];
                } else {
                        $this->nonTrouvees[] = $structure;
                }
                return $structure;
        }
        
        private function retrouverCoordonneesDansListeCommunes($structure) {
                $villeRecherche = self::transformerChainePourRecherche(($structure['cs_ville']));
                $communeTrouvee = null;
                $codeDepartement = "";
                // meme comportement que la methode precedente, mais la recherche est etendue a toutes les communes
                // si une commune est trouvee, on lui attribuera le code departement au code postal par defaut
                foreach ($this->communes as $departement => $communes) {
                        foreach ($communes as $commune) {
                                if ($commune['recherche'] == $villeRecherche) {
                                        $communeTrouvee = $commune;
                                        $codeDepartement = $departement;
                                        break;
                                }
                        }
                        if (is_null($communeTrouvee)) {
                                foreach ($communes as $commune) {
                                        if (strstr($commune['recherche'], $villeRecherche) !== false) {
                                                $communeTrouvee = $commune;
                                                $codeDepartement = $departement;
                                                break;
                                        } else if (strstr($villeRecherche, $commune['recherche']) !== false) {
                                                $communeTrouvee = $commune;
                                                $codeDepartement = $departement;
                                                break;
                                        }
                                }
                        }
                }
                if (!is_null($communeTrouvee)) {
                        $structure['cs_ville']  = $communeTrouvee['nom'];
                        $structure['latitude']  = $communeTrouvee['wgs84_latitude'];
                        $structure['longitude'] = $communeTrouvee['wgs84_longitude'];
                        $structure['cs_code_postal'] = $codeDepartement;
                } else {
                        $this->nonTrouvees[] = $structure;
                }
                return $structure;
        }
        
        private function mettreAJourDonneesStructures() {
                $this->bdd->requeter("USE ".Config::get("tables.bdd_nom_coel"));
                $updates = array();
                // pour faire une seule requete de mise a jour, on va pas utiliser l'ordre UPDATE qui n'accepte
                // qu'une seule condition, mais l'ordre INSERT en rajoutant a la fin ON DUPLICATE KEY UPDATE
                // avec les correspondances au niveau des codes postaux et villes
                foreach ($this->structures as $structure) {
                        if (isset($structure['latitude']) && isset($structure['longitude'])) {
                                $updates[] = "({$structure['cs_id_structure']},'{$structure['cs_code_postal']}',".
                                        $this->bdd->proteger($structure['cs_ville']).",'{$structure['latitude']}',".
                                        "'{$structure['longitude']}')";
                        } 
                }

        if(!$updates) return;

                $sql = "INSERT INTO ".Config::get("tables.table_structures_coel")." (cs_id_structure, cs_code_postal, ".
                "cs_ville, cs_latitude, cs_longitude) VALUES ".implode(",", $updates)." ".
                "ON DUPLICATE KEY UPDATE cs_code_postal=VALUES(cs_code_postal), cs_ville=VALUES(cs_ville), ".
                "cs_latitude=VALUES(cs_latitude), cs_longitude=VALUES(cs_longitude);";
                $this->bdd->requeter($sql);
        }
        
        private function afficherResultatScript() {
                $nombreUpdates = count($this->structures) - count($this->nonTrouvees);
                $message = "Mise à jour des coordonnées des communes terminée. Les structures qui n'avaient pas de ".
                "coordonnées se sont vues attribuer les coordonnées de la commune dans laquelle elles sont situées.\n\n".
                "Mises à jour effectuées pour $nombreUpdates structures.\n";
                if (count($this->nonTrouvees) > 0) {
                        $message .= "Des problèmes ont été rencontrées pour les structures suivantes : \n";
                        foreach ($this->nonTrouvees as $structure) {
                                $message .= "  - {$structure['cs_nom']} ({$structure['cs_ville']}, {$structure['cs_code_postal']})\n";
                        }
                        $message .= "Veuillez vérifier le nom de la commune saisi ou aller dans la fiche structure ".
                        "pour y rajouter les coordonnées longitude/latitude\n";
                } else {
                        $message .= "Vous pourrez toujours par la suite aller dans la fiche structure ".
                        "pour affiner la précision les coordonnées longitude/latitude au niveau des locaux.\n";
                }
                print($message);
        }
        
}

?>