Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
417 aurelien 1
<?php
2
// In : utf8
3
// Out : utf8
4
 
540 david 5
// TODO : doublons
483 david 6
 
1321 aurelien 7
/**
480 david 8
Octobre 2010 David Delon.
9
Import d'observations dans le carnet en ligne à partir d'un fichier excel chargé par l'utilisateur
10
et liaison d'images déjà chargee aux observations ainsi crées.
417 aurelien 11
 
480 david 12
Nom des colonnes imposé, mais présence de toutes les colonnes non obligatoires, ordre non imposé
13
Aucune valeur dans les colonnes n'est obligatoire
14
Pour une ligne donnée, si tous les champs vides on ne fait rien, ou si seul le champ image est présent.
15
Si la seule différence entre deux lignes est la valeur de la colonne image, on considère que c'est la même observation à laquelle on associe plusieurs images.
16
Si au moins deux lignes (ou plus) sont complètement identiques on prend en compte une seule ligne (les doublons sont éliminés).
1321 aurelien 17
**/
445 david 18
 
480 david 19
// Nom des colonnes
20
 
445 david 21
define('COMMUNE','commune'); // soit un nom de commune, soit un code INSEE (5 chiffres), ou "nom de commune (numero departement)"
22
define('LIEUDIT','lieu-dit'); // Texte libre
23
define('STATION','station'); // Texte libre
24
define('MILIEU','milieu'); // Texte libre
25
define('LATITUDE','latitude'); // En decimal systeme WGS84
26
define('LONGITUDE','longitude'); // En decimal systeme WGS84
27
define('NOTES','notes'); // Texte libre
28
define('DATEOBS','date'); // date au format jj/mm/aaaa
29
define('ESPECE','espece'); // texte libre, nom latin, ou code nomenclatural (format BDNFFnn999999)
30
define('IMAGE','image'); //  nom des fichiers images préalablement uploadés sur le CEL séparés par des "/"
540 david 31
define('DEPARTEMENT','departement'); //  Texte libre
760 aurelien 32
define('TRANSMETTRE','transmettre'); //  "1" ou "oui", toute autre valeur (y compris vide) sera consideree comme "non""
445 david 33
 
540 david 34
 
480 david 35
// Resultat de l'analyse d'une ligne
445 david 36
define('LIGNE_VIDE',1); //
37
define('LIGNE_NORMALE',2); //
38
define('LIGNE_IMAGE_SEULEMENT',3); //
39
 
1321 aurelien 40
 
