Subversion Repositories eFlore/Applications.del

Rev

Rev 2200 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2200 Rev 2221
1
<?php
1
<?php
2
// declare(encoding='UTF-8');
2
// declare(encoding='UTF-8');
3
/**
3
/**
4
 * Classe contenant des méthodes permettant de construire les requêtes SQL complexe concernant les images et obs.
4
 * Classe contenant des méthodes permettant de construire les requêtes SQL complexe concernant les images et obs.
5
 * Rempli un tableau des clauses "join", "where", "group by" et "oder by" nécessaire à la *recherche* des ids des
5
 * Rempli un tableau des clauses "join", "where", "group by" et "oder by" nécessaire à la *recherche* des ids des
6
 * observations/images correspondantes aux filtres passés dans l'url du web service de recherche
6
 * observations/images correspondantes aux filtres passés dans l'url du web service de recherche
7
 * (ListeImages et ListeObservations).
7
 * (ListeImages et ListeObservations).
8
 *
8
 *
9
 * Attention, cela signifie que toutes les tables ne sont pas *forcément* jointées, par exemple si aucune
9
 * Attention, cela signifie que toutes les tables ne sont pas *forcément* jointées, par exemple si aucune
10
 * contrainte ne le nécessite.
10
 * contrainte ne le nécessite.
11
 * La requête construite ici est utile pour récupérer la liste des ids d'observations/images qui match.
11
 * La requête construite ici est utile pour récupérer la liste des ids d'observations/images qui match.
12
 * Pour la récupération effective de "toutes" les données nécessaire au retour du web service en json, c'est une autre
12
 * Pour la récupération effective de "toutes" les données nécessaire au retour du web service en json, c'est une autre
13
 * requête directement dans le web service qui s'en charge. Cette technique en deux étapes est la plus rapide !
13
 * requête directement dans le web service qui s'en charge. Cette technique en deux étapes est la plus rapide !
14
 *
14
 *
15
 * Note: toujours rajouter les préfixes de table (di, do ou du), en fonction de ce que défini
15
 * Note: toujours rajouter les préfixes de table (di, do ou du), en fonction de ce que défini
16
 * les JOIN qui sont utilisés :
16
 * les JOIN qui sont utilisés :
17
 * - le préfixe de del_image est "di"
17
 * - le préfixe de del_image est "di"
18
 * - le préfixe de del_observation est "do"
18
 * - le préfixe de del_observation est "do"
19
 * - le préfixe de del_utilisateur est "du"
19
 * - le préfixe de del_utilisateur est "du"
20
 *
20
 *
21
 * @category  DEL
21
 * @category  DEL
22
 * @package   Services
22
 * @package   Services
23
 * @package   Bibliotheque
23
 * @package   Bibliotheque
24
 * @version   0.1
24
 * @version   0.1
25
 * @author    Mathias CHOUET <mathias@tela-botanica.org>
25
 * @author    Mathias CHOUET <mathias@tela-botanica.org>
26
 * @author    Jean-Pascal MILCENT <jpm@tela-botanica.org>
26
 * @author    Jean-Pascal MILCENT <jpm@tela-botanica.org>
27
 * @author    Aurelien PERONNET <aurelien@tela-botanica.org>
27
 * @author    Aurelien PERONNET <aurelien@tela-botanica.org>
28
 * @license   GPL v3 <http://www.gnu.org/licenses/gpl.txt>
28
 * @license   GPL v3 <http://www.gnu.org/licenses/gpl.txt>
29
 * @license   CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
29
 * @license   CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
30
 * @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
30
 * @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
31
 */
31
 */
