Subversion Repositories eFlore/Applications.del

Rev

Rev 1863 | Rev 1873 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1863 Rev 1871
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
 *
5
 *
6
 * @category  DEL
6
 * @category  DEL
7
 * @package   Services
7
 * @package   Services
8
 * @package   Bibliotheque
8
 * @package   Bibliotheque
9
 * @version   0.1
9
 * @version   0.1
10
 * @author    Mathias CHOUET <mathias@tela-botanica.org>
10
 * @author    Mathias CHOUET <mathias@tela-botanica.org>
11
 * @author    Jean-Pascal MILCENT <jpm@tela-botanica.org>
11
 * @author    Jean-Pascal MILCENT <jpm@tela-botanica.org>
12
 * @author    Aurelien PERONNET <aurelien@tela-botanica.org>
12
 * @author    Aurelien PERONNET <aurelien@tela-botanica.org>
13
 * @license   GPL v3 <http://www.gnu.org/licenses/gpl.txt>
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>
14
 * @license   CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
15
 * @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
15
 * @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
16
 */
16
 */
17
class Sql {
17
class Sql {
-
 
18
 
-
 
19
	const APPLI_IMG = 'IMG';
-
 
20
	const APPLI_OBS = 'OBS';
18
 
21
 
19
	private $conteneur;
22
	private $conteneur;
20
	private $bdd;
23
	private $bdd;
21
	private $parametres = array();
24
	private $parametres = array();
-
 
25
	private $appli;
22
	private $requete = array(
26
	private $requete = array(
23
		'select' => array(),
27
		'select' => array(),
24
		'join' => array(),
28
		'join' => array(),
25
		'where' => array(),
29
		'where' => array(),
26
		'groupby' => array(),
30
		'groupby' => array(),
27
		'orderby' => array());
31
		'orderby' => array());
28
 
32
 
29
	private $champsPrenom = array('du.prenom', 'vdi.prenom_utilisateur');
33
	private $champsPrenom = array('du.prenom', 'prenom_utilisateur');
30
	private $champsNom = array('du.nom',  'vdi.nom_utilisateur');
34
	private $champsNom = array('du.nom',  'nom_utilisateur');
31
 
35
 
32
 
36
 
33
	public function __construct(Conteneur $conteneur) {
37
	public function __construct(Conteneur $conteneur) {
34
		$this->conteneur = $conteneur;
38
		$this->conteneur = $conteneur;
35
		$this->bdd = $this->conteneur->getBdd();
39
		$this->bdd = $this->conteneur->getBdd();
36
	}
40
	}
37
 
41
 
38
	public function setParametres(Array $parametres) {
42
	public function setParametres(Array $parametres) {
39
		$this->parametres = $parametres;
43
		$this->parametres = $parametres;
40
	}
44
	}
-
 
45
 
-
 
46
	public function setAppli($appliType) {
-
 
47
		if ($appliType == 'IMG' || $appliType == 'OBS') {
-
 
48
			$this->appli = $appliType;
-
 
49
		} else {
-
 
50
			throw new Exception("Les types d'appli disponible sont : IMG (pour PictoFlora) et OBS (pour IdentiPlante)");
-
 
51
		}
-
 
52
	}
-
 
53
 
-
 
54
	private function getPrefixe() {
-
 
55
		return $this->appli === 'IMG' ? 'di' : 'do';
-
 
56
	}
-
 
57
 
-
 
58
	private function etreAppliImg() {
-
 
59
		return $this->appli === 'IMG' ? true : false;
-
 
60
	}
-
 
61
 
-
 
62
	private function etreAppliObs() {
-
 
63
		return $this->appli === 'OBS' ? true : false;
-
 
64
	}
41
 
65
 
42
	public function getRequeteSql() {
66
	public function getRequeteSql() {
43
		return $this->requete;
67
		return $this->requete;
44
	}
68
	}
45
 
69
 
46
	private function addJoin($join) {
70
	private function addJoin($join) {
-
 
71
		if (!isset($this->requete['join'][$join])) {
47
		$this->requete['join'][] = $join;
72
			$this->requete['join'][] = $join;
-
 
73
		}
48
	}
74
	}
49
 
75
 
50
	public function getJoin() {
76
	public function getJoin() {
51
		return ($this->requete['join'] ? implode(' ', array_unique($this->requete['join'])).' ' : '');
77
		return ($this->requete['join'] ? implode(' ', array_unique($this->requete['join'])).' ' : '');
52
	}
78
	}
53
 
79
 
54
	private function addJoinDis($join) {
80
	private function addJoinDis($join) {
55
		$this->requete['join']['dis'] = $join;
81
		$this->requete['join']['dis'] = $join;
56
	}
82
	}
57
 
83
 
58
	private function addWhere($idParam, $where) {
84
	private function addWhere($idParam, $where) {
59
		if (isset($this->parametres['_parametres_condition_or_'])
85
		if (isset($this->parametres['_parametres_condition_or_'])
60
				&& in_array($idParam, $this->parametres['_parametres_condition_or_'])) {
86
				&& in_array($idParam, $this->parametres['_parametres_condition_or_'])) {
61
			$this->requete['where']['OR'][] = $where;
87
			$this->requete['where']['OR'][] = $where;
62
		} else {
88
		} else {
63
			$this->requete['where']['AND'][] = $where;
89
			$this->requete['where']['AND'][] = $where;
64
		}
90
		}
65
	}
91
	}
66
	public function getWhere() {
92
	public function getWhere() {
67
		if (isset($this->requete['where']['OR']) && count($this->requete['where']['OR']) > 0) {
93
		if (isset($this->requete['where']['OR']) && count($this->requete['where']['OR']) > 0) {
68
			$this->requete['where']['AND'][] = '('.implode(' OR ', $this->requete['where']['OR']).')';
94
			$this->requete['where']['AND'][] = '('.implode(' OR ', $this->requete['where']['OR']).')';
69
		}
95
		}
70
 
96
 
71
		$where = ' TRUE ';
97
		$where = ' TRUE ';
72
		if (isset($this->requete['where']['AND']) && count($this->requete['where']['AND']) > 0) {
98
		if (isset($this->requete['where']['AND']) && count($this->requete['where']['AND']) > 0) {
73
			$where = implode(' AND ', $this->requete['where']['AND']).' ';
99
			$where = implode(' AND ', $this->requete['where']['AND']).' ';
74
		}
100
		}
75
		return $where;
101
		return $where;
76
	}
102
	}
77
 
103
 
78
	private function addGroupBy($groupBy) {
104
	private function addGroupBy($groupBy) {
79
		$this->requete['groupby'][] = $groupBy;
105
		$this->requete['groupby'][] = $groupBy;
80
	}
106
	}
81
 
107
 
82
	public function getGroupBy() {
108
	public function getGroupBy() {
83
		$groupby = '';
109
		$groupby = '';
84
		if (isset($this->requete['groupby']) && count($this->requete['groupby']) > 0) {
110
		if (isset($this->requete['groupby']) && count($this->requete['groupby']) > 0) {
85
			$groupby = 'GROUP BY '.implode(', ', array_unique($this->requete['groupby'])).' ';
111
			$groupby = 'GROUP BY '.implode(', ', array_unique($this->requete['groupby'])).' ';
86
		}
112
		}
87
		return $groupby;
113
		return $groupby;
88
	}
114
	}
89
 
115
 
90
	private function addOrderBy($orderby) {
116
	private function addOrderBy($orderby) {
91
		$this->requete['orderby'][] = $orderby;
117
		$this->requete['orderby'][] = $orderby;
92
	}
118
	}
93
 
119
 
94
	public function getOrderBy() {
120
	public function getOrderBy() {
95
		$orderby = '';
121
		$orderby = '';
96
		if (isset($this->requete['orderby']) && count($this->requete['orderby']) > 0) {
122
		if (isset($this->requete['orderby']) && count($this->requete['orderby']) > 0) {
97
			$orderby = 'ORDER BY '.implode(', ', array_unique($this->requete['orderby'])).' ';
123
			$orderby = 'ORDER BY '.implode(', ', array_unique($this->requete['orderby'])).' ';
98
		}
124
		}
99
		return $orderby;
125
		return $orderby;
100
	}
126
	}
101
 
127
 
102
	public function getLimit() {
128
	public function getLimit() {
103
		return 'LIMIT '.$this->parametres['navigation.depart'].','.$this->parametres['navigation.limite'].' ';
129
		return 'LIMIT '.$this->parametres['navigation.depart'].','.$this->parametres['navigation.limite'].' ';
104
	}
130
	}
105
 
131
 
106
	/**
132
	/**
107
	 * - Rempli le tableau des contraintes "where" et "join" nécessaire
133
	 * - Rempli le tableau des contraintes "where" et "join" nécessaire
108
	 * à la *recherche* des observations demandées ($req) utilisées par self::getIdObs()
134
	 * à la *recherche* des observations demandées ($req) utilisées par self::getIdObs()
109
	 *
135
	 *
110
	 * Attention, cela signifie que toutes les tables ne sont pas *forcément*
136
	 * Attention, cela signifie que toutes les tables ne sont pas *forcément*
111
	 * join'ées, par exemple si aucune contrainte ne le nécessite.
137
	 * join'ées, par exemple si aucune contrainte ne le nécessite.
112
	 * $req tel qu'il est rempli ici est utile pour récupéré la seule liste des
138
	 * $req tel qu'il est rempli ici est utile pour récupéré la seule liste des
113
	 * id d'observation qui match.
139
	 * id d'observation qui match.
114
	 * Pour la récupération effective de "toutes" les données correspondante, il faut
140
	 * Pour la récupération effective de "toutes" les données correspondante, il faut
115
	 * réinitialiser $req["join"] afin d'y ajouter toutes les autres tables.
141
	 * réinitialiser $req["join"] afin d'y ajouter toutes les autres tables.
116
	 *
142
	 *
117
	 * Note: toujours rajouter les préfixes de table (vdi,du,doi ou di), en fonction de ce que défini
143
	 * Note: toujours rajouter les préfixes de table (vdi,du,doi ou di), en fonction de ce que défini
118
	 * les JOIN qui sont utilisés.
144
	 * les JOIN qui sont utilisés.
119
	 * le préfix de v_del_image est "vdi" (cf: "FROM" de self::getIdObs())
145
	 * le préfix de v_del_image est "vdi" (cf: "FROM" de self::getIdObs())
120
	 * le préfix de del_utilisateur sur id_utilisateur = vdi.ce_utilisateur est "du"
146
	 * le préfix de del_utilisateur sur id_utilisateur = vdi.ce_utilisateur est "du"
121
	 *
147
	 *
122
	 * @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
148
	 * @param $p les paramètres (notamment de masque) passés par l'URL et déjà traités/filtrés (sauf quotes)
123
	 * @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
149
	 * @param $req le tableau, passé par référence représentant les composants de la requête à bâtir
124
	 */
150
	 */
125
	public function ajouterContraintes() {
151
	public function ajouterContraintes() {
126
		$this->ajouterContrainteAuteur();
152
		$this->ajouterContrainteAuteur();
127
		$this->ajouterContrainteDate();
153
		$this->ajouterContrainteDate();
128
		$this->ajouterContrainteDepartement();
154
		$this->ajouterContrainteDepartement();
129
		$this->ajouterContrainteIdZoneGeo();
155
		$this->ajouterContrainteIdZoneGeo();
130
		$this->ajouterContrainteGenre();
156
		$this->ajouterContrainteGenre();
131
		$this->ajouterContrainteFamille();
157
		$this->ajouterContrainteFamille();
132
		$this->ajouterContrainteNs();
158
		$this->ajouterContrainteNs();
133
		$this->ajouterContrainteNn();
159
		$this->ajouterContrainteNn();
134
		$this->ajouterContrainteReferentiel();
160
		$this->ajouterContrainteReferentiel();
135
		$this->ajouterContrainteCommune();
161
		$this->ajouterContrainteCommune();
136
	}
162
	}
137
 
163
 
138
	private function ajouterContrainteAuteur() {
164
	private function ajouterContrainteAuteur() {
139
		if (isset($this->parametres['masque.auteur'])) {
165
		if (isset($this->parametres['masque.auteur'])) {
140
			$auteur = $this->parametres['masque.auteur'];
166
			$auteur = $this->parametres['masque.auteur'];
141
			// id du poster de l'obs
167
			// id du poster de l'obs
142
			$this->addJoin('LEFT JOIN del_utilisateur AS du ON (du.id_utilisateur = vdi.ce_utilisateur) ');
-
 
143
			// id du poster de l'image... NON, c'est le même que le posteur de l'obs
168
			$prefixe = $this->getPrefixe();
144
			// Cette jointure de table est ignoré ci-dessous pour les recherches d'auteurs
-
 
145
			// $req['join'][] = 'LEFT JOIN del_utilisateur AS dui ON dui.id_utilisateur = vdi.i_ce_utilisateur';
169
			$this->addJoin("LEFT JOIN del_utilisateur AS du ON (du.id_utilisateur = $prefixe.ce_utilisateur) ");
146
 
170
 
147
			if (is_numeric($auteur)) {
171
			if (is_numeric($auteur)) {
148
				$this->ajouterContrainteAuteurId();
172
				$this->ajouterContrainteAuteurId();
149
			} elseif(preg_match('/^.{5,}@[a-z0-9-.]{5,}$/i', $auteur)) {
173
			} elseif(preg_match('/@[a-z0-9-]+(?:\.[a-z0-9-]+)*\.[a-z]{2,}$/i', $auteur)) {
150
				$this->ajouterContrainteAuteurEmail();
174
				$this->ajouterContrainteAuteurEmail();
151
			} else {
175
			} else {
152
				$this->ajouterContrainteAuteurIntitule();
176
				$this->ajouterContrainteAuteurIntitule();
153
			}
177
			}
154
		}
178
		}
155
	}
179
	}
156
 
180
 
157
	private function ajouterContrainteAuteurId() {
181
	private function ajouterContrainteAuteurId() {
158
		$id = $this->parametres['masque.auteur'];
182
		$id = $this->parametres['masque.auteur'];
-
 
183
		$prefixe = $this->getPrefixe();
159
		$sqlTpl = '(du.id_utilisateur = %1$d OR vdi.ce_utilisateur = %1$d)';
184
		$sqlTpl = "(du.id_utilisateur = %1\$d OR $prefixe.ce_utilisateur = %1\$d)";
160
		$whereAuteur = sprintf($sqlTpl, $id);
185
		$whereAuteur = sprintf($sqlTpl, $id);
161
		$this->addWhere('masque.auteur', $whereAuteur);
186
		$this->addWhere('masque.auteur', $whereAuteur);
162
	}
187
	}
163
 
188
 
164
	private function ajouterContrainteAuteurEmail() {
189
	private function ajouterContrainteAuteurEmail() {
165
		$email = $this->parametres['masque.auteur'];
190
		$email = $this->parametres['masque.auteur'];
-
 
191
		$prefixe = $this->getPrefixe();
166
		$sqlTpl = '(du.courriel LIKE %1$s OR vdi.courriel LIKE %1$s )';
192
		$sqlTpl = "(du.courriel LIKE %1\$s OR $prefixe.courriel_utilisateur LIKE %1\$s )";
167
		$emailP = $this->bdd->proteger("$email%");
193
		$emailP = $this->bdd->proteger("$email%");
168
		$whereAuteur = sprintf($sqlTpl, $emailP);
194
		$whereAuteur = sprintf($sqlTpl, $emailP);
169
		$this->addWhere('masque.auteur', $whereAuteur);
195
		$this->addWhere('masque.auteur', $whereAuteur);
170
	}
196
	}
171
 
197
 
172
	/**
198
	/**
173
	 * Retourne une clause where du style:
199
	 * Retourne une clause where du style:
174
	 * CONCAT(IF(du.prenom IS NULL, "", du.prenom), [...] vdi.i_nomutilisateur) REGEXP 'xxx'
200
	 * CONCAT(IF(du.prenom IS NULL, "", du.prenom), [...] vdi.i_nomutilisateur) REGEXP 'xxx'
175
	 * Note; i_(nom|prenom_utilisateur), alias pour cel_images.(nom|prenom), n'est pas traité
201
	 * Note; i_(nom|prenom_utilisateur), alias pour cel_images.(nom|prenom), n'est pas traité
176
	 * car cette information est redondante dans cel_image et devrait être supprimée.
202
	 * car cette information est redondante dans cel_image et devrait être supprimée.
177
	 */
203
	 */
178
	private function ajouterContrainteAuteurIntitule() {
204
	private function ajouterContrainteAuteurIntitule() {
179
		$auteurExplode = explode(' ', $this->parametres['masque.auteur']);
205
		$auteurExplode = explode(' ', $this->parametres['masque.auteur']);
180
		$nbreMots = count($auteurExplode);
206
		$nbreMots = count($auteurExplode);
181
 
207
 
182
		if ($nbreMots == 1) {
208
		if ($nbreMots == 1) {
183
			$this->ajouterContrainteAuteurPrenomOuNom();
209
			$this->ajouterContrainteAuteurPrenomOuNom();
184
		} else if ($nbreMots == 2) {
210
		} else if ($nbreMots == 2) {
185
			$this->ajouterContrainteAuteurPrenomEtNom();
211
			$this->ajouterContrainteAuteurPrenomEtNom();
186
		}
212
		}
187
	}
213
	}
188
 
214
 
189
	private function ajouterContrainteAuteurPrenomOuNom() {
215
	private function ajouterContrainteAuteurPrenomOuNom() {
190
		$prenomOuNom = $this->parametres['masque.auteur'];
216
		$prenomOuNom = $this->parametres['masque.auteur'];
191
 
217
 
192
		$sqlTpl = 'CONCAT(%s,%s) LIKE %s';
218
		$sqlTpl = 'CONCAT(%s,%s) LIKE %s';
-
 
219
		$prefixe = $this->getPrefixe();
193
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom);
220
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
194
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom);
221
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
195
		$auteurMotif = $this->bdd->proteger("%$prenomOuNom%");
222
		$auteurMotif = $this->bdd->proteger("%$prenomOuNom%");
196
 
223
 
197
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $auteurMotif);
224
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $auteurMotif);
198
		$this->addWhere('masque.auteur', $auteurWhere);
