Subversion Repositories eFlore/Applications.coel

Rev

Rev 1950 | 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'");
1954 killian 225
		// Désactive les controles strict de mysql
226
		$PDO->exec("SET SESSION sql_mode = ''");
1497 jpm 227
		// Affiche les erreurs détectées par PDO (sinon mode silencieux => aucune erreur affiché)
228
		$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
229
        return $PDO;
230
	}
231
 
232
	protected function getTxt($id) {
233
		$sortie = '';
234
		switch ($id) {
235
			case 'sql_erreur' : $sortie = 'Requête echec. Fichier : "%s". Ligne : "%s". Message : %s'; break;
1536 jpm 236
			case 'sql_erreur_requete' : $sortie = "Requête echec.\nFichier : %s.\nLigne : %s.\nMessage : %s.\nRequête : %s"; break;
1497 jpm 237
			default : $sortie = $id;
238
		}
239
		return $sortie;
240
	}
241
 
242
	protected function concatenerChamps($champs, $prefixe = null) {
243
		$chaine = '';
244
		foreach ($champs as $cle => $valeur) {
245
			if (is_null($prefixe) || (!is_null($prefixe) && stristr($cle, $prefixe.'_'))) {
246
				$chaine .= ", $cle = $valeur";
247
			}
248
		}
249
		return ltrim($chaine, ', ');
250
	}
251
 
252
	protected function separerChampsValeurs($donnees, $prefixe = null) {
253
		$sortie = array('', '');
254
		// Concaténation des champs et des valeurs dans des chaines séparées
255
		foreach ($donnees as $cle => $valeur) {
256
			if (is_null($prefixe) || (!is_null($prefixe) && stristr($cle, $prefixe.'_'))) {
257
				$sortie[0] .= "$cle, ";
258
				$sortie[1] .= "$valeur, ";
259
			}
260
		}
261
		// Suppression de la virgule finale
262
		$sortie[0] = rtrim($sortie[0], ', ');
263
		$sortie[1] = rtrim($sortie[1], ', ');
264
		return $sortie;
265
	}
266
 
267
 
268
	protected function traiterParametresUrl($params_attendu, $params, $pourBDD = true) {
269
		$sortie = array();
270
		foreach ($params_attendu as $num => $nom) {
271
			if (isset($params[$num]) && $params[$num] != '*') {
272
				if ($pourBDD) {
273
					$params[$num] = $this->bdd->quote($params[$num]);
274
				}
275
				$sortie[$nom] = $params[$num];
276
			}
277
		}
278
		return $sortie;
279
	}
280
 
281
	protected function traiterBddClauseIn($chaine) {
282
		$sortie = '';
283
		$chaine = trim($chaine, " '");
284
		if ($chaine != '') {
285
			$valeurs = explode(',', $chaine);
286
			foreach ($valeurs as $id => $valeur) {
287
				$valeurs[$id] = $this->bdd->quote($valeur);
288
			}
289
			$sortie = implode(',', $valeurs);
290
		}
291
		return $sortie;
292
	}
293
 
294
	protected function traiterParametresPost($params) {
295
		$sortie = array();
296
		foreach ($params as $cle => $valeur) {
297
			$sortie[$cle] = $this->bdd->quote($valeur);
298
		}
299
		return $sortie;
300
	}
301
 
302
	protected function getIdentification(&$params) {
303
		// Initialisation des variables
304
		$utilisateur = array(0, session_id());
305
 
306
		// L'id utilisateur est soit passé par le POST soit dans l'url
307
		if (is_array($params) && isset($params['cmhl_ce_modifier_par'])) {
308
		   	$utilisateur[0] = $params['cmhl_ce_modifier_par'];
309
			unset($params['cmhl_ce_modifier_par']);
310
		} else if (is_string($params)) {
311
			$utilisateur[0] = $params;
312
		}
313
 
314
		return $utilisateur;
315
	}
316
 
317
	protected function etreAutorise($id_utilisateur) {
318
		$autorisation = false;
1648 raphael 319
		if (!array_key_exists('coel_utilisateur', $_SESSION) || (($_SESSION['coel_utilisateur'] != '') && $_SESSION['coel_utilisateur']['id'] != $id_utilisateur)) {
1497 jpm 320
			$this->messages[] = 'Accès interdit.';
321
		} else if ($_SESSION['coel_utilisateur'] == '') {
322
			$this->messages[] = 'Veuillez vous identifiez pour accéder à cette fonction.';
323
		} else {
324
			$autorisation = true;
325
		}
326
		return $autorisation;
327
	}