32
class Sql {
32
class Sql {
33
 
33
 
34
	const APPLI_IMG = 'IMG';
34
	const APPLI_IMG = 'IMG';
35
	const APPLI_OBS = 'OBS';
35
	const APPLI_OBS = 'OBS';
36
 
36
 
37
	private $conteneur;
37
	private $conteneur;
38
	private $bdd;
38
	private $bdd;
39
	private $parametres = array();
39
	private $parametres = array();
40
	private $appli;
40
	private $appli;
41
	private $requete = array(
41
	private $requete = array(
42
		'join' => array(),
42
		'join' => array(),
43
		'where' => array(),
43
		'where' => array(),
44
		'groupby' => array(),
44
		'groupby' => array(),
45
		'orderby' => array());
45
		'orderby' => array());
46
 
46
 
47
	private $champsPrenom = array('prenom_utilisateur');
47
	private $champsPrenom = array('prenom_utilisateur');
48
	private $champsNom = array('nom_utilisateur');
48
	private $champsNom = array('nom_utilisateur');
49
	private $champsSousRequeteObs = array('masque.standard','masque.genre', 'masque.famille', 'masque.ns', 'masque.commune', 'masque.milieu', 'masque.pays');
49
	private $champsSousRequeteObs = array('masque.standard','masque.genre', 'masque.famille', 'masque.ns', 'masque.commune', 'masque.milieu', 'masque.pays');
50
 
50
 
51
	public function __construct(Conteneur $conteneur) {
51
	public function __construct(Conteneur $conteneur) {
52
		$this->conteneur = $conteneur;
52
		$this->conteneur = $conteneur;
53
		$this->bdd = $this->conteneur->getBdd();
53
		$this->bdd = $this->conteneur->getBdd();
54
	}
54
	}
55
 
55
 
56
	public function setParametres(Array $parametres) {
56
	public function setParametres(Array $parametres) {
57
		$this->parametres = $parametres;
57
		$this->parametres = $parametres;
58
	}
58
	}
59
 
59
 
60
	public function setAppli($appliType) {
60
	public function setAppli($appliType) {
61
		if ($appliType == 'IMG' || $appliType == 'OBS') {
61
		if ($appliType == 'IMG' || $appliType == 'OBS') {
62
			$this->appli = $appliType;
62
			$this->appli = $appliType;
63
		} else {
63
		} else {
64
			throw new Exception("Les types d'appli disponible sont : IMG (pour PictoFlora) et OBS (pour IdentiPlante)");
64
			throw new Exception("Les types d'appli disponible sont : IMG (pour PictoFlora) et OBS (pour IdentiPlante)");
65
		}
65
		}
66
	}
66
	}
67
 
67
 
68
	private function getPrefixe() {
68
	private function getPrefixe() {
69
		return $this->appli === 'IMG' ? 'di' : 'do';
69
		return $this->appli === 'IMG' ? 'di' : 'do';
70
	}
70
	}
71
 
71
 
72
	private function etreAppliImg() {
72
	private function etreAppliImg() {
73
		return $this->appli === 'IMG';
73
		return $this->appli === 'IMG';
74
	}
74
	}
75
 
75
 
76
	private function etreAppliObs() {
76
	private function etreAppliObs() {
77
		return $this->appli === 'OBS';
77
		return $this->appli === 'OBS';
78
	}
78
	}
79
 
79
 
80
	public function getRequeteSql() {
80
	public function getRequeteSql() {
81
		return $this->requete;
81
		return $this->requete;
82
	}
82
	}
83
 
83
 
84
	private function addJoin($join) {
84
	private function addJoin($join) {
85
		if (!isset($this->requete['join'][$join])) {
85
		if (!isset($this->requete['join'][$join])) {
86
			$this->requete['join'][$join] = $join;
86
			$this->requete['join'][$join] = $join;
87
		}
87
		}
88
	}
88
	}
89
 
89
 
90
	public function getJoin() {
90
	public function getJoin() {
91
		return ($this->requete['join'] ? implode(' ', array_unique($this->requete['join'])).' ' : '');
91
		return ($this->requete['join'] ? implode(' ', array_unique($this->requete['join'])).' ' : '');
92
	}
92
	}
93
 
93
 
94
	private function addJoinDis($join) {
94
	private function addJoinDis($join) {
95
		$this->requete['join']['dis'] = $join;
95
		$this->requete['join']['dis'] = $join;
96
	}
96
	}
97
 
97
 
98
	private function addWhere($idParam, $where) {
98
	private function addWhere($idParam, $where) {
99
		if (isset($this->parametres['_parametres_condition_or_'])
99
		if (isset($this->parametres['_parametres_condition_or_'])
100
				&& in_array($idParam, $this->parametres['_parametres_condition_or_'])) {
100
				&& in_array($idParam, $this->parametres['_parametres_condition_or_'])) {
101
			if ($this->etreAppliImg() && in_array($idParam, $this->champsSousRequeteObs)) {
101
			if ($this->etreAppliImg() && in_array($idParam, $this->champsSousRequeteObs)) {
102
				$this->requete['where']['OR_SOUS_REQUETE'][] = $where;
102
				$this->requete['where']['OR_SOUS_REQUETE'][] = $where;
103
			} else {
103
			} else {
104
				$this->requete['where']['OR'][] = $where;
104
				$this->requete['where']['OR'][] = $where;
105
			}
105
			}
106
		} else {
106
		} else {
107
			$this->requete['where']['AND'][] = $where;
107
			$this->requete['where']['AND'][] = $where;
108
		}
108
		}
109
	}
109
	}
110
 
110
 
111
	public function getWhere() {
111
	public function getWhere() {
112
		// Sous-requete spéciale pour éviter de rechercher dans la table obs jointe à img depuis Pictoflora...
112
		// Sous-requete spéciale pour éviter de rechercher dans la table obs jointe à img depuis Pictoflora...
113
		if (isset($this->requete['where']['OR_SOUS_REQUETE']) && count($this->requete['where']['OR_SOUS_REQUETE']) > 0) {
113
		if (isset($this->requete['where']['OR_SOUS_REQUETE']) && count($this->requete['where']['OR_SOUS_REQUETE']) > 0) {
114
			$clauseWhereSousRequete = implode(' OR ', $this->requete['where']['OR_SOUS_REQUETE']);
114
			$clauseWhereSousRequete = implode(' OR ', $this->requete['where']['OR_SOUS_REQUETE']);
115
			$sousRequete = 'di.ce_observation IN '.
115
			$sousRequete = 'di.ce_observation IN '.
116
				"(SELECT id_observation FROM del_observation AS do WHERE $clauseWhereSousRequete ) ";
116
				"(SELECT id_observation FROM del_observation AS do WHERE $clauseWhereSousRequete ) ";
117
			$this->requete['where']['OR'][] = "( $sousRequete )";
117
			$this->requete['where']['OR'][] = "( $sousRequete )";
118
			unset($this->requete['join'][$this->getSqlJointureObs()]);
118
			unset($this->requete['join'][$this->getSqlJointureObs()]);
119
		}
119
		}
120
 
120
 
121
		if (isset($this->requete['where']['OR']) && count($this->requete['where']['OR']) > 0) {
121
		if (isset($this->requete['where']['OR']) && count($this->requete['where']['OR']) > 0) {
122
			$this->requete['where']['AND'][] = '('.implode(' OR ', $this->requete['where']['OR']).')';
122
			$this->requete['where']['AND'][] = '('.implode(' OR ', $this->requete['where']['OR']).')';
123
		}
123
		}
124
 
124
 
125
		$where = ' TRUE ';
125
		$where = ' TRUE ';
126
		if (isset($this->requete['where']['AND']) && count($this->requete['where']['AND']) > 0) {
126
		if (isset($this->requete['where']['AND']) && count($this->requete['where']['AND']) > 0) {
127
			$where = implode(' AND ', $this->requete['where']['AND']).' ';
127
			$where = implode(' AND ', $this->requete['where']['AND']).' ';
128
		}
128
		}
129
		return $where;
129
		return $where;
130
	}
130
	}
131
 
131
 
132
	private function addGroupBy($groupBy) {
132
	private function addGroupBy($groupBy) {
133
		$this->requete['groupby'][] = $groupBy;
133
		$this->requete['groupby'][] = $groupBy;
134
	}
134
	}
135
 
135
 
136
	public function getGroupBy() {
136
	public function getGroupBy() {
137
		$groupby = '';
137
		$groupby = '';
138
		if (isset($this->requete['groupby']) && count($this->requete['groupby']) > 0) {
138
		if (isset($this->requete['groupby']) && count($this->requete['groupby']) > 0) {
139
			$groupby = 'GROUP BY '.implode(', ', array_unique($this->requete['groupby'])).' ';
139
			$groupby = 'GROUP BY '.implode(', ', array_unique($this->requete['groupby'])).' ';
140
		}
140
		}
141
		return $groupby;
141
		return $groupby;
142
	}
142
	}
143
 
143
 
144
	private function addOrderBy($orderby) {
144
	private function addOrderBy($orderby) {
145
		$this->requete['orderby'][] = $orderby;
145
		$this->requete['orderby'][] = $orderby;
146
	}
146
	}
147
 
147
 
148
	public function getOrderBy() {
148
	public function getOrderBy() {
149
		$orderby = '';
149
		$orderby = '';
150
		if (isset($this->requete['orderby']) && count($this->requete['orderby']) > 0) {
150
		if (isset($this->requete['orderby']) && count($this->requete['orderby']) > 0) {
151
			$orderby = 'ORDER BY '.implode(', ', array_unique($this->requete['orderby'])).' ';
151
			$orderby = 'ORDER BY '.implode(', ', array_unique($this->requete['orderby'])).' ';
152
		}
152
		}
153
		return $orderby;
153
		return $orderby;
154
	}
154
	}
155
 
155
 
156
	public function getLimit() {
156
	public function getLimit() {
157
		return 'LIMIT '.$this->parametres['navigation.depart'].','.$this->parametres['navigation.limite'].' ';
157
		return 'LIMIT '.$this->parametres['navigation.depart'].','.$this->parametres['navigation.limite'].' ';
158
	}
158
	}
159
 
159
 
160
	/**
160
	/**
161
	 * @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
161
	 * @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
162
	 * @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
162
	 * @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
163
	 */
163
	 */
164
	public function ajouterContraintes() {
164
	public function ajouterContraintes() {
165
		$this->ajouterContrainteStandard();
165
		$this->ajouterContrainteStandard();
166
		$this->ajouterContrainteAuteur();
166
		$this->ajouterContrainteAuteur();
167
		$this->ajouterContrainteDate();
167
		$this->ajouterContrainteDate();
168
		$this->ajouterContraintePays();
168
		$this->ajouterContraintePays();
169
		$this->ajouterContrainteDepartement();
169
		$this->ajouterContrainteDepartement();
170
		$this->ajouterContrainteIdZoneGeo();
170
		$this->ajouterContrainteIdZoneGeo();
171
		$this->ajouterContrainteGenre();
171
		$this->ajouterContrainteGenre();
172
		$this->ajouterContrainteFamille();
172
		$this->ajouterContrainteFamille();
173
		$this->ajouterContrainteNs();
173
		$this->ajouterContrainteNs();
174
		$this->ajouterContrainteNn();
174
		$this->ajouterContrainteNn();
175
		$this->ajouterContrainteReferentiel();
175
		$this->ajouterContrainteReferentiel();
176
		$this->ajouterContrainteCommune();
176
		$this->ajouterContrainteCommune();
177
		$this->ajouterContraintePnInscrits();
177
		$this->ajouterContraintePnInscrits();
178
	}
178
	}
179
 
179
 
180
	private function ajouterContrainteStandard() {
180
	private function ajouterContrainteStandard() {
181
		if (isset($this->parametres['masque.standard'])) {
181
		if (isset($this->parametres['masque.standard'])) {
182
			$donnees_standard = $this->parametres['masque.standard'];
182
			$donnees_standard = $this->parametres['masque.standard'];
183
			$this->addWhere('masque.standard', "do.donnees_standard = $donnees_standard");
183
			$this->addWhere('masque.standard', "do.donnees_standard = $donnees_standard");
184
			$this->ajouterJoinObsSiNecessaire();
184
			$this->ajouterJoinObsSiNecessaire();
185
		}
185
		}
186
	}
186
	}
187
 
187
 
188
	private function ajouterContrainteAuteur() {
188
	private function ajouterContrainteAuteur() {
189
		if (isset($this->parametres['masque.auteur'])) {
189
		if (isset($this->parametres['masque.auteur'])) {
190
			$auteur = $this->parametres['masque.auteur'];
190
			$auteur = $this->parametres['masque.auteur'];
191
			// id du poster de l'obs
191
			// id du poster de l'obs
192
			$prefixe = $this->getPrefixe();
192
			$prefixe = $this->getPrefixe();
193
 
193
 
194
			if (is_numeric($auteur)) {
194
			if (is_numeric($auteur)) {
195
				$this->ajouterContrainteAuteurId();
195
				$this->ajouterContrainteAuteurId();
196
			} elseif(preg_match('/@[a-z0-9-]+(?:\.[a-z0-9-]+)*\.[a-z]{2,}$/i', $auteur)) {
196
			} elseif(preg_match('/@[a-z0-9-]+(?:\.[a-z0-9-]+)*\.[a-z]{2,}$/i', $auteur)) {
197
				$this->ajouterContrainteAuteurEmail();
197
				$this->ajouterContrainteAuteurEmail();
198
			} else {
198
			} else {
199
				$this->ajouterContrainteAuteurIntitule();
199
				$this->ajouterContrainteAuteurIntitule();
200
			}
200
			}
201
		}
201
		}
202
	}
202
	}
203
 
203
 
204
	private function ajouterContrainteAuteurId() {
204
	private function ajouterContrainteAuteurId() {
205
		$id = $this->parametres['masque.auteur'];
205
		$id = $this->parametres['masque.auteur'];
206
		$prefixe = $this->getPrefixe();
206
		$prefixe = $this->getPrefixe();
207
		$sqlTpl = "($prefixe.ce_utilisateur = %1\$d)";
207
		$sqlTpl = "($prefixe.ce_utilisateur = %1\$d)";
208
		$whereAuteur = sprintf($sqlTpl, $id);
208
		$whereAuteur = sprintf($sqlTpl, $id);
209
		$this->addWhere('masque.auteur', $whereAuteur);
209
		$this->addWhere('masque.auteur', $whereAuteur);
210
	}
210
	}
211
 
211
 
212
	private function ajouterContrainteAuteurEmail() {
212
	private function ajouterContrainteAuteurEmail() {
213
		$email = $this->parametres['masque.auteur'];
213
		$email = $this->parametres['masque.auteur'];
214
		$prefixe = $this->getPrefixe();
214
		$prefixe = $this->getPrefixe();
215
		$sqlTpl = "($prefixe.courriel_utilisateur LIKE %1\$s )";
215
		$sqlTpl = "($prefixe.courriel_utilisateur LIKE %1\$s )";
216
		$emailP = $this->bdd->proteger("$email%");
216
		$emailP = $this->bdd->proteger("$email%");
217
		$whereAuteur = sprintf($sqlTpl, $emailP);
217
		$whereAuteur = sprintf($sqlTpl, $emailP);
218
		$this->addWhere('masque.auteur', $whereAuteur);
218
		$this->addWhere('masque.auteur', $whereAuteur);
219
	}
219
	}
220
 
220
 
221
	/**
221
	/**
222
	 * Retourne une clause where du style:
222
	 * Retourne une clause where du style:
223
	 * CONCAT(IF(du.prenom IS NULL, "", du.prenom), [...] vdi.i_nomutilisateur) REGEXP 'xxx'
223
	 * CONCAT(IF(du.prenom IS NULL, "", du.prenom), [...] vdi.i_nomutilisateur) REGEXP 'xxx'
224
	 */
224
	 */
225
	private function ajouterContrainteAuteurIntitule() {
225
	private function ajouterContrainteAuteurIntitule() {
226
		$auteurExplode = explode(' ', $this->parametres['masque.auteur']);
226
		$auteurExplode = explode(' ', $this->parametres['masque.auteur']);
227
		$nbreMots = count($auteurExplode);
227
		$nbreMots = count($auteurExplode);
228
 
228
 
229
		if ($nbreMots == 1) {
229
		if ($nbreMots == 1) {
230
			$this->ajouterContrainteAuteurPrenomOuNom();
230
			$this->ajouterContrainteAuteurPrenomOuNom();
231
		} else if ($nbreMots == 2) {
231
		} else if ($nbreMots == 2) {
232
			$this->ajouterContrainteAuteurPrenomEtNom();
232
			$this->ajouterContrainteAuteurPrenomEtNom();
233
		}
233
		}
234
	}
234
	}
235
 
235
 
236
	private function ajouterContrainteAuteurPrenomOuNom() {
236
	private function ajouterContrainteAuteurPrenomOuNom() {
237
		$prenomOuNom = $this->parametres['masque.auteur'];
237
		$prenomOuNom = $this->parametres['masque.auteur'];
238
 
238
 
239
		$sqlTpl = 'CONCAT(%s,%s) LIKE %s';
239
		$sqlTpl = 'CONCAT(%s,%s) LIKE %s';
240
		$prefixe = $this->getPrefixe();
240
		$prefixe = $this->getPrefixe();
241
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
241
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
242
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
242
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
243
		$auteurMotif = $this->bdd->proteger("%$prenomOuNom%");
243
		$auteurMotif = $this->bdd->proteger("%$prenomOuNom%");
244
 
244
 
245
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $auteurMotif);
245
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $auteurMotif);
246
		$this->addWhere('masque.auteur', $auteurWhere);
246
		$this->addWhere('masque.auteur', $auteurWhere);
247
	}
247
	}
248
 
248
 