225
		$this->addWhere('masque.auteur', $auteurWhere);
199
	}
226
	}
200
 
227
 
201
	private function ajouterContrainteAuteurPrenomEtNom() {
228
	private function ajouterContrainteAuteurPrenomEtNom() {
202
		list($prenom, $nom) = explode(' ', $this->parametres['masque.auteur']);
229
		list($prenom, $nom) = explode(' ', $this->parametres['masque.auteur']);
203
 
230
 
204
		$sqlTpl = '(CONCAT(%1$s,%2$s) LIKE %3$s AND CONCAT(%1$s,%2$s) LIKE %4$s)';
231
		$sqlTpl = '(CONCAT(%1$s,%2$s) LIKE %3$s AND CONCAT(%1$s,%2$s) LIKE %4$s)';
-
 
232
		$prefixe = $this->getPrefixe();
205
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom);
233
		$champsPrenomSql = self::ajouterIfNullPourConcat($this->champsPrenom, $prefixe);
206
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom);
234
		$champsNomSql = self::ajouterIfNullPourConcat($this->champsNom, $prefixe);
207
		$prenomMotif = $this->bdd->proteger("%$prenom%");
235
		$prenomMotif = $this->bdd->proteger("%$prenom%");
208
		$nomMotif = $this->bdd->proteger("%$nom%");
