Subversion Repositories eFlore/Applications.del

Rev

Rev 1798 | Rev 1855 | 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;
1793 jpm 28
	private $parametres = array();
29
	private $ressources = array();
1845 jpm 30
	private $mappings = array();
31
	private $paramsFiltres = array();
1375 raphael 32
 
33
 
1845 jpm 34
	public function __construct(Conteneur $conteneur) {
35
		$this->conteneur = $conteneur;
36
		$this->conteneur->chargerConfiguration('config_departements_bruts.ini');
1375 raphael 37
 
1793 jpm 38
		$this->bdd = $this->conteneur->getBdd();
1845 jpm 39
		$this->filtrage = $this->conteneur->getParametresFiltrage();
40
		$this->sql = $this->conteneur->getSql();
41
		$this->navigation = $this->conteneur->getNavigation();
1375 raphael 42
 
1845 jpm 43
		$this->mappings['votes'] = $this->conteneur->getParametreTableau('votes.mapping');
44
		$this->mappings['commentaires'] = $this->conteneur->getParametreTableau('commentaires.mapping');
45
	}
1666 jpm 46
 
1793 jpm 47
	public function consulter($ressources, $parametres) {
1845 jpm 48
		$this->ressources = $ressources;
49
		$this->parametres = $parametres;
1666 jpm 50
 
1845 jpm 51
		$this->paramsFiltres = $this->filtrage->filtrerUrlParamsAppliObs();
52
		$this->sql->setParametres($this->paramsFiltres);
53
		$this->sql->ajouterContraintes();
54
		$this->sql->ajouterConstrainteAppliObs();
55
		$this->sql->definirOrdreSqlAppliObs();
1666 jpm 56
 
1845 jpm 57
		$idObs = $this->getIdObs();
58
		$this->navigation->setTotal($this->sql->getTotalLignesTrouvees());
1666 jpm 59
 
1845 jpm 60
		// Ce n'est pas la peine de continuer s'il n'y a pas eu de résultats
61
		$resultat = new ResultatService();
62
		$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => array());
63
		if (count($idObs) > 0) {
1666 jpm 64
 
1793 jpm 65
			// 2) récupération des données nécessaires pour ces observations (obs + images)
66
			// ici les champs récupérés sont issus de self::$sql_fields_liaisons mais sans préfixes
67
			// car tout provient de v_del_image
1845 jpm 68
			$obs_unfmt = $this->getInfos($idObs);
1666 jpm 69
 
1793 jpm 70
			// 3) suppression, merge des données en tableau assez représentatif du futur JSON en output
1845 jpm 71
			$observations = $this->formaterObservations($obs_unfmt);
1666 jpm 72
 
1793 jpm 73
			// 4) récupération des données nécessaires pour ces observations (commentaires + votes)
74
			// modifie $observations
1845 jpm 75
			$this->chargerDeterminations($observations, $idObs);
1666 jpm 76
 
1793 jpm 77
			// 5) restauration de l'ordre souhaité initialement
1845 jpm 78
			$observations = $this->ordonnerObservations($observations, $idObs);
79
 
80
			$resultat->corps = array(
81
				'entete' => $this->navigation->getEntete(),
82
				'resultats' => $observations);
1618 mathias 83
		}
84
		return $resultat;
1793 jpm 85
	}
1375 raphael 86
 
1793 jpm 87
	// SQL helpers
88
	/*
89
	 * Retourne une liste ordonnée d'id d'observation correspondant aux critères
90
	 * passés dans p et aux clauses where/join présentes dans le tableau $req
91
	 *
92
	 * @param p: $params (filtrés sauf escape-string)
93
	 * @param req: le tableau représentant les composants de la requete SQL
94
	 * @param db: l'instance de db
95
	 */
