Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 248 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
237 jpm 1
<?php
2
// declare(encoding='UTF-8');
3
/**
4
* Classe implémentant l'API d'eFlore Cartes pour le projet CHORODEP.
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 Cartes {
17
 
18
	private $parametres = array();
19
	private $ressources = array();
20
	private $Bdd;
21
 
22
	const CODE_REFTAX_DEFAUT = 'bdtfx';
23
	const TYPE_ID_DEFAUT = 'nn';
24
	const CARTE_DEFAUT = 'france_02';
25
	const FORMAT_DEFAUT = '550';
26
	const MIME_SVG = 'image/svg+xml';
27
	const MIME_PNG = 'image/png';
28
 
29
	private $config = array();
30
	private $cheminCartesBase = '';
31
	private $formats_supportes = array(self::MIME_SVG, self::MIME_PNG);
32
	private $UrlNavigation = null;
33
	private $taxonsDemandes = array();
34
	private $imgLargeur = 0;
35
	private $imgHauteur = 0;
36
 
37
	public function __construct(Bdd $bdd = null, Array $config = null, CacheSimple $cache = null) {
38
		$this->Bdd = is_null($bdd) ? new Bdd() : $bdd;
39
		$this->config = is_null($config) ? Config::get('Cartes') : $config;
40
		$this->cheminCartesBase = $this->config['chemin'];
41
		$cacheOptions = array('mise_en_cache' => $this->config['cache']['miseEnCache'],
42
			'stockage_chemin' => $this->config['cache']['stockageChemin'],
43
			'duree_de_vie' => $this->config['cache']['dureeDeVie']);
44
		//die(print_r($this->config, true));
45
		$this->cache = is_null($cache) ? new CacheSimple($cacheOptions) : $cache;
46
	}
47
 
48
	public function consulter($ressources, $parametres) {
49
		//$tpsDebut = microtime(true);
50
		$this->parametres = $parametres;
51
		$this->ressources = $ressources;
52
 
53
		$this->definirValeurParDefautDesParametres();
54
		$this->verifierParametres();
55
		$this->analyserIdentifiant();
56
 
57
		$resultat = new ResultatService();
58
		if ($this->parametres['retour'] == self::MIME_SVG) {
59
			$svg = $this->genererSVG();
60
			$resultat->corps = $svg;
61
		} else if ($this->parametres['retour'] == self::MIME_PNG) {
62
			$svg = $this->genererSVG();
63
			$png = $this->convertirEnPNG($svg);
64
			$resultat->corps = $png;
65
		}
66
		$resultat->mime = $this->parametres['retour'];
67
 
68
		return $resultat;
69
	}
70
 
71
	private function definirValeurParDefautDesParametres() {
72
		if (isset($this->parametres['retour']) == false) {
73
			$this->parametres['retour'] = self::MIME_SVG;
74
		}
75
		if (isset($this->parametres['retour.format']) == false) {
76
			$this->parametres['retour.format'] = self::FORMAT_DEFAUT;
77
		}
78
	}
79
 
80
	private function verifierParametres() {
81
		$erreurs = array();
82
 
83
		if ($this->verifierIdentifiants() == false) {
84
			$erreurs[] = "L'identifiant de ressource indiqué ne respecte pas le format attendu.";
85
		}
86
		if (isset($this->parametres['retour']) == false) {
87
			$erreurs[] = "Le paramètre type de retour 'retour' est obligatoire.";
88
		}
89
		if ($this->verifierValeurParametreRetour() == false) {
90
			$erreurs[] = "Le type de retour '{$this->parametres['retour']}' n'est pas supporté.";
91
		}
92
		if (isset($this->parametres['retour.format']) == false) {
93
			$erreurs[] = "Le paramètre de format de retour 'retour.format' est obligatoire.";
94
		}
95
		if ($this->verifierValeurParametreFormat() == false) {
96
			$erreurs[] = "Le type de format '{$this->parametres['retour.format']}' n'est pas supporté.".
97
				"Veuillez indiquer un nombre entier correspondant à la largeur désirée pour la carte.";
98
		}
99
 
100
		if (count($erreurs) > 0) {
101
			$message = implode('<br />', $erreurs);
102
			$code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
103
			throw new Exception($message, $code);
104
		}
105
	}
106
 
107
	private function verifierIdentifiants() {
108
		$ok = true;
109
		if (isset($this->ressources[0])) {
110
			$ids = $this->ressources[0];
111
			$projetPattern = '(?:(?:[A-Z0-9]+(\.(?:nn|nt)?):)?(?:[0-9]+,)*[0-9]+)';
112
			$patternComplet = "/^$projetPattern(?:;$projetPattern)*$/i";
113
			$ok = preg_match($patternComplet, $ids) ? true : false;
114
		}
115
		return $ok;
116
	}
117
 
118
	private function verifierValeurParametreRetour() {
119
		return in_array($this->parametres['retour'], $this->formats_supportes);
120
	}
121
 
122
	private function verifierValeurParametreFormat() {
123
		if ($ok = preg_match('/^([0-9]+)$/', $this->parametres['retour.format'], $match)) {
124
			$this->imgLargeur = $match[1];
125
		} else if ($ok = preg_match('/^([0-9]+)x([0-9]+)$/', $this->parametres['retour.format'], $match)) {
126
			$this->imgLargeur = $match[1];
127
			$this->imgHauteur = $match[2];
128
		}
129
		return $ok;
130
	}
131
 
132
	private function analyserIdentifiant() {
133
		if (isset($this->ressources[0])) {
134
			$ids = $this->ressources[0];
135
			if (preg_match('/^[0-9]+$/', $ids)) {
136
				$this->taxonsDemandes[self::CODE_REFTAX_DEFAUT]['nn'][] = $ids;
137
			} else {
138
				// ceci contient potentiellement des formes ref_tax1.nn:1,2;ref_tax2.nt:3,4
139
				throw new Exception("A implémenter : ressource id multiples");
140
				$projetsListeEtNumNoms = explode(';', $nn);
141
				if (count($projetsListeEtNumNoms) > 0) {
142
					foreach ($projetsListeEtNumNoms as $projetEtNumNoms) {
143
						$projetEtNumNoms = (strpos($projetEtNumNoms, ':')) ? $projetEtNumNoms : self::CODE_REFTAX_DEFAUT.':'.$projetEtNumNoms;
144
						list($projet, $numNoms) = explode(':', $projetEtNumNoms);
145
						$this->ref_tax_demande[$projet] = explode(',', $numNoms);
146
					}
147
				}
148
			}
149
		} else {
150
			throw new Exception("A implémenter : carte proportionnelle ensemble des infos");
151
		}
152
	}
153
 
154
	private function genererSVG() {
155
		$fichierCssBase = $this->cheminCartesBase.self::CARTE_DEFAUT.'.css';
156
		$css = file_get_contents($fichierCssBase);
157
		$css .= ".departement2b{fill:#ff0000;}";
158
 
159
		$idCss = $this->getIdFichierCss();
160
		$fichierCss = $this->config['cache']['stockageChemin'].$idCss.'.css';
161
		file_put_contents($fichierCss, $css);
162
		$urlCss = sprintf($this->config['cssUrlTpl'], $idCss);
163
 
164
		$fichierCarteSvg = $this->cheminCartesBase.self::CARTE_DEFAUT.'.svg';
165
 
166
		$dom = new DOMDocument('1.0', 'UTF-8');
167
		$dom->load($fichierCarteSvg);
168
		$racineElement = $dom->documentElement;
169
		$racineElement->setAttribute('width', $this->imgLargeur);
170
		$piCss = $dom->createProcessingInstruction('xml-stylesheet', 'type="text/css" href="'.$urlCss.'"');
171
		$dom->insertBefore($piCss, $racineElement);
172
		$svg = $dom->saveXML();
173
		return $svg;
174
	}
175
 
176
	private function chargerDonnees() {
177
		$refTax = self::CODE_REFTAX_DEFAUT;
178
		$numNom = $this->Bdd->proteger($this->taxonsDemandes[$refTax]['nn'][0]);
179
 
180
		$requete = 'SELECT   '.
181
			'FROM cel_obs_images AS coi '.
182
			'	LEFT JOIN cel_inventory AS ci '.
183
					'ON (coi.coi_ce_observation = ci.ordre AND coi.coi_ce_utilisateur = ci.identifiant) '.
184
			'WHERE ci.transmission = 1 '.
185
			"	AND ci.num_nom_ret IN ($numNom) ";
186
		$resultat = $this->Bdd->recupererTous($requete);
187
 
188
		if (!is_array($resultat) || count($resultat) <= 0) {
189
			$message = "Aucune donnée ne correspond à la ressource demandée";
190
			$code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
191
			throw new Exception($message, $code);
192
		}
193
 
194
	}
195
 
196
	private function getIdFichierCss() {
197
		$ids = isset($this->ressources[0]) ? $this->ressources[0] : 'globale';
198
		$idCss = str_replace(array(',', ';', ':'), '-', $ids);
199
		return $idCss;
200
	}
201
 
202
	private function convertirEnPNG($svg) {
203
		$png = null;
204
		if (extension_loaded('imagick')) {
205
			$png = $this->convertirEnPNGAvecImageMagick($svg);
206
		} else {
207
			$message = "Impossible de générer l'image sur le serveur. Extenssion ImageMagick abscente.";
208
			$code = RestServeur::HTTP_CODE_ERREUR;
209
			throw new Exception($message, $code);
210
		}
211
		return $svg;
212
	}
213
 
214
	private function convertirEnPNGAvecImageMagick($svg) {
215
		$convertisseur = new Imagick();
216
		$convertisseur->readImageBlob($svg);
217
		$convertisseur->setImageFormat("png24");
218
		$convertisseur->resizeImage($this->imgLargeur, $this->imgHauteur, imagick::FILTER_LANCZOS, 0);
219
		$png = $convertisseur->getImageBlob();
220
		$convertisseur->clear();
221
		$convertisseur->destroy();
222
		return $png;
223
	}
224
}
225
?>