41
//TODO: refactoriser entièrement cette classe
970 aurelien 42
class InventoryImportExcel extends Cel  {
445 david 43
 
1321 aurelien 44
	// Element constituant une observation
760 aurelien 45
	var $format_observation=array(COMMUNE ,LIEUDIT ,STATION , DEPARTEMENT, MILIEU ,LATITUDE ,LONGITUDE ,NOTES ,DATEOBS ,ESPECE ,TRANSMETTRE, IMAGE );
480 david 46
 
1321 aurelien 47
	// Encapsulation classe lecture fichier excel
417 aurelien 48
	var $extendExcelReader;
49
 
1321 aurelien 50
	// Dernier numero d'ordre utilise
51
	var $dernier_ordre = 1;
760 aurelien 52
 
1321 aurelien 53
	var $cpt_images_liees = 0;
540 david 54
 
1321 aurelien 55
	/**
56
	 Constructeur
57
	**/
417 aurelien 58
	function InventoryImportExcel($config) {
59
 
1321 aurelien 60
		parent::__construct($config);
417 aurelien 61
		// Pas d'heritage multiple en php :(
62
		$this->extendExcelReader = new ExcelReader();
63
		$this->extendExcelReader->initExcelReader();
64
	}
65
 
1321 aurelien 66
	/**
67
	 Sur post
68
	**/
445 david 69
	function createElement($pairs) {
417 aurelien 70
 
1147 aurelien 71
		if(!isset($_SESSION)) {session_start();}
540 david 72
        $this->controleUtilisateur($pairs['utilisateur']);
480 david 73
 
540 david 74
        foreach($_FILES as $file) { // C'est le plus simple
75
            $infos_fichier = $file ;
76
        }
417 aurelien 77
 
1321 aurelien 78
		// Chargement tableau en memoire
445 david 79
		$data = new Spreadsheet_Excel_Reader($infos_fichier['tmp_name'], false); // false : pour menager la memoire.
480 david 80
		$arr = array();
445 david 81
 
82
		$rowcount=$data->rowcount(0);
83
		$colcount=$data->colcount(0);
84
 
85
		if ($rowcount<=1) { // TODO : retour erreur
86
			print "Tableau vide";
87
			exit;
88
		}
89
 
1321 aurelien 90
		// Chargement tableau
540 david 91
        for($row=1;$row<=$rowcount;$row++)
92
            for($col=1;$col<=$colcount;$col++)
93
                $arr[$col][$row] = $data->val($row,$col,0); // Attention, inversion voulue
760 aurelien 94
 
1321 aurelien 95
		// 1 : Traitement intitules
445 david 96
		$line = array();
417 aurelien 97
 
1321 aurelien 98
		/* Les colonnes ne sont pas forcemment dans l'ordre  : on les extrait pour traitement futur  */
540 david 99
        for($col=1;$col<=$colcount;$col++) {
100
            $colonne=strtolower($arr[$col][1]);
101
            $colonne=trim($colonne);
102
            $colonne=cp1252_to_utf8($colonne);
103
            $colonne=remove_accent($colonne);
104
            switch ($colonne) {  // On ne garde que les colonnes que l'on souhaite traiter
105
                case COMMUNE:
106
                case LIEUDIT:
107
                case STATION:
108
                case MILIEU:
109
                case DEPARTEMENT:
110
                case LATITUDE:
111
                case LONGITUDE:
112
                case NOTES:
113
                case DATEOBS:
114
                case ESPECE:
760 aurelien 115
                case TRANSMETTRE:
540 david 116
                case IMAGE:
117
                    $selection=array_values($arr[$col]);
118
                    array_shift($selection); // On ne garde pas la premiere ligne, qui contient les intitules
119
                    $line[$colonne]=$selection;
120
                    break;
445 david 121
 
540 david 122
            }
123
        }
1081 aurelien 124
		// 1 : Traitement lignes
483 david 125
		$cpt_obs=0;
760 aurelien 126
		$cpt_img=0;
540 david 127
 
128
        /* Recherche dernier numero d'ordre utilise : pas de mise a jour concurente a priori */
1321 aurelien 129
        $requete = "SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = ".$this->proteger($pairs['utilisateur'])." ";
130
		$resultat = $this->requeter($requete);
540 david 131
 
1321 aurelien 132
        if(is_array($resultat) && count($resultat) > 0) {
133
            $this->dernier_ordre = $resultat[0]['ordre']; // 1  par defaut
540 david 134
        }
135
 
480 david 136
		for ($i=0;$i<=$rowcount-1;$i++) {
540 david 137
			// On saute les eventuelles lignes vides du debut et les lignes contenant des information sur image uniquement
480 david 138
			while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
139
				if  ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
1321 aurelien 140
					// image non rattachée à une observation
480 david 141
				}
142
				else {
1321 aurelien 143
					// ligne vide
480 david 144
				}
445 david 145
				$i++;
146
			}
480 david 147
			while (($this->analyserLigne($line,$i)==LIGNE_NORMALE) && ($i<=$rowcount)) {
1321 aurelien 148
				$ordre=$this->traiterLigne($line,$i,$pairs['utilisateur']);
483 david 149
				if ($ordre>0) {
150
					$cpt_obs++; // Compteur d'observations crees
151
				}
445 david 152
				$i++;
480 david 153
				// On saute les lignes vide ou on traite les lignes suivantes contenant des informations sur image seulement
154
				while ((in_array($retour_analyse=$this->analyserLigne($line,$i),array(LIGNE_IMAGE_SEULEMENT, LIGNE_VIDE))) && ($i<=$rowcount)) {
445 david 155
					if  ($retour_analyse==LIGNE_IMAGE_SEULEMENT) {
480 david 156
						$this->traiterLigneComplement($line,$i,$pairs['utilisateur'],$ordre); // images supplementaires
445 david 157
					}
158
					else {
1321 aurelien 159
						// print "vide";
445 david 160
					}
161
					$i++;
162
				}
163
			}
164
		}