328
 
329
	protected function recupererCle($table) {
330
		$cle = null;
331
		if (isset($table['champs_valeurs_id'])) {
332
			$identifiants = array();
333
			// Trie des clés primaire pour avoir toujours le même ordre dans la table historique pour les clés multiples
334
			ksort($table['champs_valeurs_id']);
335
		   	foreach ($table['champs_valeurs_id'] as $id) {
336
		   		$identifiants[] = $id;
337
		   	}
338
		   	$cle = implode('-', $identifiants);
339
		}
340
		return $cle;
341
	}
342
 
343
	protected function avoirCleComplete($table) {
344
		$cle_complete = false;
345
		if (isset($table['champs_valeurs_id'])) {
346
		   	$ok = true;
347
			foreach ($table['id'] as $id) {
348
		   		if (!isset($table['champs_valeurs_id'][$id]) || $table['champs_valeurs_id'][$id] == '') {
349
		   			$ok = false;
350
		   			break;
351
		   		}
352
		   	}
353
		   	$cle_complete = $ok;
354
		}
355
		return $cle_complete;
356
	}
357
 
358
	protected function recupererEtat($table) {
359
		$etat = 1;// Ajout
360
		if ($this->avoirEnregistrement($table) === true) {
361
			$etat = 2;// Modification
362
		}
363
		return $etat;
364
	}
365
 
366
	protected function avoirEnregistrement($table) {
367
		$avoir_enregistrement = false;
368
   		$requete = 	'SELECT * '.
369
					"FROM {$table['nom']} ".
370
					"WHERE %s ";
371
 
372
   		$where = $this->construireWhere($table['champs_valeurs_id']);
373
   		$requete = sprintf($requete, $where);
374
 
375
	   	// Exécution de la requêtre SQL et test d'éventuelles erreurs
376
		$resultat = $this->bdd->query($requete, PDO::FETCH_ASSOC)->fetch();
377
 
378
		if ($resultat !== false) {
379
			$avoir_enregistrement = true;
380
		}
381
		return $avoir_enregistrement;
382
	}
383
 
1524 jpm 384
	protected function contenirDonnees($requete) {
385
		$nbre = $this->bdd->query($requete)->fetchColumn();
386
 
387
		$presence = false;
388
		if ($nbre != 0) {
389
			$presence = true;
390
		}
391
		return $presence;
392
	}
393
 
1497 jpm 394
	protected function construireWhere($table) {
395
		$where = '1';
396
	   	if (is_array($table) && count($table) > 0) {
397
			$table_where = array();
398
	   		foreach ($table as $chp => $id) {
399
	   			$table_where[] = "$chp = '$id'";
400
	   		}
401
	   		$where = implode(' AND ', $table_where);
402
	   	}
403
	   	return $where;
404
	}
405
 
406
	protected function recupererTablesAModifier($parametres) {
407
		$tables_a_modifier = $this->tables;
408
   		foreach ($this->tables as $table_id => $table) {
409
   			$tables_a_modifier[$table_id]['champs'] = null;
410
   			foreach ($parametres as $cle => $valeur) {
411
   				if (preg_match('/^'.$table['prefixe'].'_/', $cle)) {
412
   					// Contient les noms des champs seulements
413
   					$tables_a_modifier[$table_id]['champs'][] = $cle;
414
   					// Contient un tableau de résultats protégé pour l'inclusion en bdd
1684 raphael 415
   					$tables_a_modifier[$table_id]['champs_valeurs_protege'][$cle] = is_null($valeur) ? 'NULL' : $this->bdd->quote($valeur);
1497 jpm 416
   					// Contient un tableau de résultats non protégé
417
   					$tables_a_modifier[$table_id]['champs_valeurs_brut'][$cle] = $valeur;
418
   					if (preg_match('/_id_/', $cle)) {
419
   						$tables_a_modifier[$table_id]['champs_valeurs_id'][$cle] = $valeur;
420
   					}
421
   				}
422
   			}
423
   		}
424
   		return $tables_a_modifier;
425
	}
426
 
427
 
