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