760 aurelien 165
		$message = '';
166
 
167
		if($this->cpt_images_liees > 0) {
168
			$message = $this->cpt_images_liees.' images liees pour ';
169
		}
170
 
171
		$message .= $cpt_obs;
172
		print $message;
417 aurelien 173
	}
174
 
1321 aurelien 175
	function analyserLigne($line,$i) {
760 aurelien 176
 
1321 aurelien 177
		$ligne_vide=true;
178
		$ligne_image_seulement=true;
179
		$ligne_normale=true;
180
 
181
		$ligne_identique_sauf_image = true;
182
 
183
		foreach ($this->format_observation as $colonne) {
760 aurelien 184
 
1321 aurelien 185
			if($i < 1) {
760 aurelien 186
				$ligne_identique_sauf_image = false;
1321 aurelien 187
			} else {
188
 
189
				if($colonne!= IMAGE && isset($line[$colonne]) && isset($line[$colonne][$i - 1]) && isset($line[$colonne][$i])
190
					&& $line[$colonne][$i - 1] != $line[$colonne][$i] && $line[$colonne][$i] != '') {
191
					$ligne_identique_sauf_image = false;
192
				}
193
			}
194
 
195
			if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
196
				if ($colonne!=IMAGE) {
197
					$ligne_image_seulement=false;
198
					$ligne_vide=false;
199
				}
445 david 200
				$ligne_vide=false;
201
			}
202
		}
1321 aurelien 203
 
204
		if ($ligne_vide) {
205
			return LIGNE_VIDE;
206
		}
445 david 207
		else {
1321 aurelien 208
			if ($ligne_image_seulement || $ligne_identique_sauf_image) {
209
				return LIGNE_IMAGE_SEULEMENT;
210
			}
211
			else {
212
				return LIGNE_NORMALE;
213
			}
445 david 214
		}
215
	}
417 aurelien 216
 
