Subversion Repositories eFlore/Projets.eflore-projets

Rev

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

Rev Author Line No. Line
167 jpm 1
<?php
392 jpm 2
/**
1046 jpm 3
 * Permet de mettre à jour les contours à partir d'un fichier de diff.
4
 *
5
 * Exemple de lancement du script :
6
 * /opt/lampp/bin/php -d memory_limit=3500M cli.php osm -a maj -f fichier_osm_change -e fichier_osm_nouveau
7
 */
8
class MiseAJour {
9
	private $conteneur;
10
	private $bdd;
11
	private $messages;
12
	private $mode;
13
 
167 jpm 14
	private $communes = array();
15
	private $relations_communes = array();
16
	private $relation_a_chemins = array();
17
	private $chemin_a_noeuds = array();
18
	private $noeuds = array();
19
	private $pas = 10000;
20
	private $pas_commune = 1000;
1046 jpm 21
	private $elementType = '';
392 jpm 22
 
1046 jpm 23
	public function __construct($conteneur) {
24
		$this->conteneur = $conteneur;
25
		$this->bdd = $this->conteneur->getBdd();
26
		$this->messages = $this->conteneur->getMessages();
27
		$this->mode = $this->conteneur->getParametre('m');
28
	}
167 jpm 29
 
1046 jpm 30
	/**
31
	 * Fonction qui parcourt tous les ways les noeuds de chaque relation en prenant en considération l'ordre et
32
	 * le sens de chaque ways concaténés ensemble (séparés par des virgules). Update du champ polygone de chaque
33
	 * relation dans la table `osm_relations`
34
	 */
167 jpm 35
	public function executer() {
36
		// Lancement de l'action demandée
1046 jpm 37
		$cmd = $this->conteneur->getParametre('a');
38
		switch ($cmd) {
39
			case 'maj' :
40
				$this->mettreAjour();
167 jpm 41
				break;
1046 jpm 42
			default :
43
				$msgTpl = "Erreur : la commande '%s' n'est pas prise en compte par la classe %s !";
44
				$msg = sprintf($msgTpl, $cmd, get_class($this));
45
				throw new Exception($msg);
167 jpm 46
		}
1046 jpm 47
		print "\n";// Pour ramener à la ligne en fin de script
48
	}
392 jpm 49
 
167 jpm 50
	/**
51
	 * Fonction permettant de traiter et d'analyser le fichier de différence et de mettre  à jour la base de données
52
	 * en tenant compte des trois cas:Suppression, Création ,modification
53
	*/
1046 jpm 54
	private function mettreAjour() {
55
		$lecteur = $this->getLecteurXml();
56
		while ($lecteur->read()) {
57
			if ($lecteur->nodeType == XMLREADER::ELEMENT) {
58
				$this->elementType = $lecteur->localName;
59
				$this->analyserElementXml($lecteur->localName, $lecteur->expand());
167 jpm 60
			}
1046 jpm 61
 
62
			if ($this->mode == 'manuel') {
63
				$this->messages->afficherAvancement("Analyse de la ligne du fichier de diff OSM : ", 1);
64
			}
167 jpm 65
		}
66
	}
392 jpm 67
 
1046 jpm 68
	private function getLecteurXml() {
69
		$fichierOsm = $this->conteneur->getParametre('f');
70
		$lecteur = new XMLReader();
71
		$ouvertureXmlOk = $lecteur->open($fichierOsm);
72
		if ($ouvertureXmlOk === false) {
73
			$msgTpl = "Impossible d'ouvrir le fichier osm : %s";
74
			$msg = sprintf($msgTpl, $this->conteneur->getParametre('f'));
75
			new Exception($msg);
76
		}
77
		return $lecteur;
78
	}
79
 
80
	private function analyserElementXml($noeudDom) {
81
		$relations = $noeudDom->getElementsByTagName('relation');
82
		if ($relations->length > 0) {
83
			foreach ($relations as $relation) {
84
				$this->analyserRelation($relation);
85
				$this->traiterRelations();
167 jpm 86
			}
87
		}
1046 jpm 88
 
167 jpm 89
		$ways = $creations->getElementsByTagName('way');
1046 jpm 90
		if ($ways->length > 0) {
91
			foreach ($ways as $way) {
92
				$this->analyserWay($way);
93
				$this->traiterCheminANoeuds();
167 jpm 94
			}
95
		}
1046 jpm 96
 
167 jpm 97
		$noeuds = $creations->getElementsByTagName('node');
1046 jpm 98
		if ($noeuds->length > 0) {
99
			foreach ($noeuds as $noeud) {
100
				$this->analyserNode($noeud);
101
				$this->traiterNoeuds();
167 jpm 102
			}
103
		}
1046 jpm 104
 
105
		$this->traiterElementsOrphelins();
167 jpm 106
	}
392 jpm 107
 
1046 jpm 108
	private function traiterRelations() {
109
		if (count($this->relation_a_chemins) > $this->pas) {
110
			switch ($this->elementType) {
111
				case 'create' :
112
					$this->insererRelationAChemins();
113
					break;
114
				case 'modify' :
115
					$this->modifierRelationAChemins();
116
					break;
117
				case 'delete' :
118
					$this->supprimerRelationAChemins();
119
					break;
167 jpm 120
			}
1046 jpm 121
		}
122
		if (count($this->relations_communes) > $this->pas_commune) {
123
			switch ($this->elementType) {
124
				case 'create' :
125
					$this->insererRelationsCommunes();
126
					break;
127
				case 'modify' :
128
					$this->modifierRelationsCommunes();
129
					break;
130
				case 'delete' :
131
					$this->supprimerRelationsCommunes();
132
					break;
167 jpm 133
			}
134
		}
1046 jpm 135
	}
136
 
137
	private function traiterChemins() {
138
		if (count($this->chemin_a_noeuds) > $this->pas) {
139
			switch ($this->elementType) {
140
				case 'create' :
141
					$this->insererCheminANoeuds();
142
					break;
143
				case 'modify' :
144
					$this->modifierCheminANoeuds();
145
					break;
146
				case 'delete' :
147
					$this->supprimerCheminANoeuds();
148
					break;
167 jpm 149
			}
150
		}
1046 jpm 151
	}
152
 
153
	private function traiterNoeuds() {
154
		if (count($this->noeuds) > $this->pas) {
155
			switch ($this->elementType) {
156
				case 'create' :
157
					$this->insererNoeuds();
158
					break;
159
				case 'modify' :
160
					$this->modifierNoeuds();
161
					break;
162
				case 'delete' :
163
					$this->supprimerNoeuds();
164
					break;
167 jpm 165
			}
166
		}
167
	}
392 jpm 168
 
1046 jpm 169
	private function traiterElementsOrphelins() {
170
		switch ($this->elementType) {
171
			case 'create' :
172
				$this->insererRelationsCommunes();
173
				$this->insererRelationAChemins();
174
				$this->insererCheminANoeuds();
175
				$this->insererNoeuds();
176
				break;
177
			case 'modify' :
178
				$this->modifierRelationsCommunes();
179
				$this->modifierRelationAChemins();
180
				$this->modifierCheminANoeuds();
181
				$this->modifierNoeuds();
182
				break;
183
			case 'delete' :
184
				$this->supprimerRelationsCommunes();
167 jpm 185
				$this->supprimerRelationAChemins();
186
				$this->supprimerCheminANoeuds();
187
				$this->supprimerNoeuds();
1046 jpm 188
				break;
167 jpm 189
		}
190
	}
392 jpm 191
 
167 jpm 192
	/**
193
	 * Récupère l'id commune, nom commune et le code INSEE et remplie la table `osm_relations`
392 jpm 194
	 */
167 jpm 195
	private function analyserRelation($relation) {
1046 jpm 196
		$relation_id = $relation->getAttribute('id');
167 jpm 197
		$chemins = $relation->getElementsByTagName('member');
198
		foreach ($chemins as $chemin) {
199
			if ($chemin->getAttribute('type') == 'way') { //écarter le noeud centrale
1046 jpm 200
				$chemin_id = $chemin->getAttribute('ref');
201
				$role = $chemin->getAttribute('role');//role: null, inner, outer, exclave et enclave.
392 jpm 202
				$this->relation_a_chemins[] = array($relation_id, $chemin_id, $role);
167 jpm 203
			}
204
		}
1046 jpm 205
 
206
		$tags = $relation->getElementsByTagName('tag');
207
		if ($tags->length > 0) {
208
			$this->analyserTags($relation_id, $tags);
209
		}
210
	}
211
 
212
	private function analyserTags($relation_id, $tags) {
167 jpm 213
		$commune_nom = null;
214
		$commune_insee = null;
215
		foreach ($tags as $tag) {
216
			$tag_cle = $tag->getAttribute('k');
217
			$tag_val = $tag->getAttribute('v');
218
			switch ($tag_cle) {
219
				case 'name' :
1046 jpm 220
					$commune_nom = $tag_val;
392 jpm 221
					break;
167 jpm 222
				case 'ref:INSEE' :
1046 jpm 223
					$commune_insee = $tag_val;
167 jpm 224
					break;
225
			}
226
			if (!is_null($commune_nom) && !is_null($commune_insee)) {
227
				$this->relations_communes[] = array($relation_id, $commune_nom, $commune_insee);
228
				if (!isset($this->communes[$commune_insee])) {
229
					$this->communes[$commune_insee] = $relation_id;
230
				} else {
231
					$e = "La relation #%s contient déjà le tag ref:INSEE avec la valeur %s.".
232
						"Veuillez corriger la carte OSM.";
233
					$this->traiterErreur($e, array($this->communes[$commune_insee], $commune_insee, $relation_id));
234
				}
235
				break;
236
			}
392 jpm 237
		}
167 jpm 238
	}
392 jpm 239
 
167 jpm 240
	/**
241
	 * Récupère l'id_way et tous les id_node de chaque way et remplie la table `osm_chemin_a_noeuds`
392 jpm 242
	 */
167 jpm 243
	private function analyserWay($way) {
1046 jpm 244
		$chemin_id = $way->getAttribute('id');
245
		$noeuds = $way->getElementsByTagName('nd');
167 jpm 246
		$ordre = 0;
247
		foreach ($noeuds as $noeud) {
1046 jpm 248
			$noeud_id = $noeud->getAttribute('ref');
249
			$this->chemin_a_noeuds[] = array($chemin_id, $noeud_id, ++$ordre);
167 jpm 250
		}
251
	}
392 jpm 252
 
253
	/**
167 jpm 254
	 * Fonction qui récupère tous les l'id_node et les valeurs(Lat/Lon) correspondantes et remplie la table `osm_noeuds`
392 jpm 255
	 */
167 jpm 256
	private function analyserNode($node) {
1046 jpm 257
		$this->noeuds[] = array(
258
			$node->getAttribute('id'),
259
			$node->getAttribute('lat'),
260
			$node->getAttribute('lon')
261
		);
167 jpm 262
	}
392 jpm 263
 
264
	//Insertion des relations
167 jpm 265
	private function insererRelationsCommunes() {
1046 jpm 266
		$requete = 'INSERT INTO osm_relations (id_relation, nom, code_insee) '.
267
			'VALUES '.$this->creerValuesMultiple($this->relations_communes).
268
			' -- '.__FILE__.' : '.__LINE__;
269
		$this->bdd->requeter($requete);
167 jpm 270
		$this->relations_communes = array();
271
	}
272
 
392 jpm 273
	//Insertion des relations à chemins
167 jpm 274
	private function insererRelationAChemins() {
1046 jpm 275
		$requete = 'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
276
			'VALUES '.$this->creerValuesMultiple($this->relation_a_chemins).
277
			' -- '.__FILE__.' : '.__LINE__;
278
		$this->bdd->requeter($requete);
167 jpm 279
		$this->relation_a_chemins = array();
392 jpm 280
	}
167 jpm 281
 
392 jpm 282
	//Insertion des chemins à noeuds
167 jpm 283
	private function insererCheminANoeuds() {
1046 jpm 284
		$requete = 'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
285
			'VALUES '.$this->creerValuesMultiple($this->chemin_a_noeuds).
286
			' -- '.__FILE__.' : '.__LINE__;
287
		$this->bdd->requeter($requete);
167 jpm 288
		$this->chemin_a_noeuds = array();
289
	}
392 jpm 290
 
291
	//Insertion des noeuds
167 jpm 292
	private function insererNoeuds() {
293
		$requete = 'INSERT INTO osm_noeuds (id_noeud, lat, `long`) '.
1046 jpm 294
			'VALUES '.$this->creerValuesMultiple($this->noeuds).
295
			' -- '.__FILE__.' : '.__LINE__;
296
		$this->bdd->requeter($requete);
167 jpm 297
		$this->noeuds = array();
298
	}
392 jpm 299
 
300
	//Update des relations
167 jpm 301
	private function modifierRelationsCommunes() {
1046 jpm 302
		foreach ($this->relations_communes as $donnee) {
303
			$infosP = $this->bdd->proteger($donnee);
304
			$requete = 'UPDATE osm_relations '.
305
				"SET id_relation = $infosP[0], nom = $infosP[1], code_insee = $infosP[2] ".
306
				"WHERE id_relation = $infosP[0] ".
307
				' -- '.__FILE__.' : '.__LINE__;
308
			$this->bdd->requeter($requete);
167 jpm 309
		}
310
		$this->relations_communes = array();
311
	}
392 jpm 312
 
167 jpm 313
	/*
392 jpm 314
	*Update des relations à chemins en supprimant l'ancienne relation et tous ses chemins
315
	*de la table osm_relation_a_chemins et insérer la nouvelle
167 jpm 316
	*/
317
	private function modifierRelationAChemins() {
1046 jpm 318
		$this->supprimerRelationAChemins();
319
		foreach ($this->relation_a_chemins as $donnee) {
320
			$infosP = $this->bdd->proteger($donnee);
167 jpm 321
			$requete = 'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
1046 jpm 322
				"VALUES ($infosP[0], $infosP[1], $infosP[2]) ".
323
				' -- '.__FILE__.' : '.__LINE__;
324
			$this->bdd->requeter($requete);
167 jpm 325
		}
326
		$this->relation_a_chemins = array();
392 jpm 327
	}
328
 
167 jpm 329
	/*
392 jpm 330
	*Update des chemins à noeuds en supprimant l'ancien chemin et tous ses noeuds
331
	*de la table osm_chemins_a_noeuds et insérer le nouveau
167 jpm 332
	*/
333
	private function modifierCheminANoeuds() {
1046 jpm 334
		$this->supprimerCheminANoeuds();
335
		foreach ($this->chemin_a_noeuds as $donnee) {
336
			$infosP = $this->bdd->proteger($donnee);
167 jpm 337
			$requete = 'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
1046 jpm 338
				"VALUES ($infosP[0], $infosP[1], $infosP[2]) ".
339
				' -- '.__FILE__.' : '.__LINE__;
340
			$this->bdd->requeter($requete);
167 jpm 341
		}
342
		$this->chemin_a_noeuds = array();
343
	}
392 jpm 344
 
345
	//Update des noeuds
167 jpm 346
	private function modifierNoeuds() {
1046 jpm 347
		foreach ($this->noeuds as $donnee) {
348
			$infosP = $this->bdd->proteger($donnee);
392 jpm 349
			$requete = 'UPDATE osm_noeuds '.
1046 jpm 350
				"SET id_noeud = $infosP[0], lat = $infosP[1], `long` = $infosP[2] ".
351
				"WHERE id_noeud = $infosP[0] ".
352
				' -- '.__FILE__.' : '.__LINE__;
353
			$this->bdd->requeter($requete);
167 jpm 354
		}
355
		$this->noeuds = array();
356
	}
392 jpm 357
 
358
	//Suppressions des relations
167 jpm 359
	private function supprimerRelationsCommunes() {
1046 jpm 360
		$idsIn = $this->getIds($this->relations_communes);
167 jpm 361
		$this->relations_communes = array();
1046 jpm 362
		$requete = 'DELETE FROM osm_relations '.
363
			"WHERE id_relation IN ($idsIn) ".
364
			' -- '.__FILE__.' : '.__LINE__;
365
		$this->bdd->requeter($requete);
167 jpm 366
	}
392 jpm 367
 
368
	//Suppressions des relations à chemins
167 jpm 369
	private function supprimerRelationAChemins() {
1046 jpm 370
		$idsIn = $this->getIds($this->relation_a_chemins);
167 jpm 371
		$this->relation_a_chemins = array();
1046 jpm 372
		$requete = 'DELETE FROM osm_relation_a_chemins '.
373
			"WHERE id_relation IN ($idsIn) ".
374
			' -- '.__FILE__.' : '.__LINE__;
375
		$this->bdd->requeter($requete);
392 jpm 376
	}
377
 
378
	//Suppressions des chemins à noeuds
167 jpm 379
	private function supprimerCheminANoeuds() {
1046 jpm 380
		$idsIn = $this->getIds($this->chemin_a_noeuds);
167 jpm 381
		$this->chemin_a_noeuds = array();
1046 jpm 382
		$requete = 'DELETE FROM osm_chemin_a_noeuds '.
383
			"WHERE id_chemin IN ($idsIn) ".
384
			' -- '.__FILE__.' : '.__LINE__;
385
		$this->bdd->requeter($requete);
167 jpm 386
	}
392 jpm 387
 
388
	//Suppressions des chemins à noeuds
167 jpm 389
	private function supprimerNoeuds() {
1046 jpm 390
		$idsIn = $this->getIds($this->noeuds);
167 jpm 391
		$this->noeuds = array();
1046 jpm 392
		$requete = 'DELETE FROM osm_noeuds '.
393
			"WHERE id_noeud IN ($idsIn) ".
394
			' -- '.__FILE__.' : '.__LINE__;
167 jpm 395
		$this->bdd->requeter($requete);
396
	}
392 jpm 397
 
1046 jpm 398
	private function getIds(&$tableau) {
399
		$ids = array();
400
		foreach ($tableau as $info) {
401
			$ids[] = $this->bdd->proteger($info[0]);
402
		}
403
		$idsSansDoublon = array_unique($ids);
404
		$idsIn = implode(',', $idsSansDoublon);
405
		return $idsIn;
167 jpm 406
	}
392 jpm 407
 
167 jpm 408
	private function creerValuesMultiple($donnees) {
409
		$values = array();
1046 jpm 410
		foreach ($donnees as $infos) {
411
			$infosP = $this->bdd->proteger($infos);
412
			$values[] = implode(',', $infosP);
167 jpm 413
		}
1046 jpm 414
		$valuesClause = '('.implode('),(', $values).')';
415
		return $valuesClause;
167 jpm 416
	}
1046 jpm 417
}