Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 392 | Blame | Last modification | View Log | RSS feed

<?php
/**
 * Exemple lancement:
 * /opt/lampp/bin/php -d memory_limit=3500M /home/mohcen/web/cartoOSM/scripts/cli.php osm/mise_a_jour -a recupererRelationAMod
 * -f fichier_osm_change -e fichier_osm_nouveau
*/
class MiseAjour extends Script {
        private $communes = array();
        private $relations_communes = array();
        private $relation_a_chemins = array();
        private $chemin_a_noeuds = array();
        private $noeuds = array();
        private $pas = 10000;
        private $pas_commune = 1000;

        protected $parametres_autorises = array(
        '-f' => array(true, null, 'Chemin du fichier osm à analyser'));

        public function executer() {
                $this->bdd = new Bdd();

                // Lancement de l'action demandée
                $cmd = $this->getParametre('a');
            switch ($cmd) {
                        case 'MAJ' :
                                $this->MettreAjour();
                                break;
                                default :
                                $this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
                }
    }


        /**
         * Fonction permettant de traiter et d'analyser le fichier de différence et de mettre  à jour la base de données
         * en tenant compte des trois cas:Suppression, Création ,modification
        */
        private function MettreAjour() {
                $lecteur = new XMLReader();
                if ($lecteur->open($this->getParametre('f'))) {
                        $dom = new DomDocument();
                        while ($lecteur->read()) {
                                if ($lecteur->nodeType == XMLREADER::ELEMENT) {
                                        if ($lecteur->localName == 'create') {
                                                $creations = $lecteur->expand();
                                                $this-> analyserCreations($creations);
                                        }
                                        if ($lecteur->localName == 'modify') {
                                                $modifications = $lecteur->expand();
                                                $this-> analyserModifications($modifications);
                                        }
                                        if ($lecteur->localName == 'delete') {
                                                $suppressions = $lecteur->expand();
                                                $this-> analyserSuppressions($suppressions);
                                        }
                                }
                        }
                } else {
                        $e = "Impossible d'ouvrir le fichier osm : %s";
                        $this->traiterErreur($e, array($this->getParametre('f')));
                }
        }

        /**
         * Fonction permettant le traitement du cas création concernant les relations, ways et les noeuds.
         */
        private function analyserCreations($creations) {
                $relations = $creations->getElementsByTagName('relation');
                foreach ($relations as $relation) {
                        $this-> analyserRelation($relation);
                        if (count($this->relation_a_chemins) > $this->pas) {
                                $this->insererRelationAChemins();
                        }
                        if (count($this->relations_communes) > $this->pas_commune) {
                                $this->insererRelationsCommunes();
                        }
                }
                $ways = $creations->getElementsByTagName('way');
                foreach ($ways as $way) {
                        $this->analyserWay($way);
                        if (count($this->chemin_a_noeuds) > $this->pas) {
                                $this->insererCheminANoeuds();
                        }
                }
                $noeuds = $creations->getElementsByTagName('node');
                foreach ($noeuds as $noeud) {
                        $this->analyserNode($noeud);
                        if (count($this->noeuds) > $this->pas) {
                                $this->insererNoeuds();
                        }
                }
                $this->insererRelationsCommunes();
                $this->insererRelationAChemins();
                $this->insererCheminANoeuds();
                $this->insererNoeuds();
        }

        /**
         * Fonction permettant le traitement du cas modification concernant les relations, ways et les noeuds.
         */
        private function analyserModifications($modifications) {
                $relations = $modifications->getElementsByTagName('relation');
                foreach ($relations as $relation) {
                        $this-> analyserRelation($relation);
                        if (count($this->relation_a_chemins) > $this->pas) {
                                $this->modifierRelationAChemins();
                        }
                        if (count($this->relations_communes) > $this->pas_commune) {
                                $this->modifierRelationsCommunes();
                        }
                }
                $ways = $modifications->getElementsByTagName('way');
                foreach ($ways as $way) {
                        $this->analyserWay($way);
                        if (count($this->chemin_a_noeuds) > $this->pas) {
                                $this->modifierCheminANoeuds();
                        }
                }
                $noeuds = $modifications->getElementsByTagName('node');
                foreach ($noeuds as $noeud) {
                        $this->analyserNode($noeud);
                        if (count($this->noeuds) > $this->pas) {
                                $this->modifierNoeuds();
                        }
                }
                $this->modifierRelationsCommunes();
                $this->modifierRelationAChemins();
                $this->modifierCheminANoeuds();
                $this->modifierNoeuds();
        }

