1110 |
aurelien |
1 |
<?php
|
|
|
2 |
// declare(encoding='UTF-8');
|
|
|
3 |
/**
|
|
|
4 |
* Gère le sous-service Taxons de Cartes.
|
|
|
5 |
*
|
|
|
6 |
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=EfloreApi01Cartes
|
|
|
7 |
*
|
|
|
8 |
* @package eFlore/services
|
|
|
9 |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
|
|
|
10 |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
|
|
|
11 |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
|
|
|
12 |
* @version 1.0
|
|
|
13 |
* @copyright 1999-2012 Tela Botanica (accueil@tela-botanica.org)
|
|
|
14 |
*/
|
|
|
15 |
// TODO : Config et Outils sont des classes statiques qui doivent poser des pb pour les tests...
|
|
|
16 |
class FranceCartes {
|
|
|
17 |
|
|
|
18 |
private $parametres = array();
|
|
|
19 |
private $ressources = array();
|
|
|
20 |
|
|
|
21 |
protected $largeurOrig = 600;
|
|
|
22 |
protected $longeurOrig = 545;
|
|
|
23 |
|
|
|
24 |
protected $largeurDefaut = 600;
|
|
|
25 |
protected $largeurDemandee = 600;
|
|
|
26 |
|
|
|
27 |
protected $prefixe_id_zone = 'INSEE-D';
|
|
|
28 |
|
|
|
29 |
protected $options_cache = array();
|
|
|
30 |
|
|
|
31 |
const PRESENCE_CHOROLOGIE = '1';
|
|
|
32 |
|
|
|
33 |
public function __construct(Conteneur $conteneur) {
|
|
|
34 |
$this->Bdd = $conteneur->getBdd();
|
|
|
35 |
$this->tableOntologie = $conteneur->getParametre('bdd_table_ontologies');
|
|
|
36 |
$this->config = $conteneur->getParametre('Cartes');
|
|
|
37 |
$this->convertisseur = $this->config['convertisseur'];
|
|
|
38 |
$this->tableMeta = $conteneur->getParametre('bdd_table_meta');
|
|
|
39 |
$this->cheminCartesBase = $this->config['chemin'];
|
|
|
40 |
|
|
|
41 |
$this->options_cache = array('mise_en_cache' => $this->config['cache_miseEnCache'],
|
|
|
42 |
'stockage_chemin' => $this->config['cache_stockageChemin'],
|
|
|
43 |
'duree_de_vie' => $this->config['cache_dureeDeVie']);
|
|
|
44 |
}
|
|
|
45 |
|
|
|
46 |
public function consulter($ressources, $parametres) {
|
|
|
47 |
$this->parametres = $parametres;
|
|
|
48 |
$this->ressources = $ressources;
|
|
|
49 |
|
|
|
50 |
$this->chargerMetadonnees();
|
|
|
51 |
$this->definirVersion();
|
|
|
52 |
$this->tableChorodep = 'chorodep_v'.str_replace('.', '_', $this->version);
|
|
|
53 |
|
|
|
54 |
if(isset($parametres['retour.format']) && is_numeric($parametres['retour.format'])) {
|
|
|
55 |
$this->largeurDemandee = intval($parametres['retour.format']);
|
|
|
56 |
}
|
|
|
57 |
|
|
|
58 |
if(count($ressources) == 0) {
|
|
|
59 |
$resultat = $this->getCarteTaxonsParZones();
|
|
|
60 |
} else if($ressources[0] == "legende") {
|
|
|
61 |
$cache = $this->getCache('global');
|
|
|
62 |
if($cache != null) {
|
|
|
63 |
$max = $cache['nb_taxons_max'];
|
|
|
64 |
} else {
|
|
|
65 |
$max = $this->getNbMaxTaxonsParZones();
|
|
|
66 |
}
|
|
|
67 |
$resultat = $this->getLegendeCarteTaxonsParZones($max);
|
|
|
68 |
}
|
|
|
69 |
|
|
|
70 |
return $resultat;
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
private function chargerMetadonnees() {
|
|
|
74 |
$requete = 'SELECT * '.
|
|
|
75 |
"FROM {$this->tableMeta} ".
|
|
|
76 |
"ORDER BY date_creation DESC ";
|
|
|
77 |
$resultats = $this->Bdd->recupererTous($requete);
|
|
|
78 |
|
|
|
79 |
if (!is_array($resultats) || count($resultats) <= 0) {
|
|
|
80 |
$message = "Les méta-données n'ont pu être chargée pour la ressource demandée";
|
|
|
81 |
$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
|
|
|
82 |
throw new Exception($message, $code);
|
|
|
83 |
}
|
|
|
84 |
|
|
|
85 |
$this->metadonnees = $resultats;
|
|
|
86 |
}
|
|
|
87 |
|
|
|
88 |
private function definirVersion() {
|
|
|
89 |
$this->version = $this->metadonnees[0]['version'];
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
public function getLegendeCarteTaxonsParZones($nb_max) {
|
|
|
93 |
// TODO : mettre en config ou en ontologie ?
|
|
|
94 |
// mais ça fait encore un appel de plus aux ontologies
|
|
|
95 |
// qui sont déjà bien bien bien bien chargées
|
|
|
96 |
$this->couleurs_legende_globale = array("#808080", "#EFF8E1", "#F2E2C0", "#C9CC8D", "#C1E587", "#A0FF7D");
|
|
|
97 |
$couleurs = $this->couleurs_legende_globale;
|
|
|
98 |
$legende = array(
|
|
|
99 |
"seuil0" => array(
|
|
|
100 |
"code" => "",
|
|
|
101 |
"couleur" => $couleurs[0],
|
|
|
102 |
"css" => "",
|
|
|
103 |
"nom" => "Non renseignée",
|
|
|
104 |
"description" => "Zone géographique non renseignée."
|
|
|
105 |
)
|
|
|
106 |
);
|
|
|
107 |
array_shift($couleurs);
|
|
|
108 |
$borne_min = 0;
|
|
|
109 |
$borne_max = 500;
|
|
|
110 |
|
|
|
111 |
for($i = 1; $i <= 5; $i++) {
|
|
|
112 |
$borne_max = ($i == 5) ? $nb_max : $borne_max;
|
|
|
113 |
$legende["seuil".$i] = array(
|
|
|
114 |
"code" => "",
|
|
|
115 |
"couleur" => $couleurs[$i-1],
|
|
|
116 |
"css" => "",
|
|
|
117 |
"nom" => "de ".$borne_min." à ".$borne_max." taxons",
|
|
|
118 |
"description" => "de ".$borne_min." à ".$borne_max." taxons."
|
|
|
119 |
);
|
|
|
120 |
$borne_min = $borne_max + 1;
|
|
|
121 |
$borne_max = ($i == 5) ? $nb_max : ($i * 1200);
|
|
|
122 |
}
|
|
|
123 |
|
|
|
124 |
return $legende;
|
|
|
125 |
}
|
|
|
126 |
|
|
|
127 |
private function convertirLegendeVersCss($legende) {
|
|
|
128 |
$css = "";
|
|
|
129 |
foreach($legende as $cle => $item) {
|
|
|
130 |
if($item['css'] != '') {
|
|
|
131 |
$css .=
|
|
|
132 |
$item['css']." {"."\n".
|
|
|
133 |
" fill:".$item['couleur'].";"."\n".
|
|
|
134 |
"}"."\n\n";
|
|
|
135 |
}
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
return $css;
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
public function getCarteTaxonsParZones() {
|
|
|
142 |
$this->envoyerCacheSiExiste('global');
|
|
|
143 |
|
|
|
144 |
$taxonsParZones = $this->compterTaxonsParZones();
|
|
|
145 |
$legende = $this->getLegendeCarteTaxonsParZones($taxonsParZones['max']);
|
|
|
146 |
|
|
|
147 |
$infos_zones = array();
|
|
|
148 |
$max = 0;
|
|
|
149 |
|
|
|
150 |
foreach($taxonsParZones['nb_taxons_par_zones'] as $id_zone => $nb) {
|
|
|
151 |
$infos_zones[$id_zone] = "- ".$nb." taxons présents";
|
|
|
152 |
$legende[$this->getSeuil($nb)]['css'] .= $legende[$this->getSeuil($nb)]['css'] != "" ? ', ' : '' ;
|
|
|
153 |
$legende[$this->getSeuil($nb)]['css'] .= "#".$this->prefixe_id_zone.$id_zone;
|
|
|
154 |
$max = $max < $nb ? $nb : $max;
|
|
|
155 |
}
|
|
|
156 |
|
|
|
157 |
$this->style = $this->convertirLegendeVersCss($legende);
|
|
|
158 |
$svg = $this->assemblerSvg(
|
|
|
159 |
$this->calculerHauteur($this->largeurDemandee),
|
|
|
160 |
$this->largeurDemandee,
|
|
|
161 |
$this->style,
|
|
|
162 |
$infos_zones);
|
|
|
163 |
|
|
|
164 |
$this->sauverCache(array('style' => $this->style, 'infos_zones' => $infos_zones, 'nb_taxons_max' => $max), 'global');
|
|
|
165 |
$this->envoyerSvg($svg);
|
|
|
166 |
}
|
|
|
167 |
|
|
|
168 |
// Fonction bien pourrie pour renvoyer juste un max
|
|
|
169 |
// mais son résultat est mis en cache donc elle sera appelée environ
|
|
|
170 |
// une fois par an (et encore si on appelle la légende avant la carte)
|
|
|
171 |
public function getNbMaxTaxonsParZones() {
|
|
|
172 |
$taxonsParZones = $this->compterTaxonsParZones();
|
|
|
173 |
$max = 0;
|
|
|
174 |
|
|
|
175 |
foreach($taxonsParZones as $id_zone => $nb) {
|
|
|
176 |
$max = $max < $nb ? $nb : $max;
|
|
|
177 |
}
|
|
|
178 |
return $max;
|
|
|
179 |
}
|
|
|
180 |
|
|
|
181 |
public function getSeuil($nb_taxons) {
|
|
|
182 |
// TODO: factoriser les bornes avec la fonction qui gère la légende
|
|
|
183 |
$seuil = "";
|
|
|
184 |
if($nb_taxons <= 1) {
|
|
|
185 |
$seuil = "1";
|
|
|
186 |
} elseif (2 <= $nb_taxons && $nb_taxons <= 1200) {
|
|
|
187 |
$seuil = "2";
|
|
|
188 |
} elseif (1201 <= $nb_taxons && $nb_taxons <= 2400) {
|
|
|
189 |
$seuil = "3";
|
|
|
190 |
} elseif (2401 <= $nb_taxons && $nb_taxons <= 3600) {
|
|
|
191 |
$seuil = "4";
|
|
|
192 |
} elseif (3601 <= $nb_taxons) {
|
|
|
193 |
$seuil = "5";
|
|
|
194 |
}
|
|
|
195 |
return "seuil".$seuil;
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
public function compterTaxonsParZones() {
|
|
|
199 |
$req = "SELECT * FROM ".$this->tableChorodep;
|
|
|
200 |
$resultat = $this->Bdd->recupererTous($req);
|
|
|
201 |
|
|
|
202 |
$max = 0;
|
|
|
203 |
$nb_taxons_par_zones = array();
|
|
|
204 |
|
|
|
205 |
foreach($resultat as $ligne) {
|
|
|
206 |
$i = 0;
|
|
|
207 |
for($i < 0; $i <= 100; $i++) {
|
|
|
208 |
$index = $i < 10 ? "0".$i : $i;
|
|
|
209 |
if(isset($ligne[$index]) && $ligne[$index] != "" && $ligne[$index] == self::PRESENCE_CHOROLOGIE) {
|
|
|
210 |
// seules les présences certaines sont prises en compte
|
|
|
211 |
$nb_taxons_par_zones[$index] = isset($nb_taxons_par_zones[$index]) ? $nb_taxons_par_zones[$index] : 0;
|
|
|
212 |
$nb_taxons_par_zones[$index] += 1;
|
|
|
213 |
// calcul du max qui sert à générer la légende
|
|
|
214 |
$max = $nb_taxons_par_zones[$index] > $max ? $nb_taxons_par_zones[$index] : $max;
|
|
|
215 |
}
|
|
|
216 |
}
|
|
|
217 |
}
|
|
|
218 |
|
|
|
219 |
return array('nb_taxons_par_zones' => $nb_taxons_par_zones, 'max' => $max);
|
|
|
220 |
}
|
|
|
221 |
|
|
|
222 |
public function sauverCache($a_cacher, $cache_id) {
|
|
|
223 |
$cache = new CacheSimple($this->options_cache);
|
|
|
224 |
return $cache->sauver(serialize($a_cacher), $cache_id);
|
|
|
225 |
}
|
|
|
226 |
|
|
|
227 |
public function getCache($id) {
|
|
|
228 |
$cache = new CacheSimple($this->options_cache);
|
|
|
229 |
if(($contenu_cache = $cache->charger($id)) !== false) {
|
|
|
230 |
$contenu_cache = unserialize($contenu_cache);
|
|
|
231 |
}
|
|
|
232 |
return $contenu_cache;
|
|
|
233 |
}
|
|
|
234 |
|
|
|
235 |
private function calculerHauteur($largeur) {
|
|
|
236 |
$rapport = $this->longeurOrig/$this->largeurOrig;
|
|
|
237 |
$hauteur = $rapport * $largeur;
|
|
|
238 |
return intval($hauteur);
|
|
|
239 |
}
|
|
|
240 |
|
|
|
241 |
private function envoyerCacheSiExiste($id) {
|
|
|
242 |
if(($cache = $this->getCache($id))) {
|
|
|
243 |
$style = $cache['style'];
|
|
|
244 |
$infos_zones = $cache['infos_zones'];
|
|
|
245 |
$cache = $this->assemblerSvg($this->calculerHauteur($this->largeurDemandee), $this->largeurDemandee, $style, $infos_zones);
|
|
|
246 |
$this->envoyerSvg($cache);
|
|
|
247 |
}
|
|
|
248 |
}
|
|
|
249 |
|
|
|
250 |
private function assemblerSvg($hauteur, $largeur, $style, $infos_zones) {
|
|
|
251 |
$tpl_svg = $this->cheminCartesBase.'/france_02.tpl.svg';
|
|
|
252 |
$donnees = array(
|
|
|
253 |
'hauteur' => $hauteur,
|
|
|
254 |
'largeur' => $largeur,
|
|
|
255 |
'css' => $style,
|
|
|
256 |
'infos_zones' => $infos_zones
|
|
|
257 |
);
|
|
|
258 |
$svg = SquelettePhp::analyser($tpl_svg, $donnees);
|
|
|
259 |
return $svg;
|
|
|
260 |
}
|
|
|
261 |
|
|
|
262 |
private function envoyerLegende($legende) {
|
|
|
263 |
header("Content-type: application/json");
|
|
|
264 |
echo json_encode($legende);
|
|
|
265 |
exit;
|
|
|
266 |
}
|
|
|
267 |
|
|
|
268 |
private function envoyerSvg($svg) {
|
|
|
269 |
header("Content-type: image/svg+xml");
|
|
|
270 |
echo $svg;
|
|
|
271 |
exit;
|
|
|
272 |
}
|
|
|
273 |
}
|