428
	protected function mettreAJourAvecCle($id_utilisateur, $id_session, $table_id, $table) {
429
		if (!is_null($table['champs'])) {
430
	   		// Historisation (Ajout des méta-données)
431
	   		$cle = $this->recupererCle($table);
432
	   		$etat = $this->recupererEtat($table);
433
	   		$info = $this->creerXmlHisto($table['champs_valeurs_brut']);
434
			$id_meta = $this->historiser($table_id, $cle, $info, $id_utilisateur, $etat, $id_session);
435
			$champ_meta = "{$table['prefixe']}_ce_meta";
436
			$table['champs_valeurs_protege'][$champ_meta] = $this->bdd->quote($id_meta);
437
 
438
			// Mise à jour des données ou ajout en fonction de l'état
439
			if ($etat == 1) { // Ajout
440
				$this->ajouter($table);
441
			} else if ($etat == 2) { // Modif
442
				$this->modifier($table);
443
			}
444
   		}
445
	}
446
 
447
	protected function ajouter($table) {
448
		$requete = 	"INSERT INTO {$table['nom']} ".
449
   					' (%s) '.
450
					' VALUES (%s) ';
451
 
452
		$champs = $valeurs = '';
453
		foreach ($table['champs_valeurs_protege'] as $chp => $val) {
454
			$champs .= "$chp, ";
455
			$valeurs .= "$val, ";
456
		}
457
		$requete = sprintf($requete, rtrim($champs, ', '), rtrim($valeurs, ', '));
458
 
459
		$resultat = $this->bdd->exec($requete);
460
		$dernier_id = false;
461
		if ($resultat === false) {
462
			$cle = $this->recupererCle($table);
463
			$this->log[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été ajouté car la requête a échouée.";
464
		} else {
465
			$dernier_id = $this->bdd->lastInsertId();
466
		}
467
		return $dernier_id;
468
	}
469
 
470
	protected function modifier($table) {
1669 raphael 471
        // nous ne voulons pas qu'une requête malheureuse affecte toute la base de données. Par exemple:
472
        // POST "/jrest/CoelStructure/1"<<<"var=val&" // écraserait tous les enregistrements
473
        // car on ne peut garantir que tout le code existant wrap'era ses appels dans un if(avoirCleComplete())
474
        if(!array_key_exists('champs_valeurs_id', $table)) die('erreur: ' . __FILE__ . ':' . __LINE__);
1497 jpm 475
		$requete = 	"UPDATE {$table['nom']} ".
476
   					'SET %s '.
477
   					'WHERE %s ';
478
 
479
		$champs_requete = '';
480
		foreach ($table['champs_valeurs_protege'] as $chp => $val) {
481
			$champs_requete .= "$chp = $val, ";
482
		}
483
		$where = $this->construireWhere($table['champs_valeurs_id']);
484
		$requete = sprintf($requete, rtrim($champs_requete, ', '), $where);
485
		$resultat = $this->bdd->exec($requete);
486
		if ($resultat === false) {
487
			$cle = $this->recupererCle($table);
488
			$this->log[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été mis à jour car la requête a échouée.";
489
		} else {
490
			$resultat = true;
491
		}
492
		return $resultat;
493
	}
494
 
495
	protected function supprimer($table) {
496
		$requete = 	"DELETE FROM {$table['nom']} ".
497
					'WHERE %s ';
498
 
499
		$where = $this->construireWhere($table['champs_valeurs_id']);
500
		$requete = sprintf($requete, $where);
501
 
502
		$resultat = $this->bdd->exec($requete);
503
		if ($resultat === false) {
504
			$cle = $this->recupererCle($table);
505
			$this->messages[] = "L'enregistrement '$cle' de la table {$table['nom']} n'a pas été supprimé car la requête a échouée.";
506
		} else {
507
			$resultat = true;
508
		}
509
		return $resultat;
510
	}
511
 
512
	private function gererSession($demarrage) {
513
		session_name($this->sessionName);
514
 
515
		// Configuration du cookie de session
516
		// Détermination du chemin pour les cookies nécessaire à Jrest
517
		/// ATTENTION : comme les cookies sont passés à Jrest, il faut utiliser l'url de Jrest pour établir le chemin
518
		$url_morceaux = parse_url($this->config['coel']['urlBaseJrest']);
1588 aurelien 519
		self::$cookieChemin = $this->reparerCheminCookie($url_morceaux['path']);
1497 jpm 520
		unset($url_morceaux);
1588 aurelien 521
		session_set_cookie_params($this->sessionExpireTime, self::$cookieChemin);
1497 jpm 522
 
523
		// Démarrage de la session
524
		if ($demarrage) {
525
			session_start();
526
		}
527
	}
528
 
529
	private function reparerCheminCookie($chemin) {
530
		// dirname renvoit / si le chemin vaut seulement /dossier/, cela renvoit /dossier si le chemin vaut /dossier//.
531
		$chemin = dirname($chemin.'/.');
532
		// Fixe la gestion des chemins pour les cookies sous les OS utilisant le \ comme séparteur de chemin
533
		$chemin = str_replace('\\', '/', $chemin);
534
		// Ajoute un '/' terminal sauf si on est à la racine web
535
		$chemin = ($chemin != '/' ? $chemin.'/' : '');
536
		return $chemin;
537
	}
538
 
539
	private function gererIdentificationPermanente() {
540
		// Pour maintenir l'utilisateur tjrs réellement identifié nous sommes obligé de recréer une SESSION et de le recharger depuis la bdd
541
		if ($this->getUtilisateur() == ''
542
				&& isset($_COOKIE['coel_login'])
543
				&& ($utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login'], $_COOKIE['coel_mot_de_passe']))) {
544
			$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']);
545
		}
546
	}
547
 
1934 mathias 548
	/*protected function rechargerCookieUtilisateur() {
1612 aurelien 549
		$utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login']);
550
		$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']);
1934 mathias 551
	}*/
1612 aurelien 552
 
1497 jpm 553
	protected function getUtilisateur() {
554
		return (isset($_SESSION['coel_utilisateur']) ? $_SESSION['coel_utilisateur'] : '');
555
	}
1906 mathias 556
 
557
	/**
558
	 * Tente de trouver un utilisateur dans la table Personnes de CoeL, en fonction de son
559
	 * courriel ($login); si le mot de passe est fournie, le vérifie, sinon l'ignore
1950 mathias 560
	 *
561
	 * MàJ 2017 : le mot de passe n'est plus stocké en local, tout se fait via l'annuaire
1906 mathias 562
	 */
1497 jpm 563
	protected function chargerUtilisateur($login, $mot_de_passe = null) {
564
		$sortie = false;
565
		$requete =	'SELECT cp_id_personne AS id, cp_fmt_nom_complet AS nom_complet, cp_prenom AS prenom, '.
566
					'	cp_nom AS nom, cp_login AS login, cp_mot_de_passe AS mot_de_passe, cp_parametre AS parametre, '.
567
					'	cp_ville AS ville, cp_code_postal AS code_postal, '.
568
					'	cp_mark_licence AS licence '.
569
					'FROM coel_personne '.
1950 mathias 570
					"WHERE cp_login = {$this->bdd->quote($login)} ";
571
					//((!is_null($mot_de_passe)) ? "AND cp_mot_de_passe = {$this->bdd->quote($mot_de_passe)} " : '');
1497 jpm 572
		try {
573
			$resultat = $this->bdd->query($requete)->fetch();
574
			if ($resultat === false) {
1508 jpm 575
				$this->debug[] = "L'utilisateur n'est pas enregistré comme utilisateur de COEL.";
1497 jpm 576
			} else {
577
				$sortie = array('id' => $resultat['id'],
578
					'login' => $login,
579
					'mot_de_passe' => $resultat['mot_de_passe'],
580
					'nom_complet' => $resultat['nom_complet'],
581
					'nom' => $resultat['nom'],
582
					'prenom' => $resultat['prenom'],
583
					'parametre' => $resultat['parametre'],
584
					'ville' => $resultat['ville'],
585
					'code_postal' => $resultat['code_postal'],
586
					'licence' => $resultat['licence']);
587
			}
588
		} catch (PDOException $e) {
589
			$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
590
		}
591
 
592
		return $sortie;
593
	}
1906 mathias 594
 
595
	/**
596
	 * Définit un utilisateur comme "actif" en plaçant un objet Utilisateur dans la session;
597
	 * Ne pose plus de cookies depuis l'adaptation au SSO, sauf pour la licence (acceptée ou non)
598
	 * @param unknown $utilisateur
599
	 * @param number $permanence
600
	 */
1497 jpm 601
	protected function setUtilisateur($utilisateur, $permanence = 1) {
602
		$_SESSION['coel_utilisateur'] = $utilisateur;
1934 mathias 603
		//$this->setCookiePersistant('coel_licence', $utilisateur['licence'], $permanence);
1497 jpm 604
	}
605
 
606
	protected function setCookiePersistant($cookie_nom, $valeur, $permanence = 1) {
1588 aurelien 607
		setCookie($cookie_nom, $valeur, time() + ($permanence ? 100*24*60*60 : 60*60), self::$cookieChemin);
1497 jpm 608
		$_COOKIE[$cookie_nom] = $valeur;
609
	}
610
 
611
	protected function supprimerCookie($cookie_nom) {
1588 aurelien 612
		setCookie($cookie_nom, '', 1, self::$cookieChemin);
1497 jpm 613
		$_COOKIE[$cookie_nom] = '';
614
	}
615
 
616
	/**
617
	 * Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
618
	 * en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
619
	 *
620
	 * @param String $fichier	le chemin du fichier du squelette
621
	 * @param Array  $donnees	un tableau associatif contenant les variables a injecter dans le squelette.
622
	 *
623
	 * @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
624
	 */
625
	public static function traiterSquelettePhp($fichier, Array $donnees = array()) {
626
		$sortie = false;
627
		if (file_exists($fichier)) {
628
			// Extraction des variables du tableau de données
629
			extract($donnees);
630
			// Démarage de la bufferisation de sortie
631
			ob_start();
632
			// Si les tags courts sont activés
633
			if ((bool) @ini_get('short_open_tag') === true) {
634
				// Simple inclusion du squelette
635
				include $fichier;
636
			} else {
637
				// Sinon, remplacement des tags courts par la syntaxe classique avec echo
638
				$html_et_code_php = self::traiterTagsCourts($fichier);
639
				// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
640
				$html_et_code_php = '?>'.$html_et_code_php;
641
				// Interprétation du html et du php dans le buffer
642
				echo eval($html_et_code_php);
643
			}
644
			// Récupèration du contenu du buffer
645
			$sortie = ob_get_contents();
646
			// Suppression du buffer
647
			@ob_end_clean();
648
		} else {
649
			$msg = "Le fichier du squelette '$fichier' n'existe pas.";
650
			trigger_error($msg, E_USER_WARNING);
651
		}
652
		// Retourne le contenu
653
		return $sortie;
654
	}
655
 
656
	/**
657
	 * Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
658
	 *
659
	 * @param String $chemin_squelette le chemin du fichier du squelette
660
	 *
661
	 * @return string le contenu du fichier du squelette php avec les tags courts remplacés.
662
	 */
663
	private static function traiterTagsCourts($chemin_squelette) {
664
		$contenu = file_get_contents($chemin_squelette);
665
		// Remplacement de tags courts par un tag long avec echo
666
		$contenu = str_replace('<?=', '<?php echo ',  $contenu);
667
		// Ajout systématique d'un point virgule avant la fermeture php
668
		$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
669
		return $contenu;
670
	}
1527 jpm 671
 
672
	public static function debug($var) {
673
		echo '<pre>'.print_r($var, true).'</pre>';
674
	}
1649 raphael 675
 
676
	/*
1906 mathias 677
	 * Retourne une paire de coordonnée depuis un tableau représentant une adresse
1649 raphael 678
	 * ou une adresse partielle à l'aide du service Nominatim.
679
	 * (http://wiki.openstreetmap.org/wiki/Nominatim)
680
	 *
681
	 * @param in data: un tableau associatif doté de *toutes* les clefs suivantes:
682
	 * 				   'adresse', 'cp', 'ville', 'pays'
683
	 * @param out lonlat: un tableau associatif contenant 'lon' et 'lat' si elles ont été déterminées
1667 raphael 684
	 *					  Celles-ci sont sous la forme de deux chaînes de caractères numériques représentant
685
	 *					  un FLOAT() dont le séparateur des décimales est le "." (point).
1651 raphael 686
	 * @param in opts: un tableau associatif optionnel écrasant ou ajoutant des valeurs d'API
1649 raphael 687
	 * @return boolean: selon que la fonction à réussi ou non
1658 raphael 688
	 *
689
	 * opts['force-q']: force l'utilisation d'une requête en texte libre
690
	 * 					quelque soit le remplissage des composants individuels
691
	 *
692
	 * Note: le code postal est contre-productif pour Nominatim:
693
	 * https://lists.openstreetmap.org/pipermail/talk-fr/2013-April/057084.html
1649 raphael 694
	 */
1651 raphael 695
	static function coordGuess(Array $data, Array &$lonlat, Array $opts = NULL) {
1649 raphael 696
		if(!$data) return FALSE;
1651 raphael 697
		$common_query = array('accept_language' => 'fr', 'format' => 'json', 'limit' => 1);
1658 raphael 698
		if(! $data['adresse'] || (! $data['cp'] && ! $data['ville']) || @$opts['force-q']) {
699
			unset($opts['force-q']);
1651 raphael 700
			$query = array_merge($common_query,
1658 raphael 701
								 array('q' => implode(', ', array_filter($data))),
1651 raphael 702
								 $opts ? $opts : array());
703
		}
704
		else {
705
			$query = array_merge($common_query,
706
								 array_filter(array('street' => $data['adresse'],
707
													'city' => $data['ville'],
708
													'postalcode' => $data['cp'],
709
													'country' => $data['pays'])),
710
								 $opts ? $opts : array());
711
		}
712
		$fullquery = 'http://nominatim.openstreetmap.org/search.php?' . http_build_query($query);
1684 raphael 713
 
1686 raphael 714
        $ctx = stream_context_create(array('http' => array( 'timeout' => '4' )));
715
        $r = json_decode(file_get_contents($fullquery, FALSE, $ctx));
1651 raphael 716
		error_log(sprintf("COEL: Nominatim request returned %d result(s) [%s]", count($r), $fullquery));
717
		if($r && isset($r[0])) {
718
			$lonlat['lon'] = $r[0]->lon;
719
			$lonlat['lat'] = $r[0]->lat;
720
			return TRUE;
721
		}
1649 raphael 722
		return FALSE;
723
	}
724
 
725
	/*
726
	 * Retourne un tableau prêt à être utilisé par coordGuess(), c'est à dire initialisant toutes
727
	 * les clefs nécessaires (même si NULL) et disposant systématiquement d'un pays.
728
	 * Cela à partir d'un tableau au format de clefs prédéterminé.
1658 raphael 729
	 * S'occupe du filtrage basique des éléments pour maximiser les chances de détection.
1649 raphael 730
	 *
1709 raphael 731
	 * @param in: un tableau associatif contenant les clefs telles que nommées à l'issue du
1649 raphael 732
	 * 				du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
1709 raphael 733
	 * @param db: une db optionnelle, utilisée si nécessaire pour converir les code pays
734
	 * 				du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
1649 raphael 735
	 * @return un tableau associatif contenant une ou plusieurs des clefs suivantes:
736
	 *			'adresse', 'cp', 'ville', 'pays'
737
	 */
1709 raphael 738
	static function addrReStruct(Array $in, $db = NULL) {
739
        $pays = FALSE;
740
		if(is_numeric(@$in['cs_ce_truk_pays'])) {
741
            if($db) {
742
                $pays= $db->query(sprintf(
743
                    "SELECT cmlv_nom FROM coel_meta_liste_valeur ".
744
                    "WHERE cmlv_ce_parent = 1074 AND cmlv_id_valeur = %d",
745
                    intval($in['cs_ce_truk_pays'])))->fetchColumn();
746
            }
747
        }
748
        else $pays = @trim($in['cs_ce_truk_pays']);
1651 raphael 749
 
750
		// pas de précision au n°, mais Nominatim peine avec des préfixes trop élaborés
751
		// coupons jusqu'à un élément reconnaissable s'il existe
752
		$adresse = @trim($in['cs_adresse_01']);
1658 raphael 753
		$adresse = substr($adresse, stripos($adresse, "ville de "));
754
		$adresse = substr($adresse, stripos($adresse, "impasse"));
755
		$adresse = substr($adresse, stripos($adresse, "chemin"));
756
		$adresse = substr($adresse, stripos($adresse, "route"));
1651 raphael 757
		$adresse = substr($adresse, stripos($adresse, "rue"));
758
		$adresse = substr($adresse, stripos($adresse, "avenue"));
759
		$adresse = substr($adresse, stripos($adresse, "boulevard"));
760
		$adresse = substr($adresse, stripos($adresse, "place"));
1658 raphael 761
		$adresse = substr($adresse, stripos($adresse, "promenade"));
762
		$adresse = substr($adresse, stripos($adresse, "allée"));
1718 raphael 763
		$adresse = substr($adresse, stripos($adresse, "cours"));
1658 raphael 764
		$adresse = preg_replace("/[\r\n].*/", "", $adresse);
1651 raphael 765
 
1658 raphael 766
		$ville = preg_replace('/cedex.*/i', '', @trim($in['cs_ville']));
1649 raphael 767
		return array(
1651 raphael 768
			'adresse' => $adresse,
1649 raphael 769
			'cp' => @trim($in['cs_code_postal']) ? $in['cs_code_postal'] : '',
1658 raphael 770
			'ville' => $ville,
1651 raphael 771
			'pays' =>  $pays !== FALSE ? $pays : 'France'
1649 raphael 772
		);
773
	}
1497 jpm 774
}
1954 killian 775
?>