        /**
         * Fonction permettant le traitement du cas suppression concernant les relations, ways et les noeuds.
         */
        private function analyserSuppressions($suppressions) {
                $relations = $suppressions->getElementsByTagName('relation');
                foreach ($relations as $relation) {
                        $this-> analyserRelation($relation);
                        if (count($this->relation_a_chemins) > $this->pas) {
                                $this->supprimerRelationAChemins();
                        }
                        if (count($this->relations_communes) > $this->pas_commune) {
                                $this->supprimerRelationsCommunes();
                        }
                }
                $ways = $suppressions->getElementsByTagName('way');
                foreach ($ways as $way) {
                        $this->analyserWay($way);
                        if (count($this->chemin_a_noeuds) > $this->pas) {
                                $this->supprimerCheminANoeuds();
                        }
                }
                $noeuds = $suppressions->getElementsByTagName('node');
                foreach ($noeuds as $noeud) {
                        $this->analyserNode($noeud);
                        if (count($this->noeuds) > $this->pas) {
                                $this->supprimerNoeuds();
                        }
                }
                $this->supprimerRelationsCommunes();
                $this->supprimerRelationAChemins();
                $this->supprimerCheminANoeuds();
                $this->supprimerNoeuds();
        }


        /**
         * Récupère l'id commune, nom commune et le code INSEE et remplie la table `osm_relations`
         */
        private function analyserRelation($relation) {
                $relation_id = $this->proteger($relation->getAttribute('id'));
                $chemins = $relation->getElementsByTagName('member');
                foreach ($chemins as $chemin) {
                        if ($chemin->getAttribute('type') == 'way') { //écarter le noeud centrale
                                $chemin_id = $this->proteger($chemin->getAttribute('ref'));
                                $role = $this->proteger($chemin->getAttribute('role'));//role: null, inner, outer, exclave et enclave.
                                $this->relation_a_chemins[] = array($relation_id, $chemin_id, $role);
                        }
                }
                $commune_nom = null;
                $commune_insee = null;
                $tags = $relation->getElementsByTagName('tag');
                foreach ($tags as $tag) {
                        $tag_cle = $tag->getAttribute('k');
                        $tag_val = $tag->getAttribute('v');
                        switch ($tag_cle) {
                                case 'name' :
                                        $commune_nom = $this->proteger($tag_val);
                                        break;
                                case 'ref:INSEE' :
                                        $commune_insee = $this->proteger($tag_val);
                                        break;
                        }
                        if (!is_null($commune_nom) && !is_null($commune_insee)) {
                                $this->relations_communes[] = array($relation_id, $commune_nom, $commune_insee);
                                if (!isset($this->communes[$commune_insee])) {
                                        $this->communes[$commune_insee] = $relation_id;
                                } else {
                                        $e = "La relation #%s contient déjà le tag ref:INSEE avec la valeur %s.".
                                                "Veuillez corriger la carte OSM.";
                                        $this->traiterErreur($e, array($this->communes[$commune_insee], $commune_insee, $relation_id));
                                }
                                break;
                        }
                }
        }

        /**
         * Récupère l'id_way et tous les id_node de chaque way et remplie la table `osm_chemin_a_noeuds`
         */
        private function analyserWay($way) {
                $chemin_id = $this->proteger($way->getAttribute('id'));
                $ordre = 0;
                $noeuds = $way->getElementsByTagName('nd');
                $chemin_a_noeuds = array();
                foreach ($noeuds as $noeud) {
                        $noeud_id = $this->proteger($noeud->getAttribute('ref'));
                        $ordre++;
                $this->chemin_a_noeuds[] = array($chemin_id, $noeud_id, $ordre);
                }
        }

        /**
         * Fonction qui récupère tous les l'id_node et les valeurs(Lat/Lon) correspondantes et remplie la table `osm_noeuds`
         */
        private function analyserNode($node) {
                $noeud_id = $this->proteger($node->getAttribute('id'));
                $lat = $this->proteger($node->getAttribute('lat'));
                $lon = $this->proteger($node->getAttribute('lon'));
                $this->noeuds[] = array($noeud_id, $lat, $lon);
        }

        //Insertion des relations
        private function insererRelationsCommunes() {
                $requete =      'INSERT INTO osm_relations (id_relation, nom, code_insee) '.
                                        'VALUES '.$this->creerValuesMultiple($this->relations_communes);
                $this->inserer($requete);
                $this->relations_communes = array();
        }

        //Insertion des relations à chemins
        private function insererRelationAChemins() {
                $requete =      'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
                                        'VALUES '.$this->creerValuesMultiple($this->relation_a_chemins);
                $this->inserer($requete);
                $this->relation_a_chemins = array();
        }

        //Insertion des chemins à noeuds
        private function insererCheminANoeuds() {
                $requete =      'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
                                        'VALUES '.$this->creerValuesMultiple($this->chemin_a_noeuds);
                $this->inserer($requete);
                $this->chemin_a_noeuds = array();
        }

