Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 1058 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1058 jpm 1
<?php
2
/**
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
 
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;
21
	private $elementType = '';
22
 
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
	}
29
 
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
	 */
35
	public function executer() {
36
		// Lancement de l'action demandée
37
		$cmd = $this->conteneur->getParametre('a');
38
		switch ($cmd) {
39
			case 'maj' :
40
				$this->mettreAjour();
41
				break;
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);
46
		}
47
		print "\n";// Pour ramener à la ligne en fin de script
48
	}
49
 
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
	*/
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());
60
			}
61
 
62
			if ($this->mode == 'manuel') {
63
				$this->messages->afficherAvancement("Analyse de la ligne du fichier de diff OSM : ", 1);
64
			}
65
		}
66
	}
67
 
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();
86
			}
87
		}
88
 
89
		$ways = $creations->getElementsByTagName('way');
90
		if ($ways->length > 0) {
91
			foreach ($ways as $way) {
92
				$this->analyserWay($way);
93
				$this->traiterCheminANoeuds();
94
			}
95
		}
96
 
97
		$noeuds = $creations->getElementsByTagName('node');
98
		if ($noeuds->length > 0) {
99
			foreach ($noeuds as $noeud) {
100
				$this->analyserNode($noeud);
101
				$this->traiterNoeuds();
102
			}
103
		}
104
 
105
		$this->traiterElementsOrphelins();
106
	}
107
 
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;
120
			}
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;
133
			}
134
		}
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;
149
			}
150
		}
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;
165
			}
166
		}
167
	}
168
 
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();
185
				$this->supprimerRelationAChemins();
186
				$this->supprimerCheminANoeuds();
187
				$this->supprimerNoeuds();
188
				break;
189
		}
190
	}
191
 
192
	/**
193
	 * Récupère l'id commune, nom commune et le code INSEE et remplie la table `osm_relations`
194
	 */
195
	private function analyserRelation($relation) {
196
		$relation_id = $relation->getAttribute('id');
197
		$chemins = $relation->getElementsByTagName('member');
198
		foreach ($chemins as $chemin) {
199
			if ($chemin->getAttribute('type') == 'way') { //écarter le noeud centrale
200
				$chemin_id = $chemin->getAttribute('ref');
201
				$role = $chemin->getAttribute('role');//role: null, inner, outer, exclave et enclave.
202
				$this->relation_a_chemins[] = array($relation_id, $chemin_id, $role);
203
			}
204
		}
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) {
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' :
220
					$commune_nom = $tag_val;
221
					break;
222
				case 'ref:INSEE' :
223
					$commune_insee = $tag_val;
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
			}
237
		}
238
	}
239
 
240
	/**
241
	 * Récupère l'id_way et tous les id_node de chaque way et remplie la table `osm_chemin_a_noeuds`
242
	 */
243
	private function analyserWay($way) {
244
		$chemin_id = $way->getAttribute('id');
245
		$noeuds = $way->getElementsByTagName('nd');
246
		$ordre = 0;
247
		foreach ($noeuds as $noeud) {
248
			$noeud_id = $noeud->getAttribute('ref');
249
			$this->chemin_a_noeuds[] = array($chemin_id, $noeud_id, ++$ordre);
250
		}
251
	}
252
 
253
	/**
254
	 * Fonction qui récupère tous les l'id_node et les valeurs(Lat/Lon) correspondantes et remplie la table `osm_noeuds`
255
	 */
256
	private function analyserNode($node) {
257
		$this->noeuds[] = array(
258
			$node->getAttribute('id'),
259
			$node->getAttribute('lat'),
260
			$node->getAttribute('lon')
261
		);
262
	}
263
 
264
	//Insertion des relations
265
	private function insererRelationsCommunes() {
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);
270
		$this->relations_communes = array();
271
	}
272
 
273
	//Insertion des relations à chemins
274
	private function insererRelationAChemins() {
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);
279
		$this->relation_a_chemins = array();
280
	}
281
 
282
	//Insertion des chemins à noeuds
283
	private function insererCheminANoeuds() {
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);
288
		$this->chemin_a_noeuds = array();
289
	}
290
 
291
	//Insertion des noeuds
