Subversion Repositories eFlore/Applications.del

Rev

Rev 1922 | Rev 1978 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1375 raphael 1
<?php
1845 jpm 2
// declare(encoding='UTF-8');
1375 raphael 3
/**
1845 jpm 4
 * Web service récupèrant toutes les observations et, pour chacune d'elle, les images qui lui sont associées.
1375 raphael 5
 *
1845 jpm 6
 * ATTENTION : le web service commence par récupérer seulement les id des obs (1er requete SQL), puis dans une
7
 * deuxième requête SQL récupère les informations complémentaires. Il s'avère qu'en procédant ainsi le web service
8
 * est 3 fois plus rapide !
1375 raphael 9
 *
1845 jpm 10
 * @category   DEL
11
 * @package    Services
12
 * @subpackage Observations
13
 * @version    0.1
14
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
15
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
16
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
17
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
18
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
19
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
1375 raphael 20
 */
1451 raphael 21
class ListeObservations {
1375 raphael 22
 
1793 jpm 23
	private $conteneur;
24
	private $bdd;
1845 jpm 25
	private $navigation;
26
	private $filtrage;
27
	private $sql;
1881 jpm 28
 
1845 jpm 29
	private $mappings = array();
30
	private $paramsFiltres = array();
1375 raphael 31
 
1881 jpm 32
	private $idsObsOrdonnees = array();
33
	private $infosObs = array();
34
	private $infosObsOrdonnee = array();
1375 raphael 35
 
1881 jpm 36
 
1845 jpm 37
	public function __construct(Conteneur $conteneur) {
38
		$this->conteneur = $conteneur;
39
		$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
1375 raphael 40
 
1793 jpm 41
		$this->bdd = $this->conteneur->getBdd();
1845 jpm 42
		$this->filtrage = $this->conteneur->getParametresFiltrage();
43
		$this->sql = $this->conteneur->getSql();
44
		$this->navigation = $this->conteneur->getNavigation();
1375 raphael 45
 
1845 jpm 46
		$this->mappings['votes'] = $this->conteneur->getParametreTableau('votes.mapping');
47
		$this->mappings['commentaires'] = $this->conteneur->getParametreTableau('commentaires.mapping');
48
	}
1666 jpm 49
 
1793 jpm 50
	public function consulter($ressources, $parametres) {
1845 jpm 51
		$this->paramsFiltres = $this->filtrage->filtrerUrlParamsAppliObs();
1871 jpm 52
		$this->sql->setAppli(Sql::APPLI_OBS);
1845 jpm 53
		$this->sql->setParametres($this->paramsFiltres);
54
		$this->sql->ajouterContraintes();
55
		$this->sql->ajouterConstrainteAppliObs();
56
		$this->sql->definirOrdreSqlAppliObs();
1666 jpm 57
 
1881 jpm 58
		$this->idsObsOrdonnees = $this->getIdObs();
1845 jpm 59
		$this->navigation->setTotal($this->sql->getTotalLignesTrouvees());
1666 jpm 60
 
1845 jpm 61
		// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats
62
		$resultat = new ResultatService();
63
		$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => array());
1881 jpm 64
		if (count($this->idsObsOrdonnees) > 0) {
1666 jpm 65
 
1793 jpm 66
			// 2) récupération des données nécessaires pour ces observations (obs + images)
1881 jpm 67
			$this->infosObs = $this->getInfosObs();
1793 jpm 68
			// 3) suppression, merge des données en tableau assez représentatif du futur JSON en output
1881 jpm 69
			$this->infosObsOrdonnees = $this->formaterObservations();
70
			// 4) Ajouter commentaires + votes à $this->infosObsOrdonnees
71
			$this->chargerDeterminations();
1666 jpm 72
 
1845 jpm 73
			$resultat->corps = array(
1933 aurelien 74
				'entete' => $this->navigation->getEntete(),
75
				// 5) Applatissage du tableau afin de garder l'ordre de tri
76
				// (qui n'est pas garanti dans un objet json)
77
				'resultats' => array_values($this->infosObsOrdonnees));
1618 mathias 78
		}
79
		return $resultat;
1793 jpm 80
	}
1375 raphael 81
 
1793 jpm 82
	// SQL helpers
83
	/*
84
	 * Retourne une liste ordonnée d'id d'observation correspondant aux critères
85
	 * passés dans p et aux clauses where/join présentes dans le tableau $req
86
	 *
87
	 * @param p: $params (filtrés sauf escape-string)
88
	 * @param req: le tableau représentant les composants de la requete SQL
89
	 * @param db: l'instance de db
90
	 */
