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 |
|
1934 |
mathias |
546 |
/*protected function rechargerCookieUtilisateur() {
|
1612 |
aurelien |
547 |
$utilisateur = $this->chargerUtilisateur($_COOKIE['coel_login']);
|
|
|
548 |
$this->setUtilisateur($utilisateur, $_COOKIE['coel_permanence']);
|
1934 |
mathias |
549 |
}*/
|
1612 |
aurelien |
550 |
|
1497 |
jpm |
551 |
protected function getUtilisateur() {
|
|
|
552 |
return (isset($_SESSION['coel_utilisateur']) ? $_SESSION['coel_utilisateur'] : '');
|
|
|
553 |
}
|
1906 |
mathias |
554 |
|
|
|
555 |
/**
|
|
|
556 |
* Tente de trouver un utilisateur dans la table Personnes de CoeL, en fonction de son
|
|
|
557 |
* courriel ($login); si le mot de passe est fournie, le vérifie, sinon l'ignore
|
1951 |
mathias |
558 |
*
|
|
|
559 |
* MàJ 2017 : le mot de passe n'est plus stocké en local, tout se fait via l'annuaire
|
1906 |
mathias |
560 |
*/
|
1497 |
jpm |
561 |
protected function chargerUtilisateur($login, $mot_de_passe = null) {
|
|
|
562 |
$sortie = false;
|
|
|
563 |
$requete = 'SELECT cp_id_personne AS id, cp_fmt_nom_complet AS nom_complet, cp_prenom AS prenom, '.
|
|
|
564 |
' cp_nom AS nom, cp_login AS login, cp_mot_de_passe AS mot_de_passe, cp_parametre AS parametre, '.
|
|
|
565 |
' cp_ville AS ville, cp_code_postal AS code_postal, '.
|
|
|
566 |
' cp_mark_licence AS licence '.
|
|
|
567 |
'FROM coel_personne '.
|
1951 |
mathias |
568 |
"WHERE cp_login = {$this->bdd->quote($login)} ";
|
|
|
569 |
//((!is_null($mot_de_passe)) ? "AND cp_mot_de_passe = {$this->bdd->quote($mot_de_passe)} " : '');
|
1497 |
jpm |
570 |
try {
|
|
|
571 |
$resultat = $this->bdd->query($requete)->fetch();
|
|
|
572 |
if ($resultat === false) {
|
1508 |
jpm |
573 |
$this->debug[] = "L'utilisateur n'est pas enregistré comme utilisateur de COEL.";
|
1497 |
jpm |
574 |
} else {
|
|
|
575 |
$sortie = array('id' => $resultat['id'],
|
|
|
576 |
'login' => $login,
|
|
|
577 |
'mot_de_passe' => $resultat['mot_de_passe'],
|
|
|
578 |
'nom_complet' => $resultat['nom_complet'],
|
|
|
579 |
'nom' => $resultat['nom'],
|
|
|
580 |
'prenom' => $resultat['prenom'],
|
|
|
581 |
'parametre' => $resultat['parametre'],
|
|
|
582 |
'ville' => $resultat['ville'],
|
|
|
583 |
'code_postal' => $resultat['code_postal'],
|
|
|
584 |
'licence' => $resultat['licence']);
|
|
|
585 |
}
|
|
|
586 |
} catch (PDOException $e) {
|
|
|
587 |
$this->messages[] = sprintf($this->getTxt('sql_erreur'), $e->getFile(), $e->getLine(), $e->getMessage());
|
|
|
588 |
}
|
|
|
589 |
|
|
|
590 |
return $sortie;
|
|
|
591 |
}
|
1906 |
mathias |
592 |
|
|
|
593 |
/**
|
|
|
594 |
* Définit un utilisateur comme "actif" en plaçant un objet Utilisateur dans la session;
|
|
|
595 |
* Ne pose plus de cookies depuis l'adaptation au SSO, sauf pour la licence (acceptée ou non)
|
|
|
596 |
* @param unknown $utilisateur
|
|
|
597 |
* @param number $permanence
|
|
|
598 |
*/
|
1497 |
jpm |
599 |
protected function setUtilisateur($utilisateur, $permanence = 1) {
|
|
|
600 |
$_SESSION['coel_utilisateur'] = $utilisateur;
|
1934 |
mathias |
601 |
//$this->setCookiePersistant('coel_licence', $utilisateur['licence'], $permanence);
|
1497 |
jpm |
602 |
}
|
|
|
603 |
|
|
|
604 |
protected function setCookiePersistant($cookie_nom, $valeur, $permanence = 1) {
|
1588 |
aurelien |
605 |
setCookie($cookie_nom, $valeur, time() + ($permanence ? 100*24*60*60 : 60*60), self::$cookieChemin);
|
1497 |
jpm |
606 |
$_COOKIE[$cookie_nom] = $valeur;
|
|
|
607 |
}
|
|
|
608 |
|
|
|
609 |
protected function supprimerCookie($cookie_nom) {
|
1588 |
aurelien |
610 |
setCookie($cookie_nom, '', 1, self::$cookieChemin);
|
1497 |
jpm |
611 |
$_COOKIE[$cookie_nom] = '';
|
|
|
612 |
}
|
|
|
613 |
|
|
|
614 |
/**
|
|
|
615 |
* Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
|
|
|
616 |
* en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
|
|
|
617 |
*
|
|
|
618 |
* @param String $fichier le chemin du fichier du squelette
|
|
|
619 |
* @param Array $donnees un tableau associatif contenant les variables a injecter dans le squelette.
|
|
|
620 |
*
|
|
|
621 |
* @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
|
|
|
622 |
*/
|
|
|
623 |
public static function traiterSquelettePhp($fichier, Array $donnees = array()) {
|
|
|
624 |
$sortie = false;
|
|
|
625 |
if (file_exists($fichier)) {
|
|
|
626 |
// Extraction des variables du tableau de données
|
|
|
627 |
extract($donnees);
|
|
|
628 |
// Démarage de la bufferisation de sortie
|
|
|
629 |
ob_start();
|
|
|
630 |
// Si les tags courts sont activés
|
|
|
631 |
if ((bool) @ini_get('short_open_tag') === true) {
|
|
|
632 |
// Simple inclusion du squelette
|
|
|
633 |
include $fichier;
|
|
|
634 |
} else {
|
|
|
635 |
// Sinon, remplacement des tags courts par la syntaxe classique avec echo
|
|
|
636 |
$html_et_code_php = self::traiterTagsCourts($fichier);
|
|
|
637 |
// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
|
|
|
638 |
$html_et_code_php = '?>'.$html_et_code_php;
|
|
|
639 |
// Interprétation du html et du php dans le buffer
|
|
|
640 |
echo eval($html_et_code_php);
|
|
|
641 |
}
|
|
|
642 |
// Récupèration du contenu du buffer
|
|
|
643 |
$sortie = ob_get_contents();
|
|
|
644 |
// Suppression du buffer
|
|
|
645 |
@ob_end_clean();
|
|
|
646 |
} else {
|
|
|
647 |
$msg = "Le fichier du squelette '$fichier' n'existe pas.";
|
|
|
648 |
trigger_error($msg, E_USER_WARNING);
|
|
|
649 |
}
|
|
|
650 |
// Retourne le contenu
|
|
|
651 |
return $sortie;
|
|
|
652 |
}
|
|
|
653 |
|
|
|
654 |
/**
|
|
|
655 |
* Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
|
|
|
656 |
*
|
|
|
657 |
* @param String $chemin_squelette le chemin du fichier du squelette
|
|
|
658 |
*
|
|
|
659 |
* @return string le contenu du fichier du squelette php avec les tags courts remplacés.
|
|
|
660 |
*/
|
|
|
661 |
private static function traiterTagsCourts($chemin_squelette) {
|
|
|
662 |
$contenu = file_get_contents($chemin_squelette);
|
|
|
663 |
// Remplacement de tags courts par un tag long avec echo
|
|
|
664 |
$contenu = str_replace('<?=', '<?php echo ', $contenu);
|
|
|
665 |
// Ajout systématique d'un point virgule avant la fermeture php
|
|
|
666 |
$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
|
|
|
667 |
return $contenu;
|
|
|
668 |
}
|
1527 |
jpm |
669 |
|
|
|
670 |
public static function debug($var) {
|
|
|
671 |
echo '<pre>'.print_r($var, true).'</pre>';
|
|
|
672 |
}
|
1649 |
raphael |
673 |
|
|
|
674 |
/*
|
1906 |
mathias |
675 |
* Retourne une paire de coordonnée depuis un tableau représentant une adresse
|
1649 |
raphael |
676 |
* ou une adresse partielle à l'aide du service Nominatim.
|
|
|
677 |
* (http://wiki.openstreetmap.org/wiki/Nominatim)
|
|
|
678 |
*
|
|
|
679 |
* @param in data: un tableau associatif doté de *toutes* les clefs suivantes:
|
|
|
680 |
* 'adresse', 'cp', 'ville', 'pays'
|
|
|
681 |
* @param out lonlat: un tableau associatif contenant 'lon' et 'lat' si elles ont été déterminées
|
1667 |
raphael |
682 |
* Celles-ci sont sous la forme de deux chaînes de caractères numériques représentant
|
|
|
683 |
* un FLOAT() dont le séparateur des décimales est le "." (point).
|
1651 |
raphael |
684 |
* @param in opts: un tableau associatif optionnel écrasant ou ajoutant des valeurs d'API
|
1649 |
raphael |
685 |
* @return boolean: selon que la fonction à réussi ou non
|
1658 |
raphael |
686 |
*
|
|
|
687 |
* opts['force-q']: force l'utilisation d'une requête en texte libre
|
|
|
688 |
* quelque soit le remplissage des composants individuels
|
|
|
689 |
*
|
|
|
690 |
* Note: le code postal est contre-productif pour Nominatim:
|
|
|
691 |
* https://lists.openstreetmap.org/pipermail/talk-fr/2013-April/057084.html
|
1649 |
raphael |
692 |
*/
|
1651 |
raphael |
693 |
static function coordGuess(Array $data, Array &$lonlat, Array $opts = NULL) {
|
1649 |
raphael |
694 |
if(!$data) return FALSE;
|
1651 |
raphael |
695 |
$common_query = array('accept_language' => 'fr', 'format' => 'json', 'limit' => 1);
|
1658 |
raphael |
696 |
if(! $data['adresse'] || (! $data['cp'] && ! $data['ville']) || @$opts['force-q']) {
|
|
|
697 |
unset($opts['force-q']);
|
1651 |
raphael |
698 |
$query = array_merge($common_query,
|
1658 |
raphael |
699 |
array('q' => implode(', ', array_filter($data))),
|
1651 |
raphael |
700 |
$opts ? $opts : array());
|
|
|
701 |
}
|
|
|
702 |
else {
|
|
|
703 |
$query = array_merge($common_query,
|
|
|
704 |
array_filter(array('street' => $data['adresse'],
|
|
|
705 |
'city' => $data['ville'],
|
|
|
706 |
'postalcode' => $data['cp'],
|
|
|
707 |
'country' => $data['pays'])),
|
|
|
708 |
$opts ? $opts : array());
|
|
|
709 |
}
|
|
|
710 |
$fullquery = 'http://nominatim.openstreetmap.org/search.php?' . http_build_query($query);
|
1684 |
raphael |
711 |
|
1686 |
raphael |
712 |
$ctx = stream_context_create(array('http' => array( 'timeout' => '4' )));
|
|
|
713 |
$r = json_decode(file_get_contents($fullquery, FALSE, $ctx));
|
1651 |
raphael |
714 |
error_log(sprintf("COEL: Nominatim request returned %d result(s) [%s]", count($r), $fullquery));
|
|
|
715 |
if($r && isset($r[0])) {
|
|
|
716 |
$lonlat['lon'] = $r[0]->lon;
|
|
|
717 |
$lonlat['lat'] = $r[0]->lat;
|
|
|
718 |
return TRUE;
|
|
|
719 |
}
|
1649 |
raphael |
720 |
return FALSE;
|
|
|
721 |
}
|
|
|
722 |
|
|
|
723 |
/*
|
|
|
724 |
* Retourne un tableau prêt à être utilisé par coordGuess(), c'est à dire initialisant toutes
|
|
|
725 |
* les clefs nécessaires (même si NULL) et disposant systématiquement d'un pays.
|
|
|
726 |
* Cela à partir d'un tableau au format de clefs prédéterminé.
|
1658 |
raphael |
727 |
* S'occupe du filtrage basique des éléments pour maximiser les chances de détection.
|
1649 |
raphael |
728 |
*
|
1709 |
raphael |
729 |
* @param in: un tableau associatif contenant les clefs telles que nommées à l'issue du
|
1649 |
raphael |
730 |
* du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
|
1709 |
raphael |
731 |
* @param db: une db optionnelle, utilisée si nécessaire pour converir les code pays
|
|
|
732 |
* du formulaire de saisie: 'cs_adresse_01', 'cs_code_postal', 'cs_ville'
|
1649 |
raphael |
733 |
* @return un tableau associatif contenant une ou plusieurs des clefs suivantes:
|
|
|
734 |
* 'adresse', 'cp', 'ville', 'pays'
|
|
|
735 |
*/
|
1709 |
raphael |
736 |
static function addrReStruct(Array $in, $db = NULL) {
|
|
|
737 |
$pays = FALSE;
|
|
|
738 |
if(is_numeric(@$in['cs_ce_truk_pays'])) {
|
|
|
739 |
if($db) {
|
|
|
740 |
$pays= $db->query(sprintf(
|
|
|
741 |
"SELECT cmlv_nom FROM coel_meta_liste_valeur ".
|
|
|
742 |
"WHERE cmlv_ce_parent = 1074 AND cmlv_id_valeur = %d",
|
|
|
743 |
intval($in['cs_ce_truk_pays'])))->fetchColumn();
|
|
|
744 |
}
|
|
|
745 |
}
|
|
|
746 |
else $pays = @trim($in['cs_ce_truk_pays']);
|
1651 |
raphael |
747 |
|
|
|
748 |
// pas de précision au n°, mais Nominatim peine avec des préfixes trop élaborés
|
|
|
749 |
// coupons jusqu'à un élément reconnaissable s'il existe
|
|
|
750 |
$adresse = @trim($in['cs_adresse_01']);
|
1658 |
raphael |
751 |
$adresse = substr($adresse, stripos($adresse, "ville de "));
|
|
|
752 |
$adresse = substr($adresse, stripos($adresse, "impasse"));
|
|
|
753 |
$adresse = substr($adresse, stripos($adresse, "chemin"));
|
|
|
754 |
$adresse = substr($adresse, stripos($adresse, "route"));
|
1651 |
raphael |
755 |
$adresse = substr($adresse, stripos($adresse, "rue"));
|
|
|
756 |
$adresse = substr($adresse, stripos($adresse, "avenue"));
|
|
|
757 |
$adresse = substr($adresse, stripos($adresse, "boulevard"));
|
|
|
758 |
$adresse = substr($adresse, stripos($adresse, "place"));
|
1658 |
raphael |
759 |
$adresse = substr($adresse, stripos($adresse, "promenade"));
|
|
|
760 |
$adresse = substr($adresse, stripos($adresse, "allée"));
|
1718 |
raphael |
761 |
$adresse = substr($adresse, stripos($adresse, "cours"));
|
1658 |
raphael |
762 |
$adresse = preg_replace("/[\r\n].*/", "", $adresse);
|
1651 |
raphael |
763 |
|
1658 |
raphael |
764 |
$ville = preg_replace('/cedex.*/i', '', @trim($in['cs_ville']));
|
1649 |
raphael |
765 |
return array(
|
1651 |
raphael |
766 |
'adresse' => $adresse,
|
1649 |
raphael |
767 |
'cp' => @trim($in['cs_code_postal']) ? $in['cs_code_postal'] : '',
|
1658 |
raphael |
768 |
'ville' => $ville,
|
1651 |
raphael |
769 |
'pays' => $pays !== FALSE ? $pays : 'France'
|
1649 |
raphael |
770 |
);
|
|
|
771 |
}
|
1497 |
jpm |
772 |
}
|
|
|
773 |
?>
|