Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
3228 delphine 1
 <?php
3120 delphine 2
// declare(encoding='UTF-8');
3
/**
4
 * Service affichant les dernières photo publiques du CEL ouvrable sous forme de diaporama.
5
 * Encodage en entrée : utf8
6
 * Encodage en sortie : utf8
7
 *
8
 * Cas d'utilisation et documentation :
9
 * @link http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=AideCELWidgetPhoto
10
 *
11
 * Paramètres :
12
 * ===> extra = booléen (1 ou 0)  [par défaut : 1]
13
 * Affiche / Cache la vignette en taille plus importante au bas du widget.
14
 * ===> vignette = [0-9]+,[0-9]+  [par défaut : 4,3]
15
 * Indique le nombre de vignette par ligne et le nombre de ligne.
16
 *
3228 delphine 17
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
18
 * @license	GPL v3 <http://www.gnu.org/licenses/gpl.txt>
19
 * @license	CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
20
 * @version	$Id$
21
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
3120 delphine 22
 */
23
class Saisie2 extends WidgetCommun {
3228 delphine 24
 
25
	const DS = DIRECTORY_SEPARATOR;
26
	const SERVICE_DEFAUT = 'saisie';
27
	const LANGUE_DEFAUT = 'fr';
28
	const PROJET_DEFAUT = 'base';
29
	const WS_NOM = 'noms';
30
	const EFLORE_API_VERSION = '0.1';
31
	private $cel_url_tpl = null;
32
	/** Si spécifié, on ajoute une barre de navigation inter-applications */
33
	private $bar;
34
	//private $parametres_autorises = array('projet', 'type', 'langue', 'order');
35
	private $parametres_autorises = array(
36
			'projet' => 'projet',
37
			'type' => 'type',
38
			'langue' => 'langue',
39
			'order' => 'order'
40
	);
41
	/**
42
	 * Méthode appelée par défaut pour charger ce widget.
43
	 */
44
	public function executer() {
45
		$retour = null;
46
		// Pour la création de l'id du cache nous ne tenons pas compte du paramètre de l'url callback
47
		unset($this->parametres['callback']);
48
		extract($this->parametres);
49
		$this->bar = (isset($bar)) ? $bar : false;
50
		/* Le fichier Framework.php du Framework de Tela Botanica doit être appelé avant tout autre chose dans l'application.
51
		 Sinon, rien ne sera chargé.
52
		 L'emplacement du Framework peut varier en fonction de l'environnement (test, prod...). Afin de faciliter la configuration
53
		 de l'emplacement du Framework, un fichier framework.defaut.php doit être renommé en framework.php et configuré pour chaque installation de
54
		 l'application.
55
		 Chemin du fichier chargeant le framework requis */
56
		$framework = dirname(__FILE__).'/framework.php';
57
		if (!file_exists($framework)) {
58
			$e = "Veuillez paramêtrer l'emplacement et la version du Framework dans le fichier $framework";
59
			trigger_error($e, E_USER_ERROR);
60
		} else {
61
			// Inclusion du Framework
62
			require_once $framework;
63
			// Ajout d'information concernant cette application
64
			Framework::setCheminAppli(__FILE__);// Obligatoire
65
			Framework::setInfoAppli(Config::get('info'));// Optionnel
66
 
67
		}
68
		$langue = (isset($langue)) ? $langue : self::LANGUE_DEFAUT;
69
		$this->langue = I18n::setLangue($langue);
70
		$this->parametres['langue'] = $langue;
3120 delphine 71
 
3228 delphine 72
		if (!isset($mode)) {
73
			$mode = self::SERVICE_DEFAUT;
74
		}
75
		if (!isset($projet)) {
76
			$this->parametres['projet'] = self::PROJET_DEFAUT;
77
		}
78
 
79
		$methode = $this->traiterNomMethodeExecuter($mode);
80
		if (method_exists($this, $methode)) {
81
			$retour = $this->$methode();
82
		} else {
83
			$this->messages[] = "Ce type de service '$methode' n'est pas disponible.";
84
		}
85
 
86
		$contenu = '';
87
		if (is_null($retour)) {
88
			$this->messages[] = 'La ressource demandée a retourné une valeur nulle.';
89
		} else {
90
			if (isset($retour['donnees'])) {
91
				$retour['donnees']['prod'] = ($this->config['parametres']['modeServeur'] == "prod");
92
				$retour['donnees']['bar'] = $this->bar;
93
				$retour['donnees']['url_base'] = sprintf($this->config['chemins']['baseURLAbsoluDyn'], '');
94
				$retour['donnees']['url_ws_annuaire'] = sprintf($this->config['chemins']['baseURLServicesAnnuaireTpl'], 'utilisateur/identite-par-courriel/');
95
				$retour['donnees']['authTpl'] = $this->config['manager']['authTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
96
				$retour['donnees']['mode'] = $mode;
97
				$squelette = dirname(__FILE__).self::DS.'squelettes'.self::DS.$retour['squelette'].'.tpl.html';
98
				$contenu = $this->traiterSquelettePhp($squelette, $retour['donnees']);
99
			} else {
100
				$this->messages[] = 'Les données à transmettre au squelette sont nulles.';
101
			}
102
		}
103
		$this->envoyer($contenu);
104
	}
3120 delphine 105
 
3228 delphine 106
 
107
	private function executerSaisie() {
108
		$retour = array();
109
		$retour['squelette'] = 'saisie';
110
		$retour['donnees']['general'] = I18n::get('General');
111
		$retour['donnees']['aide'] = I18n::get('Aide');
112
		$retour['donnees']['observateur'] = I18n::get('Observateur');
113
		$retour['donnees']['observation'] = I18n::get('Observation');
114
		$retour['donnees']['widget'] = $this->rechercherProjet();
115
		return $retour;
116
	}
117
 
118
	/* Recherche si le projet existe sinon va chercher les infos de base */
119
	private function rechercherProjet() {
120
		// projet avec un squelette défini (et non juste un mot-clé d'observation)
121
		$estProjetDefini = true; $tab = array();
122
		$url = $this->config['manager']['celUrlTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
123
		$json = $this->getDao()->consulter($url);
124
		$tableau = json_decode($json, true);
125
		if ($tableau== array()) {
126
			$estProjetDefini = false;
127
		} else {
128
			$tab = $this->rechercherChampsSupp();
129
		}
130
 
131
		$tableau = $this->traiterParametres($estProjetDefini, $tableau[0]);
132
		$tableau['especes'] = $this->rechercherInfosEspeces($tableau);
133
		if ($tableau['milieux'] != "") {
134
			$tableau['milieux']= explode(";", $tableau['milieux']);
135
		} else {
136
			$tableau['milieux'] = array();
137
		}
138
		$tableau['chpSupp'] = $tab;
139
		return $tableau;
140
	}
141
 
142
	/* Recherche si un projet a des champs de saisie supplémentaire */
143
	private function rechercherChampsSupp() {
144
		$retour = array();
145
		$url = $this->config['manager']['celChpSupTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
146
		$json = $this->getDao()->consulter($url);
147
		$retour = (array) json_decode($json, true);
148
		foreach ($retour['sauvagessupp']['champs-supp'] as $key => $chsup) {
149
			if (isset($chsup['fieldValues'])) {
150
				$retour['sauvagessupp']['champs-supp'][$key]['fieldValues'] = json_decode($chsup['fieldValues'], true);
151
				if (isset($retour['sauvagessupp']['champs-supp'][$key]['fieldValues']["listValue"])) {
152
					foreach($retour['sauvagessupp']['champs-supp'][$key]['fieldValues']["listValue"] as $list_value) {
153
						// Obtenir une liste de valeurs utilisables dans les attributs for id ou name par exemple
154
						$retour['sauvagessupp']['champs-supp'][$key]['fieldValues']['cleanListValue'][] = 'val-' . preg_replace('/[^A-Za-z0-9_\-]/', '',$this->remove_accents($list_value));
155
					}
156
				}
157
			}
158
			$retour['sauvagessupp']['champs-supp'][$key]['mandatory'] = intval($chsup['mandatory']);
159
		}
160
		return $retour;
161
	}
162
 
163
	// remplace certains parametres définis en bd par les parametres définis dans l'url
164
	private function traiterParametres($estProjetDefini, $tableau) {
165
		$criteres = array('tag', 'motcle', 'projet', 'titre', 'logo');
166
		$criteresProjetNonDefini = array('commune', 'num_nom', 'referentiel');
167
		foreach($this->parametres as $nom_critere => $valeur_critere) {
168
			if (($estProjetDefini == false || $tableau['projet'] == "base") && in_array($nom_critere, $criteresProjetNonDefini)) {
169
				$tableau[$nom_critere] = $valeur_critere;
170
			} else if (in_array($nom_critere, $criteres)) {
171
				$tableau[$nom_critere] = $valeur_critere;
172
			}
173
		}
174
		return $tableau;
175
	}
176
 
177
 
178
	private function rechercherInfosEspeces($infos_projets) { //print_r($infos_projets);exit;
179
		$retour = ""; $referentiel = $infos_projets['referentiel'];
180
		$urlWsNsTpl = $this->config['chemins']['baseURLServicesEfloreTpl'];
181
		$urlWsNs = sprintf($urlWsNsTpl, self::EFLORE_API_VERSION, $referentiel, self::WS_NOM);
182
		$urlWsNsSansRef = sprintf($urlWsNsTpl, self::EFLORE_API_VERSION, '{referentiel}', self::WS_NOM);
183
		$retour['url_ws_autocompletion_ns'] = $urlWsNs;
184
		$retour['url_ws_autocompletion_ns_tpl'] = $urlWsNsSansRef;
185
		$retour['ns_referentiel'] = $referentiel;
186
 
187
		if (isset($infos_projets['type_especes'])) {
188
			switch ($infos_projets['type_especes']) {
189
				case "referentiel" : $referentiel = $infos_projets['referentiel']; break;
190
				case "liste" : $referentiel = $infos_projets['referentiel']; break;
191
				case "fixe" :
192
					$retour['especes'] = $this->chargerInfosTaxon($infos_projets['referentiel'], $infos_projets['especes']);
193
					break;
194
			}
195
		} else if (isset($infos_projets['referentiel'])) {
196
			$referentiel = $infos_projets['referentiel'];
197
			if (isset($infos_projets['num_nom'])) {
198
				$retour['especes'] = $this->chargerInfosTaxon($infos_projets['referentiel'], $infos_projets['num_nom']);
199
			}
200
		}
201
 
202
		$projetsAListeDeNoms = $this->transformerEnTableau($this->config['projets']['liste_noms']);
203
		if (in_array($this->projet, $projetsAListeDeNoms) && !$this->especeEstImposee()) {
204
			$projetsAListeDeNomsSciEtVerna = $this->transformerEnTableau($this->config['projets']['liste_noms_sci_et_verna']);
205
			if (in_array($this->projet, $projetsAListeDeNomsSciEtVerna)) {
206
				$retour['taxons'] = $this->recupererListeNoms();
207
			} else {
208
				$retour['taxons'] = $this->recupererListeNomsSci();
209
			}
210
		}
211
		return $retour;
212
	}
213
 
214
	/**
215
	 * Consulte un webservice pour obtenir des informations sur le taxon dont le
216
	 * numéro nomenclatural est $num_nom (ce sont donc plutôt des infos sur le nom
217
	 * et non le taxon?)
218
	 * @param string|int $num_nom
219
	 * @return array
220
	 */
221
	protected function chargerInfosTaxon($referentiel, $num_nom) {
222
		$url_service_infos = sprintf($this->config['chemins']['infosTaxonUrl'], $referentiel, $num_nom);
223
		$infos = json_decode(file_get_contents($url_service_infos));
224
		// trop de champs injectés dans les infos espèces peuvent
225
		// faire planter javascript
226
		$champs_a_garder = array('id', 'nom_sci','nom_sci_complet', 'nom_complet',
227
				'famille','nom_retenu.id', 'nom_retenu_complet', 'num_taxonomique');
228
		$resultat = array();
229
		$retour = array();
230
		if (isset($infos) && !empty($infos)) {
231
			$infos = (array)$infos;
232
			if (isset($infos['nom_sci']) && $infos['nom_sci'] != '') {
233
				$resultat = array_intersect_key($infos, array_flip($champs_a_garder));
234
				$resultat['retenu'] = ($infos['id'] == $infos['nom_retenu.id']) ? "true" : "false";
235
				$retour['espece_imposee'] = true;
236
				$retour['nn_espece_defaut'] = $nnEspeceImposee;
237
				$retour['nom_sci_espece_defaut'] = $resultat['nom_complet'];
238
				$retour['infos_espece'] = $this->array2js($resultat, true);
239
			}
240
		}
241
		return $retour;
242
	}
243
 
244
	protected function getReferentielImpose() {
245
		$referentiel_impose = true;
246
		if (!empty($_GET['referentiel']) && $_GET['referentiel'] != "autre") {
247
			$this->ns_referentiel = $_GET['referentiel'];
248
		} else if (isset($this->configProjet['referentiel'])) {
249
			$this->ns_referentiel = $this->configProjet['referentiel'];
250
		} else if (isset($this->configMission['referentiel'])) {
251
			$this->ns_referentiel = $this->configMission['referentiel'];
252
		} else {
253
			$referentiel_impose = false;
254
		}
255
		return $referentiel_impose;
256
	}
3120 delphine 257
 
3228 delphine 258
	/**
259
	 * Trie par nom français les taxons lus dans le fichier tsv
260
	 */
261
	protected function recupererListeNomsSci() {
262
		$taxons = $this->recupererListeTaxon();
263
		if (is_array($taxons)) {
264
			$taxons = self::trierTableauMd($taxons, array('nom_fr' => SORT_ASC));
265
		}
266
		return $taxons;
267
	}
268
 
269
	/**
270
	 * @TODO documenter
271
	 * @return array
272
	 */
273
	protected function recupererListeNoms() {
274
		$taxons = $this->recupererListeTaxon();
275
		$nomsAAfficher = array();
276
		$nomsSpeciaux = array();
277
		if (is_array($taxons)) {
278
			foreach ($taxons as $taxon) {
279
				$nomSciTitle = $taxon['nom_ret'].
280
				($taxon['nom_fr'] != '' ? ' - '.$taxon['nom_fr'] : '' ).
281
				($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
282
				$nomFrTitle = $taxon['nom_sel'].
283
				($taxon['nom_ret'] != $taxon['nom_sel']? ' - '.$taxon['nom_ret'] : '' ).
284
				($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
285
 
286
				if ($taxon['groupe'] == 'special') {
287
					$nomsSpeciaux[] = array(
288
							'num_nom' => $taxon['num_nom_sel'],
289
							'nom_a_afficher' => $taxon['nom_fr'],
290
							'nom_a_sauver' => $taxon['nom_sel'],
291
							'nom_title' => $nomSciTitle,
292
							'nom_type' => 'nom-special');
293
				} else {
294
					$nomsAAfficher[] = array(
295
							'num_nom' => $taxon['num_nom_sel'],
296
							'nom_a_afficher' => $taxon['nom_sel'],
297
							'nom_a_sauver' => $taxon['nom_sel'],
298
							'nom_title' => $nomSciTitle,
299
							'nom_type' => 'nom-sci');
300
					$nomsAAfficher[] = array(
301
							'num_nom' => $taxon['num_nom_sel'],
302
							'nom_a_afficher' => $taxon['nom_fr'],
303
							'nom_a_sauver' => $taxon['nom_fr'],
304
							'nom_title' => $nomFrTitle,
305
							'nom_type' => 'nom-fr');
306
				}
307
			}
308
			$nomsAAfficher = self::trierTableauMd($nomsAAfficher, array('nom_a_afficher' => SORT_ASC));
309
			$nomsSpeciaux = self::trierTableauMd($nomsSpeciaux, array('nom_a_afficher' => SORT_ASC));
310
		}
311
		return array('speciaux' => $nomsSpeciaux, 'sci-et-fr' => $nomsAAfficher);
312
	}
313
 
314
	/**
315
	 * Lit une liste de taxons depuis un fichier tsv fourni
316
	 */
317
	protected function recupererListeTaxon() {
318
		$taxons = array();
319
		if ($this->projet == 'missions-flore') {
320
			$fichier_tsv = dirname(__FILE__).self::DS.'configurations'.self::DS.$this->projet.'_'.$this->mission.'_taxons.tsv';
321
		} else {
322
			$fichier_tsv = dirname(__FILE__).self::DS.'configurations'.self::DS.$this->projet.'_taxons.tsv';
323
		}
324
		if (file_exists($fichier_tsv) && is_readable($fichier_tsv)) {
325
			$taxons = $this->decomposerFichierTsv($fichier_tsv);
326
		} else {
327
			$this->debug[] = "Impossible d'ouvrir le fichier '$fichier_tsv'.";
328
		}
329
		return $taxons;
330
	}
331
 
332
	/**
333
	 * Découpe un fihcier tsv
334
	 */
335
	protected function decomposerFichierTsv($fichier, $delimiter = "\t"){
336
		$header = null;
337
		$data = array();
338
		if (($handle = fopen($fichier, 'r')) !== FALSE) {
339
			while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
340
				if (!$header) {
341
					$header = $row;
342
				} else {
343
					$data[] = array_combine($header, $row);
344
				}
345
			}
346
			fclose($handle);
347
		}
348
		return $data;
349
	}
350
 
351
	/**
352
	 * Convertit un tableau PHP en Javascript - @WTF pourquoi ne pas faire un json_encode ?
353
	 * @param array $array
354
	 * @param boolean $show_keys
355
	 * @return une portion de JSON représentant le tableau
356
	 */
357
	protected function array2js($array,$show_keys) {
358
		$tableauJs = '{}';
359
		if (!empty($array)) {
360
			$total = count($array) - 1;
361
			$i = 0;
362
			$dimensions = array();
363
			foreach ($array as $key => $value) {
364
				if (is_array($value)) {
365
					$dimensions[$i] = array2js($value,$show_keys);
366
					if ($show_keys) {
367
						$dimensions[$i] = '"'.$key.'":'.$dimensions[$i];
368
					}
369
				} else {
370
					$dimensions[$i] = '"'.addslashes($value).'"';
371
					if ($show_keys) {
372
						$dimensions[$i] = '"'.$key.'":'.$dimensions[$i];
373
					}
374
				}
375
				if ($i == 0) {
376
					$dimensions[$i] = '{'.$dimensions[$i];
377
				}
378
				if ($i == $total) {
379
					$dimensions[$i].= '}';
380
				}
381
				$i++;
382
			}
383
			$tableauJs = implode(',', $dimensions);
384
		}
385
		return $tableauJs;
386
	}
387
 
388
	private function remove_accents($string) {
389
		if ( !preg_match('/[\x80-\xff]/', $string) ) return $string;
390
 
391
		$chars = array(
392
			// Decompositions for Latin-1 Supplement
393
			chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
394
			chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
395
			chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
396
			chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
397
			chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
398
			chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
399
			chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
400
			chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
401
			chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
402
			chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
403
			chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
404
			chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
405
			chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
406
			chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
407
			chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
408
			chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
409
			chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
410
			chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
411
			chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
412
			chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
413
			chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
414
			chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
415
			chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
416
			chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
417
			chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
418
			chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
419
			chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
420
			chr(195).chr(191) => 'y',
421
			// Decompositions for Latin Extended-A
422
			chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
423
			chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
424
			chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
425
			chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
426
			chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
427
			chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
428
			chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
429
			chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
430
			chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
431
			chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
432
			chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
433
			chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
434
			chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
435
			chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
436
			chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
437
			chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
438
			chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
439
			chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
440
			chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
441
			chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
442
			chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
443
			chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
444
			chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
445
			chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
446
			chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
447
			chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
448
			chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
449
			chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
450
			chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
451
			chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
452
			chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
453
			chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
454
			chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
455
			chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
456
			chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
457
			chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
458
			chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
459
			chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
460
			chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
461
			chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
462
			chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
463
			chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
464
			chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
465
			chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
466
			chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
467
			chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
468
			chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
469
			chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
470
			chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
471
			chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
472
			chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
473
			chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
474
			chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
475
			chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
476
			chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
477
			chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
478
			chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
479
			chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
480
			chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
481
			chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
482
			chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
483
			chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
484
			chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
485
			chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
486
		);
487
 
488
		$string = strtr($string, $chars);
489
		return $string;
490
	}
3120 delphine 491
 
492
}
3228 delphine 493
?>