1321 aurelien 217
	function traiterLigne($line,$i,$utilisateur) {
218
		// Controle donnee et insertion
219
		$info_image=array();
220
		$info_transmettre = "0";
221
		$info_espece = array('en_id_nom' => '',
222
			'nom_sel' => '',
223
			'nom_ret' => '',
224
			'nom_ret_nn' => '',
225
			'nt' => '',
226
			'famille' => ''
227
		);
228
 
229
		foreach ($this->format_observation as $colonne) {
230
			if (isset ($line[$colonne][$i]) && $line[$colonne][$i]!='') {
231
				switch ($colonne) {  // On ne garde que les colonnes que l'on souhaite traiter
232
					case COMMUNE:
233
						$info_commune = $this->traiterCommune($line[COMMUNE][$i]);
234
						break;
235
					case LIEUDIT:
236
						$info_lieudit = $this->traiterLieudit($line[LIEUDIT][$i]);
237
						break;
238
					case STATION:
239
						$info_station = $this->traiterStation($line[STATION][$i]);
240
						break;
241
					case MILIEU:
242
						$info_milieu = $this->traiterMilieu($line[MILIEU][$i]);
243
						break;
244
	                case DEPARTEMENT:
245
						$info_commune['code'] = $this->traiterDepartement($line[DEPARTEMENT][$i]);
246
						break;
247
					case LATITUDE:
248
						$info_latitude = $this->traiterLatitude($line[LATITUDE][$i]);
249
						break;
250
					case LONGITUDE:
251
						$info_longitude = $this->traiterLongitude($line[LONGITUDE][$i]);
252
						break;
253
					case NOTES:
254
						$info_notes = $this->traiterNotes($line[NOTES][$i]);
255
						break;
256
					case DATEOBS:
257
						$info_dateobs = $this->traiterDateObs($line[DATEOBS][$i]);
258
						break;
259
					case TRANSMETTRE:
260
						$info_transmettre = $this->traiterTransmettre($line[TRANSMETTRE][$i]);
445 david 261
					break;
1321 aurelien 262
					case ESPECE:
263
						$chercheur_infos_taxon = new RechercheInfosTaxon($this->config);
264
						$resultat_recherche_espece = $chercheur_infos_taxon->rechercherInfosSurTexteCodeOuNumTax($line[ESPECE][$i]);
265
	                    if (isset($resultat_recherche_espece['en_id_nom']) && $resultat_recherche_espece['en_id_nom']!='') {
266
	                    	$info_espece['nom_sel'] = $resultat_recherche_espece['nom_sel'];
267
	                    	$info_espece['nom_sel_nn'] = $resultat_recherche_espece['en_id_nom'];
268
	                        $complement = $chercheur_infos_taxon->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
269
	                        $info_espece['nom_ret'] = $complement['Nom_Retenu'];
270
	                        $info_espece['nom_ret_nn'] = $complement['Num_Nom_Retenu'];
271
	                        $info_espece['nt'] = $complement['Num_Taxon'];
272
	                        $info_espece['famille'] = $complement['Famille'];
273
	                    } else {
274
	                    	$info_espece['nom_sel'] = $line[ESPECE][$i];
275
	                    }
276
	                    break;
277
					case IMAGE:
278
						$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / +  utilisateur
279
						break;
280
				}
445 david 281
			}
1321 aurelien 282
			else {
283
			 	switch($colonne) {
284
					case COMMUNE:
285
						$info_commune['nom']="";
286
						break;
287
					case LIEUDIT:
288
						$info_lieudit="";
289
						break;
290
					case STATION:
291
						$info_station="";
292
						break;
293
					case MILIEU:
294
						$info_milieu="";
295
						break;
296
					case DEPARTEMENT:
297
			            if (!isset ($info_commune['code']) || $info_commune['code']=='') {
298
						    $info_commune['code']="";
299
	                    }
300
						break;
301
					case LATITUDE:
302
						$info_latitude = "";
303
						break;
304
					case LONGITUDE:
305
						$info_longitude = "";
306
						break;
307
					case NOTES:
308
						$info_notes='';
309
						break;
310
					case TRANSMETTRE:
311
						$info_transmettre = "0";
480 david 312
					break;
1321 aurelien 313
				}
480 david 314
			}
315
		}
760 aurelien 316
 
1321 aurelien 317
        $this->dernier_ordre++;
318
        list($jour,$mois,$annee) = isset($info_dateobs) ? explode("/",$info_dateobs) : array(null,null,null);
319
        $info_dateobs=$annee."-".$mois."-".$jour." 0:0:0";
320
        $requete  = "INSERT INTO cel_obs (".
321
	        "ce_utilisateur,ordre,".
322
	        "nom_sel,nom_sel_nn,nom_ret,nom_ret_nn,nt,famille,".
323
	        "zone_geo,ce_zone_geo,".
324
	        "date_observation,".
325
	        "lieudit,station, milieu, commentaire, transmission, ".
326
	        "date_creation,date_modification,latitude,longitude) ".
327
	        " VALUES(".$this->proteger($utilisateur).",".
328
	        $this->proteger($this->dernier_ordre).",".
329
	        $this->proteger($info_espece['nom_sel']).",".
330
	        $this->proteger($info_espece['nom_sel_nn']).",".
331
	        $this->proteger($info_espece['nom_ret']).",".
332
	        $this->proteger($info_espece['nom_ret_nn']).",".
333
	        $this->proteger($info_espece['nt']).",".
334
	        $this->proteger($info_espece['famille']).",".
335
	        $this->proteger($info_commune['nom']).",".
336
	        $this->proteger($info_commune['code']).",".
337
	        $this->proteger($info_dateobs).",".
338
	        $this->proteger($info_lieudit).",".
339
	        $this->proteger($info_station).",".
340
	        $this->proteger($info_milieu).",".
341
	        $this->proteger($info_notes).",".
342
	        $this->proteger($info_transmettre).",".
343
	        "now() , now(),".
344
	        $this->proteger($info_latitude).",".
345
	        $this->proteger($info_longitude).")";
760 aurelien 346
 
1321 aurelien 347
		$insertion = $this->executer($requete);
348
 
349
		// creation lien image
350
		foreach ($info_image as $pic) {
351
 
352
			$requete_liaison = 'INSERT INTO cel_obs_images (id_image, id_utilisateur, id_observation ) VALUES ('.$this->proteger($pic['id_image']).','.$this->proteger($utilisateur).', '.$this->proteger($this->dernier_ordre).') ON DUPLICATE KEY UPDATE id_image = id_image ';
353
 
354
			$liaison = $this->executer($requete_liaison);
355
            if ($liaison !== false) {
356
            	$this->cpt_images_liees++;
357
            } else {
358
            	return false;
540 david 359
            }
1321 aurelien 360
		}
361
 
362
		return $this->dernier_ordre;
445 david 363
	}