1845 jpm 96
	private function getIdObs() {
97
		$requete = 'SELECT SQL_CALC_FOUND_ROWS id_observation '.
98
			'FROM v_del_image AS vdi '.
99
			$this->sql->getJoin().
100
			'WHERE '.$this->sql->getWhere().
101
			$this->sql->getGroupBy().
102
			$this->sql->getOrderBy().
103
			$this->sql->getLimit().
104
			' -- '.__FILE__.':'.__LINE__;
1666 jpm 105
 
1845 jpm 106
		$resultats = $this->bdd->recupererTous($requete);
1375 raphael 107
 
1845 jpm 108
		$idObs = array();
109
		if ($resultats !== false ) {
110
			foreach ($resultats as $resultat) {
111
				$idObs[] = $resultat['id_observation'];
112
			}
1793 jpm 113
		}
1845 jpm 114
		return $idObs;
1375 raphael 115
	}
116
 
1793 jpm 117
	/**
1845 jpm 118
	 * Après avoir récupérer seulement les ids dans une première requête, nous récupérons maintenant les infos.
119
	 * Le web service est ainsi 3 fois plus rapide.
1793 jpm 120
	 */
1845 jpm 121
	private function getInfos($idObs) {
122
		$idsObsConcat = implode(',', $idObs);
123
		$requete = "SELECT id_observation, nom_sel AS `determination.ns`, nt AS `determination.nt`, ".
124
			'nom_sel_nn AS `determination.nn`, famille AS `determination.famille`, '.
125
			'nom_referentiel AS `determination.referentiel`, ce_zone_geo AS id_zone_geo, '.
126
			'zone_geo, lieudit, station, milieu, date_observation, mots_cles_texte, '.
127
			'date_transmission, commentaire, '.
128
			'ce_utilisateur AS `auteur.id`, prenom_utilisateur AS `auteur.prenom`, '.
129
			'nom_utilisateur AS `auteur.nom`, courriel_utilisateur AS `auteur.courriel`, '.
130
			'id_image, date_prise_de_vue AS `date`, hauteur, largeur, nom_original '.
131
			'FROM v_del_image AS vdi '.
132
			"WHERE id_observation IN ($idsObsConcat) ".
133
			' -- '.__FILE__.':'.__LINE__;
134
		return $this->bdd->recupererTous($requete);
1793 jpm 135
	}
1375 raphael 136
 
1793 jpm 137
	/**
1845 jpm 138
	 * Les informations étant extraites d'une vue dont les infos des obs sont dupliquées pour chaque image,
139
	 * il nous faut maintenant récupérer qu'une seule fois les données d'observations et y intégrer les données
140
	 * des images.
1793 jpm 141
	 */
1845 jpm 142
	private function formaterObservations($observations) {
143
		$observations = array_map('array_filter', $observations);
144
		$obsFormatees = array();
145
		foreach ($observations as $obs) {
146
			$this->nettoyerAuteur($obs);
147
			$image = $this->extraireInfosImage($obs);
1375 raphael 148
 
1845 jpm 149
			$id = 'idx-'.$obs['id_observation'];
150
			if (!isset($obsFormatees[$id])) {
151
				$obsFormatees[$id] = $obs;
1793 jpm 152
			}
1845 jpm 153
			$obsFormatees[$id]['images'][] = $image;
1793 jpm 154
		}
1845 jpm 155
		return $obsFormatees;
156
	}
1494 raphael 157
 
1845 jpm 158
	private function nettoyerAuteur(&$obs) {
159
		// car auteur.id peut être un email, un hash, ou un annuaire_tela.U_ID
160
		// mais dans les deux premiers cas SELECT courriel AS observateur fait déjà l'affaire
161
		if (!isset($obs['auteur.id']) || !is_numeric($obs['auteur.id'])) {
162
			$obs['auteur.id'] = "0";
1375 raphael 163
		}
1845 jpm 164
		if (!isset($obs['auteur.nom'])) {
165
			$obs['auteur.nom'] = '[inconnu]';
166
		}
1416 raphael 167
	}
1375 raphael 168
 
1845 jpm 169
	private function extraireInfosImage(&$obs) {
170
		$champsImageAffichables = array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original');
171
		$image = array_intersect_key($obs, array_flip($champsImageAffichables));
1375 raphael 172
 
1845 jpm 173
		$urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl');
174
		$image['binaire.href'] = sprintf($urlImgTpl, $image['id_image'], 'XL');
1498 raphael 175
 
1845 jpm 176
		unset($obs['id_image'], $obs['date'], $obs['hauteur'], $obs['largeur'], $obs['nom_original']);
177
		return $image;
178
	}
