Subversion Repositories eFlore/Applications.coel

Rev

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