292
	private function insererNoeuds() {
293
		$requete = 'INSERT INTO osm_noeuds (id_noeud, lat, `long`) '.
294
			'VALUES '.$this->creerValuesMultiple($this->noeuds).
295
			' -- '.__FILE__.' : '.__LINE__;
296
		$this->bdd->requeter($requete);
297
		$this->noeuds = array();
298
	}
299
 
300
	//Update des relations
301
	private function modifierRelationsCommunes() {
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);
309
		}
310
		$this->relations_communes = array();
311
	}
312
 
313
	/*
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
316
	*/
317
	private function modifierRelationAChemins() {
318
		$this->supprimerRelationAChemins();
319
		foreach ($this->relation_a_chemins as $donnee) {
320
			$infosP = $this->bdd->proteger($donnee);
321
			$requete = 'INSERT INTO osm_relation_a_chemins (id_relation, id_chemin, role) '.
322
				"VALUES ($infosP[0], $infosP[1], $infosP[2]) ".
323
				' -- '.__FILE__.' : '.__LINE__;
324
			$this->bdd->requeter($requete);
325
		}
326
		$this->relation_a_chemins = array();
327
	}
328
 
329
	/*
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
332
	*/
333
	private function modifierCheminANoeuds() {
334
		$this->supprimerCheminANoeuds();
335
		foreach ($this->chemin_a_noeuds as $donnee) {
336
			$infosP = $this->bdd->proteger($donnee);
337
			$requete = 'INSERT INTO osm_chemin_a_noeuds (id_chemin, id_noeud, ordre) '.
338
				"VALUES ($infosP[0], $infosP[1], $infosP[2]) ".
339
				' -- '.__FILE__.' : '.__LINE__;
340
			$this->bdd->requeter($requete);
341
		}
342
		$this->chemin_a_noeuds = array();
343
	}
344
 
345
	//Update des noeuds
346
	private function modifierNoeuds() {
347
		foreach ($this->noeuds as $donnee) {
348
			$infosP = $this->bdd->proteger($donnee);
349
			$requete = 'UPDATE osm_noeuds '.
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);
354
		}
355
		$this->noeuds = array();
356
	}
357
 
358
	//Suppressions des relations
359
	private function supprimerRelationsCommunes() {
360
		$idsIn = $this->getIds($this->relations_communes);
361
		$this->relations_communes = array();
362
		$requete = 'DELETE FROM osm_relations '.
363
			"WHERE id_relation IN ($idsIn) ".
364
			' -- '.__FILE__.' : '.__LINE__;
365
		$this->bdd->requeter($requete);
366
	}
367
 
368
	//Suppressions des relations à chemins
369
	private function supprimerRelationAChemins() {
370
		$idsIn = $this->getIds($this->relation_a_chemins);
371
		$this->relation_a_chemins = array();
372
		$requete = 'DELETE FROM osm_relation_a_chemins '.
373
			"WHERE id_relation IN ($idsIn) ".
374
			' -- '.__FILE__.' : '.__LINE__;
375
		$this->bdd->requeter($requete);
376
	}
377
 
378
	//Suppressions des chemins à noeuds
379
	private function supprimerCheminANoeuds() {
380
		$idsIn = $this->getIds($this->chemin_a_noeuds);
381
		$this->chemin_a_noeuds = array();
382
		$requete = 'DELETE FROM osm_chemin_a_noeuds '.
383
			"WHERE id_chemin IN ($idsIn) ".
384
			' -- '.__FILE__.' : '.__LINE__;
385
		$this->bdd->requeter($requete);
386
	}
387
 
388
	//Suppressions des chemins à noeuds
389
	private function supprimerNoeuds() {
390
		$idsIn = $this->getIds($this->noeuds);
391
		$this->noeuds = array();
392
		$requete = 'DELETE FROM osm_noeuds '.
393
			"WHERE id_noeud IN ($idsIn) ".
394
			' -- '.__FILE__.' : '.__LINE__;
395
		$this->bdd->requeter($requete);
396
	}
397
 
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;
406
	}
407
 
408
	private function creerValuesMultiple($donnees) {
409
		$values = array();
410
		foreach ($donnees as $infos) {
411
			$infosP = $this->bdd->proteger($infos);
412
			$values[] = implode(',', $infosP);
413
		}
414
		$valuesClause = '('.implode('),(', $values).')';
415
		return $valuesClause;
416
	}
417
}