249
	private function ajouterContrainteAuteurPrenomEtNom() {
249
	private function ajouterContrainteAuteurPrenomEtNom() {
250
		list($prenom, $nom) = explode(' ', $this->parametres['masque.auteur']);
250
		list($prenom, $nom) = explode(' ', $this->parametres['masque.auteur']);
251
 
251
 
252
		$sqlTpl = '(CONCAT(%1$s,%2$s) LIKE %3$s AND CONCAT(%1$s,%2$s) LIKE %4$s)';
252
		$sqlTpl = '(CONCAT(%1$s,%2$s) LIKE %3$s AND CONCAT(%1$s,%2$s) LIKE %4$s)';
253
		$prefixe = $this->getPrefixe();
253
		$prefixe = $this->getPrefixe();
254
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
254
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
255
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
255
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
256
		$prenomMotif = $this->bdd->proteger("%$prenom%");
256
		$prenomMotif = $this->bdd->proteger("%$prenom%");
257
		$nomMotif = $this->bdd->proteger("%$nom%");
257
		$nomMotif = $this->bdd->proteger("%$nom%");
258
 
258
 
259
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $prenomMotif, $nomMotif);
259
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $prenomMotif, $nomMotif);
260
		$this->addWhere('masque.auteur', $auteurWhere);
260
		$this->addWhere('masque.auteur', $auteurWhere);
261
	}
261
	}
262
 
262
 
263
	/**
263
	/**
264
	 * Lorsque l'on concatène des champs, un seul NULL prend le dessus.
264
	 * Lorsque l'on concatène des champs, un seul NULL prend le dessus.
265
	 * Il faut donc utiliser la syntaxe IFNULL(%s, "").
265
	 * Il faut donc utiliser la syntaxe IFNULL(%s, "").
266
	 * Cette fonction effectue aussi l'implode() "final".
266
	 * Cette fonction effectue aussi l'implode() "final".
267
	 */
267
	 */
268
	private static function ajouterIfNullPourConcat($champs, $prefixe) {
268
	private static function ajouterIfNullPourConcat($champs, $prefixe) {
269
		$champsProteges = array();
269
		$champsProteges = array();
270
		foreach ($champs as $champ) {
270
		foreach ($champs as $champ) {
271
			if (strstr($champ, '.') === false) {
271
			if (strstr($champ, '.') === false) {
272
				$champ = "$prefixe.$champ";
272
				$champ = "$prefixe.$champ";
273
			}
273
			}
274
			$champsProteges[] = "IFNULL($champ, '')";
274
			$champsProteges[] = "IFNULL($champ, '')";
275
		}
275
		}
276
		return implode(',', $champsProteges);
276
		return implode(',', $champsProteges);
277
	}
277
	}
278
 
278
 
279
	private function ajouterContrainteDate() {
279
	private function ajouterContrainteDate() {
280
		if (isset($this->parametres['masque.date'])) {
280
		if (isset($this->parametres['masque.date'])) {
281
			$date = $this->parametres['masque.date'];
281
			$date = $this->parametres['masque.date'];
282
			if (preg_match('/^\d{4}$/', $date) && $date < 2030 && $date > 1600) {
282
			if (preg_match('/^\d{4}$/', $date) && $date < 2030 && $date > 1600) {
283
				$sqlTpl = "YEAR(do.date_observation) = %d";
283
				$sqlTpl = "YEAR(do.date_observation) = %d";
284
				$dateWhere = sprintf($sqlTpl, $date);
284
				$dateWhere = sprintf($sqlTpl, $date);
285
				$this->addWhere('masque.date', $dateWhere);
285
				$this->addWhere('masque.date', $dateWhere);
286
			} else {
286
			} else {
287
				$sqlTpl = "do.date_observation = %s";
287
				$sqlTpl = "do.date_observation = %s";
288
				$dateP = $this->bdd->proteger($date);
288
				$dateP = $this->bdd->proteger($date);
289
				$dateWhere = sprintf($sqlTpl, $dateP);
289
				$dateWhere = sprintf($sqlTpl, $dateP);
290
				$this->addWhere('masque.date', $dateWhere);
290
				$this->addWhere('masque.date', $dateWhere);
291
			}
291
			}
292
 
292
 
293
			$this->ajouterJoinObsSiNecessaire();
293
			$this->ajouterJoinObsSiNecessaire();
294
		}
294
		}
295
	}
295
	}
296
 
296
 
297
	private function ajouterContrainteDepartement() {
297
	private function ajouterContrainteDepartement() {
298
		if (isset($this->parametres['masque.departement'])) {
298
		if (isset($this->parametres['masque.departement'])) {
299
			$dept = $this->parametres['masque.departement'];
299
			$dept = $this->parametres['masque.departement'];
300
			$deptMotif = $this->bdd->proteger("$dept");
300
			$deptMotif = $this->bdd->proteger("$dept");
301
			$this->addWhere('masque.departement', "do.ce_zone_geo like $deptMotif");
301
			$this->addWhere('masque.departement', "do.ce_zone_geo like $deptMotif");
302
 
302
 
303
			$this->ajouterJoinObsSiNecessaire();
303
			$this->ajouterJoinObsSiNecessaire();
304
		}
304
		}
305
	}
305
	}
306
	
306
	
307
	private function ajouterContraintePays() {
307
	private function ajouterContraintePays() {
308
		if (isset($this->parametres['masque.pays'])) {
308
		if (isset($this->parametres['masque.pays'])) {
309
			// Attention le standard contient parfois FX pour la france métropolitaine
309
			// Attention le standard contient parfois FX pour la france métropolitaine
310
			// Dans ce cas particulier on cherche donc FR et FX
310
			// Dans ce cas particulier on cherche donc FR et FX
311
			$this->parametres['masque.pays'] = strtoupper($this->parametres['masque.pays']);
311
			$this->parametres['masque.pays'] = strtoupper($this->parametres['masque.pays']);
312
			if(strpos($this->parametres['masque.pays'], 'FR') !== false) {
312
			if(strpos($this->parametres['masque.pays'], 'FR') !== false) {
313
				$this->parametres['masque.pays'] = str_replace('FR', 'FR,FX', $this->parametres['masque.pays']);
313
				$this->parametres['masque.pays'] = str_replace('FR', 'FR,FX', $this->parametres['masque.pays']);
314
			}
314
			}
315
			$pays = explode(',', $this->parametres['masque.pays']);
315
			$pays = explode(',', $this->parametres['masque.pays']);
316
			$pays = implode(',', $this->bdd->proteger($pays));
316
			$pays = implode(',', $this->bdd->proteger($pays));
317
			$this->addWhere('masque.pays', "do.pays IN ($pays)");
317
			$this->addWhere('masque.pays', "do.pays IN ($pays)");
318
	
318
	
319
			$this->ajouterJoinObsSiNecessaire();
319
			$this->ajouterJoinObsSiNecessaire();
320
		}
320
		}
321
	}
321
	}
322
 
322
 
323
	private function ajouterContrainteIdZoneGeo() {
323
	private function ajouterContrainteIdZoneGeo() {
324
		if (isset($this->parametres['masque.id_zone_geo'])) {
324
		if (isset($this->parametres['masque.id_zone_geo'])) {
325
			$idZgMotif = $this->bdd->proteger($this->parametres['masque.id_zone_geo']);
325
			$idZgMotif = $this->bdd->proteger($this->parametres['masque.id_zone_geo']);
326
			$this->addWhere('masque.id_zone_geo', "do.ce_zone_geo = $idZgMotif");
326
			$this->addWhere('masque.id_zone_geo', "do.ce_zone_geo = $idZgMotif");
327
			
327
			
328
			$this->ajouterJoinObsSiNecessaire();
328
			$this->ajouterJoinObsSiNecessaire();
329
		}
329
		}
330
	}
330
	}
331
 
331
 
332
	private function ajouterContrainteGenre() {
332
	private function ajouterContrainteGenre() {
333
		if (isset($this->parametres['masque.genre'])) {
333
		if (isset($this->parametres['masque.genre'])) {
334
			$genre = $this->parametres['masque.genre'];
334
			$genre = $this->parametres['masque.genre'];
335
			$genreMotif = $this->bdd->proteger("$genre%");
335
			$genreMotif = $this->bdd->proteger("$genre%");
336
			$this->addWhere('masque.genre', "do.nom_sel LIKE $genreMotif");
336
			$this->addWhere('masque.genre', "do.nom_sel LIKE $genreMotif");
337
 
337
 
338
			$this->ajouterJoinObsSiNecessaire();
338
			$this->ajouterJoinObsSiNecessaire();
339
		}
339
		}
340
	}
340
	}
341
 
341
 
342
	private function ajouterContrainteFamille() {
342
	private function ajouterContrainteFamille() {
343
		if (isset($this->parametres['masque.famille'])) {
343
		if (isset($this->parametres['masque.famille'])) {
344
			$familleMotif = $this->bdd->proteger($this->parametres['masque.famille']);
344
			$familleMotif = $this->bdd->proteger($this->parametres['masque.famille']);
345
			$this->addWhere('masque.famille', "do.famille = $familleMotif");
345
			$this->addWhere('masque.famille', "do.famille = $familleMotif");
346
 
346
 
347
			$this->ajouterJoinObsSiNecessaire();
347
			$this->ajouterJoinObsSiNecessaire();
348
		}
348
		}
349
	}
349
	}
350
 
350
 
351
	private function ajouterContrainteNs() {
351
	private function ajouterContrainteNs() {
352
		if (isset($this->parametres['masque.ns'])) {
352
		if (isset($this->parametres['masque.ns'])) {
353
			$ns = $this->parametres['masque.ns'];
353
			$ns = $this->parametres['masque.ns'];
354
			$nsMotif = $this->bdd->proteger("$ns%");
354
			$nsMotif = $this->bdd->proteger("$ns%");
355
			$this->addWhere('masque.ns', "do.nom_sel LIKE $nsMotif");
355
			$this->addWhere('masque.ns', "do.nom_sel LIKE $nsMotif");
356
			
356
			
357
			$this->ajouterJoinObsSiNecessaire();
357
			$this->ajouterJoinObsSiNecessaire();
358
		}
358
		}
359
	}
359
	}
360
 
360
 
361
	private function ajouterContrainteNn() {
361
	private function ajouterContrainteNn() {
362
		if (isset($this->parametres['masque.nn'])) {
362
		if (isset($this->parametres['masque.nn'])) {
363
			$sqlTpl = '(do.nom_sel_nn = %1$d OR do.nom_ret_nn = %1$d)';
363
			$sqlTpl = '(do.nom_sel_nn = %1$d OR do.nom_ret_nn = %1$d)';
364
			$nnWhere = sprintf($sqlTpl, $this->parametres['masque.nn']);
364
			$nnWhere = sprintf($sqlTpl, $this->parametres['masque.nn']);
365
			$this->addWhere('masque.nn', $nnWhere);
365
			$this->addWhere('masque.nn', $nnWhere);
366
 
366
 
367
			$this->ajouterJoinObsSiNecessaire();
367
			$this->ajouterJoinObsSiNecessaire();
368
		}
368
		}
369
	}
369
	}