1498 raphael 179
 
1845 jpm 180
	private function ordonnerObservations($observations, $ordreDesObs) {
181
		$obsOrdonnees = array();
182
		foreach ($ordreDesObs as $id) {
183
			if (array_key_exists("idx-$id", $observations)) {
184
				$obsOrdonnees["idx-$id"] = $observations["idx-$id"];
185
				unset($observations["idx-$id"]);
1793 jpm 186
			}
187
		}
1845 jpm 188
		return $obsOrdonnees + $observations;
1793 jpm 189
	}
1375 raphael 190
 
1793 jpm 191
	/**
192
	 * Récupérer toutes les déterminations et le nombre de commentaire au total
193
	 * @param array $observations la liste des observations à mettre à jour
194
	 */
1845 jpm 195
	private function chargerDeterminations(&$observations, $idObs) {
196
		$idObsConcat = implode(',', $idObs);
197
		$requete = 'SELECT * '.
198
			'FROM del_commentaire AS dc '.
199
			'WHERE dc.nom_sel IS NOT NULL '.
200
			"AND ce_observation IN ($idObsConcat) ".
201
			'-- '.__FILE__.':'.__LINE__;
1375 raphael 202
 
1845 jpm 203
		$propositions = $this->bdd->recupererTous($requete);
204
		if ($propositions) {
205
			foreach ($propositions as $proposition) {
206
				$idObs = $proposition['ce_observation'];
207
				$idComment = $proposition['id_commentaire'];
208
				$comment = $this->formaterDetermination($idComment, $proposition);
209
				if ($comment) {
210
					$observations["idx-$idObs"]['commentaires'][$idComment] = $comment;
211
				}
212
			}
1793 jpm 213
		}
1494 raphael 214
	}
215
 
1845 jpm 216
	private function formaterDetermination($propositionId, $propositionInfos) {
217
		if (!$propositionInfos) return NULL;
1494 raphael 218
 
1845 jpm 219
		$propositionFormatee = array();
220
		foreach ($this->mappings['commentaires'] as $nomChamp => $nomAttributJson) {
221
			if (isset($propositionInfos[$nomChamp])) {
222
				$propositionFormatee[$nomAttributJson] = $propositionInfos[$nomChamp];
1793 jpm 223
			}
224
		}
1666 jpm 225
 
1793 jpm 226
		// Charger les votes sur les déterminations
1845 jpm 227
		$requete = "SELECT * FROM del_commentaire_vote WHERE ce_proposition = $propositionId".
228
			'-- '.__FILE__.':'.__LINE__;
229
		$resultatsVotes = $this->bdd->recupererTous($requete);
1793 jpm 230
		foreach ($resultatsVotes as $vote) {
1845 jpm 231
			$propositionFormatee['votes'][$vote['id_vote']] = $this->formaterVote($vote);
1793 jpm 232
		}
1386 raphael 233
 
1845 jpm 234
		$propositionFormatee['nb_commentaires'] = $this->chargerNombreCommentaire($propositionId);
1386 raphael 235
 
1845 jpm 236
		return $propositionFormatee;
1494 raphael 237
	}
1375 raphael 238
 
1793 jpm 239
	/**
240
	 * Formater un vote en fonction du fichier de configuration config_votes.ini
241
	 * @param $votes array()
242
	 */
243
	private function formaterVote($vote) {
1845 jpm 244
		$voteFormate = array();
245
		foreach ($vote as $nomChamp => $valeur) {
246
			$voteFormate[$this->mappings['votes'][$nomChamp]] = $valeur;
1375 raphael 247
		}
1845 jpm 248
		return $voteFormate;
1375 raphael 249
	}
1845 jpm 250
 
251
	private function chargerNombreCommentaire($propositionId) {
252
		$requete = 'SELECT COUNT( id_commentaire ) AS nb '.
253
			'FROM del_commentaire '.
254
			"WHERE ce_proposition = $propositionId ".
255
			'GROUP BY ce_proposition '.
256
			'-- '.__FILE__.':'.__LINE__;
257
		$commentaires = $this->bdd->recuperer($requete);
258
		return $commentaires ? $commentaires['nb'] : 0;
259
	}
1793 jpm 260
}