236
		$nomMotif = $this->bdd->proteger("%$nom%");
209
 
237
 
210
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $prenomMotif, $nomMotif);
238
		$auteurWhere = sprintf($sqlTpl, $champsPrenomSql, $champsNomSql, $prenomMotif, $nomMotif);
211
		$this->addWhere('masque.auteur', $auteurWhere);
239
		$this->addWhere('masque.auteur', $auteurWhere);
212
	}
240
	}
213
 
241
 
214
		/**
242
		/**
215
	 * Lorsque l'on concatène des champs, un seul NULL prend le dessus,
243
	 * Lorsque l'on concatène des champs, un seul NULL prend le dessus,
216
	 * Il faut donc utiliser la syntaxe IFNULL(%s, "").
244
	 * Il faut donc utiliser la syntaxe IFNULL(%s, "").
217
	 * (Cette fonction effectue aussi l'implode() "final"
245
	 * (Cette fonction effectue aussi l'implode() "final"
218
	 */
246
	 */
219
	private static function ajouterIfNullPourConcat($champs) {
247
	private static function ajouterIfNullPourConcat($champs, $prefixe) {
220
		$champsProteges = array();
248
		$champsProteges = array();
221
		foreach ($champs as $champ) {
249
		foreach ($champs as $champ) {
-
 
250
			if (strstr($champ, '.') === false) {
-
 
251
				$champ = "$prefixe.$champ";
-
 
252
			}
222
			$champsProteges[] = "IFNULL($champ, '')";
253
			$champsProteges[] = "IFNULL($champ, '')";
223
		}
254
		}
224
		return implode(',', $champsProteges);
255
		return implode(',', $champsProteges);
225
	}
256
	}
226
 
257
 
227
	private function ajouterContrainteDate() {
258
	private function ajouterContrainteDate() {
228
		if (isset($this->parametres['masque.date'])) {
259
		if (isset($this->parametres['masque.date'])) {
229
			$date = $this->parametres['masque.date'];
260
			$date = $this->parametres['masque.date'];
230
			if (is_integer($date) && $date < 2030 && $date > 1600) {
261
			if (preg_match('/^\d{4}$/', $date) && $date < 2030 && $date > 1600) {
231
				$sqlTpl = "YEAR(vdi.date_observation) = %d";
262
				$sqlTpl = "YEAR(do.date_observation) = %d";
232
				$dateWhere = sprintf($sqlTpl, $date);
263
				$dateWhere = sprintf($sqlTpl, $date);
233
				$this->addWhere('masque.date', $dateWhere);
264
				$this->addWhere('masque.date', $dateWhere);
234
			} else {
265
			} else {
235
				$sqlTpl = "DATE_FORMAT(vdi.date_observation, '%%Y-%%m-%%d') = %s";
266
				$sqlTpl = "do.date_observation = %s";
236
				$dateP = $this->bdd->proteger(strftime('%Y-%m-%d', $date));
267
				$dateP = $this->bdd->proteger($date);
237
				$dateWhere = sprintf($sqlTpl, $dateP);
268
				$dateWhere = sprintf($sqlTpl, $dateP);
238
				$this->addWhere('masque.date', $dateWhere);
269
				$this->addWhere('masque.date', $dateWhere);
239
			}
270
			}
-
 
271
 
-
 
272
			if ($this->etreAppliImg()) {
-
 
273
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
274
			}
240
		}
275
		}
241
	}
276
	}
242
 
277
 