370
 
370
 
371
	private function ajouterContrainteReferentiel() {
371
	private function ajouterContrainteReferentiel() {
372
		if (isset($this->parametres['masque.referentiel'])) {
372
		if (isset($this->parametres['masque.referentiel'])) {
373
			$ref = $this->parametres['masque.referentiel'];
373
			$ref = $this->parametres['masque.referentiel'];
374
			$refMotif = $this->bdd->proteger("$ref");
374
			$refMotif = $this->bdd->proteger("$ref");
375
			$this->addWhere('masque.referentiel', "do.nom_referentiel = $refMotif");
375
			$this->addWhere('masque.referentiel', "do.nom_referentiel = $refMotif");
376
 
376
 
377
			$this->ajouterJoinObsSiNecessaire();
377
			$this->ajouterJoinObsSiNecessaire();
378
		}
378
		}
379
	}
379
	}
380
 
380
 
381
	private function ajouterContrainteCommune() {
381
	private function ajouterContrainteCommune() {
382
		if (isset($this->parametres['masque.commune'])) {
382
		if (isset($this->parametres['masque.commune'])) {
383
			$commune = $this->parametres['masque.commune'];
383
			$commune = $this->parametres['masque.commune'];
384
			$communeMotif = $this->bdd->proteger("$commune%");
384
			$communeMotif = $this->bdd->proteger("$commune%");
385
			$this->addWhere('masque.commune', "do.zone_geo LIKE $communeMotif");
385
			$this->addWhere('masque.commune', "do.zone_geo LIKE $communeMotif");
386
 
386
 
387
			$this->ajouterJoinObsSiNecessaire();
387
			$this->ajouterJoinObsSiNecessaire();
388
		}
388
		}
389
	}
389
	}
390
 
390
 
391
	/**
391
	/**
392
	 * Si masque.pninscritsseulement vaut true, les observations ayant un tag
392
	 * Si masque.pninscritsseulement vaut true, les observations ayant un tag
393
	 * "plantnet" mais dont l'auteur n'est pas inscrit à TB seront éliminées
393
	 * "plantnet" mais dont l'auteur n'est pas inscrit à TB seront éliminées
394
	 * (décision FlorisTic 2016-09)
394
	 * (décision FlorisTic 2016-09)
395
	 */
395
	 */
