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