243
	private function ajouterContrainteDepartement() {
278
	private function ajouterContrainteDepartement() {
244
		if (isset($this->parametres['masque.departement'])) {
279
		if (isset($this->parametres['masque.departement'])) {
245
			$dept = $this->parametres['masque.departement'];
280
			$dept = $this->parametres['masque.departement'];
246
			$deptMotif = $this->bdd->proteger("INSEE-C:$dept");
281
			$deptMotif = $this->bdd->proteger("INSEE-C:$dept");
247
			$this->addWhere('masque.departement', "vdi.ce_zone_geo LIKE $deptMotif");
282
			$this->addWhere('masque.departement', "do.ce_zone_geo LIKE $deptMotif");
-
 
283
 
-
 
284
			if ($this->etreAppliImg()) {
-
 
285
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
286
			}
248
		}
287
		}
249
	}
288
	}
250
 
289
 
251
	private function ajouterContrainteIdZoneGeo() {
290
	private function ajouterContrainteIdZoneGeo() {
252
		if (isset($this->parametres['masque.id_zone_geo'])) {
291
		if (isset($this->parametres['masque.id_zone_geo'])) {
253
			$idZgMotif = $this->bdd->proteger($this->parametres['masque.id_zone_geo']);
292
			$idZgMotif = $this->bdd->proteger($this->parametres['masque.id_zone_geo']);
254
			$this->addWhere('masque.id_zone_geo', "vdi.ce_zone_geo = $idZgMotif");
293
			$this->addWhere('masque.id_zone_geo', "do.ce_zone_geo = $idZgMotif");
-
 
294
 
-
 
295
			if ($this->etreAppliImg()) {
-
 
296
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
297
			}
255
		}
298
		}
256
	}
299
	}
257
 
300
 
258
	private function ajouterContrainteGenre() {
301
	private function ajouterContrainteGenre() {
259
		if (isset($this->parametres['masque.genre'])) {
302
		if (isset($this->parametres['masque.genre'])) {
260
			$genre = $this->parametres['masque.genre'];
303
			$genre = $this->parametres['masque.genre'];
261
			$genreMotif = $this->bdd->proteger("%$genre% %");
304
			$genreMotif = $this->bdd->proteger("%$genre% %");
262
			$this->addWhere('masque.genre', "vdi.nom_sel LIKE $genreMotif");
305
			$this->addWhere('masque.genre', "do.nom_sel LIKE $genreMotif");
-
 
306
 
-
 
307
			if ($this->etreAppliImg()) {
-
 
308
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
309
			}
263
		}
310
		}
264
	}
311
	}
265
 
312
 
266
	private function ajouterContrainteFamille() {
313
	private function ajouterContrainteFamille() {
267
		if (isset($this->parametres['masque.famille'])) {
314
		if (isset($this->parametres['masque.famille'])) {
268
			$familleMotif = $this->bdd->proteger($this->parametres['masque.famille']);
315
			$familleMotif = $this->bdd->proteger($this->parametres['masque.famille']);
269
			$this->addWhere('masque.famille', "vdi.famille = $familleMotif");
316
			$this->addWhere('masque.famille', "do.famille = $familleMotif");
-
 
317
 
-
 
318
			if ($this->etreAppliImg()) {
-
 
319
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
320
			}
270
		}
321
		}
271
	}
322
	}
272
 
323
 
273
	private function ajouterContrainteNs() {
324
	private function ajouterContrainteNs() {
274
		if (isset($this->parametres['masque.ns'])) {
325
		if (isset($this->parametres['masque.ns'])) {
275
			$ns = $this->parametres['masque.ns'];
326
			$ns = $this->parametres['masque.ns'];
276
			$nsMotif = $this->bdd->proteger("$ns%");
327
			$nsMotif = $this->bdd->proteger("$ns%");
277
			$this->addWhere('masque.ns', "vdi.nom_sel LIKE $nsMotif");
328
			$this->addWhere('masque.ns', "do.nom_sel LIKE $nsMotif");
-
 
329
 
-
 
330
			if ($this->etreAppliImg()) {
-
 
331
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
332
			}
278
		}
333
		}
279
	}
334
	}
280
 
335
 
281
	private function ajouterContrainteNn() {
336
	private function ajouterContrainteNn() {
282
		if (isset($this->parametres['masque.nn'])) {
337
		if (isset($this->parametres['masque.nn'])) {
283
			$sqlTpl = '(vdi.nom_sel_nn = %1$d OR vdi.nom_ret_nn = %1$d)';
338
			$sqlTpl = '(do.nom_sel_nn = %1$d OR do.nom_ret_nn = %1$d)';
284
			$nnWhere = sprintf($sqlTpl, $this->parametres['masque.nn']);
339
			$nnWhere = sprintf($sqlTpl, $this->parametres['masque.nn']);
285
			$this->addWhere('masque.nn', $nnWhere);
340
			$this->addWhere('masque.nn', $nnWhere);
-
 
341
 
-
 
342
			if ($this->etreAppliImg()) {
-
 
343
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
344
			}
286
		}
345
		}
287
	}
346
	}
288
 
347
 
289
	private function ajouterContrainteReferentiel() {
348
	private function ajouterContrainteReferentiel() {
290
		if (isset($this->parametres['masque.referentiel'])) {
349
		if (isset($this->parametres['masque.referentiel'])) {
291
			$ref = $this->parametres['masque.referentiel'];
350
			$ref = $this->parametres['masque.referentiel'];
292
			$refMotif = $this->bdd->proteger("$ref%");
351
			$refMotif = $this->bdd->proteger("$ref%");
293
			$this->addWhere('masque.referentiel', "vdi.nom_referentiel LIKE $refMotif");
352
			$this->addWhere('masque.referentiel', "do.nom_referentiel LIKE $refMotif");
-
 
353
 
-
 
354
			if ($this->etreAppliImg()) {
-
 
355
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
356
			}
294
		}
357
		}
295
	}
358
	}
296
 
359
 
297
	private function ajouterContrainteCommune() {
360
	private function ajouterContrainteCommune() {
298
		if (isset($this->parametres['masque.commune'])) {
361
		if (isset($this->parametres['masque.commune'])) {
299
			$commune = $this->parametres['masque.commune'];
362
			$commune = $this->parametres['masque.commune'];
300
			$communeMotif = $this->bdd->proteger("$commune%");
363
			$communeMotif = $this->bdd->proteger("$commune%");
301
			$this->addWhere('masque.commune', "vdi.zone_geo LIKE $communeMotif");
364
			$this->addWhere('masque.commune', "do.zone_geo LIKE $communeMotif");
-
 
365
 
-
 
366
			if ($this->etreAppliImg()) {
-
 
367
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
368
			}
302
		}
369
		}
303
	}
370
	}
304
 
371
 
305
	public function ajouterConstrainteAppliObs() {
372
	public function ajouterConstrainteAppliObs() {
306
		$this->ajouterContrainteTagCel();
373
		$this->ajouterContrainteTagCel();
307
		$this->ajouterContrainteType();
374
		$this->ajouterContrainteType();
308
		// TODO : ATTENTION -> vue que l'on utilise une vue basée sur les images, nous devons grouper par obs
375
		// TODO : ATTENTION -> vue que l'on utilise une vue basée sur les images, nous devons grouper par obs
309
		$this->addGroupBy('vdi.id_observation');
376
		$this->addGroupBy('do.id_observation');
310
	}
377
	}
311
 
378
 
312
		/**
379
		/**
313
	 * @param $req: la représentation de la requête MySQL complète, à amender.
380
	 * @param $req: la représentation de la requête MySQL complète, à amender.
314
	 */
381
	 */