396
	protected function ajouterContraintePnInscrits() {
396
	protected function ajouterContraintePnInscrits() {
-
 
397
	// en prod, noté désactivé pour performance
397
		if (isset($this->parametres['masque.pninscritsseulement'])) {
398
		    //if (isset($this->parametres['masque.pninscritsseulement'])) {
398
			// avec la classe ParametresFiltrage, on ne passe là que si le masque vaut 1
399
			// avec la classe ParametresFiltrage, on ne passe là que si le masque vaut 1
399
			$motifMotClePlantnet = "'plantnet'";
400
		/*	$motifMotClePlantnet = "'plantnet'";
400
			$this->addWhere('masque.pninscritsseulement', "((do.input_source != $motifMotClePlantnet) OR 
401
			$this->addWhere('masque.pninscritsseulement', "((do.input_source != $motifMotClePlantnet) OR 
401
			    (do.input_source = $motifMotClePlantnet AND do.ce_utilisateur != 0))");
402
			    (do.input_source = $motifMotClePlantnet AND do.ce_utilisateur != 0))");
402
 
403
 
403
			$this->ajouterJoinObsSiNecessaire();
404
			$this->ajouterJoinObsSiNecessaire();
404
		}
405
		}*/
405
	}
406
	}
406
	
407
	
407
	private function ajouterJoinObsSiNecessaire() {
408
	private function ajouterJoinObsSiNecessaire() {
408
			if ($this->etreAppliImg()) {
409
			if ($this->etreAppliImg()) {
409
				$this->addJoin($this->getSqlJointureObs());
410
				$this->addJoin($this->getSqlJointureObs());
410
			}
411
			}
411
	}
412
	}
412
	
413
	
413
	private function getSqlJointureObs() {
414
	private function getSqlJointureObs() {
414
		$typeJointure = !empty($this->parametres['masque']) ? 'LEFT' : 'INNER';
415
		$typeJointure = !empty($this->parametres['masque']) ? 'LEFT' : 'INNER';
415
		return $typeJointure.' JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ';
416
		return $typeJointure.' JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ';
416
	}
417
	}
417
 
418
 
418
	// la constrainte de nostre bon roy
419
	// la constrainte de nostre bon roy
419
	public function ajouterConstrainteAppliObs() {
420
	public function ajouterConstrainteAppliObs() {
420
		$this->ajouterContrainteTagCel();
421
		$this->ajouterContrainteTagCel();
421
		$this->ajouterContrainteType();
422
		$this->ajouterContrainteType();
422
		// TODO : ATTENTION -> vu que l'on utilise une vue basée sur les images, nous devons grouper par obs
423
		// TODO : ATTENTION -> vu que l'on utilise une vue basée sur les images, nous devons grouper par obs
423
		$this->addGroupBy('do.id_observation');
424
		$this->addGroupBy('do.id_observation');
424
	}
425
	}
425
 
426
 
426
	private function ajouterContrainteType() {
427
	private function ajouterContrainteType() {
427
		// Les contraintes régissant les onglets sont issus de la réunion dont le compte rendu 
428
		// Les contraintes régissant les onglets sont issus de la réunion dont le compte rendu 
428
		// disponible ici : http://tela-botanica.net/intranet/wakka.php?wiki=Octobre2014
429
		// disponible ici : http://tela-botanica.net/intranet/wakka.php?wiki=Octobre2014
429
		// Ce lien est à modifier pour pointer vers toute nouvelle réunion modifiant ce fonctionnement
430
		// Ce lien est à modifier pour pointer vers toute nouvelle réunion modifiant ce fonctionnement
430
		
431
		
431
		if (isset($this->parametres['masque.type'])) {
432
		if (isset($this->parametres['masque.type'])) {
432
			if (array_key_exists('adeterminer', $this->parametres['masque.type'])) {
433
			if (array_key_exists('adeterminer', $this->parametres['masque.type'])) {
433
				// A DETERMINER : toutes les observations qui ont le tag "aDeterminer" 
434
				// A DETERMINER : toutes les observations qui ont le tag "aDeterminer" 
434
				// *ou* qui n'ont pas de nom d'espèce
435
				// *ou* qui n'ont pas de nom d'espèce
435
				// *ou* qui ont la "certitude" à ("aDeterminer" *ou* "douteux")
436
				// *ou* qui ont la "certitude" à ("aDeterminer" *ou* "douteux")
436
				$this->addWhere('masque.type', '('.
437
				$this->addWhere('masque.type', '('.
437
					'do.certitude = "à déterminer" '.
438
					'do.certitude = "à déterminer" '.
438
					'OR do.certitude = "douteux" '.
439
					'OR do.certitude = "douteux" '.
439
					'OR do.mots_cles_texte LIKE "%aDeterminer%" '.
440
					'OR do.mots_cles_texte LIKE "%aDeterminer%" '.
440
					'OR do.nom_sel_nn IS NULL '.
441
					'OR do.nom_sel_nn IS NULL '.
441
					'OR do.nom_sel_nn = 0 '.// il ne DEVRAIT pas y avoir d'entrées à 0, mais il y en a quand-même !!
442
					'OR do.nom_sel_nn = 0 '.// il ne DEVRAIT pas y avoir d'entrées à 0, mais il y en a quand-même !!
442
					')');
443
					')');
443
			}
444
			}
444
			
445
			
445
			if (array_key_exists('validees', $this->parametres['masque.type'])) {
446
			if (array_key_exists('validees', $this->parametres['masque.type'])) {
446
				// VALIDEES : toutes les observations ayant un commentaire doté de proposition_retenue = 1
447
				// VALIDEES : toutes les observations ayant un commentaire doté de proposition_retenue = 1
447
				// ou bien possédant une proposition initiale avec un nom valide ayant totalisé un score d'au moins 4
448
				// ou bien possédant une proposition initiale avec un nom valide ayant totalisé un score d'au moins 4
448
				// (ce qui correspond à au moins deux votes positifs dans la plupart des cas, dont un identifié)
449
				// (ce qui correspond à au moins deux votes positifs dans la plupart des cas, dont un identifié)
449
				$sous_requete_score_prop_votees = $this->getSousRequeteSommeVotesPropositions();				
450
				$sous_requete_score_prop_votees = $this->getSousRequeteSommeVotesPropositions();				
450
				$this->addJoin('INNER JOIN del_commentaire AS dc '.
451
				$this->addJoin('INNER JOIN del_commentaire AS dc '.
451
					'ON ( '.
452
					'ON ( '.
452
						'do.id_observation = dc.ce_observation '.
453
						'do.id_observation = dc.ce_observation '.
453
						'AND ( '.
454
						'AND ( '.
454
							'dc.proposition_retenue = 1 OR '.
455
							'dc.proposition_retenue = 1 OR '.
455
							'( '.
456
							'( '.
456
								'dc.proposition_initiale = 1 '.
457
								'dc.proposition_initiale = 1 '.
457
								'AND dc.nom_sel_nn != 0 '.
458
								'AND dc.nom_sel_nn != 0 '.
458
								'AND dc.nom_sel_nn IS NOT NULL '.
459
								'AND dc.nom_sel_nn IS NOT NULL '.
459
								' AND dc.id_commentaire IN ('.$sous_requete_score_prop_votees.' >= 4) '.
460
								' AND dc.id_commentaire IN ('.$sous_requete_score_prop_votees.' >= 4) '.
460
							') '.
461
							') '.
461
						') '.
462
						') '.
462
					')'
463
					')'
463
				);
464
				);
464
			}
465
			}
465
			
466
			
466
			if(array_key_exists('aconfirmer', $this->parametres['masque.type'])) {
467
			if(array_key_exists('aconfirmer', $this->parametres['masque.type'])) {
467
				// A CONFIRMER : toutes les observations moins les validées et à confirmer
468
				// A CONFIRMER : toutes les observations moins les validées et à confirmer
468
				// i.e. : des observations avec un nom valide, qui ne sont pas à déterminer
469
				// i.e. : des observations avec un nom valide, qui ne sont pas à déterminer
469
				// (ni certitude "aDeterminer" ou "douteuse", ni mot clé),
470
				// (ni certitude "aDeterminer" ou "douteuse", ni mot clé),
470
				// ne possédant pas de proposition officiellement retenue 
471
				// ne possédant pas de proposition officiellement retenue 
471
				// et ayant une proposition initiale totalisant un score de moins de 4 
472
				// et ayant une proposition initiale totalisant un score de moins de 4 
472
				$sous_requete_score_prop_votees = $this->getSousRequeteSommeVotesPropositions();
473
				$sous_requete_score_prop_votees = $this->getSousRequeteSommeVotesPropositions();
473
				$this->addWhere('masque.type', 
474
				$this->addWhere('masque.type', 
474
						'('.
475
						'('.
475
							'do.id_observation IN ('.
476
							'do.id_observation IN ('.
476
								'SELECT dc.ce_observation FROM del_commentaire dc WHERE dc.proposition_retenue = 0'.
477
								'SELECT dc.ce_observation FROM del_commentaire dc WHERE dc.proposition_retenue = 0'.
477
								' AND ( '.
478
								' AND ( '.
478
									'dc.proposition_initiale = 1 '.
479
									'dc.proposition_initiale = 1 '.
479
									'AND dc.nom_sel_nn != 0 '.
480
									'AND dc.nom_sel_nn != 0 '.
480
									'AND dc.nom_sel_nn IS NOT NULL '.
481
									'AND dc.nom_sel_nn IS NOT NULL '.
481
									'AND dc.id_commentaire IN ('.$sous_requete_score_prop_votees.' < 4) '.
482
									'AND dc.id_commentaire IN ('.$sous_requete_score_prop_votees.' < 4) '.
482
								') '.
483
								') '.
483
							') AND do.id_observation NOT IN ('.
484
							') AND do.id_observation NOT IN ('.
484
								'SELECT dc.ce_observation FROM del_commentaire dc '.
485
								'SELECT dc.ce_observation FROM del_commentaire dc '.
485
								'WHERE '.
486
								'WHERE '.
486
								' dc.proposition_retenue = 1'.
487
								' dc.proposition_retenue = 1'.
487
							') '.
488
							') '.
488
							'AND do.certitude != "douteux" AND do.certitude != "aDeterminer" '.
489
							'AND do.certitude != "douteux" AND do.certitude != "aDeterminer" '.
489
							'AND do.mots_cles_texte NOT LIKE "%aDeterminer%" '.
490
							'AND do.mots_cles_texte NOT LIKE "%aDeterminer%" '.
490
							'AND do.nom_sel_nn != 0 '.
491
							'AND do.nom_sel_nn != 0 '.
491
							'AND do.nom_sel_nn IS NOT NULL'.
492
							'AND do.nom_sel_nn IS NOT NULL'.
492
						') '	
493
						') '	
493
					);
494
					);
494
			}	
495
			}	
495
 
496
 
496
			$this->ajouterJoinObsSiNecessaire();
497
			$this->ajouterJoinObsSiNecessaire();
497
		}
498
		}
498
	}
499
	}
499
	
500
	
500
	private function getSousRequeteSommeVotesPropositions() {
501
	private function getSousRequeteSommeVotesPropositions() {
501
		// ATTENTION : un vote identifié compte 3 votes anonymes (dans les deux sens)
502
		// ATTENTION : un vote identifié compte 3 votes anonymes (dans les deux sens)
502
		return  'SELECT ce_proposition '.
503
		return  'SELECT ce_proposition '.
503
				'FROM del_commentaire_vote dcv '.
504
				'FROM del_commentaire_vote dcv '.
504
				'GROUP BY ce_proposition HAVING '.
505
				'GROUP BY ce_proposition HAVING '.
505
				'SUM(CASE '.
506
				'SUM(CASE '.
506
				'	WHEN valeur = 1 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' != 0 THEN 3 '.
507
				'	WHEN valeur = 1 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' != 0 THEN 3 '.
507
				'	WHEN valeur = 0 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' != 0 THEN -3 '.
508
				'	WHEN valeur = 0 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' != 0 THEN -3 '.
508
				'	WHEN valeur = 1 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' = 0 THEN 1 '.
509
				'	WHEN valeur = 1 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' = 0 THEN 1 '.
509
				'	WHEN valeur = 0 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' = 0 THEN -1 '.
510
				'	WHEN valeur = 0 AND dcv.ce_utilisateur REGEXP \'^-?[0-9]+$\' = 0 THEN -1 '.
510
				'END '.
511
				'END '.
511
			') ';
512
			') ';
512
	}
513
	}
513
 
514
 
514
	public function ajouterConstrainteAppliImg() {
515
	public function ajouterConstrainteAppliImg() {
515
		$this->ajouterContrainteMilieu();
516
		$this->ajouterContrainteMilieu();
516
		$this->ajouterContrainteTri();
517
		$this->ajouterContrainteTri();
517
		$this->ajouterContrainteTagCel();
518
		$this->ajouterContrainteTagCel();
518
		$this->ajouterContrainteTagDel();
519
		$this->ajouterContrainteTagDel();
519
		$this->ajouterContraintePnInscrits();
520
		$this->ajouterContraintePnInscrits();
520
	}
521
	}
521
 
522
 
522
	private function ajouterContrainteMilieu() {
523
	private function ajouterContrainteMilieu() {
523
		if (isset($this->parametres['masque.milieu'])) {
524
		if (isset($this->parametres['masque.milieu'])) {
524
			$milieu = $this->parametres['masque.milieu'];
525
			$milieu = $this->parametres['masque.milieu'];
525
			$milieuMotif = $this->bdd->proteger("%$milieu%");
526
			$milieuMotif = $this->bdd->proteger("%$milieu%");
526
			$this->addWhere('masque.milieu', "do.milieu LIKE $milieuMotif");
527
			$this->addWhere('masque.milieu', "do.milieu LIKE $milieuMotif");
527
 
528
 
528
			$this->ajouterJoinObsSiNecessaire();
529
			$this->ajouterJoinObsSiNecessaire();
529
		}
530
		}
530
	}
531
	}
531
 
532
 
532
	private function ajouterContrainteTri() {
533
	private function ajouterContrainteTri() {
533
		if (isset($this->parametres['tri'])) {
534
		if (isset($this->parametres['tri'])) {
534
			$tri = $this->parametres['tri'];
535
			$tri = $this->parametres['tri'];
535
 
536
 
536
			if (isset($this->parametres['protocole'])  && ($tri == 'moyenne-arithmetique' || $tri == 'points')) {
537
			if (isset($this->parametres['protocole'])  && ($tri == 'moyenne-arithmetique' || $tri == 'points')) {
537
				// $this->parametres['protocole'] *est* défini (cf Outils::filtrerUrlsParams...())
538
				// $this->parametres['protocole'] *est* défini (cf Outils::filtrerUrlsParams...())
538
				$sqlTpl = 'LEFT JOIN del_image_stat AS dis ON di.id_image = dis.ce_image AND dis.ce_protocole = %d';
539
				$sqlTpl = 'LEFT JOIN del_image_stat AS dis ON di.id_image = dis.ce_image AND dis.ce_protocole = %d';
539
				$triSql = sprintf($sqlTpl, $this->parametres['protocole']);
540
				$triSql = sprintf($sqlTpl, $this->parametres['protocole']);
540
				$this->addJoinDis($triSql);
541
				$this->addJoinDis($triSql);
541
			}
542
			}
542
 
543
 
543
			if (isset($this->parametres['ordre']) && $tri == 'tags') {
544
			if (isset($this->parametres['ordre']) && $tri == 'tags') {
544
				$typeJointure = ($this->parametres['ordre'] == 'desc') ? 'INNER' : 'LEFT';
545
				$typeJointure = ($this->parametres['ordre'] == 'desc') ? 'INNER' : 'LEFT';
545
				$this->addJoin("$typeJointure JOIN del_image_stat AS dis ON di.id_image = dis.ce_image");
546
				$this->addJoin("$typeJointure JOIN del_image_stat AS dis ON di.id_image = dis.ce_image");
546
			}
547
			}
547
		}
548
		}
548
	}
549
	}
549
 
550
 
550
	private function ajouterContrainteTagCel() {
551
	private function ajouterContrainteTagCel() {
551
		if (isset($this->parametres['masque.tag_cel'])) {
552
		if (isset($this->parametres['masque.tag_cel'])) {
552
			if (isset($this->parametres['masque.tag_cel']['AND'])) {
553
			if (isset($this->parametres['masque.tag_cel']['AND'])) {
553
				$tags = $this->parametres['masque.tag_cel']['AND'];
554
				$tags = $this->parametres['masque.tag_cel']['AND'];
554
				$clausesWhere = array();
555
				$clausesWhere = array();
555
				foreach ($tags as $tag) {
556
				foreach ($tags as $tag) {
556
					$tagMotif = $this->bdd->proteger("%$tag%");
557
					$tagMotif = $this->bdd->proteger("%$tag%");
557
					if ($this->etreAppliImg()) {
558
					if ($this->etreAppliImg()) {
558
						$sousRequete = 'SELECT id_observation '.
559
						$sousRequete = 'SELECT id_observation '.
559
							'FROM del_observation '.
560
							'FROM del_observation '.
560
							"WHERE mots_cles_texte LIKE $tagMotif ";
561
							"WHERE mots_cles_texte LIKE $tagMotif ";
561
						$sql = " (di.mots_cles_texte LIKE $tagMotif OR di.id_image IN ($sousRequete) ) ";
562
						$sql = " (di.mots_cles_texte LIKE $tagMotif OR di.id_image IN ($sousRequete) ) ";
562
					} else {
563
					} else {
563
						// WARNING : la sous-requête est la meilleure solution trouvée pour contrer le fonctionnement
564
						// WARNING : la sous-requête est la meilleure solution trouvée pour contrer le fonctionnement
564
						// étrange de l'optimiseur de MYSQL 5.6 (à retester avec Mysql 5.7 et suivant).
565
						// étrange de l'optimiseur de MYSQL 5.6 (à retester avec Mysql 5.7 et suivant).
565
						$sousRequete = 'SELECT DISTINCT ce_observation '.
566
						$sousRequete = 'SELECT DISTINCT ce_observation '.
566
							'FROM del_image '.
567
							'FROM del_image '.
567
							"WHERE mots_cles_texte LIKE $tagMotif ".
568
							"WHERE mots_cles_texte LIKE $tagMotif ".
568
							'AND ce_observation IS NOT NULL';
569
							'AND ce_observation IS NOT NULL';
569
						$sql = " (do.mots_cles_texte LIKE $tagMotif OR do.id_observation IN ($sousRequete)) ";
570
						$sql = " (do.mots_cles_texte LIKE $tagMotif OR do.id_observation IN ($sousRequete)) ";
570
					}
571
					}
571
					$clausesWhere[] = $sql;
572
					$clausesWhere[] = $sql;
572
				}
573
				}
573
				$whereTags = implode(' AND ', $clausesWhere);
574
				$whereTags = implode(' AND ', $clausesWhere);
574
				$this->addWhere('masque.tag_cel', "($whereTags)");
575
				$this->addWhere('masque.tag_cel', "($whereTags)");
575
			} else if (isset($this->parametres['masque.tag_cel']['OR'])) {
576
			} else if (isset($this->parametres['masque.tag_cel']['OR'])) {
576
				$tags = $this->parametres['masque.tag_cel']['OR'];
577
				$tags = $this->parametres['masque.tag_cel']['OR'];
577
				$tagMotif = $this->bdd->proteger(implode('|', $tags));
578
				$tagMotif = $this->bdd->proteger(implode('|', $tags));
578
				$sqlTpl = "CONCAT(IFNULL(do.mots_cles_texte,''),IFNULL(di.mots_cles_texte,'')) REGEXP %s";
579
				$sqlTpl = "CONCAT(IFNULL(do.mots_cles_texte,''),IFNULL(di.mots_cles_texte,'')) REGEXP %s";
579
				$tagSql = sprintf($sqlTpl, $tagMotif);
580
				$tagSql = sprintf($sqlTpl, $tagMotif);
580
 
581
 
581
				$this->addWhere('masque.tag_cel', $tagSql);
582
				$this->addWhere('masque.tag_cel', $tagSql);
582
 
583
 
583
				if ($this->etreAppliObs()) {
584
				if ($this->etreAppliObs()) {
584
					$this->addJoin('LEFT JOIN del_image AS di ON (di.ce_observation = do.id_observation) ');
585
					$this->addJoin('LEFT JOIN del_image AS di ON (di.ce_observation = do.id_observation) ');
585
				}
586
				}
586
			}
587
			}
587
			$this->ajouterJoinObsSiNecessaire();
588
			$this->ajouterJoinObsSiNecessaire();
588
		}
589
		}
589
	}
590
	}
590
 
591
 
591
	/**
592
	/**
592
	 * Plusieurs solutions sont disponibles dans les anciennes versions (voir DelTk et l'historique SVN de ce fichier).
593
	 * Plusieurs solutions sont disponibles dans les anciennes versions (voir DelTk et l'historique SVN de ce fichier).
593
	 */
594
	 */
594
	private function ajouterContrainteTagDel() {
595
	private function ajouterContrainteTagDel() {
595
		if (isset($this->parametres['masque.tag_del'])) {
596
		if (isset($this->parametres['masque.tag_del'])) {
596
			$nbTags = $this->getNombreDeTags();
597
			$nbTags = $this->getNombreDeTags();
597
			if($nbTags > 1) {
598
			if($nbTags > 1) {
598
				// sous-requêtes car le GROUP BY avec GROUP_CONCAT est *trop* lent
599
				// sous-requêtes car le GROUP BY avec GROUP_CONCAT est *trop* lent
599
				if (isset($this->parametres['masque.tag_del']['AND'])) {
600
				if (isset($this->parametres['masque.tag_del']['AND'])) {
600
					foreach ($this->parametres['masque.tag_del']['AND'] as $mc) {
601
					foreach ($this->parametres['masque.tag_del']['AND'] as $mc) {
601
						$sousRequete = 'SELECT ce_image '.
602
						$sousRequete = 'SELECT ce_image '.
602
							'FROM del_image_tag '.
603
							'FROM del_image_tag '.
603
							'WHERE actif = 1 '.
604
							'WHERE actif = 1 '.
604
							"AND tag_normalise LIKE '%$mc%' ";
605
							"AND tag_normalise LIKE '%$mc%' ";
605
						$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
606
						$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
606
					}
607
					}
607
				} else if (isset($this->parametres['masque.tag_del']['OR'])) {
608
				} else if (isset($this->parametres['masque.tag_del']['OR'])) {
608
					$tagsMotif = "'(" . implode('|', $this->parametres['masque.tag_del']['OR']) . ")'";
609
					$tagsMotif = "'(" . implode('|', $this->parametres['masque.tag_del']['OR']) . ")'";
609
					$sousRequete = 'SELECT ce_image '.
610
					$sousRequete = 'SELECT ce_image '.
610
						'FROM del_image_tag '.
611
						'FROM del_image_tag '.
611
						'WHERE actif = 1 '.
612
						'WHERE actif = 1 '.
612
						"AND tag_normalise REGEXP $tagsMotif ";
613
						"AND tag_normalise REGEXP $tagsMotif ";
613
					
614
					
614
					$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
615
					$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
615
				}
616
				}
616
			} else {
617
			} else {
617
				// Si un seul tag est demandé il se trouve dans le OR dans le cas de la recherche
618
				// Si un seul tag est demandé il se trouve dans le OR dans le cas de la recherche
618
				// spécifique et dans le AND dans le cas de la recherche générale
619
				// spécifique et dans le AND dans le cas de la recherche générale
619
				// WTF?
620
				// WTF?
620
				$tag = "";
621
				$tag = "";
621
				if(isset($this->parametres['masque.tag_del']['OR'][0])) {
622
				if(isset($this->parametres['masque.tag_del']['OR'][0])) {
622
					$tag = $this->parametres['masque.tag_del']['OR'][0];
623
					$tag = $this->parametres['masque.tag_del']['OR'][0];
623
				} else if(isset($this->parametres['masque.tag_del']['AND'][0])) {
624
				} else if(isset($this->parametres['masque.tag_del']['AND'][0])) {
624
					$tag = $this->parametres['masque.tag_del']['AND'][0];
625
					$tag = $this->parametres['masque.tag_del']['AND'][0];
625
				}
626
				}
626
				
627
				
627
				$sousRequete = 'SELECT ce_image '.
628
				$sousRequete = 'SELECT ce_image '.
628
						'FROM del_image_tag '.
629
						'FROM del_image_tag '.
629
						'WHERE actif = 1 '.
630
						'WHERE actif = 1 '.
630
						'AND tag_normalise LIKE '.$this->bdd->proteger($tag.'%');
631
						'AND tag_normalise LIKE '.$this->bdd->proteger($tag.'%');
631
 
632
 
632
				$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
633
				$this->addWhere('masque.tag_del', "di.id_image IN ($sousRequete)");
633
			}
634
			}
634
			
635
			
635
		}
636
		}
636
	}
637
	}
637
	
638
	
638
	private function getNombreDeTags() {
639
	private function getNombreDeTags() {
639
		$somme = 0;
640
		$somme = 0;
640
		if (isset($this->parametres['masque.tag_del']['AND'])) {
641
		if (isset($this->parametres['masque.tag_del']['AND'])) {
641
			$somme = count($this->parametres['masque.tag_del']['AND']);
642
			$somme = count($this->parametres['masque.tag_del']['AND']);
642
		} else {
643
		} else {
643
			$somme = count($this->parametres['masque.tag_del']['OR']);
644
			$somme = count($this->parametres['masque.tag_del']['OR']);
644
		}
645
		}
645
		return $somme;
646
		return $somme;
646
	}
647
	}
647
 
648
 
648
	/**
649
	/**
649
	 * Partie spécifique à PictoFlora:
650
	 * Partie spécifique à PictoFlora:
650
	 * Attention : si le critère de tri n'est pas suffisant, les résultats affichés peuvent varier à chaque appel
651
	 * Attention : si le critère de tri n'est pas suffisant, les résultats affichés peuvent varier à chaque appel
651
	 * de la même page de résultat de PictoFlora.
652
	 * de la même page de résultat de PictoFlora.
652
	 */
653
	 */
653
	public function definirOrdreSqlAppliImg() {
654
	public function definirOrdreSqlAppliImg() {
654
		$ordre = $this->parametres['ordre'];
655
		$ordre = $this->parametres['ordre'];
655
		
656
		
656
		$tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : '';
657
		$tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : '';
657
		switch ($tri) {
658
		switch ($tri) {
658
			case 'moyenne-arithmetique' :
659
			case 'moyenne-arithmetique' :
659
				$this->addOrderBy("dis.moyenne $ordre, dis.nb_votes $ordre, id_image $ordre");
660
				$this->addOrderBy("dis.moyenne $ordre, dis.nb_votes $ordre, id_image $ordre");
660
				break;
661
				break;
661
			case 'points' :
662
			case 'points' :
662
				$this->addOrderBy("dis.nb_points $ordre, dis.moyenne $ordre, dis.nb_votes $ordre, id_image $ordre");
663
				$this->addOrderBy("dis.nb_points $ordre, dis.moyenne $ordre, dis.nb_votes $ordre, id_image $ordre");
663
				break;
664
				break;
664
			case 'tags' :
665
			case 'tags' :
665
				$this->addOrderBy("dis.nb_tags $ordre, id_image $ordre");
666
				$this->addOrderBy("dis.nb_tags $ordre, id_image $ordre");
666
				break;
667
				break;
667
			case 'date_observation' :
668
			case 'date_observation' :
668
				$this->addOrderBy("date_observation $ordre, ce_observation $ordre");
669
				$this->addOrderBy("date_observation $ordre, ce_observation $ordre");
669
				break;
670
				break;
670
			case 'date_transmission' :
671
			case 'date_transmission' :
671
			default:
672
			default:
672
				$this->addOrderBy("di.date_transmission $ordre, ce_observation $ordre");
673
				$this->addOrderBy("di.date_transmission $ordre, ce_observation $ordre");
673
		}
674
		}
674
	}
675
	}
675
 
676
 
676
	public function definirOrdreSqlAppliObs() {
677
	public function definirOrdreSqlAppliObs() {
677
		$ordre = $this->parametres['ordre'];
678
		$ordre = $this->parametres['ordre'];
678
 
679
 
679
		// parmi self::$tri_possible
680
		// parmi self::$tri_possible
680
		$tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : '';
681
		$tri = isset($this->parametres['tri']) ? $this->parametres['tri'] : '';
681
			switch ($tri) {
682
			switch ($tri) {
682
			case 'date_observation' :
683
			case 'date_observation' :
683
				$this->addOrderBy("date_observation $ordre, id_observation $ordre");
684
				$this->addOrderBy("date_observation $ordre, id_observation $ordre");
684
				break;			
685
				break;			
685
			case 'nb_commentaires' :
686
			case 'nb_commentaires' :
686
				$sql_nb_comms = '(SELECT COUNT(id_commentaire) FROM del_commentaire AS dc WHERE ce_observation = id_observation)';
687
				$sql_nb_comms = '(SELECT COUNT(id_commentaire) FROM del_commentaire AS dc WHERE ce_observation = id_observation)';
687
				$this->addOrderBy("$sql_nb_comms $ordre, id_observation $ordre");
688
				$this->addOrderBy("$sql_nb_comms $ordre, id_observation $ordre");
688
				break;
689
				break;
689
			case 'date_transmission' :
690
			case 'date_transmission' :
690
			default:
691
			default:
691
				$this->addOrderBy("do.date_transmission $ordre, id_observation $ordre");
692
				$this->addOrderBy("do.date_transmission $ordre, id_observation $ordre");
692
		}
693
		}
693
	}
694
	}
694
 
695
 
695
	public function getAliasDesChamps($champsEtAlias, $select = null, $prefix = null) {
696
	public function getAliasDesChamps($champsEtAlias, $select = null, $prefix = null) {
696
		$arr = ($select) ? array_intersect_key($champsEtAlias, array_flip($select)) :  $champsEtAlias;
697
		$arr = ($select) ? array_intersect_key($champsEtAlias, array_flip($select)) :  $champsEtAlias;
697
		$keys = array_keys($arr);
698
		$keys = array_keys($arr);
698
 
699
 
699
		if ($prefix) {
700
		if ($prefix) {
700
		    array_walk($keys, function(&$val, $k, $prefix) { $val = sprintf("%s.`%s`", $prefix, $val);}, $prefix);
701
		    array_walk($keys, function(&$val, $k, $prefix) { $val = sprintf("%s.`%s`", $prefix, $val);}, $prefix);
701
		} else {
702
		} else {
702
		    array_walk($keys, function(&$val, $k) { $val = sprintf("`%s`", $val);});
703
		    array_walk($keys, function(&$val, $k) { $val = sprintf("`%s`", $val);});
703
		}
704
		}
704
 
705
 
705
		return implode(', ', array_map(function($v, $k) {return sprintf("%s AS `%s`", $k, $v);}, $arr, $keys));
706
		return implode(', ', array_map(function($v, $k) {return sprintf("%s AS `%s`", $k, $v);}, $arr, $keys));
706
	}
707
	}
707
 
708
 
708
	public function getVotesDesImages($idsImages, $protocole = null) {
709
	public function getVotesDesImages($idsImages, $protocole = null) {
709
		if (!$idsImages) return;
710
		if (!$idsImages) return;
710
 
711
 
711
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
712
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
712
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
713
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
713
 		$selectVotes = array('id_vote', 'ce_image', 'ce_protocole', 'ce_utilisateur', 'valeur', 'date');
714
 		$selectVotes = array('id_vote', 'ce_image', 'ce_protocole', 'ce_utilisateur', 'valeur', 'date');
714
		$selectProtocole = array('id_protocole', 'intitule', 'descriptif', 'tag');
715
		$selectProtocole = array('id_protocole', 'intitule', 'descriptif', 'tag');
715
		$voteChamps = $this->getAliasDesChamps($mappingVotes, $selectVotes, 'v'); // "v": cf alias dans la requête
716
		$voteChamps = $this->getAliasDesChamps($mappingVotes, $selectVotes, 'v'); // "v": cf alias dans la requête
716
		$protoChamps = $this->getAliasDesChamps($mappingProtocoles, $selectProtocole, 'p');
717
		$protoChamps = $this->getAliasDesChamps($mappingProtocoles, $selectProtocole, 'p');
717
		$idImgsConcat = implode(',', $idsImages);
718
		$idImgsConcat = implode(',', $idsImages);
718
 
719
 
719
		$requete = "SELECT $voteChamps, $protoChamps ".
720
		$requete = "SELECT $voteChamps, $protoChamps ".
720
			'FROM del_image_vote AS v '.
721
			'FROM del_image_vote AS v '.
721
			'	INNER JOIN del_image_protocole AS p ON (v.ce_protocole = p.id_protocole) '.
722
			'	INNER JOIN del_image_protocole AS p ON (v.ce_protocole = p.id_protocole) '.
722
			"WHERE v.ce_image IN ($idImgsConcat) ".
723
			"WHERE v.ce_image IN ($idImgsConcat) ".
723
			($protocole ? "	AND v.ce_protocole = $protocole " : '').
724
			($protocole ? "	AND v.ce_protocole = $protocole " : '').
724
			"ORDER BY FIELD(v.ce_image, $idImgsConcat) ".
725
			"ORDER BY FIELD(v.ce_image, $idImgsConcat) ".
725
			'-- '.__FILE__.':'.__LINE__;
726
			'-- '.__FILE__.':'.__LINE__;
726
		return $this->bdd->recupererTous($requete);
727
		return $this->bdd->recupererTous($requete);
727
	}
728
	}
728
 
729
 
729
	/**
730
	/**
730
	 * Ajoute les informations sur le protocole et les votes aux images.
731
	 * Ajoute les informations sur le protocole et les votes aux images.
731
	 *
732
	 *
732
	 * ATTENTION : Subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien
733
	 * ATTENTION : Subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien
733
	 * plus pratique pour associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
734
	 * plus pratique pour associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
734
	 * Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
735
	 * Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
735
	 * cf ListeImages::reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions
736
	 * cf ListeImages::reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions
736
	 * simultanément lorsque c'est encore possible.
737
	 * simultanément lorsque c'est encore possible.
737
	 */
738
	 */
738
	// TODO : supprimer cette "subtilité" source d'erreurs
739
	// TODO : supprimer cette "subtilité" source d'erreurs
739
	public function ajouterInfosVotesProtocoles($votes, &$images) {
740
	public function ajouterInfosVotesProtocoles($votes, &$images) {
740
		if (!$votes) return;
741
		if (!$votes) return;
741
 
742
 
742
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
743
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
743
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
744
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
744
 
745
 
745
		// pour chaque vote
746
		// pour chaque vote
746
		foreach ($votes as $vote) {
747
		foreach ($votes as $vote) {
747
			$imgId = $vote['image.id'];
748
			$imgId = $vote['image.id'];
748
			$protoId = $vote['protocole.id'];
749
			$protoId = $vote['protocole.id'];
749
 
750
 
750
			if (!array_key_exists('protocoles_votes', $images[$imgId]) ||
751
			if (!array_key_exists('protocoles_votes', $images[$imgId]) ||
751
					!array_key_exists($protoId, $images[$imgId]['protocoles_votes'])) {
752
					!array_key_exists($protoId, $images[$imgId]['protocoles_votes'])) {
752
				// extrait les champs spécifique au protocole (le LEFT JOIN de chargerVotesImage les ramène en doublons
753
				// extrait les champs spécifique au protocole (le LEFT JOIN de chargerVotesImage les ramène en doublons
753
				$protocole = array_intersect_key($vote, array_flip($mappingProtocoles));
754
				$protocole = array_intersect_key($vote, array_flip($mappingProtocoles));
754
				$images[$imgId]['protocoles_votes'][$protoId] = $protocole;
755
				$images[$imgId]['protocoles_votes'][$protoId] = $protocole;
755
			}
756
			}
756
 
757
 
757
			$chpsVotes = array('id_vote', 'ce_image', 'ce_utilisateur', 'valeur', 'date');
758
			$chpsVotes = array('id_vote', 'ce_image', 'ce_utilisateur', 'valeur', 'date');
758
			$voteSelection = array_intersect_key($mappingVotes, array_flip($chpsVotes));
759
			$voteSelection = array_intersect_key($mappingVotes, array_flip($chpsVotes));
759
			$vote = array_intersect_key($vote, array_flip($voteSelection));
760
			$vote = array_intersect_key($vote, array_flip($voteSelection));
760
			$images[$imgId]['protocoles_votes'][$protoId]['votes'][$vote['vote.id']] = $vote;
761
			$images[$imgId]['protocoles_votes'][$protoId]['votes'][$vote['vote.id']] = $vote;
761
		}
762
		}
762
	}
763
	}
763
 
764
 
764
	public function getTotalLignesTrouvees() {
765
	public function getTotalLignesTrouvees() {
765
		$resultat = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre -- '.__FILE__.':'.__LINE__);
766
		$resultat = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre -- '.__FILE__.':'.__LINE__);
766
		return intval($resultat['nbre']);
767
		return intval($resultat['nbre']);
767
	}
768
	}
768
	
769
	
769
	public function getRequeteIdObsMonactiviteTout($id_utilisateur, $limite = "") {
770
	public function getRequeteIdObsMonactiviteTout($id_utilisateur, $limite = "") {
770
		/*	
771
		/*	
771
		Une action c'est :
772
		Une action c'est :
772
		- Quelqu'un commente mon observation
773
		- Quelqu'un commente mon observation
773
		- Quelqu'un fait une proposition sur mon observation
774
		- Quelqu'un fait une proposition sur mon observation
774
	
775
	
775
		- Quelqu'un vote pour ma proposition
776
		- Quelqu'un vote pour ma proposition
776
		- Quelqu'un commente ma proposition ou mon commentaire
777
		- Quelqu'un commente ma proposition ou mon commentaire
777
	
778
	
778
		- Quelqu'un vote pour une proposition sur mon observation
779
		- Quelqu'un vote pour une proposition sur mon observation
779
		- Quelqu'un commente une proposition ou un commentaire sur mon observation
780
		- Quelqu'un commente une proposition ou un commentaire sur mon observation
780
		*/
781
		*/
781
		
782
		
782
		// on selectionne aussi la combinaison des champs de date afin que la liste soit triée correctement
783
		// on selectionne aussi la combinaison des champs de date afin que la liste soit triée correctement
783
		// pas d'autre meilleure solution mais attention ce comportement dépend entièrement de mysql
784
		// pas d'autre meilleure solution mais attention ce comportement dépend entièrement de mysql
784
		$requete = "SELECT SQL_CALC_FOUND_ROWS DISTINCT id_observation, ".$this->getCombinaisonChampsDateMax()." as date_max FROM del_observation do ".
785
		$requete = "SELECT SQL_CALC_FOUND_ROWS DISTINCT id_observation, ".$this->getCombinaisonChampsDateMax()." as date_max FROM del_observation do ".
785
				$this->getJointureMonActivite($id_utilisateur).
786
				$this->getJointureMonActivite($id_utilisateur).
786
				$this->getConditionMonActivite($id_utilisateur).
787
				$this->getConditionMonActivite($id_utilisateur).
787
				"ORDER BY date_max DESC ".
788
				"ORDER BY date_max DESC ".
788
				$limite;
789
				$limite;
789
 
790
 
790
		return $requete;
791
		return $requete;
791
	}
792
	}
792
	
793
	
793
	public function getRequeteNbEvenementsDepuisDate($id_utilisateur, $date) {
794
	public function getRequeteNbEvenementsDepuisDate($id_utilisateur, $date) {
794
		$requete = "SELECT COUNT(DISTINCT id_observation) as nb_evenements FROM del_observation do ".
795
		$requete = "SELECT COUNT(DISTINCT id_observation) as nb_evenements FROM del_observation do ".
795
				$this->getJointureMonActivite($id_utilisateur).
796
				$this->getJointureMonActivite($id_utilisateur).
796
				$this->getConditionMonActivite($id_utilisateur).
797
				$this->getConditionMonActivite($id_utilisateur).
797
				"AND ".$this->getCombinaisonChampsDateMax()." > '".$date."' ". 
798
				"AND ".$this->getCombinaisonChampsDateMax()." > '".$date."' ". 
798
				"ORDER BY ".$this->getCombinaisonChampsDateMax()." DESC ";
799
				"ORDER BY ".$this->getCombinaisonChampsDateMax()." DESC ";
799
 
800
 
800
		return $requete;
801
		return $requete;
801
	}
802
	}
802
	
803
	
803
	public function getEvenementsObs($idsObsConcat, $id_utilisateur) {
804
	public function getEvenementsObs($idsObsConcat, $id_utilisateur) {
804
		$sous_champ_date_max = $this->getCombinaisonChampsDateMax()." as date_max";
805
		$sous_champ_date_max = $this->getCombinaisonChampsDateMax()." as date_max";
805
		$sous_champ_date = "dc.date as date_com, dc.nom_sel as nom_sel_com, dcpr.ce_commentaire_parent as parent_com, dcv.date as date_vote, ".
806
		$sous_champ_date = "dc.date as date_com, dc.nom_sel as nom_sel_com, dcpr.ce_commentaire_parent as parent_com, dcv.date as date_vote, ".
806
							"do.date_observation as date_obs, dcp.date_validation as date_validation, dcpr.date as date_com_reponse, ".
807
							"do.date_observation as date_obs, dcp.date_validation as date_validation, dcpr.date as date_com_reponse, ".
807
							"dcvp.nom_sel as nom_sel_com_parent";
808
							"dcvp.nom_sel as nom_sel_com_parent";
808
		$sous_champs_utilisateurs = "dc.ce_utilisateur as utilisateur_commentaire, dcp.ce_utilisateur as utilisateur_commentaire_valide, ".
809
		$sous_champs_utilisateurs = "dc.ce_utilisateur as utilisateur_commentaire, dcp.ce_utilisateur as utilisateur_commentaire_valide, ".
809
									"dcv.ce_utilisateur as utilisateur_vote_commentaire, do.ce_utilisateur as utilisateur_observation, ".
810
									"dcv.ce_utilisateur as utilisateur_vote_commentaire, do.ce_utilisateur as utilisateur_observation, ".
810
									"dcp.ce_validateur as utilisateur_validation, dcvp.ce_utilisateur as utilisateur_commentaire_vote, ".
811
									"dcp.ce_validateur as utilisateur_validation, dcvp.ce_utilisateur as utilisateur_commentaire_vote, ".
811
									"dcpr.ce_utilisateur as utilisateur_commentaire_reponse";
812
									"dcpr.ce_utilisateur as utilisateur_commentaire_reponse";
812
 
813
 
813
		$sous_champs_infos = "dc.nom_sel as proposition_commentaire_nom_sel, dc.texte as proposition_commentaire_texte, dcp.nom_sel as proposition_validee_nom_sel, ".
814
		$sous_champs_infos = "dc.nom_sel as proposition_commentaire_nom_sel, dc.texte as proposition_commentaire_texte, dcp.nom_sel as proposition_validee_nom_sel, ".
814
							 "dcvp.nom_sel as proposition_commentaire_nom_sel_votee, dcpr.texte as proposition_commentaire_texte_commente";
815
							 "dcvp.nom_sel as proposition_commentaire_nom_sel_votee, dcpr.texte as proposition_commentaire_texte_commente";
815
			
816
			
816
		$requete = "SELECT DISTINCT id_observation, ".$sous_champs_utilisateurs.", ".$sous_champ_date_max.", ".$sous_champ_date.", ".$sous_champs_infos." ".
817
		$requete = "SELECT DISTINCT id_observation, ".$sous_champs_utilisateurs.", ".$sous_champ_date_max.", ".$sous_champ_date.", ".$sous_champs_infos." ".
817
				"FROM del_observation do ".
818
				"FROM del_observation do ".
818
				$this->getJointureMonActivite($id_utilisateur).
819
				$this->getJointureMonActivite($id_utilisateur).
819
				$this->getConditionMonActivite($id_utilisateur).
820
				$this->getConditionMonActivite($id_utilisateur).
820
				"AND id_observation IN ($idsObsConcat) ORDER BY date_max DESC";
821
				"AND id_observation IN ($idsObsConcat) ORDER BY date_max DESC";
821
 
822
 
822
		$evenements = $this->bdd->recupererTous($requete);
823
		$evenements = $this->bdd->recupererTous($requete);
823
		return $evenements;
824
		return $evenements;
824
	}
825
	}
825
	
826
	
826
	public function getJointureMonActivite($id_utilisateur) {
827
	public function getJointureMonActivite($id_utilisateur) {
827
		return 	// quelqu'un commente mon observation ou fait une proposition
828
		return 	// quelqu'un commente mon observation ou fait une proposition
828
		"LEFT JOIN del_commentaire dc ON do.id_observation = dc.ce_observation ".
829
		"LEFT JOIN del_commentaire dc ON do.id_observation = dc.ce_observation ".
829
		"	AND do.ce_utilisateur = ".$id_utilisateur." ".
830
		"	AND do.ce_utilisateur = ".$id_utilisateur." ".
830
		"	AND dc.ce_utilisateur != ".$id_utilisateur." ".
831
		"	AND dc.ce_utilisateur != ".$id_utilisateur." ".
831
		// quelqu'un valide ma proposition (et ce n'est pas moi qui l'ai validée)
832
		// quelqu'un valide ma proposition (et ce n'est pas moi qui l'ai validée)
832
		"LEFT JOIN del_commentaire dcp ON do.id_observation = dcp.ce_observation ".
833
		"LEFT JOIN del_commentaire dcp ON do.id_observation = dcp.ce_observation ".
833
		"	AND dcp.nom_sel IS NOT NULL AND dcp.ce_validateur != ".$id_utilisateur." ".
834
		"	AND dcp.nom_sel IS NOT NULL AND dcp.ce_validateur != ".$id_utilisateur." ".
834
		"	AND dcp.ce_validateur != 0 ".
835
		"	AND dcp.ce_validateur != 0 ".
835
		"	AND dcp.date_validation IS NOT NULL ".
836
		"	AND dcp.date_validation IS NOT NULL ".
836
		"	AND dcp.ce_utilisateur = ".$id_utilisateur." ".
837
		"	AND dcp.ce_utilisateur = ".$id_utilisateur." ".
837
		// quelqu'un vote pour ma proposition ou sur une proposition sur une de mes observations
838
		// quelqu'un vote pour ma proposition ou sur une proposition sur une de mes observations
838
		"LEFT JOIN del_commentaire dcvp ON do.id_observation = dcvp.ce_observation ".
839
		"LEFT JOIN del_commentaire dcvp ON do.id_observation = dcvp.ce_observation ".
839
		"LEFT JOIN del_commentaire_vote dcv ON dcv.ce_proposition = dcvp.id_commentaire ".
840
		"LEFT JOIN del_commentaire_vote dcv ON dcv.ce_proposition = dcvp.id_commentaire ".
840
		"AND (dcvp.ce_utilisateur = $id_utilisateur OR do.ce_utilisateur = $id_utilisateur) ".
841
		"AND (dcvp.ce_utilisateur = $id_utilisateur OR do.ce_utilisateur = $id_utilisateur) ".
841
		"AND dcv.ce_utilisateur != $id_utilisateur ".
842
		"AND dcv.ce_utilisateur != $id_utilisateur ".
842
		"AND dcv.ce_utilisateur != dcvp.ce_utilisateur ".
843
		"AND dcv.ce_utilisateur != dcvp.ce_utilisateur ".
843
		// Quelqu'un répond à l'un de mes commentaires ou commente une de mes propositions
844
		// Quelqu'un répond à l'un de mes commentaires ou commente une de mes propositions
844
		"LEFT JOIN del_commentaire dcpr ON do.id_observation = dcpr.ce_observation ".
845
		"LEFT JOIN del_commentaire dcpr ON do.id_observation = dcpr.ce_observation ".
845
		"AND dcpr.ce_commentaire_parent = dcvp.id_commentaire AND dcvp.ce_utilisateur = $id_utilisateur ";
846
		"AND dcpr.ce_commentaire_parent = dcvp.id_commentaire AND dcvp.ce_utilisateur = $id_utilisateur ";
846
	}
847
	}
847
	
848
	
848
	public function getConditionMonActivite($id_utilisateur, $type = "autres") {
849
	public function getConditionMonActivite($id_utilisateur, $type = "autres") {
849
		//TODO: gérer les cas suivants :
850
		//TODO: gérer les cas suivants :
850
		// demander les activités des autres sur mes obs ou propositions (c'est dejà le cas)
851
		// demander les activités des autres sur mes obs ou propositions (c'est dejà le cas)
851
		// demander mes activités
852
		// demander mes activités
852
		// demander toutes les activités (combinaisons des deux cas ci dessus)
853
		// demander toutes les activités (combinaisons des deux cas ci dessus)
853
		return 	// Vérification que l'évènement me concerne (de près ou ou de loin)
854
		return 	// Vérification que l'évènement me concerne (de près ou ou de loin)
854
		"WHERE (do.ce_utilisateur = $id_utilisateur OR dc.ce_utilisateur = $id_utilisateur ".
855
		"WHERE (do.ce_utilisateur = $id_utilisateur OR dc.ce_utilisateur = $id_utilisateur ".
855
		"OR dcp.ce_utilisateur = $id_utilisateur OR dcv.ce_utilisateur = $id_utilisateur ".
856
		"OR dcp.ce_utilisateur = $id_utilisateur OR dcv.ce_utilisateur = $id_utilisateur ".
856
		"OR dcvp.ce_utilisateur = $id_utilisateur) AND ".
857
		"OR dcvp.ce_utilisateur = $id_utilisateur) AND ".
857
		// mais qu'il y a au moins eu une action de la part d'une autre personne
858
		// mais qu'il y a au moins eu une action de la part d'une autre personne
858
		"(dc.ce_utilisateur IS NOT NULL OR dcp.ce_utilisateur IS NOT NULL OR dcv.ce_utilisateur IS NOT NULL) ";
859
		"(dc.ce_utilisateur IS NOT NULL OR dcp.ce_utilisateur IS NOT NULL OR dcv.ce_utilisateur IS NOT NULL) ";
859
	}
860
	}
860
	
861
	
861
	private function getCombinaisonChampsDateMax() {
862
	private function getCombinaisonChampsDateMax() {
862
		return "GREATEST(IFNULL(dc.date,0), IFNULL(dcv.date,0), IFNULL(do.date_observation,0), IFNULL(dcp.date_validation,0), IFNULL(dcpr.date,0))";
863
		return "GREATEST(IFNULL(dc.date,0), IFNULL(dcv.date,0), IFNULL(do.date_observation,0), IFNULL(dcp.date_validation,0), IFNULL(dcpr.date,0))";
863
	}
864
	}
864
}
865
}