        //Insertion des noeuds
        private function insererNoeuds() {
                $requete = 'INSERT INTO osm_noeuds (id_noeud, lat, `long`) '.
                           'VALUES '.$this->creerValuesMultiple($this->noeuds);
                $this->inserer($requete);
                $this->noeuds = array();
        }

        //Update des relations
        private function modifierRelationsCommunes() {
                $donnees = $this->relations_communes;
                foreach ($donnees as $donnee) {
                $requete = 'UPDATE osm_relations '.
                                        "SET id_relation = $donnee[0], nom = $donnee[1], code_insee = $donnee[2] ".
                                        "WHERE id_relation = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->relations_communes = array();
        }

        /*
        *Update des relations à chemins en supprimant l'ancienne relation et tous ses chemins
        *de la table osm_relation_a_chemins et insérer la nouvelle
        */
        private function modifierRelationAChemins() {
                $relations_a_chemins_a_supp = array();
                $donnees = $this->relation_a_chemins;
                foreach ($donnees as $donnee) {
                        $relations_a_chemins_a_supp[] = $donnee[0];
                }
                $values_chaine = '('.implode(',',array_unique($relations_a_chemins_a_supp)).')';
                $requete = 'DELETE FROM osm_relation_a_chemins '.
                                        "WHERE id_relation IN $values_chaine";
                $this->inserer($requete);
                foreach ($donnees as $donnee) {
                        $requete = 'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
                                                "VALUES ($donnee[0], $donnee[1], $donnee[2]);";
                        $this->inserer($requete);
                }
                $this->relation_a_chemins = array();
        }

        /*
        *Update des chemins à noeuds en supprimant l'ancien chemin et tous ses noeuds
        *de la table osm_chemins_a_noeuds et insérer le nouveau
        */
        private function modifierCheminANoeuds() {
                $chemin_a_noeuds_a_supp = array();
                $donnees = $this->chemin_a_noeuds;
                foreach ($donnees as $donnee) {
                        $chemin_a_noeuds_a_supp[] = $donnee[0];
                }
                $values_chaine = '('.implode(',',array_unique($chemin_a_noeuds_a_supp)).')';
                $requete = 'DELETE FROM osm_chemin_a_noeuds '.
                                        "WHERE id_chemin IN $values_chaine";
                $this->inserer($requete);
                foreach ($donnees as $donnee) {
                        $requete = 'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
                                                "VALUES ($donnee[0], $donnee[1], $donnee[2]);";
                        $this->inserer($requete);
                }
                $this->chemin_a_noeuds = array();
        }


        //Update des noeuds
        private function modifierNoeuds() {
                $donnees = $this->noeuds;
                foreach ($donnees as $donnee) {
                        $requete = 'UPDATE osm_noeuds '.
                                                "SET id_noeud = $donnee[0], lat = $donnee[1], `long` = $donnee[2] ".
                                                "WHERE id_noeud = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->noeuds = array();
        }


        //Suppressions des relations
        private function supprimerRelationsCommunes() {
                $donnees = $this->relations_communes;
                foreach ($donnees as $donnee) {
                        $requete = 'DELETE FROM osm_relations '.
                                                "WHERE id_relation = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->relations_communes = array();
        }

        //Suppressions des relations à chemins
        private function supprimerRelationAChemins() {
                $donnees = $this->relations_communes;
                foreach ($donnees as $donnee) {
                        $donnees = $this->relation_a_chemins;
                        $requete = 'DELETE FROM osm_relation_a_chemins '.
                                                "WHERE id_relation = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->relation_a_chemins = array();
        }

        //Suppressions des chemins à noeuds
        private function supprimerCheminANoeuds() {
                $donnees = $this->chemin_a_noeuds;
                foreach ($donnees as $donnee) {
                        $donnees = $this->relation_a_chemins;
                        $requete = 'DELETE FROM osm_chemin_a_noeuds '.
                                                "WHERE id_chemin = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->chemin_a_noeuds = array();
        }

        //Suppressions des chemins à noeuds
        private function supprimerNoeuds() {
                $donnees = $this->noeuds;
                foreach ($donnees as $donnee) {
                        $requete = 'DELETE FROM osm_noeuds '.
                                                "WHERE id_noeud = $donnee[0]";
                        $this->inserer($requete);
                }
                $this->noeuds = array();
        }

        private function inserer($requete) {
                $this->bdd->requeter($requete);
        }

        private function proteger($chaine) {
                return $this->bdd->proteger($chaine);
        }

        private function creerValuesMultiple($donnees) {
                $values = array();
                foreach ($donnees as $donnee) {
                        $values[] = implode(',', $donnee);
                }
                $values_chaine = '('.implode('),(', $values).')';
                return $values_chaine;
        }
}
?>