315
	private function ajouterContrainteType() {
382
	private function ajouterContrainteType() {
-
 
383
		if (isset($this->parametres['masque.type'])) {
316
		if (array_key_exists('adeterminer', $this->parametres['masque.type'])) {
384
			if (array_key_exists('adeterminer', $this->parametres['masque.type'])) {
317
			// Récupèration de toutes les observations qui on le tag "aDeterminer" *ou* qui n'ont pas de nom d'espèce
385
				// Récupèration de toutes les observations qui on le tag "aDeterminer" *ou* qui n'ont pas de nom d'espèce
318
			// *ou* qui ont la "certitude" à ("aDeterminer" *ou* "douteux")
386
				// *ou* qui ont la "certitude" à ("aDeterminer" *ou* "douteux")
319
			$this->addWhere('masque.type', '('.
387
				$this->addWhere('masque.type', '('.
320
				'vdi.certitude = "aDeterminer" '.
388
					'do.certitude = "aDeterminer" '.
321
				'OR vdi.certitude = "douteux" '.
389
					'OR do.certitude = "douteux" '.
322
				'OR vdi.mots_cles_texte LIKE "%aDeterminer%" '.
390
					'OR do.mots_cles_texte LIKE "%aDeterminer%" '.
323
				'OR vdi.nom_sel_nn IS NULL '.
391
					'OR do.nom_sel_nn IS NULL '.
324
				'OR vdi.nom_sel_nn = 0 '.// il ne DEVRAIT pas y avoir d'entrées à 0, mais il y en a quand-même !!
392
					'OR do.nom_sel_nn = 0 '.// il ne DEVRAIT pas y avoir d'entrées à 0, mais il y en a quand-même !!
325
				')');
393
					')');
326
		}
394
			}
327
		if (array_key_exists('validees', $this->parametres['masque.type'])) {
395
			if (array_key_exists('validees', $this->parametres['masque.type'])) {
328
			// Récupèration de toutes les observations ayant un commentaire doté de proposition_retenue = 1
396
				// Récupèration de toutes les observations ayant un commentaire doté de proposition_retenue = 1
329
			$this->addJoin('INNER JOIN del_commentaire AS dc '.
397
				$this->addJoin('INNER JOIN del_commentaire AS dc '.
330
				'ON (vdi.id_observation = dc.ce_observation AND dc.proposition_retenue = 1) ');
398
					'ON (do.id_observation = dc.ce_observation AND dc.proposition_retenue = 1) ');
331
		}
399
			}
332
 
400
 
333
		if (array_key_exists('endiscussion', $this->parametres['masque.type'])) {
401
			if (array_key_exists('endiscussion', $this->parametres['masque.type'])) {
334
			$nbreCommentaire =(int) ($this->conteneur->getParametre('observations.nb_commentaires_discussion'));
402
				$nbreCommentaire =(int) ($this->conteneur->getParametre('observations.nb_commentaires_discussion'));
335
			$this->addWhere('masque.type', '(SELECT COUNT(id_commentaire) FROM del_commentaire AS dc '.
403
				$this->addWhere('masque.type', '(SELECT COUNT(id_commentaire) FROM del_commentaire AS dc '.
336
				"WHERE ce_observation = id_observation) > $nbreCommentaire ");
404
					"WHERE ce_observation = id_observation) > $nbreCommentaire ");
-
 
405
			}
-
 
406
 
-
 
407
			if ($this->etreAppliImg()) {
-
 
408
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
409
			}
337
		}
410
		}
338
	}
411
	}
339
 
412
 
340
	/**
413
	/**
341
	 * in $p: un tableau de paramètres, dont:
414
	 * in $p: un tableau de paramètres, dont:
342
	 * - 'masque.tag_cel': *tableau* de mots-clefs à chercher parmi cel_image.mots_clefs_texte
415
	 * - 'masque.tag_cel': *tableau* de mots-clefs à chercher parmi cel_image.mots_clefs_texte
343
	 * - 'masque.tag_del': *tableau* de mots-clefs à chercher parmi del_image_tag.tag_normalise
416
	 * - 'masque.tag_del': *tableau* de mots-clefs à chercher parmi del_image_tag.tag_normalise
344
	 * - 'tag_explode_semantic': défini si les éléments sont tous recherchés ou NON
417
	 * - 'tag_explode_semantic': défini si les éléments sont tous recherchés ou NON
345
	 *
418
	 *
346
	 * in/ou: $req: un tableau de structure de requête MySQL
419
	 * in/ou: $req: un tableau de structure de requête MySQL
347
	 *
420
	 *
348
	 * Attention, le fait que nous cherchions masque.tag_cel OU/ET masque.tag_cel
421
	 * Attention, le fait que nous cherchions masque.tag_cel OU/ET masque.tag_cel
349
	 * ne dépend pas de nous, mais du niveau supérieur de construction de la requête:
422
	 * ne dépend pas de nous, mais du niveau supérieur de construction de la requête:
350
	 * Soit directement $this->consulter() si des masque.tag* sont passés
423
	 * Soit directement $this->consulter() si des masque.tag* sont passés
351
	 * (split sur ",", "AND" entre chaque condition, "OR" pour chaque valeur de tag)
424
	 * (split sur ",", "AND" entre chaque condition, "OR" pour chaque valeur de tag)
352
	 * Soit via sqlAddMasqueConstraint():
425
	 * Soit via sqlAddMasqueConstraint():
353
	 * (pas de split, "OR" entre chaque condition) [ comportement historique ]
426
	 * (pas de split, "OR" entre chaque condition) [ comportement historique ]
354
	 * équivalent à:
427
	 * équivalent à:
355
	 * (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
428
	 * (split sur " ", "OR" entre chaque condition, "AND" pour chaque valeur de tag)
356
	 *
429
	 *
357
	 */
430
	 */
358
	public function ajouterConstrainteAppliImg() {
431
	public function ajouterConstrainteAppliImg() {
359
		$this->ajouterContrainteMilieu();
432
		$this->ajouterContrainteMilieu();
360
		$this->ajouterContrainteTri();
433
		$this->ajouterContrainteTri();
361
		$this->ajouterContrainteTagCel();
434
		$this->ajouterContrainteTagCel();
362
		$this->ajouterContrainteTagDel();
435
		$this->ajouterContrainteTagDel();
363
	}
436
	}
364
 
437
 
365
	private function ajouterContrainteMilieu() {
438
	private function ajouterContrainteMilieu() {
366
		if (isset($this->parametres['masque.milieu'])) {
439
		if (isset($this->parametres['masque.milieu'])) {
367
			$milieu = $this->parametres['masque.milieu'];
440
			$milieu = $this->parametres['masque.milieu'];
368
			$milieuMotif = $this->bdd->proteger("%$milieu%");
441
			$milieuMotif = $this->bdd->proteger("%$milieu%");
369
			$this->addWhere('masque.milieu', "vdi.milieu LIKE $milieuMotif");
442
			$this->addWhere('masque.milieu', "do.milieu LIKE $milieuMotif");
-
 
443
 
-
 
444
			if ($this->etreAppliImg()) {
-
 
445
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
446
			}
370
		}
447
		}
371
	}
448
	}
372
 
449
 
373
	/** Pour le tri par AVG() des votes nous avons toujours un protocole donné,
450
	/** Pour le tri par AVG() des votes nous avons toujours un protocole donné,
374
	 * celui-ci indique sur quels votes porte l'AVG.
451
	 * celui-ci indique sur quels votes porte l'AVG.
375
	 * (c'est un *vote* qui porte sur un protocole et non l'image elle-même)
452
	 * (c'est un *vote* qui porte sur un protocole et non l'image elle-même)
376
	 * TODO: perf problème:
453
	 * TODO: perf problème:
377
	 * 1) SQL_CALC_FOUND_ROWS: fixable en:
454
	 * 1) SQL_CALC_FOUND_ROWS: fixable en:
378
	 * - dissociant le comptage de la récup d'id + javascript async
455
	 * - dissociant le comptage de la récup d'id + javascript async
379
	 * - ou ne rafraîchir le total *que* pour les requête impliquant un changement de pagination
456
	 * - ou ne rafraîchir le total *que* pour les requête impliquant un changement de pagination
380
	 * (paramètre booléen "with-total" par exemple)
457
	 * (paramètre booléen "with-total" par exemple)
381
	 * 2) jointure forcées: en utilisant `del_imagè`, nous forçons les 2 premiers
458
	 * 2) jointure forcées: en utilisant `del_imagè`, nous forçons les 2 premiers
382
	 * JOIN sur cel_obs_images et cel_obs pour filtrer sur "transmission".
459
	 * JOIN sur cel_obs_images et cel_obs pour filtrer sur "transmission".
383
	 * Dénormaliser cette valeur et l'intégrer à `cel_images` ferait économiser cette couteuse
460
	 * Dénormaliser cette valeur et l'intégrer à `cel_images` ferait économiser cette couteuse
384
	 * jointure, ... lorsqu'aucun masque portant sur `cel_obs` n'est utilisé
461
	 * jointure, ... lorsqu'aucun masque portant sur `cel_obs` n'est utilisé
385
	 * 3) non-problème: l'ordre des joins est forcé par l'usage de la vue:
462
	 * 3) non-problème: l'ordre des joins est forcé par l'usage de la vue:
386
	 * (cel_images/cel_obs_images/cel_obs/del_image_stat)
463
	 * (cel_images/cel_obs_images/cel_obs/del_image_stat)
387
	 * Cependant c'est à l'optimiseur de définir son ordre préféré.
464
	 * Cependant c'est à l'optimiseur de définir son ordre préféré.
388
	 */
