Subversion Repositories eFlore/Applications.cel

Rev

Rev 3228 | Rev 3239 | 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');
3231 delphine 114
		$retour['donnees']['image'] = I18n::get('Image');
115
		$retour['donnees']['chpsupp'] = I18n::get('Chpsupp');
116
		$retour['donnees']['resume'] = I18n::get('Resume');
3228 delphine 117
		$retour['donnees']['widget'] = $this->rechercherProjet();
118
		return $retour;
119
	}
120
 
121
	/* Recherche si le projet existe sinon va chercher les infos de base */
122
	private function rechercherProjet() {
123
		// projet avec un squelette défini (et non juste un mot-clé d'observation)
124
		$estProjetDefini = true; $tab = array();
125
		$url = $this->config['manager']['celUrlTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
126
		$json = $this->getDao()->consulter($url);
127
		$tableau = json_decode($json, true);
128
		if ($tableau== array()) {
129
			$estProjetDefini = false;
130
		} else {
131
			$tab = $this->rechercherChampsSupp();
132
		}
133
 
134
		$tableau = $this->traiterParametres($estProjetDefini, $tableau[0]);
135
		$tableau['especes'] = $this->rechercherInfosEspeces($tableau);
136
		if ($tableau['milieux'] != "") {
137
			$tableau['milieux']= explode(";", $tableau['milieux']);
138
		} else {
139
			$tableau['milieux'] = array();
140
		}
141
		$tableau['chpSupp'] = $tab;
142
		return $tableau;
143
	}
144
 
145
	/* Recherche si un projet a des champs de saisie supplémentaire */
146
	private function rechercherChampsSupp() {
147
		$retour = array();
148
		$url = $this->config['manager']['celChpSupTpl'].'?projet='.$this->parametres['projet'].'&langue='.$this->parametres['langue'];
149
		$json = $this->getDao()->consulter($url);
150
		$retour = (array) json_decode($json, true);
151
		foreach ($retour['sauvagessupp']['champs-supp'] as $key => $chsup) {
152
			if (isset($chsup['fieldValues'])) {
153
				$retour['sauvagessupp']['champs-supp'][$key]['fieldValues'] = json_decode($chsup['fieldValues'], true);
154
				if (isset($retour['sauvagessupp']['champs-supp'][$key]['fieldValues']["listValue"])) {
155
					foreach($retour['sauvagessupp']['champs-supp'][$key]['fieldValues']["listValue"] as $list_value) {
156
						// Obtenir une liste de valeurs utilisables dans les attributs for id ou name par exemple
157
						$retour['sauvagessupp']['champs-supp'][$key]['fieldValues']['cleanListValue'][] = 'val-' . preg_replace('/[^A-Za-z0-9_\-]/', '',$this->remove_accents($list_value));
158
					}
159
				}
160
			}
161
			$retour['sauvagessupp']['champs-supp'][$key]['mandatory'] = intval($chsup['mandatory']);
162
		}
163
		return $retour;
164
	}
165
 
166
	// remplace certains parametres définis en bd par les parametres définis dans l'url
167
	private function traiterParametres($estProjetDefini, $tableau) {
168
		$criteres = array('tag', 'motcle', 'projet', 'titre', 'logo');
169
		$criteresProjetNonDefini = array('commune', 'num_nom', 'referentiel');
170
		foreach($this->parametres as $nom_critere => $valeur_critere) {
171
			if (($estProjetDefini == false || $tableau['projet'] == "base") && in_array($nom_critere, $criteresProjetNonDefini)) {
172
				$tableau[$nom_critere] = $valeur_critere;
173
			} else if (in_array($nom_critere, $criteres)) {
174
				$tableau[$nom_critere] = $valeur_critere;
175
			}
176
		}
177
		return $tableau;
178
	}
179
 
180
 
181
	private function rechercherInfosEspeces($infos_projets) { //print_r($infos_projets);exit;
182
		$retour = ""; $referentiel = $infos_projets['referentiel'];
183
		$urlWsNsTpl = $this->config['chemins']['baseURLServicesEfloreTpl'];
184
		$urlWsNs = sprintf($urlWsNsTpl, self::EFLORE_API_VERSION, $referentiel, self::WS_NOM);
185
		$urlWsNsSansRef = sprintf($urlWsNsTpl, self::EFLORE_API_VERSION, '{referentiel}', self::WS_NOM);
186
		$retour['url_ws_autocompletion_ns'] = $urlWsNs;
187
		$retour['url_ws_autocompletion_ns_tpl'] = $urlWsNsSansRef;
188
		$retour['ns_referentiel'] = $referentiel;
189
 
190
		if (isset($infos_projets['type_especes'])) {
191
			switch ($infos_projets['type_especes']) {
192
				case "referentiel" : $referentiel = $infos_projets['referentiel']; break;
193
				case "liste" : $referentiel = $infos_projets['referentiel']; break;
194
				case "fixe" :
195
					$retour['especes'] = $this->chargerInfosTaxon($infos_projets['referentiel'], $infos_projets['especes']);
196
					break;
197
			}
198
		} else if (isset($infos_projets['referentiel'])) {
199
			$referentiel = $infos_projets['referentiel'];
200
			if (isset($infos_projets['num_nom'])) {
201
				$retour['especes'] = $this->chargerInfosTaxon($infos_projets['referentiel'], $infos_projets['num_nom']);
202
			}
203
		}
204
 
205
		$projetsAListeDeNoms = $this->transformerEnTableau($this->config['projets']['liste_noms']);
206
		if (in_array($this->projet, $projetsAListeDeNoms) && !$this->especeEstImposee()) {
207
			$projetsAListeDeNomsSciEtVerna = $this->transformerEnTableau($this->config['projets']['liste_noms_sci_et_verna']);
208
			if (in_array($this->projet, $projetsAListeDeNomsSciEtVerna)) {
209
				$retour['taxons'] = $this->recupererListeNoms();
210
			} else {
211
				$retour['taxons'] = $this->recupererListeNomsSci();
212
			}
213
		}
214
		return $retour;
215
	}
216
 
217
	/**
218
	 * Consulte un webservice pour obtenir des informations sur le taxon dont le
219
	 * numéro nomenclatural est $num_nom (ce sont donc plutôt des infos sur le nom
220
	 * et non le taxon?)
221
	 * @param string|int $num_nom
222
	 * @return array
223
	 */
224
	protected function chargerInfosTaxon($referentiel, $num_nom) {
225
		$url_service_infos = sprintf($this->config['chemins']['infosTaxonUrl'], $referentiel, $num_nom);
226
		$infos = json_decode(file_get_contents($url_service_infos));
227
		// trop de champs injectés dans les infos espèces peuvent
228
		// faire planter javascript
229
		$champs_a_garder = array('id', 'nom_sci','nom_sci_complet', 'nom_complet',
230
				'famille','nom_retenu.id', 'nom_retenu_complet', 'num_taxonomique');
231
		$resultat = array();
232
		$retour = array();
233
		if (isset($infos) && !empty($infos)) {
234
			$infos = (array)$infos;
235
			if (isset($infos['nom_sci']) && $infos['nom_sci'] != '') {
236
				$resultat = array_intersect_key($infos, array_flip($champs_a_garder));
237
				$resultat['retenu'] = ($infos['id'] == $infos['nom_retenu.id']) ? "true" : "false";
238
				$retour['espece_imposee'] = true;
239
				$retour['nn_espece_defaut'] = $nnEspeceImposee;
240
				$retour['nom_sci_espece_defaut'] = $resultat['nom_complet'];
241
				$retour['infos_espece'] = $this->array2js($resultat, true);
242
			}
243
		}
244
		return $retour;
245
	}
246
 
3120 delphine 247
 
3231 delphine 248
 
3228 delphine 249
	/**
250
	 * Trie par nom français les taxons lus dans le fichier tsv
251
	 */
252
	protected function recupererListeNomsSci() {
253
		$taxons = $this->recupererListeTaxon();
254
		if (is_array($taxons)) {
255
			$taxons = self::trierTableauMd($taxons, array('nom_fr' => SORT_ASC));
256
		}
257
		return $taxons;
258
	}
259
 
260
	/**
261
	 * @TODO documenter
262
	 * @return array
263
	 */
264
	protected function recupererListeNoms() {
265
		$taxons = $this->recupererListeTaxon();
266
		$nomsAAfficher = array();
267
		$nomsSpeciaux = array();
268
		if (is_array($taxons)) {
269
			foreach ($taxons as $taxon) {
270
				$nomSciTitle = $taxon['nom_ret'].
271
				($taxon['nom_fr'] != '' ? ' - '.$taxon['nom_fr'] : '' ).
272
				($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
273
				$nomFrTitle = $taxon['nom_sel'].
274
				($taxon['nom_ret'] != $taxon['nom_sel']? ' - '.$taxon['nom_ret'] : '' ).
275
				($taxon['nom_fr_autre'] != '' ? ' - '.$taxon['nom_fr_autre'] : '' );
276
 
277
				if ($taxon['groupe'] == 'special') {
278
					$nomsSpeciaux[] = array(
279
							'num_nom' => $taxon['num_nom_sel'],
280
							'nom_a_afficher' => $taxon['nom_fr'],
281
							'nom_a_sauver' => $taxon['nom_sel'],
282
							'nom_title' => $nomSciTitle,
283
							'nom_type' => 'nom-special');
284
				} else {
285
					$nomsAAfficher[] = array(
286
							'num_nom' => $taxon['num_nom_sel'],
287
							'nom_a_afficher' => $taxon['nom_sel'],
288
							'nom_a_sauver' => $taxon['nom_sel'],
289
							'nom_title' => $nomSciTitle,
290
							'nom_type' => 'nom-sci');
291
					$nomsAAfficher[] = array(
292
							'num_nom' => $taxon['num_nom_sel'],
293
							'nom_a_afficher' => $taxon['nom_fr'],
294
							'nom_a_sauver' => $taxon['nom_fr'],
295
							'nom_title' => $nomFrTitle,
296
							'nom_type' => 'nom-fr');
297
				}
298
			}
299
			$nomsAAfficher = self::trierTableauMd($nomsAAfficher, array('nom_a_afficher' => SORT_ASC));
300
			$nomsSpeciaux = self::trierTableauMd($nomsSpeciaux, array('nom_a_afficher' => SORT_ASC));
301
		}
302
		return array('speciaux' => $nomsSpeciaux, 'sci-et-fr' => $nomsAAfficher);
303
	}
304
 
305
	/**
306
	 * Lit une liste de taxons depuis un fichier tsv fourni
307
	 */
308
	protected function recupererListeTaxon() {
309
		$taxons = array();
310
		if ($this->projet == 'missions-flore') {
311
			$fichier_tsv = dirname(__FILE__).self::DS.'configurations'.self::DS.$this->projet.'_'.$this->mission.'_taxons.tsv';
312
		} else {
313
			$fichier_tsv = dirname(__FILE__).self::DS.'configurations'.self::DS.$this->projet.'_taxons.tsv';
314
		}
315
		if (file_exists($fichier_tsv) && is_readable($fichier_tsv)) {
316
			$taxons = $this->decomposerFichierTsv($fichier_tsv);
317
		} else {
318
			$this->debug[] = "Impossible d'ouvrir le fichier '$fichier_tsv'.";
319
		}
320
		return $taxons;
321
	}
322
 
323
	/**
324
	 * Découpe un fihcier tsv
325
	 */
326
	protected function decomposerFichierTsv($fichier, $delimiter = "\t"){
327
		$header = null;
328
		$data = array();
329
		if (($handle = fopen($fichier, 'r')) !== FALSE) {
330
			while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
331
				if (!$header) {
332
					$header = $row;
333
				} else {
334
					$data[] = array_combine($header, $row);
335
				}
336
			}
337
			fclose($handle);
338
		}
339
		return $data;
340
	}
341
 
342
	/**
343
	 * Convertit un tableau PHP en Javascript - @WTF pourquoi ne pas faire un json_encode ?
344
	 * @param array $array
345
	 * @param boolean $show_keys
346
	 * @return une portion de JSON représentant le tableau
347
	 */
348
	protected function array2js($array,$show_keys) {
349
		$tableauJs = '{}';
350
		if (!empty($array)) {
351
			$total = count($array) - 1;
352
			$i = 0;
353
			$dimensions = array();
354
			foreach ($array as $key => $value) {
355
				if (is_array($value)) {
356
					$dimensions[$i] = array2js($value,$show_keys);
357
					if ($show_keys) {
358
						$dimensions[$i] = '"'.$key.'":'.$dimensions[$i];
359
					}
360
				} else {
361
					$dimensions[$i] = '"'.addslashes($value).'"';
362
					if ($show_keys) {
363
						$dimensions[$i] = '"'.$key.'":'.$dimensions[$i];
364
					}
365
				}
366
				if ($i == 0) {
367
					$dimensions[$i] = '{'.$dimensions[$i];
368
				}
369
				if ($i == $total) {
370
					$dimensions[$i].= '}';
371
				}
372
				$i++;
373
			}
374
			$tableauJs = implode(',', $dimensions);
375
		}
376
		return $tableauJs;
377
	}
378
 
379
	private function remove_accents($string) {
380
		if ( !preg_match('/[\x80-\xff]/', $string) ) return $string;
381
 
382
		$chars = array(
383
			// Decompositions for Latin-1 Supplement
384
			chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
385
			chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
386
			chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
387
			chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
388
			chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
389
			chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
390
			chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
391
			chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
392
			chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
393
			chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
394
			chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
395
			chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
396
			chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
397
			chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
398
			chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
399
			chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
400
			chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
401
			chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
402
			chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
403
			chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
404
			chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
405
			chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
406
			chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
407
			chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
408
			chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
409
			chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
410
			chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
411
			chr(195).chr(191) => 'y',
412
			// Decompositions for Latin Extended-A
413
			chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
414
			chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
415
			chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
416
			chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
417
			chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
418
			chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
419
			chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
420
			chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
421
			chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
422
			chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
423
			chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
424
			chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
425
			chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
426
			chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
427
			chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
428
			chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
429
			chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
430
			chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
431
			chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
432
			chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
433
			chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
434
			chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
435
			chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
436
			chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
437
			chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
438
			chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
439
			chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
440
			chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
441
			chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
442
			chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
443
			chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
444
			chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
445
			chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
446
			chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
447
			chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
448
			chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
449
			chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
450
			chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
451
			chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
452
			chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
453
			chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
454
			chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
455
			chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
456
			chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
457
			chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
458
			chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
459
			chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
460
			chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
461
			chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
462
			chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
463
			chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
464
			chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
465
			chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
466
			chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
467
			chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
468
			chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
469
			chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
470
			chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
471
			chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
472
			chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
473
			chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
474
			chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
475
			chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
476
			chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
477
		);
478
 
479
		$string = strtr($string, $chars);
480
		return $string;
481
	}
3120 delphine 482
 
483
}
3228 delphine 484
?>