1845 jpm 91
	private function getIdObs() {
92
		$requete = 'SELECT SQL_CALC_FOUND_ROWS id_observation '.
1871 jpm 93
			'FROM del_observation AS do '.
1845 jpm 94
			$this->sql->getJoin().
95
			'WHERE '.$this->sql->getWhere().
96
			$this->sql->getGroupBy().
97
			$this->sql->getOrderBy().
98
			$this->sql->getLimit().
99
			' -- '.__FILE__.':'.__LINE__;
1871 jpm 100
		//Debug::printr($requete);
1845 jpm 101
		$resultats = $this->bdd->recupererTous($requete);
1375 raphael 102
 
1845 jpm 103
		$idObs = array();
104
		if ($resultats !== false ) {
105
			foreach ($resultats as $resultat) {
106
				$idObs[] = $resultat['id_observation'];
107
			}
1793 jpm 108
		}
1845 jpm 109
		return $idObs;
1375 raphael 110
	}
111
 
1793 jpm 112
	/**
1845 jpm 113
	 * Après avoir récupérer seulement les ids dans une première requête, nous récupérons maintenant les infos.
114
	 * Le web service est ainsi 3 fois plus rapide.
1793 jpm 115
	 */
1881 jpm 116
	private function getInfosObs() {
117
		$idsObsConcat = implode(',', $this->idsObsOrdonnees);
1922 jpm 118
		// TODO : bizarement MYSQL 5.6 retourne plusieurs fois les mêmes enregistrements d'où le DISTINCT (normalement inutile)
119
		$requete = "SELECT DISTINCT id_observation, nom_sel AS `determination.ns`, nt AS `determination.nt`, ".
1845 jpm 120
			'nom_sel_nn AS `determination.nn`, famille AS `determination.famille`, '.
121
			'nom_referentiel AS `determination.referentiel`, ce_zone_geo AS id_zone_geo, '.
1871 jpm 122
			'zone_geo, lieudit, station, milieu, date_observation, do.mots_cles_texte, '.
123
			'do.date_transmission, do.commentaire, '.
124
			'do.ce_utilisateur AS `auteur.id`, do.prenom_utilisateur AS `auteur.prenom`, '.
125
			'do.nom_utilisateur AS `auteur.nom`, do.courriel_utilisateur AS `auteur.courriel`, '.
1845 jpm 126
			'id_image, date_prise_de_vue AS `date`, hauteur, largeur, nom_original '.
1871 jpm 127
			'FROM del_observation AS do '.
128
			'	LEFT JOIN del_image AS di ON (do.id_observation = di.ce_observation) '.
1845 jpm 129
			"WHERE id_observation IN ($idsObsConcat) ".
130
			' -- '.__FILE__.':'.__LINE__;
1922 jpm 131
		//Debug::printr($requete);
1845 jpm 132
		return $this->bdd->recupererTous($requete);
1793 jpm 133
	}
1375 raphael 134
 
1793 jpm 135
	/**
1845 jpm 136
	 * Les informations étant extraites d'une vue dont les infos des obs sont dupliquées pour chaque image,
137
	 * il nous faut maintenant récupérer qu'une seule fois les données d'observations et y intégrer les données
138
	 * des images.
1793 jpm 139
	 */
1881 jpm 140
	private function formaterObservations() {
141
		$observations = array_map('array_filter', $this->infosObs);
142
		$obsFormatees = array_flip($this->idsObsOrdonnees);// Permet de garder l'ordre de sortie !
1922 jpm 143
		foreach ($observations as &$obs) {
1845 jpm 144
			$this->nettoyerAuteur($obs);
1881 jpm 145
 
146
			$id = $obs['id_observation'];
1922 jpm 147
			// ATTENTION : la requête retourne de nombreuses lignes avec les mêmes données (test de l'existence nécessaire)
148
			if (is_array($obsFormatees[$id]) === false) {
149
				$obsFormatees[$id] = $obs;
150
			}
151
			$obsFormatees[$id]['images'][] = $this->extraireInfosImage($obs);
1793 jpm 152
		}
1845 jpm 153
		return $obsFormatees;
154
	}
1494 raphael 155
 
1845 jpm 156
	private function nettoyerAuteur(&$obs) {
157
		// car auteur.id peut être un email, un hash, ou un annuaire_tela.U_ID
158
		// mais dans les deux premiers cas SELECT courriel AS observateur fait déjà l'affaire
159
		if (!isset($obs['auteur.id']) || !is_numeric($obs['auteur.id'])) {
160
			$obs['auteur.id'] = "0";
1375 raphael 161
		}
1845 jpm 162
		if (!isset($obs['auteur.nom'])) {
163
			$obs['auteur.nom'] = '[inconnu]';
164
		}
1416 raphael 165
	}
1375 raphael 166
 
1845 jpm 167
	private function extraireInfosImage(&$obs) {
168
		$champsImageAffichables = array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original');
169
		$image = array_intersect_key($obs, array_flip($champsImageAffichables));
170
		$urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl');
171
		$image['binaire.href'] = sprintf($urlImgTpl, $image['id_image'], 'XL');
1498 raphael 172
 
1845 jpm 173
		unset($obs['id_image'], $obs['date'], $obs['hauteur'], $obs['largeur'], $obs['nom_original']);
174
		return $image;
175
	}
