Subversion Repositories eFlore/Applications.coel

Rev

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

Rev Author Line No. Line
1497 jpm 1
<?php
1528 jpm 2
/** Paramêtres indiquant que l'on est en français pour permettre l'affichage des dates en français. */
3
setlocale(LC_TIME, 'fr_FR.UTF-8');
1578 jpm 4
/** Définition de l'encodage interne des fichiers. */
5
mb_internal_encoding('UTF-8');
6
 
1497 jpm 7
/**
8
 * Classe mère abstraite contenant les méthodes génériques des services.
9
 * Encodage en entrée : utf8
10
 * Encodage en sortie : utf8
11
 *
12
 * @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
13
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
14
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
15
 * @version $Id$
16
 * @copyright 2009
17
 */
18
abstract class Coel {
19
 
20
	const ETAT_AJOUTER = 1;
21
	const ETAT_MODIFIER = 2;
22
	const ETAT_SUPPRIMER = 3;
23
 
24
	protected $sessionName = 'CoelSession';
25
	protected $sessionExpireTime = 8640000;// 60*60*24*100 = 100 jours
26
	protected static $cookieChemin = '';
27
	public $config;
28
	protected $bdd;
29
	protected $log = array();
30
	protected $messages = array();
31
	protected $debug = array();
32
	protected $distinct = false;
33
	protected $orderby = null;
34
	protected $formatRetour = 'objet';
35
	protected $start = 0;
36
	protected $limit = 150;
37
 
38
	public function __construct($config, $demarrer_session = true) {
39
		// Tableau contenant la config de Jrest
40
		$this->config = $config;
41
 
42
		// Connection à la base de données
43
		$this->bdd = $this->connecterPDO($this->config, 'coel');
44
 
45
		$this->gererSession($demarrer_session);
46
		$this->gererIdentificationPermanente();
1697 raphael 47
 
48
        if(isset($_GET['start'])) $this->start = intval($_GET['start']);
49
        if(isset($_GET['limit'])) $this->limit = intval($_GET['limit']);
1497 jpm 50
 
1697 raphael 51
		// Nettoyage du $_GET (non-sécurisé)
1497 jpm 52
		if (isset($_GET)) {
1697 raphael 53
			$get_params = array('orderby', 'distinct', 'formatRetour', 'searchCity');
1497 jpm 54
			foreach ($get_params as $get) {
55
				$verifier = array('NULL', "\n", "\r", "\\", "'", '"', "\x00", "\x1a", ';');
56
				if (isset($_GET[$get]) && $_GET[$get] != '') {
1587 aurelien 57
					$_GET[$get] = str_replace($verifier, '', $_GET[$get]);
1497 jpm 58
					$this->$get = $_GET[$get];
59
				} else {
60
					$_GET[$get] = null;
61
				}
62
			}
63
		}
64
	}
65
 
66
	/**
67
	 * Méthode appelée quand aucun paramètre n'est passé dans l'url et avec une requête de type GET.
68
	 */
69
	public function getRessource() {
70
		$this->getElement(array());
71
	}
72
 
73
 
74
	protected function creerXmlHisto($donnees) {
75
		// Création du xml de l'enregistrement à historiser
76
		$info = null;
77
		$xml_tpl = '<?xml version="1.0" encoding="UTF-8" ?>'."\n<resultset>\n<row>\n%s</row>\n</resultset>";
78
		$xml = null;
79
 
80
		foreach ($donnees as $cle => $valeur) {
81
			if (!is_null($valeur) && $valeur != '') {
82
				$xml .= "<$cle>$valeur</$cle>\n";
83
			}
84
		}
85
		if ($xml !== null) {
86
			$info = sprintf($xml_tpl, $xml);
87
			$info = $this->bdd->quote($info);
88
		}
89
 
90
		return $info;
91
	}
92
 
93
	protected function getTableauDepuisXmlHisto($xml) {
94
		// Création du xml de l'enregistrement à historiser
95
		$info = array();
96
 
97
		if (!empty($xml) && preg_match_all('|<([^>]+)>(.*)</[^>]+>|U', $xml, $matches, PREG_SET_ORDER)) {
98
			foreach ($matches as $val) {
99
				$info[$val[1]] = $val[2];
100
			}
101
		}
102
 
103
		return $info;
104
	}
105
 
106
	protected function historiser($table_id, $ligne_cle, $info, $id_utilisateur, $etat, $id_session) {
1648 raphael 107
		date_default_timezone_set('Europe/Paris');
1497 jpm 108
		// Pré-traitement des variables
109
		$info = (is_null($info)) ? 'NULL' : $info;
110
 
111
		// Historisation (Ajout des méta-données)
112
		$requete = 	'INSERT INTO coel_meta_historique_ligne '.
113
					'	(cmhl_ce_table, cmhl_cle_ligne, cmhl_enregistrement, cmhl_date_modification, cmhl_ce_modifier_par, cmhl_ce_etat, cmhl_ip, cmhl_session_id) '.
114
					'VALUES ('.
115
					"		$table_id, ".
116
					'		"'.$ligne_cle.'", '.
117
					"		$info, ".
118
 					'		"'.date('Y-m-d H:i:s', time()).'", '.
119
					"		$id_utilisateur, ".
120
					"		$etat, ".
121
					'		"'.$_SERVER['REMOTE_ADDR'].'", '.
122
					'		"'.$id_session.'") ';
123
 
124
   		// Exécution de la requêtre SQL et test d'éventuelles erreurs
125
		$resultat = $this->bdd->exec($requete);
126
		if ($resultat === false ) {
127
			$this->log[] = "Des données de la table '$table_id' (enrg. $ligne_cle) n'ont pas été historisées car la requête a échouée.";
128
		}
129
		return $this->bdd->lastInsertId();
130
	}
131
 
1621 aurelien 132
	protected function envoyer($donnees = null, $mime = 'application/json', $encodage = 'utf-8', $json = true) {
1497 jpm 133
		// Traitements des messages d'erreurs et données
134
		if (count($this->messages) != 0) {
135
			header('HTTP/1.1 500 Internal Server Error');
136
			$mime = 'text/html';
137
			$encodage = 'utf-8';
138
			$json = true;
139
			$sortie = $this->messages;
140
		} else {
141
			$sortie = $donnees;
142
			if (is_null($donnees)) {
143
				$sortie = 'OK';
144
			}
145
		}
146
 
147
		// Gestion de l'envoie du déboguage
148
		$this->envoyerDebogage();
149
 
150
		// Encodage au format et JSON et envoie sur la sortie standard
151
		$contenu = $json ? json_encode($sortie) : $sortie;
152
		$this->envoyerContenu($encodage, $mime, $contenu);
153
	}
154
 
1527 jpm 155
	protected function envoyerHTML($donnees = null) {
156
		// Traitements des messages d'erreurs et données
157
		$contenu = '';
158
		if (count($this->messages) > 0) {
159
			$contenu = '<p>'.implode('<br />', $this->messages).'</p>';
160
		} else {
161
			$contenu = $donnees;
162
			if (is_null($donnees)) {
163
				$contenu = 'OK';
164
			}
165
		}
166
 
167
		// Gestion de l'envoie du déboguage
168
		$this->envoyerDebogage();
169
 
170
		// Envoie sur la sortie standard
1587 aurelien 171
		$this->envoyerContenu(null, null, $contenu);
1527 jpm 172
	}
173
 
174
	protected function envoyerEnteteMessage() {
175
		if (!is_array($this->messages)) {
176
			$this->messages[] = $this->messages;
177
		}
178
		if (count($this->messages) != 0) {
179
			foreach ($this->messages as $cle => $val) {
180
				if (is_array($val)) {
181
					$this->messages[$cle] = print_r($val, true);
182
				}
183
			}
184
			header('X-MessageJrest-Data: '.json_encode($this->messages));
185
		}
186
	}
187
 
1497 jpm 188
	protected function envoyerDebogage() {
1527 jpm 189
		$this->envoyerEnteteDebogage();
190
	}
191
 
192
	protected function envoyerEnteteDebogage() {
1497 jpm 193
		if (!is_array($this->debug)) {
194
			$this->debug[] = $this->debug;
195
		}
196
		if (count($this->debug) != 0) {
197
			foreach ($this->debug as $cle => $val) {
198
				if (is_array($val)) {
199
					$this->debug[$cle] = print_r($val, true);
200
				}
201
			}
1527 jpm 202
			header('X-DebugJrest-Data: '.json_encode($this->debug));
1497 jpm 203
		}
204
	}
205
 
206
	protected function envoyerContenu($encodage, $mime, $contenu) {
1577 jpm 207
		if (!is_null($mime) && !is_null($encodage)) {
208
			header("Content-Type: $mime; charset=$encodage");
209
		} else if (!is_null($mime) && is_null($encodage)) {
210
			header("Content-Type: $mime");
211
		}
1497 jpm 212
		print $contenu;
213
	}
214
 
215
	private function connecterPDO($config, $base = 'database') {
216
        $cfg = $config[$base];
217
		$dsn = $cfg['phptype'].':dbname='.$cfg['database'].';host='.$cfg['hostspec'];
218
		try {
219
    		$PDO = new PDO($dsn, $cfg['username'], $cfg['password']);
220
		} catch (PDOException $e) {
221
    		echo 'La connexion à la base de donnée via PDO a échouée : ' . $e->getMessage();
222
		}
223
		// Passe en UTF-8 la connexion à la BDD
224
		$PDO->exec("SET NAMES 'utf8'");
225
		// Affiche les erreurs détectées par PDO (sinon mode silencieux => aucune erreur affiché)
226
		$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
227
        return $PDO;
228
	}
229
 
230
	protected function getTxt($id) {
231
		$sortie = '';
232
		switch ($id) {
233
			case 'sql_erreur' : $sortie = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s'; break;
1536 jpm 234
			case 'sql_erreur_requete' : $sortie = "Requête echec.\nFichier : %s.\nLigne : %s.\nMessage : %s.\nRequête : %s"; break;
1497 jpm 235
			default : $sortie = $id;
236
		}
237
		return $sortie;
238
	}
239
 
240
	protected function concatenerChamps($champs, $prefixe = null) {
241
		$chaine = '';
242
		foreach ($champs as $cle => $valeur) {
243
			if (is_null($prefixe) || (!is_null($prefixe) && stristr($cle, $prefixe.'_'))) {
244
				$chaine .= ", $cle = $valeur";
245
			}
246
		}
247
		return ltrim($chaine, ', ');
248
	}
249
 
250
	protected function separerChampsValeurs($donnees, $prefixe = null) {
251
		$sortie = array('', '');
252
		// Concaténation des champs et des valeurs dans des chaines séparées
253
		foreach ($donnees as $cle => $valeur) {
254
			if (is_null($prefixe) || (!is_null($prefixe) && stristr($cle, $prefixe.'_'))) {
255
				$sortie[0] .= "$cle, ";
256
				$sortie[1] .= "$valeur, ";
257
			}
258
		}
259
		// Suppression de la virgule finale
260
		$sortie[0] = rtrim($sortie[0], ', ');
261
		$sortie[1] = rtrim($sortie[1], ', ');
262
		return $sortie;
263
	}
264
 
265
 
266
	protected function traiterParametresUrl($params_attendu, $params, $pourBDD = true) {
267
		$sortie = array();
268
		foreach ($params_attendu as $num => $nom) {
269
			if (isset($params[$num]) && $params[$num] != '*') {
270
				if ($pourBDD) {
271
					$params[$num] = $this->bdd->quote($params[$num]);
272
				}
273
				$sortie[$nom] = $params[$num];
274
			}
275
		}
276
		return $sortie;
277
	}
278
 
279
	protected function traiterBddClauseIn($chaine) {
280
		$sortie = '';
281
		$chaine = trim($chaine, " '");
282
		if ($chaine != '') {
283
			$valeurs = explode(',', $chaine);
284
			foreach ($valeurs as $id => $valeur) {
285
				$valeurs[$id] = $this->bdd->quote($valeur);
286
			}
287
			$sortie = implode(',', $valeurs);
288
		}
289
		return $sortie;
290
	}
291
 
292
	protected function traiterParametresPost($params) {
293
		$sortie = array();
294
		foreach ($params as $cle => $valeur) {
295
			$sortie[$cle] = $this->bdd->quote($valeur);
296
		}
297
		return $sortie;
298
	}
299
 
300
	protected function getIdentification(&$params) {
301
		// Initialisation des variables
302
		$utilisateur = array(0, session_id());
303
 
304
		// L'id utilisateur est soit passé par le POST soit dans l'url
305
		if (is_array($params) && isset($params['cmhl_ce_modifier_par'])) {
306
		   	$utilisateur[0] = $params['cmhl_ce_modifier_par'];
307
			unset($params['cmhl_ce_modifier_par']);
308
		} else if (is_string($params)) {
309
			$utilisateur[0] = $params;
310
		}
311
 
312
		return $utilisateur;
313
	}
314
 
315
	protected function etreAutorise($id_utilisateur) {
316
		$autorisation = false;
1648 raphael 317
		if (!array_key_exists('coel_utilisateur', $_SESSION) || (($_SESSION['coel_utilisateur'] != '') && $_SESSION['coel_utilisateur']['id'] != $id_utilisateur)) {
1497 jpm 318
			$this->messages[] = 'Accès interdit.';
319
		} else if ($_SESSION['coel_utilisateur'] == '') {
320
			$this->messages[] = 'Veuillez vous identifiez pour accéder à cette fonction.';
321
		} else {
322
			$autorisation = true;
323
		}
324
		return $autorisation;
325
	}
326
 
327
	protected function recupererCle($table) {
328
		$cle = null;
329
		if (isset($table['champs_valeurs_id'])) {
330
			$identifiants = array();
331
			// Trie des clés primaire pour avoir toujours le même ordre dans la table historique pour les clés multiples
332
			ksort($table['champs_valeurs_id']);
333
		   	foreach ($table['champs_valeurs_id'] as $id) {
334
		   		$identifiants[] = $id;
335
		   	}
336
		   	$cle = implode('-', $identifiants);
337
		}
338
		return $cle;
339
	}
340
 
341
	protected function avoirCleComplete($table) {
342
		$cle_complete = false;
343
		if (isset($table['champs_valeurs_id'])) {
344
		   	$ok = true;
345
			foreach ($table['id'] as $id) {
346
		   		if (!isset($table['champs_valeurs_id'][$id]) || $table['champs_valeurs_id'][$id] == '') {
347
		   			$ok = false;
348
		   			break;
349
		   		}
350
		   	}
351
		   	$cle_complete = $ok;
352
		}
353
		return $cle_complete;
354
	}
355
 
356
	protected function recupererEtat($table) {
357
		$etat = 1;// Ajout
358
		if ($this->avoirEnregistrement($table) === true) {
359
			$etat = 2;// Modification
360
		}
361
		return $etat;
362
	}
363
 
364
	protected function avoirEnregistrement($table) {
365
		$avoir_enregistrement = false;
366
   		$requete = 	'SELECT * '.
367
					"FROM {$table['nom']} ".
368
					"WHERE %s ";
369
 
370
   		$where = $this->construireWhere($table['champs_valeurs_id']);
371
   		$requete = sprintf($requete, $where);
372
 
373
	   	// Exécution de la requêtre SQL et test d'éventuelles erreurs
374
		$resultat = $this->bdd->query($requete, PDO::FETCH_ASSOC)->fetch();
375
 
376
		if ($resultat !== false) {
377
			$avoir_enregistrement = true;
378
		}
379
		return $avoir_enregistrement;
380
	}
381
 
1524 jpm 382
	protected function contenirDonnees($requete) {
383
		$nbre = $this->bdd->query($requete)->fetchColumn();
384
 
385
		$presence = false;
386
		if ($nbre != 0) {
387
			$presence = true;
388
		}
389
		return $presence;
390
	}
391
 
1497 jpm 392
	protected function construireWhere($table) {
393
		$where = '1';
394
	   	if (is_array($table) && count($table) > 0) {
395
			$table_where = array();
396
	   		foreach ($table as $chp => $id) {
397
	   			$table_where[] = "$chp = '$id'";
398
	   		}
399
	   		$where = implode(' AND ', $table_where);
400
	   	}
401
	   	return $where;
402
	}
403
 
404
	protected function recupererTablesAModifier($parametres) {
405
		$tables_a_modifier = $this->tables;
406
   		foreach ($this->tables as $table_id => $table) {
407
   			$tables_a_modifier[$table_id]['champs'] = null;
408
   			foreach ($parametres as $cle => $valeur) {
409
   				if (preg_match('/^'.$table['prefixe'].'_/', $cle)) {
410
   					// Contient les noms des champs seulements
411
   					$tables_a_modifier[$table_id]['champs'][] = $cle;
412
   					// Contient un tableau de résultats protégé pour l'inclusion en bdd
1684 raphael 413
   					$tables_a_modifier[$table_id]['champs_valeurs_protege'][$cle] = is_null($valeur) ? 'NULL' : $this->bdd->quote($valeur);
1497 jpm 414
   					// Contient un tableau de résultats non protégé
415
   					$tables_a_modifier[$table_id]['champs_valeurs_brut'][$cle] = $valeur;
416
   					if (preg_match('/_id_/', $cle)) {
417
   						$tables_a_modifier[$table_id]['champs_valeurs_id'][$cle] = $valeur;
418
   					}
419
   				}
420
   			}
421
   		}
422
   		return $tables_a_modifier;
423
	}
424
 
425
 
426
	protected function mettreAJourAvecCle($id_utilisateur, $id_session, $table_id, $table) {
427
		if (!is_null($table['champs'])) {
428
	   		// Historisation (Ajout des méta-données)
429
	   		$cle = $this->recupererCle($table);
430
	   		$etat = $this->recupererEtat($table);
431
	   		$info = $this->creerXmlHisto($table['champs_valeurs_brut']);
432
			$id_meta = $this->historiser($table_id, $cle, $info, $id_utilisateur, $etat, $id_session);
433
			$champ_meta = "{$table['prefixe']}_ce_meta";
434
			$table['champs_valeurs_protege'][$champ_meta] = $this->bdd->quote($id_meta);
435
 
436
			// Mise à jour des données ou ajout en fonction de l'état
437
			if ($etat == 1) { // Ajout
438
				$this->ajouter($table);
439
			} else if ($etat == 2) { // Modif
440
				$this->modifier($table);
441
			}
442
   		}
443
	}
444
 
445
	protected function ajouter($table) {
446
		$requete = 	"INSERT INTO {$table['nom']} ".
447
   					' (%s) '.
448
					' VALUES (%s) ';
449
 
450
		$champs = $valeurs = '';
451
		foreach ($table['champs_valeurs_protege'] as $chp => $val) {
452
			$champs .= "$chp, ";
453
			$valeurs .= "$val, ";
454
		}
455
		$requete = sprintf($requete, rtrim($champs, ', '), rtrim($valeurs, ', '));
456
 
457
		$resultat = $this->bdd->exec($requete);
458
		$dernier_id = false;
459
		if ($resultat === false) {
460
			$cle = $this->recupererCle($table);
461
			$this->log[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été ajouté car la requête a échouée.";
462
		} else {
463
			$dernier_id = $this->bdd->lastInsertId();
464
		}
465
		return $dernier_id;
466
	}
467
 
468
	protected function modifier($table) {
1669 raphael 469
        // nous ne voulons pas qu'une requête malheureuse affecte toute la base de données. Par exemple:
470
        // POST "/jrest/CoelStructure/1"<<<"var=val&" // écraserait tous les enregistrements
471
        // car on ne peut garantir que tout le code existant wrap'era ses appels dans un if(avoirCleComplete())
472
        if(!array_key_exists('champs_valeurs_id', $table)) die('erreur: ' . __FILE__ . ':' . __LINE__);
1497 jpm 473
		$requete = 	"UPDATE {$table['nom']} ".
474
   					'SET %s '.
475
   					'WHERE %s ';
476
 
477
		$champs_requete = '';
478
		foreach ($table['champs_valeurs_protege'] as $chp => $val) {
479
			$champs_requete .= "$chp = $val, ";
480
		}
481
		$where = $this->construireWhere($table['champs_valeurs_id']);
482
		$requete = sprintf($requete, rtrim($champs_requete, ', '), $where);
483
		$resultat = $this->bdd->exec($requete);
484
		if ($resultat === false) {
485
			$cle = $this->recupererCle($table);
486
			$this->log[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été mis à jour car la requête a échouée.";
487
		} else {
488
			$resultat = true;
489
		}
490
		return $resultat;
491
	}
492
 
493
	protected function supprimer($table) {
494
		$requete = 	"DELETE FROM {$table['nom']} ".
495
					'WHERE %s ';
496
 
497
		$where = $this->construireWhere($table['champs_valeurs_id']);
498
		$requete = sprintf($requete, $where);
499
 
500
		$resultat = $this->bdd->exec($requete);
501
		if ($resultat === false) {
502
			$cle = $this->recupererCle($table);
503
			$this->messages[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été supprimé car la requête a échouée.";
504
		} else {
505
			$resultat = true;
506
		}
507
		return $resultat;
508
	}
509
 
510
	private function gererSession($demarrage) {
511
		session_name($this->sessionName);
512
 
513
		// Configuration du cookie de session
514
		// Détermination du chemin pour les cookies nécessaire à Jrest
515
		/// ATTENTION : comme les cookies sont passés à Jrest, il faut utiliser l'url de Jrest pour établir le chemin
516
		$url_morceaux = parse_url($this->config['coel']['urlBaseJrest']);
1588 aurelien 517
		self::$cookieChemin = $this->reparerCheminCookie($url_morceaux['path']);
1497 jpm 518
		unset($url_morceaux);
1588 aurelien 519
		session_set_cookie_params($this->sessionExpireTime, self::$cookieChemin);
1497 jpm 520
 
521
		// Démarrage de la session
522
		if ($demarrage) {
523
			session_start();
524
		}
525
	}
526
 
527
	private function reparerCheminCookie($chemin) {
528
		// dirname renvoit / si le chemin vaut seulement /dossier/, cela renvoit /dossier si le chemin vaut /dossier//.
529
		$chemin = dirname($chemin.'/.');
530
		// Fixe la gestion des chemins pour les cookies sous les OS utilisant le \ comme séparteur de chemin
531
		$chemin = str_replace('\\', '/', $chemin);
532
		// Ajoute un '/' terminal sauf si on est à la racine web
533
		$chemin = ($chemin != '/' ? $chemin.'/' : '');
534
		return $chemin;
535
	}
536
 
537
	private function gererIdentificationPermanente() {
538
		// Pour maintenir l'utilisateur tjrs réellement identifié nous sommes obligé de recréer une SESSION et de le recharger depuis la bdd
539
		if ($this->getUtilisateur() == ''
540
				&& isset($_COOKIE['coel_login'])
541
				&& ($utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe']))) {
542
			$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']);
543
		}
544
	}
545
 
1612 aurelien 546
	protected function rechargerCookieUtilisateur() {
547
		$utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login']);
548
		$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']);
549
	}
550
 
1497 jpm 551
	protected function getUtilisateur() {
552
		return (isset($_SESSION['coel_utilisateur']) ? $_SESSION['coel_utilisateur'] : '');
553
	}
554
 
555
	protected function chargerUtilisateur($login, $mot_de_passe = null) {
556
		$sortie = false;
557
		$requete =	'SELECT cp_id_personne AS id, cp_fmt_nom_complet AS nom_complet, cp_prenom AS prenom, '.
558
					'	cp_nom AS nom, cp_login AS login, cp_mot_de_passe AS mot_de_passe, cp_parametre AS parametre, '.
559
					'	cp_ville AS ville, cp_code_postal AS code_postal, '.
560
					'	cp_mark_licence AS licence '.
561
					'FROM coel_personne '.
562
					"WHERE cp_login = {$this->bdd->quote($login)} ".
563
					((!is_null($mot_de_passe)) ? "AND cp_mot_de_passe = {$this->bdd->quote($mot_de_passe)} " : '');
564
		try {
565
			$resultat = $this->bdd->query($requete)->fetch();
566
			if ($resultat === false) {
1508 jpm 567
				$this->debug[] = "L'utilisateur n'est pas enregistré comme utilisateur de COEL.";
1497 jpm 568
			} else {
569
				$sortie = array('id' => $resultat['id'],
570
					'login' => $login,
571
					'mot_de_passe' => $resultat['mot_de_passe'],
572
					'nom_complet' => $resultat['nom_complet'],
573
					'nom' => $resultat['nom'],
574
					'prenom' => $resultat['prenom'],
575
					'parametre' => $resultat['parametre'],
576
					'ville' => $resultat['ville'],
577
					'code_postal' => $resultat['code_postal'],
578
					'licence' => $resultat['licence']);
579
			}
580
		} catch (PDOException $e) {
581
			$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
582
		}
583
 
584
		return $sortie;
585
	}
586
 
587
	protected function setUtilisateur($utilisateur, $permanence = 1) {
588
		$_SESSION['coel_utilisateur'] = $utilisateur;
589
		$this->debug[] = $_SESSION['coel_utilisateur'];
590
		$this->setCookiePersistant('coel_login', $utilisateur['login'], $permanence);
591
		$this->setCookiePersistant('coel_mot_de_passe', $utilisateur['mot_de_passe'], $permanence);
592
		$this->setCookiePersistant('coel_licence', $utilisateur['licence'], $permanence);
593
		$this->setCookiePersistant('coel_permanence', $permanence, $permanence);
594
	}
595
 
596
	protected function setCookiePersistant($cookie_nom, $valeur, $permanence = 1) {
1588 aurelien 597
		setCookie($cookie_nom, $valeur, time() + ($permanence ? 100*24*60*60 : 60*60), self::$cookieChemin);
1497 jpm 598
		$_COOKIE[$cookie_nom] = $valeur;
599
	}
600
 
601
	protected function supprimerCookie($cookie_nom) {
1588 aurelien 602
		setCookie($cookie_nom, '', 1, self::$cookieChemin);
1497 jpm 603
		$_COOKIE[$cookie_nom] = '';
604
	}
605
 
606
	/**
607
	 * Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
608
	 * en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
609
	 *
610
	 * @param String $fichier	le chemin du fichier du squelette
611
	 * @param Array  $donnees	un tableau associatif contenant les variables a injecter dans le squelette.
612
	 *
613
	 * @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
614
	 */
615
	public static function traiterSquelettePhp($fichier, Array $donnees = array()) {
616
		$sortie = false;
617
		if (file_exists($fichier)) {
618
			// Extraction des variables du tableau de données
619
			extract($donnees);
620
			// Démarage de la bufferisation de sortie
621
			ob_start();
622
			// Si les tags courts sont activés
623
			if ((bool) @ini_get('short_open_tag') === true) {
624
				// Simple inclusion du squelette
625
				include $fichier;
626
			} else {
627
				// Sinon, remplacement des tags courts par la syntaxe classique avec echo
628
				$html_et_code_php = self::traiterTagsCourts($fichier);
629
				// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
630
				$html_et_code_php = '?>'.$html_et_code_php;
631
				// Interprétation du html et du php dans le buffer
632
				echo eval($html_et_code_php);
633
			}
634
			// Récupèration du contenu du buffer
635
			$sortie = ob_get_contents();
636
			// Suppression du buffer
637
			@ob_end_clean();
638
		} else {
639
			$msg = "Le fichier du squelette '$fichier' n'existe pas.";
640
			trigger_error($msg, E_USER_WARNING);
641
		}
642
		// Retourne le contenu
643
		return $sortie;
644
	}
645
 
646
	/**
647
	 * Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
648
	 *
649
	 * @param String $chemin_squelette le chemin du fichier du squelette
650
	 *
651
	 * @return string le contenu du fichier du squelette php avec les tags courts remplacés.
652
	 */
653
	private static function traiterTagsCourts($chemin_squelette) {
654
		$contenu = file_get_contents($chemin_squelette);
655
		// Remplacement de tags courts par un tag long avec echo
656
		$contenu = str_replace('<?=', '<?php echo ',  $contenu);
657
		// Ajout systématique d'un point virgule avant la fermeture php
658
		$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
659
		return $contenu;
660
	}
1527 jpm 661
 
662
	public static function debug($var) {
663
		echo '<pre>'.print_r($var, true).'</pre>';
664
	}
1649 raphael 665
 
666
	/*
667
	 * Retourne une pair de coordonnée depuis un tableau représentant une adresse
668
	 * ou une adresse partielle à l'aide du service Nominatim.
669
	 * (http://wiki.openstreetmap.org/wiki/Nominatim)
670
	 *
671
	 * @param in data: un tableau associatif doté de *toutes* les clefs suivantes:
672
	 * 				   'adresse', 'cp', 'ville', 'pays'
673
	 * @param out lonlat: un tableau associatif contenant 'lon' et 'lat' si elles ont été déterminées
1667 raphael 674
	 *					  Celles-ci sont sous la forme de deux chaînes de caractères numériques représentant
675
	 *					  un FLOAT() dont le séparateur des décimales est le "." (point).
1651 raphael 676
	 * @param in opts: un tableau associatif optionnel écrasant ou ajoutant des valeurs d'API
1649 raphael 677
	 * @return boolean: selon que la fonction à réussi ou non
1658 raphael 678
	 *
679
	 * opts['force-q']: force l'utilisation d'une requête en texte libre
680
	 * 					quelque soit le remplissage des composants individuels
681
	 *
682
	 * Note: le code postal est contre-productif pour Nominatim:
683
	 * https://lists.openstreetmap.org/pipermail/talk-fr/2013-April/057084.html
1649 raphael 684
	 */
1651 raphael 685
	static function coordGuess(Array $data, Array &$lonlat, Array $opts = NULL) {
1649 raphael 686
		if(!$data) return FALSE;
1651 raphael 687
		$common_query = array('accept_language' => 'fr', 'format' => 'json', 'limit' => 1);
1658 raphael 688
		if(! $data['adresse'] || (! $data['cp'] && ! $data['ville']) || @$opts['force-q']) {
689
			unset($opts['force-q']);
1651 raphael 690
			$query = array_merge($common_query,
1658 raphael 691
								 array('q' => implode(', ', array_filter($data))),
1651 raphael 692
								 $opts ? $opts : array());
693
		}
694
		else {
695
			$query = array_merge($common_query,
696
								 array_filter(array('street' => $data['adresse'],
697
													'city' => $data['ville'],
698
													'postalcode' => $data['cp'],
699
													'country' => $data['pays'])),
700
								 $opts ? $opts : array());
701
		}
702
		$fullquery = 'http://nominatim.openstreetmap.org/search.php?' . http_build_query($query);
1684 raphael 703
 
1686 raphael 704
        $ctx = stream_context_create(array('http' => array( 'timeout' => '4' )));
705
        $r = json_decode(file_get_contents($fullquery, FALSE, $ctx));
1651 raphael 706
		error_log(sprintf("COEL: Nominatim request returned %d result(s) [%s]", count($r), $fullquery));
707
		if($r && isset($r[0])) {
708
			$lonlat['lon'] = $r[0]->lon;
709
			$lonlat['lat'] = $r[0]->lat;
710
			return TRUE;
711
		}
1649 raphael 712
		return FALSE;
713
	}
714
 
715
	/*
716
	 * Retourne un tableau prêt à être utilisé par coordGuess(), c'est à dire initialisant toutes
717
	 * les clefs nécessaires (même si NULL) et disposant systématiquement d'un pays.
718
	 * Cela à partir d'un tableau au format de clefs prédéterminé.
1658 raphael 719
	 * S'occupe du filtrage basique des éléments pour maximiser les chances de détection.
1649 raphael 720
	 *
1709 raphael 721
	 * @param in: un tableau associatif contenant les clefs telles que nommées à l'issue du
1649 raphael 722
	 * 				du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
1709 raphael 723
	 * @param db: une db optionnelle, utilisée si nécessaire pour converir les code pays
724
	 * 				du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
1649 raphael 725
	 * @return un tableau associatif contenant une ou plusieurs des clefs suivantes:
726
	 *			'adresse', 'cp', 'ville', 'pays'
727
	 */
1709 raphael 728
	static function addrReStruct(Array $in, $db = NULL) {
729
        $pays = FALSE;
730
		if(is_numeric(@$in['cs_ce_truk_pays'])) {
731
            if($db) {
732
                $pays= $db->query(sprintf(
733
                    "SELECT cmlv_nom FROM coel_meta_liste_valeur ".
734
                    "WHERE cmlv_ce_parent = 1074 AND cmlv_id_valeur = %d",
735
                    intval($in['cs_ce_truk_pays'])))->fetchColumn();
736
            }
737
        }
738
        else $pays = @trim($in['cs_ce_truk_pays']);
1651 raphael 739
 
740
		// pas de précision au n°, mais Nominatim peine avec des préfixes trop élaborés
741
		// coupons jusqu'à un élément reconnaissable s'il existe
742
		$adresse = @trim($in['cs_adresse_01']);
1658 raphael 743
		$adresse = substr($adresse, stripos($adresse, "ville de "));
744
		$adresse = substr($adresse, stripos($adresse, "impasse"));
745
		$adresse = substr($adresse, stripos($adresse, "chemin"));
746
		$adresse = substr($adresse, stripos($adresse, "route"));
1651 raphael 747
		$adresse = substr($adresse, stripos($adresse, "rue"));
748
		$adresse = substr($adresse, stripos($adresse, "avenue"));
749
		$adresse = substr($adresse, stripos($adresse, "boulevard"));
750
		$adresse = substr($adresse, stripos($adresse, "place"));
1658 raphael 751
		$adresse = substr($adresse, stripos($adresse, "promenade"));
752
		$adresse = substr($adresse, stripos($adresse, "allée"));
1718 raphael 753
		$adresse = substr($adresse, stripos($adresse, "cours"));
1658 raphael 754
		$adresse = preg_replace("/[\r\n].*/", "", $adresse);
1651 raphael 755
 
1658 raphael 756
		$ville = preg_replace('/cedex.*/i', '', @trim($in['cs_ville']));
1649 raphael 757
		return array(
1651 raphael 758
			'adresse' => $adresse,
1649 raphael 759
			'cp' => @trim($in['cs_code_postal']) ? $in['cs_code_postal'] : '',
1658 raphael 760
			'ville' => $ville,
1651 raphael 761
			'pays' =>  $pays !== FALSE ? $pays : 'France'
1649 raphael 762
		);
763
	}
1497 jpm 764
}
765
?>