465
	 */
389
	private function ajouterContrainteTri() {
466
	private function ajouterContrainteTri() {
390
		if (isset($this->parametres['tri'])) {
467
		if (isset($this->parametres['tri'])) {
391
			$tri = $this->parametres['tri'];
468
			$tri = $this->parametres['tri'];
392
 
469
 
393
			if (isset($this->parametres['protocole'])  && ($tri == 'moyenne-arithmetique' || $tri == 'points')) {
470
			if (isset($this->parametres['protocole'])  && ($tri == 'moyenne-arithmetique' || $tri == 'points')) {
394
				// $this->parametres['protocole'] *est* défini (cf Outils::filtrerUrlsParams...())
471
				// $this->parametres['protocole'] *est* défini (cf Outils::filtrerUrlsParams...())
395
				$sqlTpl = 'LEFT JOIN del_image_stat dis ON vdi.id_image = dis.ce_image AND dis.ce_protocole = %d';
472
				$sqlTpl = 'LEFT JOIN del_image_stat AS dis ON di.id_image = dis.ce_image AND dis.ce_protocole = %d';
396
				$triSql = sprintf($sqlTpl, $this->parametres['protocole']);
473
				$triSql = sprintf($sqlTpl, $this->parametres['protocole']);
397
				$this->addJoinDis($triSql);
474
				$this->addJoinDis($triSql);
398
			}
475
			}
399
 
476
 
400
			if (isset($this->parametres['ordre']) && $tri == 'tags') {
477
			if (isset($this->parametres['ordre']) && $tri == 'tags') {
401
				$typeJointure = ($this->parametres['ordre'] == 'desc') ? 'INNER' : 'LEFT';
478
				$typeJointure = ($this->parametres['ordre'] == 'desc') ? 'INNER' : 'LEFT';
402
				$this->addJoin("$typeJointure JOIN del_image_stat dis ON vdi.id_image = dis.ce_image");
479
				$this->addJoin("$typeJointure JOIN del_image_stat AS dis ON di.id_image = dis.ce_image");
403
				// nécessaire (dup ce_image dans del_image_stat)
480
				// nécessaire (dup ce_image dans del_image_stat)
404
				$this->addGroupBy('vdi.id_observation');
481
				$this->addGroupBy('di.ce_observation');
405
			}
482
			}
406
		}
483
		}
407
	}
484
	}
408
 
485
 
409
	/**
486
	/**
410
	 * Car il ne sont pas traités par la générique requestFilterParams() les clefs "masque.tag_*"
487
	 * Car il ne sont pas traités par la générique requestFilterParams() les clefs "masque.tag_*"
411
	 * sont toujours présentes; bien que parfois NULL.
488
	 * sont toujours présentes; bien que parfois NULL.
412
	 */
489
	 */
413
	// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ? et auquel cas laisser au client le choix du couteux "%" ?
490
	// TODO: utiliser les tables de mots clefs normaliées dans tb_cel ? et auquel cas laisser au client le choix du couteux "%" ?
414
	private function ajouterContrainteTagCel() {
491
	private function ajouterContrainteTagCel() {
415
		if (isset($this->parametres['masque.tag_cel'])) {
492
		if (isset($this->parametres['masque.tag_cel'])) {
416
			if (isset($this->parametres['masque.tag_cel']['AND'])) {
493
			if (isset($this->parametres['masque.tag_cel']['AND'])) {
417
				$tags = $this->parametres['masque.tag_cel']['AND'];
494
				$tags = $this->parametres['masque.tag_cel']['AND'];
418
				$clausesWhere = array();
495
				$clausesWhere = array();
419
				foreach ($tags as $tag) {
496
				foreach ($tags as $tag) {
420
					$tagMotif = $this->bdd->proteger("%$tag%");
497
					$tagMotif = $this->bdd->proteger("%$tag%");
421
					$sqlTpl = "CONCAT(IFNULL(vdi.mots_cles_texte,''),IFNULL(vdi.i_mots_cles_texte,'')) LIKE %s";
498
					$sqlTpl = "CONCAT(IFNULL(do.mots_cles_texte,''),IFNULL(di.mots_cles_texte,'')) LIKE %s";
422
					$clausesWhere[] = sprintf($sqlTpl, $tagMotif);
499
					$clausesWhere[] = sprintf($sqlTpl, $tagMotif);
423
				}
500
				}
424
				$whereTags = implode(' AND ', $clausesWhere);
501
				$whereTags = implode(' AND ', $clausesWhere);
425
				$this->addWhere('masque.tag_cel', "($whereTags)");
502
				$this->addWhere('masque.tag_cel', "($whereTags)");
426
			} else if (isset($this->parametres['masque.tag_cel']['OR'])) {
503
			} else if (isset($this->parametres['masque.tag_cel']['OR'])) {
427
				$tags = $this->parametres['masque.tag_cel']['OR'];
504
				$tags = $this->parametres['masque.tag_cel']['OR'];
428
				$sqlTpl = "CONCAT(IFNULL(vdi.mots_cles_texte,''),IFNULL(vdi.i_mots_cles_texte,'')) REGEXP %s";
505
				$sqlTpl = "CONCAT(IFNULL(do.mots_cles_texte,''),IFNULL(di.mots_cles_texte,'')) REGEXP %s";
429
				$tagMotif = $this->bdd->proteger(implode('|', $tags));
506
				$tagMotif = $this->bdd->proteger(implode('|', $tags));
430
				$tagSql = sprintf($sqlTpl, $tagMotif);
507
				$tagSql = sprintf($sqlTpl, $tagMotif);
431
				$this->addWhere('masque.tag_cel', $tagSql);
508
				$this->addWhere('masque.tag_cel', $tagSql);
432
			}
509
			}
-
 
510
			if ($this->etreAppliImg()) {
-
 
511
				$this->addJoin('LEFT JOIN del_observation AS do ON (di.ce_observation = do.id_observation) ');
-
 
512
			}
-
 
513
			if ($this->etreAppliObs()) {
-
 
514
				$this->addJoin('LEFT JOIN del_image AS di ON (do.id_observation = di.ce_observation) ');
-
 
515
			}
433
		}
516
		}
434
	}
517
	}
435
 
518
 
436
	/**
519
	/**
437
	 * Plusieurs solutions sont disponibles dans les anciennes versions (voir DelTk).
520
	 * Plusieurs solutions sont disponibles dans les anciennes versions (voir DelTk).
438
	 */
521
	 */