364
 
1321 aurelien 365
	function traiterLigneComplement($line,$i,$utilisateur, $ordre = null) {
366
 
367
		$info_image=$this->traiterImage($line[IMAGE][$i],$utilisateur); // Image separee par des / +  utilisateur
368
		// creation lien image
369
		foreach ($info_image as $pic) {
370
			$requete = 'INSERT INTO cel_obs_images (id_image, id_utilisateur, id_observations) VALUES ('.$this->proteger($pic['id_image']).','.$this->proteger($utilisateur).', '.$this->proteger($this->dernier_ordre).') ON DUPLICATE KEY UPDATE id_image = id_image' ;
371
			$resultat_liaison = $this->executer($requete);
372
	    	if ($resultat_liaison !== false) {
373
	    		$this->cpt_images_liees++;
374
	    	} else {
375
	    		return false;
376
	    	}
377
		}
445 david 378
	}
379
 
1321 aurelien 380
	function traiterCommune($identifiant_commune) {
381
		// Recherche correspondance sur nom, si pas unique, correspondance dep. sinon code insee
382
	    $identifiant_commune=trim($identifiant_commune);
383
	    $identifiant_commune=utf8_encode($identifiant_commune); // FIXME : devrait deja etre en utf8 a ce niveau
1081 aurelien 384
 
1321 aurelien 385
		preg_match('/(.*) \(([0-9][0-9]*)\)/',$identifiant_commune,$elements);
386
 
387
		if (isset($elements[1])) { // commune + departement : montpellier (34)
388
			$nom_commune=$elements[1];
389
			$code_commune=$elements[2];
390
	 	    $requete="SELECT DISTINCT nom, code  FROM cel_zone_geo WHERE nom = ".$this->proteger($nom_commune)." AND code LIKE ".$this->proteger($code_commune.'%');
391
		}
392
		else { // Code insee seul
393
	        preg_match('/([0-9][0-9]*)|(2A[0-9][0-9]*)|(2B[0-9][0-9]*)/',$identifiant_commune,$elements);
394
	        if (isset($elements[1])) { // code insee  commune
395
	            $code_insee_commune=$elements[1];
396
	            $requete="SELECT DISTINCT nom, code  FROM cel_zones_geo WHERE code = ".$this->proteger($code_insee_commune);
397
	        }
398
	        else { // Commune seule (le departement sera recupere dans la colonne departement si elle est presente, on prend le risque ici de retourner une mauvaise
399
	               // Commune
400
	            preg_match('/(.*)/',$identifiant_commune,$elements);
401
	            if (isset($elements[1])) { // commune
402
	                $nom_commune=$elements[1];
403
	                $nom_commune=trim($nom_commune);
404
	                $nom_commune=utf8_decode($nom_commune);
405
	                $nom_commune=cp1252_to_utf8($nom_commune);
406
	                $nom_commune=remove_accent($nom_commune);
407
	                $nom_commune=preg_replace("/ /","%",$nom_commune);
408
	                $requete="SELECT DISTINCT nom, code  FROM cel_zones_geo WHERE nom like ".$this->proteger($nom_commune.'%');
409
	            }
410
	        }
411
		}
412
 
413
		$resultat_commune = $this->requeter($requete);
414
 
415
		// cas de la commune introuvable dans le référentiel
416
		if(!is_array($resultat_commune) || count($resultat_commune) == 0) {
417
			$resultat_commune['nom'] = fix_latin($identifiant_commune);
418
			$resultat_commune['code'] = 'NULL';
419
		} else {
420
			$resultat_commune = $resultat_commune[0];
421
		}
422
 
423
		return $resultat_commune;
1081 aurelien 424
	}