1498 raphael 176
 
1793 jpm 177
	/**
178
	 * Récupérer toutes les déterminations et le nombre de commentaire au total
179
	 * @param array $observations la liste des observations à mettre à jour
180
	 */
1881 jpm 181
	private function chargerDeterminations() {
182
		$idObsConcat = implode(',', $this->idsObsOrdonnees);
1845 jpm 183
		$requete = 'SELECT * '.
184
			'FROM del_commentaire AS dc '.
185
			'WHERE dc.nom_sel IS NOT NULL '.
186
			"AND ce_observation IN ($idObsConcat) ".
187
			'-- '.__FILE__.':'.__LINE__;
1933 aurelien 188
 
189
		$commentaires = $this->chargerNombreCommentaireObs();
1375 raphael 190
 
1845 jpm 191
		$propositions = $this->bdd->recupererTous($requete);
192
		if ($propositions) {
193
			foreach ($propositions as $proposition) {
194
				$idObs = $proposition['ce_observation'];
195
				$idComment = $proposition['id_commentaire'];
196
				$comment = $this->formaterDetermination($idComment, $proposition);
197
				if ($comment) {
1881 jpm 198
					$this->infosObsOrdonnees[$idObs]['commentaires'][$idComment] = $comment;
1845 jpm 199
				}
1933 aurelien 200
				$this->infosObsOrdonnees[$idObs]['nb_commentaires'] = isset($commentaires[$idObs]) ? $commentaires[$idObs] : 0;
1845 jpm 201
			}
1793 jpm 202
		}
1494 raphael 203
	}
204
 
1845 jpm 205
	private function formaterDetermination($propositionId, $propositionInfos) {
206
		if (!$propositionInfos) return NULL;
1494 raphael 207
 
1845 jpm 208
		$propositionFormatee = array();
209
		foreach ($this->mappings['commentaires'] as $nomChamp => $nomAttributJson) {
210
			if (isset($propositionInfos[$nomChamp])) {
211
				$propositionFormatee[$nomAttributJson] = $propositionInfos[$nomChamp];
1793 jpm 212
			}
213
		}
1666 jpm 214
 
1793 jpm 215
		// Charger les votes sur les déterminations
1845 jpm 216
		$requete = "SELECT * FROM del_commentaire_vote WHERE ce_proposition = $propositionId".
217
			'-- '.__FILE__.':'.__LINE__;
218
		$resultatsVotes = $this->bdd->recupererTous($requete);
1793 jpm 219
		foreach ($resultatsVotes as $vote) {
1845 jpm 220
			$propositionFormatee['votes'][$vote['id_vote']] = $this->formaterVote($vote);
1793 jpm 221
		}
1386 raphael 222
 
1845 jpm 223
		$propositionFormatee['nb_commentaires'] = $this->chargerNombreCommentaire($propositionId);
1386 raphael 224
 
1845 jpm 225
		return $propositionFormatee;
1494 raphael 226
	}
1375 raphael 227
 
1793 jpm 228
	/**
229
	 * Formater un vote en fonction du fichier de configuration config_votes.ini
230
	 * @param $votes array()
231
	 */
232
	private function formaterVote($vote) {
1845 jpm 233
		$voteFormate = array();
234
		foreach ($vote as $nomChamp => $valeur) {
235
			$voteFormate[$this->mappings['votes'][$nomChamp]] = $valeur;
1375 raphael 236
		}
1845 jpm 237
		return $voteFormate;
1375 raphael 238
	}
1933 aurelien 239
 
240
	private function chargerNombreCommentaireObs() {
241
		$idObsConcat = implode(',', $this->idsObsOrdonnees);
242
		$requete = 'SELECT ce_observation, COUNT( id_commentaire ) AS nb '.
243
				'FROM del_commentaire '.
244
				"WHERE ce_observation IN ($idObsConcat) ".
245
				'GROUP BY ce_observation '.
246
				'-- '.__FILE__.':'.__LINE__;
247
		$commentaires = $this->bdd->recupererTous($requete);
248
 
249
		$commentaires_par_obs = array();
250
		foreach($commentaires as $commentaire) {
251
			$commentaires_par_obs[$commentaire['ce_observation']] = $commentaire['nb'];
252
		}
253
 
254
		return $commentaires_par_obs;
255
	}
1845 jpm 256
 
257
	private function chargerNombreCommentaire($propositionId) {
258
		$requete = 'SELECT COUNT( id_commentaire ) AS nb '.
259
			'FROM del_commentaire '.
260
			"WHERE ce_proposition = $propositionId ".
261
			'GROUP BY ce_proposition '.
262
			'-- '.__FILE__.':'.__LINE__;
263
		$commentaires = $this->bdd->recuperer($requete);
264
		return $commentaires ? $commentaires['nb'] : 0;
265
	}
1793 jpm 266
}