439
	private function ajouterContrainteTagDel() {
522
	private function ajouterContrainteTagDel() {
440
		if (isset($this->parametres['masque.tag_del'])) {
523
		if (isset($this->parametres['masque.tag_del'])) {
441
			if (isset($this->parametres['masque.tag_del']['AND'])) {
524
			if (isset($this->parametres['masque.tag_del']['AND'])) {
442
				$tags = $this->parametres['masque.tag_del']['AND'];
525
				$tags = $this->parametres['masque.tag_del']['AND'];
443
				// optimisation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
526
				// optimisation: en cas de "AND" on sort() l'input et le GROUP_CONCAT()
444
				// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
527
				// donc nous utilisons des ".*" plutôt que de multiples conditions et "|"
445
				sort($tags);
528
				sort($tags);
446
				$tagsMotif = $this->bdd->proteger(implode('.*', $tags));
529
				$tagsMotif = $this->bdd->proteger(implode('.*', $tags));
447
				$requete = 'SELECT ce_image '.
530
				$requete = 'SELECT ce_image '.
448
					'FROM del_image_tag '.
531
					'FROM del_image_tag '.
449
					'WHERE actif = 1 '.
532
					'WHERE actif = 1 '.
450
					'GROUP BY ce_image '.
533
					'GROUP BY ce_image '.
451
					"HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP $tagsMotif ".
534
					"HAVING GROUP_CONCAT(tag_normalise ORDER BY tag_normalise) REGEXP $tagsMotif ".
452
					' -- '.__FILE__.' : '.__LINE__;
535
					' -- '.__FILE__.' : '.__LINE__;
453
				$sql = $this->recupererSqlContrainteTag($requete);
536
				$sql = $this->recupererSqlContrainteTag($requete);
454
				$this->addWhere('masque.tag_del', $sql);
537
				$this->addWhere('masque.tag_del', $sql);
455
 
538
 
456
			} else if (isset($this->parametres['masque.tag_del']['OR'])) {
539
			} else if (isset($this->parametres['masque.tag_del']['OR'])) {
457
				$tags = $this->parametres['masque.tag_del']['OR'];
540
				$tags = $this->parametres['masque.tag_del']['OR'];
458
				$tagsMotif = $this->bdd->proteger(implode('|', $tags));
541
				$tagsMotif = $this->bdd->proteger(implode('|', $tags));
459
				$requete = 'SELECT ce_image '.
542
				$requete = 'SELECT ce_image '.
460
					'FROM del_image_tag '.
543
					'FROM del_image_tag '.
461
					'WHERE actif = 1 '.
544
					'WHERE actif = 1 '.
462
					'GROUP BY ce_image '.
545
					'GROUP BY ce_image '.
463
					"HAVING GROUP_CONCAT(tag_normalise) REGEXP $tagsMotif ".
546
					"HAVING GROUP_CONCAT(tag_normalise) REGEXP $tagsMotif ".
464
					' -- '.__FILE__.' : '.__LINE__;
547
					' -- '.__FILE__.' : '.__LINE__;
-
 
548
 
465
				$sql = $this->recupererSqlContrainteTag($requete);
549
				$sql = $this->recupererSqlContrainteTag($requete);
466
				$this->addWhere('masque.tag_del', $sql);
550
				$this->addWhere('masque.tag_del', $sql);
467
			}
551
			}
468
		}
552
		}
469
	}
553
	}
470
 
554
 
471
	private function recupererSqlContrainteTag($requete) {
555
	private function recupererSqlContrainteTag($requete) {
472
		$resultats = $this->bdd->recupererTous($requete);
556
		$resultats = $this->bdd->recupererTous($requete);
473
		$ids = array();
557
		$ids = array();
474
		foreach ($resultats as $resultat) {
558
		foreach ($resultats as $resultat) {
475
			$ids[] = $resultat['ce_image'];
559
			$ids[] = $resultat['ce_image'];
476
		}
560
		}
477
 
561
 
478
		if (!empty($ids)) {
562
		if (!empty($ids)) {
479
			$clauseIn = implode(',', $ids);
563
			$clauseIn = implode(',', $ids);
480
		} else {
564
		} else {
481
			$clauseIn = 'SELECT ce_image FROM del_image_tag WHERE false';
565
			$clauseIn = 'SELECT ce_image FROM del_image_tag WHERE false';
482
		}
566
		}
483
		return "vdi.id_image IN ($clauseIn)";
567
		return "di.id_image IN ($clauseIn)";
484
	}
568
	}
485
 
569
 
486
	/**
570
	/**
487
	 * Partie spécifique à PictoFlora:
571
	 * Partie spécifique à PictoFlora:
488
	 * Attention : si le critère de tri n'est pas suffisant, les résultats affichés peuvent varier à chaque appel
572
	 * Attention : si le critère de tri n'est pas suffisant, les résultats affichés peuvent varier à chaque appel
489
	 * de la même page de résultat de PictoFlora.
573
	 * de la même page de résultat de PictoFlora.
490
	 */
574
	 */
491
	public function definirOrdreSqlAppliImg() {
575
	public function definirOrdreSqlAppliImg() {
492
		$ordre = $this->parametres['ordre'];
576
		$ordre = $this->parametres['ordre'];
493
 
577
 
494
		switch ($this->parametres['tri']) {
578
		switch ($this->parametres['tri']) {
495
			case 'moyenne-arithmetique' :
579
			case 'moyenne-arithmetique' :
496
				$this->addOrderBy("dis.moyenne $ordre, dis.nb_votes $ordre, id_image DESC");
580
				$this->addOrderBy("dis.moyenne $ordre, dis.nb_votes $ordre, id_image DESC");
497
				break;
581
				break;
498
			case 'points' :
582
			case 'points' :
499
				$this->addOrderBy("dis.nb_points $ordre, dis.moyenne $ordre, dis.nb_votes $ordre, id_image DESC");
583
				$this->addOrderBy("dis.nb_points $ordre, dis.moyenne $ordre, dis.nb_votes $ordre, id_image DESC");
500
				break;
584
				break;
501
			case 'tags' :
585
			case 'tags' :
502
				$this->addOrderBy("dis.nb_tags $ordre, id_image DESC");
586
				$this->addOrderBy("dis.nb_tags $ordre, id_image DESC");
503
				break;
587
				break;
504
			case 'date_observation' :
588
			case 'date_observation' :
505
				$this->addOrderBy("date_observation $ordre, id_observation $ordre");
589
				$this->addOrderBy("date_observation $ordre, ce_observation $ordre");
506
				break;
590
				break;
507
			case 'date_transmission' :
591
			case 'date_transmission' :
508
			default:
592
			default:
509
				$this->addOrderBy("date_transmission $ordre, id_observation $ordre");
593
				$this->addOrderBy("di.date_transmission $ordre, ce_observation $ordre");
510
		}
594
		}
511
	}
595
	}
512
 
596
 
513
	public function definirOrdreSqlAppliObs() {
597
	public function definirOrdreSqlAppliObs() {
514
		$ordre = $this->parametres['ordre'];
598
		$ordre = $this->parametres['ordre'];
515
 
599
 
516
		// parmi self::$tri_possible
600
		// parmi self::$tri_possible
517
		switch ($this->parametres['tri']) {
601
		switch ($this->parametres['tri']) {
518
			case 'date_observation' :
602
			case 'date_observation' :
519
				$this->addOrderBy("date_observation $ordre, id_observation $ordre");
603
				$this->addOrderBy("date_observation $ordre, id_observation $ordre");
520
				break;
604
				break;
521
			default:
605
			default:
522
				$this->addOrderBy("date_transmission $ordre, id_observation $ordre");
606
				$this->addOrderBy("do.date_transmission $ordre, id_observation $ordre");
523
		}
607
		}
524
	}
608
	}
525
 
609
 