445 david 425
 
1321 aurelien 426
	function traiterLieudit($lieudit) {
427
		// texte libre
428
	    $lieudit=fix_latin($lieudit);
429
		return trim($lieudit);
430
	}
445 david 431
 
1321 aurelien 432
	function traiterStation($station) {
433
		// texte libre
434
	    $station=fix_latin($station);
435
		return trim($station);
436
	}
445 david 437
 
1321 aurelien 438
	function traiterMilieu($milieu) {
439
		// texte libre
440
	    $milieu=fix_latin($milieu);
441
		return trim($milieu);
442
	}
445 david 443
 
1321 aurelien 444
	function traiterDepartement($departement) {
445
		// texte libre
446
		if(is_numeric($departement) && strlen($departement) == 5) {
447
			$departement = substr($departement,0,2);
448
		}
449
 
450
		if(is_numeric($departement) && strlen($departement) == 4) {
451
			$departement = substr($departement,0,1);
452
			$departement = "0"+$departement;
453
		}
760 aurelien 454
 
1321 aurelien 455
		if(is_numeric($departement) && $departement <= 9) {
456
			$departement = "0"+$departement;
457
		}
458
		return utf8_encode(trim($departement));
760 aurelien 459
	}
1081 aurelien 460
 
1321 aurelien 461
	function traiterLatitude($latitude) {
462
		//  verifier formal decimal + limite france ? TODO
463
		return trim($latitude);
1081 aurelien 464
	}
760 aurelien 465
 
1321 aurelien 466
	function traiterLongitude($longitude) {
467
		// verifier format decimal + limite france ? TODO
468
		return trim($longitude);
469
	}
760 aurelien 470
 
1321 aurelien 471
	function traiterNotes($notes) {
472
		// texte libre
473
	    $notes=remove_accent($notes);
474
		return utf8_encode(trim($notes));
760 aurelien 475
	}
476
 
1321 aurelien 477
	function traiterDateObs($dateobs) {
478
		// verifier jj/mm/aaaa sinon date vide TODO
479
		$date = trim($dateobs);
480
		if(!preg_match("#[0-9]{2}/[0-9]{2}/([0-9]{4}|[0-9]{2})#", $date)) {
481
			$date = '00/00/0000';
482
		}
483
		return $date;
484
	}
760 aurelien 485
 
1321 aurelien 486
	function traiterTransmettre($transmettre) {
487
		$transmission = '0';
488
		if (trim($transmettre) == "1" || trim($transmettre) == "oui") {
489
			$transmission = '1';
490
		}
491
		return $transmission;
492
	}
540 david 493
 
1321 aurelien 494
	function traiterImage($images,$utilisateur) { // recherche id image de ce nom
495
		$liste_images = explode("/",$images) ;
496
		$row =array();
497
	   	foreach($liste_images as $image) {
498
			$requete = "SELECT * FROM cel_images WHERE ce_utilisateur = ".$this->proteger($utilisateur)." AND nom_original= ".$this->proteger($image);
499
			$ligne = $this->requeter($requete);
500
		    if(is_array($ligne) && !empty($ligne)) {
501
		    	$row[] = $ligne[0];
502
		    }
449 david 503
		}
1321 aurelien 504
		return $row;
480 david 505
	}
445 david 506
}
507
 
582 david 508
function init_byte_map(){
606 aurelien 509
    $byte_map = array();
582 david 510
    for($x=128;$x<256;++$x){
511
        $byte_map[chr($x)]=utf8_encode(chr($x));
512
    }
513
    $cp1252_map=array(
514
            "\x80"=>"\xE2\x82\xAC",    // EURO SIGN
515
            "\x82" => "\xE2\x80\x9A",  // SINGLE LOW-9 QUOTATION MARK
516
            "\x83" => "\xC6\x92",      // LATIN SMALL LETTER F WITH HOOK
517
            "\x84" => "\xE2\x80\x9E",  // DOUBLE LOW-9 QUOTATION MARK
518
            "\x85" => "\xE2\x80\xA6",  // HORIZONTAL ELLIPSIS
519
            "\x86" => "\xE2\x80\xA0",  // DAGGER
520
            "\x87" => "\xE2\x80\xA1",  // DOUBLE DAGGER
521
            "\x88" => "\xCB\x86",      // MODIFIER LETTER CIRCUMFLEX ACCENT
522
            "\x89" => "\xE2\x80\xB0",  // PER MILLE SIGN
523
            "\x8A" => "\xC5\xA0",      // LATIN CAPITAL LETTER S WITH CARON
524
            "\x8B" => "\xE2\x80\xB9",  // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
525
            "\x8C" => "\xC5\x92",      // LATIN CAPITAL LIGATURE OE
526
            "\x8E" => "\xC5\xBD",      // LATIN CAPITAL LETTER Z WITH CARON
527
            "\x91" => "\xE2\x80\x98",  // LEFT SINGLE QUOTATION MARK
528
            "\x92" => "\xE2\x80\x99",  // RIGHT SINGLE QUOTATION MARK
529
            "\x93" => "\xE2\x80\x9C",  // LEFT DOUBLE QUOTATION MARK
530
            "\x94" => "\xE2\x80\x9D",  // RIGHT DOUBLE QUOTATION MARK
531
            "\x95" => "\xE2\x80\xA2",  // BULLET
532
            "\x96" => "\xE2\x80\x93",  // EN DASH
533
            "\x97" => "\xE2\x80\x94",  // EM DASH
534
            "\x98" => "\xCB\x9C",      // SMALL TILDE
535
            "\x99" => "\xE2\x84\xA2",  // TRADE MARK SIGN
536
            "\x9A" => "\xC5\xA1",      // LATIN SMALL LETTER S WITH CARON
537
            "\x9B" => "\xE2\x80\xBA",  // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
538
            "\x9C" => "\xC5\x93",      // LATIN SMALL LIGATURE OE
539
            "\x9E" => "\xC5\xBE",      // LATIN SMALL LETTER Z WITH CARON
540
            "\x9F" => "\xC5\xB8"       // LATIN CAPITAL LETTER Y WITH DIAERESIS
541
                );
542
    foreach($cp1252_map as $k=>$v){
543
        $byte_map[$k]=$v;
544
    }
606 aurelien 545
 
546
    return $byte_map;
582 david 547
}
449 david 548
 