526
	public function getAliasDesChamps($champsEtAlias, $select = null, $prefix = null) {
610
	public function getAliasDesChamps($champsEtAlias, $select = null, $prefix = null) {
527
		$arr = ($select) ? array_intersect_key($champsEtAlias, array_flip($select)) :  $champsEtAlias;
611
		$arr = ($select) ? array_intersect_key($champsEtAlias, array_flip($select)) :  $champsEtAlias;
528
		$keys = array_keys($arr);
612
		$keys = array_keys($arr);
529
 
613
 
530
		if ($prefix) {
614
		if ($prefix) {
531
			array_walk($keys, create_function('&$val, $k, $prefix', '$val = sprintf("%s.`%s`", $prefix, $val);'), $prefix);
615
			array_walk($keys, create_function('&$val, $k, $prefix', '$val = sprintf("%s.`%s`", $prefix, $val);'), $prefix);
532
		} else {
616
		} else {
533
			array_walk($keys, create_function('&$val, $k', '$val = sprintf("`%s`", $val);'));
617
			array_walk($keys, create_function('&$val, $k', '$val = sprintf("`%s`", $val);'));
534
		}
618
		}
535
 
619
 
536
		return implode(', ', array_map(create_function('$v, $k', 'return sprintf("%s AS `%s`", $k, $v);'), $arr, $keys));
620
		return implode(', ', array_map(create_function('$v, $k', 'return sprintf("%s AS `%s`", $k, $v);'), $arr, $keys));
537
	}
621
	}
538
 
622
 
539
		// Charger les images et leurs votes associés
623
		// Charger les images et leurs votes associés
540
	public function getVotesDesImages($idsImages, $protocole = null) {
624
	public function getVotesDesImages($idsImages, $protocole = null) {
541
		if (!$idsImages) return;
625
		if (!$idsImages) return;
542
 
626
 
543
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
627
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
544
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
628
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
545
 		$selectVotes = array('id_vote', 'ce_image', 'ce_protocole', 'ce_utilisateur', 'valeur', 'date');
629
 		$selectVotes = array('id_vote', 'ce_image', 'ce_protocole', 'ce_utilisateur', 'valeur', 'date');
546
		$selectProtocole = array('id_protocole', 'intitule', 'descriptif', 'tag');
630
		$selectProtocole = array('id_protocole', 'intitule', 'descriptif', 'tag');
547
		$voteChamps = $this->getAliasDesChamps($mappingVotes, $selectVotes, 'v'); // "v": cf alias dans la requête
631
		$voteChamps = $this->getAliasDesChamps($mappingVotes, $selectVotes, 'v'); // "v": cf alias dans la requête
548
		$protoChamps = $this->getAliasDesChamps($mappingProtocoles, $selectProtocole, 'p');
632
		$protoChamps = $this->getAliasDesChamps($mappingProtocoles, $selectProtocole, 'p');
549
		$idImgsConcat = implode(',', $idsImages);
633
		$idImgsConcat = implode(',', $idsImages);
550
 
634
 
551
		$requete = "SELECT $voteChamps, $protoChamps ".
635
		$requete = "SELECT $voteChamps, $protoChamps ".
552
			'FROM del_image_vote AS v '.
636
			'FROM del_image_vote AS v '.
553
			'	INNER JOIN del_image_protocole AS p ON (v.ce_protocole = p.id_protocole) '.
637
			'	INNER JOIN del_image_protocole AS p ON (v.ce_protocole = p.id_protocole) '.
554
			"WHERE v.ce_image IN ($idImgsConcat) ".
638
			"WHERE v.ce_image IN ($idImgsConcat) ".
555
			($protocole ? "	AND v.ce_protocole = $protocole " : '').
639
			($protocole ? "	AND v.ce_protocole = $protocole " : '').
556
			"ORDER BY FIELD(v.ce_image, $idImgsConcat) ".
640
			"ORDER BY FIELD(v.ce_image, $idImgsConcat) ".
557
			'-- '.__FILE__.':'.__LINE__;
641
			'-- '.__FILE__.':'.__LINE__;
558
 
642
 
559
		return $this->bdd->recupererTous($requete);
643
		return $this->bdd->recupererTous($requete);
560
	}
644
	}
561
 
645
 
562
	/**
646
	/**
563
	 * Ajoute les informations sur le protocole et les votes aux images.
647
	 * Ajoute les informations sur le protocole et les votes aux images.
564
	 *
648
	 *
565
	 * ATTENTION : Subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien
649
	 * ATTENTION : Subtilité, nous passons ici le tableau d'images indexé par id_image qui est bien
566
	 * plus pratique pour associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
650
	 * plus pratique pour associer les vote à un tableau, puisque nous ne connaissons pas les id d'observation.
567
	 * Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
651
	 * Mais magiquement (par référence), cela va remplir notre tableau indexé par couple d'id (id_image, id_observation)
568
	 * cf ListeImages::reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions
652
	 * cf ListeImages::reformateImagesDoubleIndex() à qui revient la tâche de créer ces deux versions
569
	 * simultanément lorsque c'est encore possible.
653
	 * simultanément lorsque c'est encore possible.
570
	 */
654
	 */
571
	public function ajouterInfosVotesProtocoles($votes, &$images) {
655
	public function ajouterInfosVotesProtocoles($votes, &$images) {
572
		if (!$votes) return;
656
		if (!$votes) return;
573
 
657
 
574
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
658
		$mappingVotes = $this->conteneur->getParametreTableau('votes.mapping');
575
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
659
		$mappingProtocoles = $this->conteneur->getParametreTableau('protocoles.mapping');
576
 
660
 
577
		// pour chaque vote
661
		// pour chaque vote
578
		foreach ($votes as $vote) {
662
		foreach ($votes as $vote) {
579
			$imgId = $vote['image.id'];
663
			$imgId = $vote['image.id'];
580
			$protoId = $vote['protocole.id'];
664
			$protoId = $vote['protocole.id'];
581
 
665
 
582
			if (!array_key_exists('protocoles_votes', $images[$imgId]) ||
666
			if (!array_key_exists('protocoles_votes', $images[$imgId]) ||
583
					!array_key_exists($protoId, $images[$imgId]['protocoles_votes'])) {
667
					!array_key_exists($protoId, $images[$imgId]['protocoles_votes'])) {
584
				// extrait les champs spécifique au protocole (le LEFT JOIN de chargerVotesImage les ramène en doublons
668
				// extrait les champs spécifique au protocole (le LEFT JOIN de chargerVotesImage les ramène en doublons
585
				$protocole = array_intersect_key($vote, array_flip($mappingProtocoles));
669
				$protocole = array_intersect_key($vote, array_flip($mappingProtocoles));
586
				$images[$imgId]['protocoles_votes'][$protoId] = $protocole;
670
				$images[$imgId]['protocoles_votes'][$protoId] = $protocole;
587
			}
671
			}
588
 
672
 
589
			$chpsVotes = array('id_vote', 'ce_image', 'ce_utilisateur', 'valeur', 'date');
673
			$chpsVotes = array('id_vote', 'ce_image', 'ce_utilisateur', 'valeur', 'date');
590
			$voteSelection = array_intersect_key($mappingVotes, array_flip($chpsVotes));
674
			$voteSelection = array_intersect_key($mappingVotes, array_flip($chpsVotes));
591
			$vote = array_intersect_key($vote, array_flip($voteSelection));
675
			$vote = array_intersect_key($vote, array_flip($voteSelection));
592
			$images[$imgId]['protocoles_votes'][$protoId]['votes'][$vote['vote.id']] = $vote;
676
			$images[$imgId]['protocoles_votes'][$protoId]['votes'][$vote['vote.id']] = $vote;
593
		}
677
		}
594
	}
678
	}
595
 
679
 
596
	public function getTotalLignesTrouvees() {
680
	public function getTotalLignesTrouvees() {
597
		$resultat = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre');
681
		$resultat = $this->bdd->recuperer('SELECT FOUND_ROWS() AS nbre');
598
		return intval($resultat['nbre']);
682
		return intval($resultat['nbre']);
599
	}
683
	}
600
}
684
}