602 aurelien 549
function fix_latin($instr){
550
 
606 aurelien 551
    $byte_map = init_byte_map();
552
 
602 aurelien 553
    $ascii_char='[\x00-\x7F]';
554
    $cont_byte='[\x80-\xBF]';
555
    $utf8_2='[\xC0-\xDF]'.$cont_byte;
556
    $utf8_3='[\xE0-\xEF]'.$cont_byte.'{2}';
557
    $utf8_4='[\xF0-\xF7]'.$cont_byte.'{3}';
558
    $utf8_5='[\xF8-\xFB]'.$cont_byte.'{4}';
606 aurelien 559
 
602 aurelien 560
    $nibble_good_chars = "@^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$@s";
601 aurelien 561
 
582 david 562
    if(mb_check_encoding($instr,'UTF-8'))return $instr; // no need for the rest if it's all valid UTF-8 already
563
    $outstr='';
564
    $char='';
565
    $rest='';
566
    while((strlen($instr))>0){
602 aurelien 567
        if(1==@preg_match($nibble_good_chars,$instr,$match)){
582 david 568
            $char=$match[1];
569
            $rest=$match[2];
570
            $outstr.=$char;
602 aurelien 571
        }elseif(1==@preg_match('@^(.)(.*)$@s',$instr,$match)){
582 david 572
            $char=$match[1];
573
            $rest=$match[2];
574
            $outstr.=$byte_map[$char];
575
        }
576
        $instr=$rest;
577
    }
578
    return $outstr;
579
}
580
 
1321 aurelien 581
function remove_accent($str) {
540 david 582
  $a = array('À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î',
583
             'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß',
584
             'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î',
585
             'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā',
586
             'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď',
587
             'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ',
588
             'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ',
589
             'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ',
590
             'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ',
591
             'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ',
592
             'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ',
593
             'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż',
594
             'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ',
595
             'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ');
596
 
597
  $b = array('A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I',
598
             'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's',
599
             'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i',
600
             'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a',
601
             'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd',
602
             'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g',
603
             'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i',
604
             'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l',
605
             'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R',
606
             'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't',
607
             'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y',
608
             'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I',
609
             'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
610
  return str_replace($a, $b, $str);
611
}
449 david 612
 
540 david 613
function cp1252_to_utf8($str) {
1321 aurelien 614
	$cp1252_map = array ("\xc2\x80" => "\xe2\x82\xac",
615
		"\xc2\x82" => "\xe2\x80\x9a",
616
		"\xc2\x83" => "\xc6\x92",
617
		"\xc2\x84" => "\xe2\x80\x9e",
618
		"\xc2\x85" => "\xe2\x80\xa6",
619
		"\xc2\x86" => "\xe2\x80\xa0",
620
		"\xc2\x87" => "\xe2\x80\xa1",
621
		"\xc2\x88" => "\xcb\x86",
622
		"\xc2\x89" => "\xe2\x80\xb0",
623
		"\xc2\x8a" => "\xc5\xa0",
624
		"\xc2\x8b" => "\xe2\x80\xb9",
625
		"\xc2\x8c" => "\xc5\x92",
626
		"\xc2\x8e" => "\xc5\xbd",
627
		"\xc2\x91" => "\xe2\x80\x98",
628
		"\xc2\x92" => "\xe2\x80\x99",
629
		"\xc2\x93" => "\xe2\x80\x9c",
630
		"\xc2\x94" => "\xe2\x80\x9d",
631
		"\xc2\x95" => "\xe2\x80\xa2",
632
		"\xc2\x96" => "\xe2\x80\x93",
633
		"\xc2\x97" => "\xe2\x80\x94",
634
 
635
		"\xc2\x98" => "\xcb\x9c",
636
		"\xc2\x99" => "\xe2\x84\xa2",
637
		"\xc2\x9a" => "\xc5\xa1",
638
		"\xc2\x9b" => "\xe2\x80\xba",
639
		"\xc2\x9c" => "\xc5\x93",
640
		"\xc2\x9e" => "\xc5\xbe",
641
		"\xc2\x9f" => "\xc5\xb8"
642
	);
643
	return strtr(utf8_encode($str), $cp1252_map);
540 david 644
}
1321 aurelien 645
?>