Subversion Repositories eFlore/Applications.cel

Rev

Rev 1640 | Rev 1646 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1640 Rev 1642
1
<?php
1
<?php
2
 
2
 
3
/**
3
/**
4
* @category  PHP
4
* @category  PHP
5
* @package   jrest
5
* @package   jrest
6
* @author    Raphaël Droz <raphael@tela-botania.org>
6
* @author    Raphaël Droz <raphael@tela-botania.org>
7
* @copyright 2013 Tela-Botanica
7
* @copyright 2013 Tela-Botanica
8
* @license   http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
8
* @license   http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
9
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
9
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
10
*/
10
*/
11
 
11
 
12
/**
12
/**
13
 * Service d'import de données d'observation du CEL au format XLS
13
 * Service d'import de données d'observation du CEL au format XLS
14
 */
14
 */
15
 
15
 
16
// sont define()'d commme n° de colonne tous les abbrevs retournés par ExportXLS::nom_d_ensemble_vers_liste_de_colonnes()
16
// sont define()'d commme n° de colonne tous les abbrevs retournés par ExportXLS::nom_d_ensemble_vers_liste_de_colonnes()
17
// préfixés par C_  cf: detectionEntete()
17
// préfixés par C_  cf: detectionEntete()
18
 
18
 
19
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
19
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
20
// TERM
20
// TERM
21
error_reporting(-1);
21
error_reporting(-1);
22
ini_set('html_errors', 0);
22
ini_set('html_errors', 0);
23
ini_set('xdebug.cli_color', 2);
23
ini_set('xdebug.cli_color', 2);
24
require_once('lib/PHPExcel/Classes/PHPExcel.php');
24
require_once('lib/PHPExcel/Classes/PHPExcel.php');
25
require_once('ExportXLS.php');
25
require_once('ExportXLS.php');
26
 
26
 
27
 
27
 
28
date_default_timezone_set("Europe/Paris");
28
date_default_timezone_set("Europe/Paris");
29
 
29
 
30
// nombre d'INSERT à cumuler par requête SQL
30
// nombre d'INSERT à cumuler par requête SQL
31
// (= nombre de lignes XLS à bufferiser)
31
// (= nombre de lignes XLS à bufferiser)
32
define('NB_LIRE_LIGNE_SIMUL', 30);
32
define('NB_LIRE_LIGNE_SIMUL', 30);
33
 
33
 
34
// Numbers of days between January 1, 1900 and 1970 (including 19 leap years)
34
// Numbers of days between January 1, 1900 and 1970 (including 19 leap years)
35
// see traiterDateObs()
35
// see traiterDateObs()
36
define("MIN_DATES_DIFF", 25569);
36
define("MIN_DATES_DIFF", 25569);
37
 
37
 
38
 
38
 
39
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
39
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
40
	// exclusion de colonnes
40
	// exclusion de colonnes
41
	public $exclues = array();
41
	public $exclues = array();
42
 
42
 
43
	// lecture par morceaux
43
	// lecture par morceaux
44
    public $ligne_debut = 0; 
44
    public $ligne_debut = 0; 
45
    public $ligne_fin = 0;
45
    public $ligne_fin = 0;
46
 
46
 
47
	public function __construct() {}
47
	public function __construct() {}
48
	public function def_interval($debut, $nb) {
48
	public function def_interval($debut, $nb) {
49
		$this->ligne_debut = $debut;
49
		$this->ligne_debut = $debut;
50
		$this->ligne_fin = $debut + $nb;
50
		$this->ligne_fin = $debut + $nb;
51
	}
51
	}
52
    public function readCell($colonne, $ligne, $worksheetName = '') {
52
    public function readCell($colonne, $ligne, $worksheetName = '') {
53
		if(@$this->exclues[$colonne]) return false;
53
		if(@$this->exclues[$colonne]) return false;
54
		// si des n° de morceaux ont été initialisés, on filtre...
54
		// si des n° de morceaux ont été initialisés, on filtre...
55
		if($this->ligne_debut && ($ligne < $this->ligne_debut || $ligne >= $this->ligne_fin)) return false;
55
		if($this->ligne_debut && ($ligne < $this->ligne_debut || $ligne >= $this->ligne_fin)) return false;
56
		return true;
56
		return true;
57
    } 
57
    } 
58
} 
58
} 
59
 
59
 
60
class ImportXLS extends Cel  {
60
class ImportXLS extends Cel  {
61
 
61
 
62
	static $ordre_BDD = Array(
62
	static $ordre_BDD = Array(
63
		"ce_utilisateur",
63
		"ce_utilisateur",
64
		"prenom_utilisateur",
64
		"prenom_utilisateur",
65
		"nom_utilisateur",
65
		"nom_utilisateur",
66
		"courriel_utilisateur",
66
		"courriel_utilisateur",
67
		"ordre",
67
		"ordre",
68
		"nom_sel",
68
		"nom_sel",
69
		"nom_sel_nn",
69
		"nom_sel_nn",
70
		"nom_ret",
70
		"nom_ret",
71
		"nom_ret_nn",
71
		"nom_ret_nn",
72
		"nt",
72
		"nt",
73
		"famille",
73
		"famille",
74
		"nom_referentiel",
74
		"nom_referentiel",
75
		"zone_geo",
75
		"zone_geo",
76
		"ce_zone_geo",
76
		"ce_zone_geo",
77
		"date_observation",
77
		"date_observation",
78
		"lieudit",
78
		"lieudit",
79
		"station",
79
		"station",
80
		"milieu",
80
		"milieu",
81
		"commentaire",
81
		"commentaire",
82
		"transmission",
82
		"transmission",
83
		"date_creation",
83
		"date_creation",
84
		"date_modification",
84
		"date_modification",
85
		"latitude",
85
		"latitude",
86
		"longitude");
86
		"longitude");
87
 
87
 
88
	/*
88
	/*
89
	  Ces colonnes:
89
	  Ces colonnes:
90
	  - sont propre à tous les enregistrements uploadés
90
	  - sont propres à l'ensemble des enregistrements uploadés
91
	  - sont indépendantes du numéro de lignes
91
	  - sont indépendantes du numéro de lignes
92
	  - n'ont pas de valeur par défaut dans la structure de la table
92
	  - n'ont pas de valeur par défaut dans la structure de la table
93
	  - nécessitent une initialisation dans le cadre de l'upload
93
	  - nécessitent une initialisation dans le cadre de l'upload
94
	*/
94
	*/
95
	public $colonnes_statiques = Array(
95
	public $colonnes_statiques = Array(
96
		"ce_utilisateur" => NULL,
96
		"ce_utilisateur" => NULL,
97
		"prenom_utilisateur" => NULL,
97
		"prenom_utilisateur" => NULL,
98
		"nom_utilisateur" => NULL,
98
		"nom_utilisateur" => NULL,
99
		"courriel_utilisateur" => NULL,
99
		"courriel_utilisateur" => NULL,
-
 
100
 
100
 
101
		// fixes (fonction SQL)
101
		// XXX: fixes (mais pourraient varier dans le futur si la mise-à-jour
102
		// XXX future: mais pourraient varier dans le futur si la mise-à-jour
102
		// d'observation est implémentée
103
		// d'observation est implémentée
103
		"date_creation" => NULL, // ne peut initialiser d'une date ici
104
		"date_creation" => "now()",
104
		"date_modification" => NULL, // idem, cf initialiser_colonnes_statiques()
105
		"date_modification" => "now()",
-
 
106
	);
-
 
107
 
-
 
108
	public $id_utilisateur = NULL;
-
 
109
	// erreurs d'import
105
	);
110
	public $bilan = Array();
106
 
111
 
107
	function ExportXLS($config) {
112
	function ExportXLS($config) {
108
		parent::__construct($config);
113
		parent::__construct($config);
109
	}
114
	}
110
 
115
 
111
	function createElement($pairs) {
116
	function createElement($pairs) {
112
		if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
117
		if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
113
			echo '0'; exit;
118
			echo '0'; exit;
114
		}
119
		}
115
		$id_utilisateur = intval($pairs['utilisateur']);
120
		$id_utilisateur = intval($pairs['utilisateur']);
-
 
121
		$this->id_utilisateur = $id_utilisateur; // pour traiterImage();
116
 
122
 
117
		if(!isset($_SESSION)) session_start();
123
		if(!isset($_SESSION)) session_start();
118
        $this->controleUtilisateur($id_utilisateur);
124
        $this->controleUtilisateur($id_utilisateur);
119
 
125
 
120
        $this->utilisateur = $this->getInfosComplementairesUtilisateur($id_utilisateur);
126
        $this->utilisateur = $this->getInfosComplementairesUtilisateur($id_utilisateur);
121
		$this->initialiser_colonnes_statiques($id_utilisateur);
127
		$this->initialiser_colonnes_statiques($id_utilisateur);
122
 
128
 
123
 
129
 
124
		$infos_fichier = array_pop($_FILES);
130
		$infos_fichier = array_pop($_FILES);
125
		
131
		
126
		/*$objPHPExcel = PHPExcel_IOFactory::load($infos_fichier['tmp_name']);
132
		/*$objPHPExcel = PHPExcel_IOFactory::load($infos_fichier['tmp_name']);
127
		  $donnees = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);*/
133
		  $donnees = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);*/
128
 
134
 
129
		/*$objReader = PHPExcel_IOFactory::createReader("Excel5");
135
		/*$objReader = PHPExcel_IOFactory::createReader("Excel5");
130
		$objReader->setReadDataOnly(true);
136
		$objReader->setReadDataOnly(true);
131
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/
137
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/
132
 
138
 
133
		//var_dump($donnees);
139
		//var_dump($donnees);
-
 
140
 
-
 
141
		// renomme le fichier pour lui ajouter son extension initiale, ce qui
-
 
142
		// permet (une sorte) d'autodétection du format.
-
 
143
		$fichier = $infos_fichier['tmp_name'];
-
 
144
		$extension = pathinfo($infos_fichier['name'], PATHINFO_EXTENSION);
-
 
145
		if( (strlen($extension) == 3 || strlen($extension) == 4) &&
-
 
146
			(rename($fichier, $fichier . '.' . $extension))) {
-
 
147
			$fichier = $fichier . '.' . $extension;
-
 
148
		}
134
 
149
 
135
		$objReader = PHPExcel_IOFactory::createReader("Excel5");
150
		$objReader = PHPExcel_IOFactory::createReaderForFile($fichier);
-
 
151
		$objReader->setReadDataOnly(true);
-
 
152
 
-
 
153
		if(is_a($objReader, 'PHPExcel_Reader_CSV')) {
-
 
154
			$objReader->setDelimiter(',')
-
 
155
				->setEnclosure('"')
-
 
156
				->setLineEnding("\n")
-
 
157
				->setSheetIndex(0);
136
		$objReader->setReadDataOnly(true);
158
		}
137
 
159
 
138
		// on ne conserve que l'en-tête
160
		// on ne conserve que l'en-tête
139
		$filtre = new MyReadFilter();
161
		$filtre = new MyReadFilter();
140
		$filtre->def_interval(1, 2);
162
		$filtre->def_interval(1, 2);
141
		$objReader->setReadFilter($filtre);
163
		$objReader->setReadFilter($filtre);
142
 
164
 
143
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
165
		$objPHPExcel = $objReader->load($fichier);
144
		$obj_infos = $objReader->listWorksheetInfo($infos_fichier['tmp_name']);
166
		$obj_infos = $objReader->listWorksheetInfo($fichier);
145
		// XXX: indépendant du readFilter ?
167
		// XXX: indépendant du readFilter ?
146
		$nb_lignes = $obj_infos[0]['totalRows'];
168
		$nb_lignes = $obj_infos[0]['totalRows'];
147
 
169
 
148
		$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
170
		$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
149
		$filtre->exclues = self::detectionEntete($donnees[1]);
171
		$filtre->exclues = self::detectionEntete($donnees[1]);
150
 
172
 
151
		$obs_ajouts = 0;
173
		$obs_ajouts = 0;
152
		$obs_maj = 0;
174
		$obs_maj = 0;
153
		$dernier_ordre = $this->requeter("SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = $id_utilisateur");
175
		$dernier_ordre = $this->requeter("SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = $id_utilisateur");
154
		$dernier_ordre = intval($dernier_ordre[0]['ordre']) + 1;
176
		$dernier_ordre = intval($dernier_ordre[0]['ordre']) + 1;
155
		if(! $dernier_ordre) $dernier_ordre = 0;
177
		if(! $dernier_ordre) $dernier_ordre = 0;
-
 
178
 
-
 
179
		// on catch to les trigger_error(E_USER_NOTICE);
-
 
180
		set_error_handler(array($this, 'erreurs_stock'), E_USER_NOTICE);
156
 
181
 
157
		// lecture par morceaux (chunks), NB_LIRE_LIGNE_SIMUL lignes à fois
182
		// lecture par morceaux (chunks), NB_LIRE_LIGNE_SIMUL lignes à fois
158
		// pour aboutir des requêtes SQL d'insert groupés.
183
		// pour aboutir des requêtes SQL d'insert groupés.
159
		for($ligne = 2; $ligne < $nb_lignes + NB_LIRE_LIGNE_SIMUL; $ligne += NB_LIRE_LIGNE_SIMUL) {
184
		for($ligne = 2; $ligne < $nb_lignes + NB_LIRE_LIGNE_SIMUL; $ligne += NB_LIRE_LIGNE_SIMUL) {
160
			$filtre->def_interval($ligne, NB_LIRE_LIGNE_SIMUL);
185
			$filtre->def_interval($ligne, NB_LIRE_LIGNE_SIMUL);
161
			$objReader->setReadFilter($filtre);
186
			$objReader->setReadFilter($filtre);
162
 
187
 
163
			/* recharge avec $filtre actif (filtre sur lignes colonnes):
188
			/* recharge avec $filtre actif (filtre sur lignes colonnes):
164
			   - exclue les colonnes inutiles/inutilisables)
189
			   - exclue les colonnes inutiles/inutilisables)
165
			   - ne selectionne que les lignes dans le range [$ligne - $ligne + NB_LIRE_LIGNE_SIMUL] */
190
			   - ne selectionne que les lignes dans le range [$ligne - $ligne + NB_LIRE_LIGNE_SIMUL] */
166
			$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
191
			$objPHPExcel = $objReader->load($fichier);
167
			$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
192
			$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
168
 
193
 
169
			// ici on appel la fonction qui fera effectivement l'insertion multiple
194
			// ici on appel la fonction qui fera effectivement l'insertion multiple
170
			// à partir des (au plus) NB_LIRE_LIGNE_SIMUL lignes
195
			// à partir des (au plus) NB_LIRE_LIGNE_SIMUL lignes
171
 
196
 
172
			// TODO: passer $this, ne sert que pour appeler des méthodes public qui pourraient être statiques
197
			// TODO: passer $this, ne sert que pour appeler des méthodes public qui pourraient être statiques
173
			// notamment dans RechercheInfosTaxonBeta.php
198
			// notamment dans RechercheInfosTaxonBeta.php
-
 
199
			list($enregistrements, $images) =
174
			self::chargerLignes($donnees, $this->colonnes_statiques, $dernier_ordre, $this, $obs_ajouts, $obs_maj);
200
				self::chargerLignes($this, $donnees, $this->colonnes_statiques, $dernier_ordre);
-
 
201
			if(! $enregistrements) break;
-
 
202
 
-
 
203
			$dernier_autoinc = self::stockerEnregistrements($this, $enregistrements);
-
 
204
			$obs_ajouts += count($enregistrements);
-
 
205
			// $obs_maj += count($enregistrements_a_MAJ);
-
 
206
			self::stockerImages($this, $enregistrements, $images, $dernier_autoinc);
175
		}
207
		}
-
 
208
 
176
		die('end');
209
		restore_error_handler();
-
 
210
 
-
 
211
		if($this->bilan) echo implode("\n", $this->bilan) . "\n";
-
 
212
		// fin: renvoi summary
-
 
213
		die("$obs_ajouts observations ajoutées");
177
	}
214
	}
178
 
215
 
179
	static function detectionEntete($entete) {
216
	static function detectionEntete($entete) {
180
		$colonnes_reconnues = Array();
217
		$colonnes_reconnues = Array();
181
		$cols = ExportXLS::nom_d_ensemble_vers_liste_de_colonnes('standard');
218
		$cols = ExportXLS::nom_d_ensemble_vers_liste_de_colonnes('standard');
182
		foreach($entete as $k => $v) {
219
		foreach($entete as $k => $v) {
183
			$entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
220
			$entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
184
			foreach($cols as $col) {
221
			foreach($cols as $col) {
185
				$entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
222
				$entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
186
				$entete_officiel_abbrev = $col['abbrev'];
223
				$entete_officiel_abbrev = $col['abbrev'];
187
				if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_abbrev) {
224
				if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_abbrev) {
188
					// debug echo "define C_" . strtoupper($entete_officiel_abbrev) . ", $k\n";
225
					//debug echo "define C_" . strtoupper($entete_officiel_abbrev) . ", $k ($v)\n";
189
					define("C_" . strtoupper($entete_officiel_abbrev), $k);
226
					define("C_" . strtoupper($entete_officiel_abbrev), $k);
190
					$colonnes_reconnues[$k] = 1;
227
					$colonnes_reconnues[$k] = 1;
191
					break;
228
					break;
192
				}
229
				}
193
			}
230
			}
194
		}
231
		}
195
 
232
 
196
		// prépare le filtre de PHPExcel qui évitera le traitement de toutes les colonnes superflues
233
		// prépare le filtre de PHPExcel qui évitera le traitement de toutes les colonnes superflues
197
 
234
 
198
		// eg: diff ( Array( H => Commune, I => rien ) , Array( H => 1, K => 1 )
235
		// eg: diff ( Array( H => Commune, I => rien ) , Array( H => 1, K => 1 )
199
		// ==> Array( I => rien )
236
		// ==> Array( I => rien )
200
		$colonnesID_non_reconnues = array_diff_key($entete, $colonnes_reconnues);
237
		$colonnesID_non_reconnues = array_diff_key($entete, $colonnes_reconnues);
201
 
238
 
202
		// des colonnes de ExportXLS::nom_d_ensemble_vers_liste_de_colonnes()
239
		// des colonnes de ExportXLS::nom_d_ensemble_vers_liste_de_colonnes()
203
		// ne retient que celles marquées "importables"
240
		// ne retient que celles marquées "importables"
204
		$colonnes_automatiques = array_filter($cols, function($v) {	return !$v['importable']; });
241
		$colonnes_automatiques = array_filter($cols, function($v) {	return !$v['importable']; });
205
 
242
 
206
		// ne conserve que le nom long pour matcher avec la ligne XLS d'entête
243
		// ne conserve que le nom long pour matcher avec la ligne XLS d'entête
207
		array_walk($colonnes_automatiques, function(&$v) {	$v = $v['nom']; });
244
		array_walk($colonnes_automatiques, function(&$v) {	$v = $v['nom']; });
208
 
245
 
209
		// intersect ( Array ( N => Milieu, S => Ordre ), Array ( ordre => Ordre, phenologie => Phénologie ) )
246
		// intersect ( Array ( N => Milieu, S => Ordre ), Array ( ordre => Ordre, phenologie => Phénologie ) )
210
		// ==> Array ( S => Ordre, AA => Phénologie )
247
		// ==> Array ( S => Ordre, AA => Phénologie )
211
		$colonnesID_a_exclure = array_intersect($entete, $colonnes_automatiques);
248
		$colonnesID_a_exclure = array_intersect($entete, $colonnes_automatiques);
212
 
249
 
213
		// TODO: pourquoi ne pas comparer avec les abbrevs aussi ?
250
		// TODO: pourquoi ne pas comparer avec les abbrevs aussi ?
214
		// merge ( Array( I => rien ) , Array ( S => Ordre, AA => Phénologie ) )
251
		// merge ( Array( I => rien ) , Array ( S => Ordre, AA => Phénologie ) )
215
		// ==> Array ( I => rien, AA => Phénologie )
252
		// ==> Array ( I => rien, AA => Phénologie )
216
		return array_merge($colonnesID_non_reconnues, $colonnesID_a_exclure);
253
		return array_merge($colonnesID_non_reconnues, $colonnesID_a_exclure);
217
	}
254
	}
218
 
255
 
219
	/*
256
	/*
220
	 * charge un groupe de lignes
257
	 * charge un groupe de lignes
221
	 */
258
	 */
222
	static function chargerLignes($lignes, $colonnes_statiques, &$dernier_ordre, $cel, &$inserted, &$updated) {
259
	static function chargerLignes($cel, $lignes, $colonnes_statiques, &$dernier_ordre) {
223
		$enregistrement = NULL;
260
		$enregistrement = NULL;
224
		$enregistrements = Array();
261
		$enregistrements = Array();
225
		$images = Array();
262
		$toutes_images = Array();
226
 
263
 
227
		foreach($lignes as $ligne) {
264
		foreach($lignes as $ligne) {
228
			$ligne = array_filter($ligne, function($cell) { return !is_null($cell); });
265
			//$ligne = array_filter($ligne, function($cell) { return !is_null($cell); });
-
 
266
			//if(!$ligne) continue;
-
 
267
			// on a besoin des NULL pour éviter des notice d'index indéfini
229
			if(!$ligne) continue;
268
			if(! array_filter($ligne, function($cell) { return !is_null($cell); })) continue;
230
 
269
 
231
			if( ($enregistrement = self::chargerLigne($ligne, $colonnes_statiques, $dernier_ordre, $cel)) ) {
270
			if( ($enregistrement = self::chargerLigne($ligne, $dernier_ordre, $cel)) ) {
232
				$enregistrements[] = $enregistrement;
271
				$enregistrements[] = array_merge($colonnes_statiques, $enregistrement);
233
 
272
 
234
				if(isset($enregistrement['_images'])) {
273
				if(isset($enregistrement['_images'])) {
235
					$pos = count($enregistrements) - 1;
274
					$pos = count($enregistrements) - 1;
-
 
275
					$last = &$enregistrements[$pos];
236
					// ne dépend pas de cel_obs, et seront insérées *après* les enregistrements
276
					// ne dépend pas de cel_obs, et seront insérées *après* les enregistrements
237
					// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
277
					// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
238
					$images[] = Array("text" => $enregistrements[$pos]['_images'],
278
					$toutes_images[] = Array("images" => $last['_images'],
239
									  "obs_pos" => $pos);
279
											 "obs_pos" => $pos);
240
					// ce champ n'a pas a faire partie de l'insertion dans cel_obs,
280
					// ce champ n'a pas a faire partie de l'insertion dans cel_obs,
241
					// mais est utile pour cel_obs_images
281
					// mais est utile pour cel_obs_images
242
					unset($enregistrements[$pos]['_images']);
282
					unset($last['_images']);
243
				}
283
				}
244
 
284
 
245
				$dernier_ordre++;
285
				$dernier_ordre++;
246
			}
286
			}
247
		}
287
		}
-
 
288
 
248
 
289
		// XXX future: return Array($enregistrements_a_inserer, $enregistrements_a_MAJ, $toutes_images);
-
 
290
		return Array($enregistrements, $toutes_images);
249
		if(!$enregistrements) die('AIE // XXX');
-
 
-
 
291
	}
-
 
292
 
250
 
293
 
251
		$req = '';
294
	static function stockerEnregistrements($cel, $enregistrements) {
-
 
295
		$req = '';
-
 
296
 
252
 
297
		foreach($enregistrements as $enregistrement) {
-
 
298
			$enregistrement = self::sortArrayByArray($enregistrement, self::$ordre_BDD);
-
 
299
			array_walk($enregistrement,
-
 
300
					   function(&$item, $k, $obj) { $item = is_null($item) ? "NULL" : $item; },
-
 
301
					   $cel);
253
 
302
			$req .= implode(', ', $enregistrement) . "\n";
254
		foreach($enregistrements as $enregistrement)
303
		}
255
			$req .= implode(', ', self::sortArrayByArray($enregistrement, self::$ordre_BDD));
304
		echo "$req\n";
256
		print_r($req);
305
		// TODO: insert
257
 
306
 
258
		// $cel->executer($req);
307
		// $cel->executer($req);
259
		// transactionnel + auto-inc
308
		// transactionnel + auto-inc
260
		$lastid = $cel->bdd->lastInsertId();
309
		return $cel->bdd->lastInsertId();
-
 
310
	}
-
 
311
 
-
 
312
 
-
 
313
	static function stockerImages($cel, $enregistrements, $toutes_images, $lastid) {
-
 
314
		if(! $lastid) $lastid = rand();
-
 
315
 
-
 
316
		$images_insert =
-
 
317
			'INSERT INTO cel_obs_images (id_image, id_observation) VALUES'
-
 
318
			.' %s '
-
 
319
			.'ON DUPLICATE KEY UPDATE id_image = id_image';
-
 
320
		$images_obs_assoc = Array();
-
 
321
 
261
		foreach($images as $image) {
322
		foreach($toutes_images as $images_pour_obs) {
262
			$obs = $enregistrements[$image["obs_pos"]];
323
			$obs = $enregistrements[$images_pour_obs["obs_pos"]];
263
			$id_obs = $lastid // dernier autoinc inséré
324
			$id_obs = $lastid // dernier autoinc inséré
264
				- count($enregistrements) - 1 // correspondrait au premier autoinc
325
				- count($enregistrements) - 1 // correspondrait au premier autoinc
265
				+ $image["obs_pos"]; // ordre d'insertion = ordre dans le tableau $enregistrements
326
				+ $images_pour_obs["obs_pos"]; // ordre d'insertion = ordre dans le tableau $enregistrements
-
 
327
			foreach($images_pour_obs['images'] as $image) {
-
 
328
				$images_obs_assoc[] = sprintf('(%d,%d)',
-
 
329
											  $image['id_image'], // intval() useless
-
 
330
											  $id_obs); // intval() useless
-
 
331
			}
-
 
332
		}
-
 
333
 
-
 
334
		if($images_obs_assoc) {
-
 
335
			$requete = sprintf($images_insert, implode(', ', $images_obs_assoc));
266
			// TODO: INSERT
336
			echo "$requete\n";
267
		}
337
		}
268
	}
338
	}
269
 
339
 
270
 
340
 
271
	static function chargerLigne($ligne, $colonnes_statiques, $dernier_ordre, $cel) {
341
	static function chargerLigne($ligne, $dernier_ordre, $cel) {
272
		// en premier car le résultat est utile pour
342
		// en premier car le résultat est utile pour
273
		// traiter longitude et latitude (traiterLonLat())
343
		// traiter longitude et latitude (traiterLonLat())
274
		$referentiel = self::identReferentiel($ligne[C_NOM_REFERENTIEL]);
344
		$referentiel = self::identReferentiel($ligne[C_NOM_REFERENTIEL]);
275
 
345
 
276
		// $espece est rempli de plusieurs informations
346
		// $espece est rempli de plusieurs informations
277
		$espece = Array();
347
		$espece = Array(C_NOM_SEL => NULL, C_NOM_SEL_NN => NULL, C_NOM_RET => NULL,
-
 
348
						C_NOM_RET_NN => NULL, C_NT => NULL, C_FAMILLE => NULL);
278
		self::traiterEspece($ligne, $espece, $cel);
349
		self::traiterEspece($ligne, $espece, $cel);
-
 
350
 
-
 
351
		// $localisation est rempli à partir de plusieurs champs: C_ZONE_GEO et C_CE_ZONE_GEO
279
 
352
		$localisation = Array(C_ZONE_GEO => NULL, C_CE_ZONE_GEO => NULL);
-
 
353
		self::traiterLocalisation($ligne, $localisation, $cel);
280
		return array_merge($colonnes_statiques,
354
 
281
						   // Dans ce tableau, seules devraient apparaître les données variable pour chaque ligne.
355
		// Dans ce tableau, seules devraient apparaître les données variable pour chaque ligne.
282
						   // Dans ce tableau, l'ordre des clefs n'importe pas (cf: self::sortArrayByArray())
356
		// Dans ce tableau, l'ordre des clefs n'importe pas (cf: self::sortArrayByArray())
283
						   Array(
357
		$enregistrement = Array(
284
							   "ordre" => $dernier_ordre,
358
			"ordre" => $dernier_ordre,
-
 
359
 
285
 
360
			// $this->quoteNonNull() est déjà appliquée dans traiterEspece()
286
							   "nom_sel" => $espece[C_NOM_SEL],
361
			"nom_sel" => $espece[C_NOM_SEL],
287
							   "nom_sel_nn" => $espece[C_NOM_SEL_NN],
362
			"nom_sel_nn" => $espece[C_NOM_SEL_NN],
288
							   "nom_ret" => $espece[C_NOM_RET],
363
			"nom_ret" => $espece[C_NOM_RET],
289
							   "nom_ret_nn" => $espece[C_NOM_RET_NN],
364
			"nom_ret_nn" => $espece[C_NOM_RET_NN],
290
							   "nt" => $espece[C_NT],
365
			"nt" => $espece[C_NT],
291
							   "famille" => $espece[C_FAMILLE],
366
			"famille" => $espece[C_FAMILLE],
292
 
367
 
293
							   "nom_referentiel" => $referentiel,
368
			"nom_referentiel" => $cel->quoteNonNull($referentiel),
-
 
369
 
294
 
370
			// $this->quoteNonNull() est déjà appliquée dans traiterLocalisation()
295
							   "zone_geo" => TODO,
371
			"zone_geo" => $localisation[C_ZONE_GEO],
296
							   "ce_zone_geo" => self::traiterDepartement(trim($ligne[C_CE_ZONE_GEO])),
372
			"ce_zone_geo" => $localisation[C_CE_ZONE_GEO],
-
 
373
 
297
 
374
			// $ligne: uniquement pour les infos en cas de gestion d'erreurs (date incompréhensible)
-
 
375
			"date_observation" => $cel->quoteNonNull(self::traiterDateObs($ligne[C_DATE_OBSERVATION], $ligne)),
298
							   "date_observation" => self::traiterDateObs($ligne[C_DATE_OBSERVATION]),
376
 
299
							   "lieudit" => trim($ligne[C_LIEUDIT]),
377
			"lieudit" => $cel->quoteNonNull(trim($ligne[C_LIEUDIT])),
300
							   "station" => trim($ligne[C_STATION]),
378
			"station" => $cel->quoteNonNull(trim($ligne[C_STATION])),
301
							   "milieu" => trim($ligne[C_MILIEU]),
379
			"milieu" => $cel->quoteNonNull(trim($ligne[C_MILIEU])),
-
 
380
			"commentaire" => $cel->quoteNonNull(trim($ligne[C_COMMENTAIRE])), // TODO: foreign-key
302
							   "commentaire" => trim($ligne[C_COMMENTAIRE]), // TODO: foreign-key
381
 
303
 
382
 
304
							   "transmission" => in_array(strtolower(trim($ligne[C_TRANSMISSION])), array(1, 'oui')) ? 1 : 0,
383
			"transmission" => in_array(strtolower(trim($ligne[C_TRANSMISSION])), array(1, 'oui')) ? 1 : 0,
-
 
384
 
305
 
385
			// $ligne: uniquement pour les infos en cas de gestion d'erreurs (lon/lat incompréhensible)
306
							   "latitude" => self::traiterLonLat(NULL, $ligne[C_LATITUDE], $referentiel),
386
			"latitude" => self::traiterLonLat(NULL, $ligne[C_LATITUDE], $referentiel, $ligne),
307
							   "longitude" => self::traiterLonLat($ligne[C_LONGITUDE], NULL, $referentiel),
387
			"longitude" => self::traiterLonLat($ligne[C_LONGITUDE], NULL, $referentiel, $ligne),
-
 
388
		);
-
 
389
 
-
 
390
		// passage de $enregistrement par référence, ainsi ['_images'] n'est défini
-
 
391
		// que si des résultats sont trouvés
-
 
392
		// "@" car PHPExcel supprime les colonnes null sur toute la feuille (ou tout le chunk)
-
 
393
		if(@$ligne[C_IMAGES]) self::traiterImage($ligne[C_IMAGES], $cel, $enregistrement);
-
 
394
 
308
						   ));
395
		return $enregistrement;
-
 
396
	}
-
 
397
 
-
 
398
	static function traiterImage($str, $cel, &$enregistrement) {
-
 
399
		$liste_images = array_filter(explode("/", $str));
-
 
400
		array_walk($liste_images,
-
 
401
				   function($item, $key, $obj) { $item = $obj->quoteNonNull(trim($item)); },
-
 
402
				   $cel);
-
 
403
		$requete = sprintf(
-
 
404
			"SELECT id_image, nom_original FROM cel_images WHERE ce_utilisateur = %d AND nom_original IN (\"%s\")",
-
 
405
			$cel->id_utilisateur,
-
 
406
			implode('","', $liste_images));
-
 
407
 
-
 
408
		$resultat = $cel->requeter($requete);
-
 
409
 
309
	}
410
		if($resultat) $enregistrement['_images'] = $resultat;
310
 
411
	}
311
 
412
 
312
 
413
 
313
	/* FONCTIONS de TRANSFORMATION de VALEUR DE CELLULE */
414
	/* FONCTIONS de TRANSFORMATION de VALEUR DE CELLULE */
314
 
415
 
315
	// TODO: PHP 5.3, utiliser date_parse_from_format()
416
	// TODO: PHP 5.3, utiliser date_parse_from_format()
316
	// TODO: parser les heures (cf product-owner)
417
	// TODO: parser les heures (cf product-owner)
317
	// TODO: passer par le timestamp pour s'assurer de la validité
418
	// TODO: passer par le timestamp pour s'assurer de la validité
318
	static function traiterDateObs($date) {
419
	static function traiterDateObs($date, $ligne) {
319
		// TODO: see https://github.com/PHPOffice/PHPExcel/issues/208
420
		// TODO: see https://github.com/PHPOffice/PHPExcel/issues/208
320
		if(is_double($date)) {
421
		if(is_double($date)) {
321
			if($date > 0)
422
			if($date > 0)
322
				return PHPExcel_Style_NumberFormat::toFormattedString($date, PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2) . " 00:00:00";
423
				return PHPExcel_Style_NumberFormat::toFormattedString($date, PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2) . " 00:00:00";
-
 
424
			trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": " .
-
 
425
						  "Attention: date antérieure à 1970 et format de cellule \"DATE\" utilisés ensemble",
-
 
426
						  E_USER_NOTICE);
-
 
427
			
323
			throw new Exception("erreur: date antérieure à 1970 et format de cellule \"DATE\" utilisés ensemble");
428
			// throw new Exception("erreur: date antérieure à 1970 et format de cellule \"DATE\" utilisés ensemble");
324
 
429
 
325
			// attention, UNIX timestamp, car Excel les décompte depuis 1900
430
			// attention, UNIX timestamp, car Excel les décompte depuis 1900
326
			// cf http://fczaja.blogspot.fr/2011/06/convert-excel-date-into-timestamp.html
431
			// cf http://fczaja.blogspot.fr/2011/06/convert-excel-date-into-timestamp.html
327
			// $timestamp = ($date - MIN_DATES_DIFF) * 60 * 60 * 24 - time(); // NON
432
			// $timestamp = ($date - MIN_DATES_DIFF) * 60 * 60 * 24 - time(); // NON
328
 
433
 
329
			// $timestamp = PHPExcel_Calculation::getInstance()->calculateFormula("=" . $date . "-DATE(1970,1,1)*60*60*24"); // NON
434
			// $timestamp = PHPExcel_Calculation::getInstance()->calculateFormula("=" . $date . "-DATE(1970,1,1)*60*60*24"); // NON
330
 
435
 
331
			// echo strftime("%Y/%m/%d 00:00:00", $timestamp); // NON
436
			// echo strftime("%Y/%m/%d 00:00:00", $timestamp); // NON
332
		}
437
		}
333
		else {
438
		else {
334
			$timestamp = strtotime($date);
439
			$timestamp = strtotime($date);
335
			if(!$timestamp) return NULL; // TODO: throw error
440
			if(! $timestamp) {
-
 
441
				if($date) trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": Attention: date erronée ($date)", E_USER_NOTICE);
-
 
442
				return NULL;
-
 
443
			}
336
			return strftime("%Y-%m-%d 00:00:00", strtotime($date));
444
			return strftime("%Y-%m-%d 00:00:00", strtotime($date));
337
		}
445
		}
338
	}
446
	}
339
 
447
 
340
	static function identReferentiel($referentiel) {
448
	static function identReferentiel($referentiel) {
341
		// SELECT DISTINCT nom_referentiel, COUNT(id_observation) AS count FROM cel_obs GROUP BY nom_referentiel ORDER BY count DESC;
449
		// SELECT DISTINCT nom_referentiel, COUNT(id_observation) AS count FROM cel_obs GROUP BY nom_referentiel ORDER BY count DESC;
342
		if(strpos(strtolower($referentiel), 'bdtfx') !== FALSE) return 'bdtfx:v1.01';
450
		if(strpos(strtolower($referentiel), 'bdtfx') !== FALSE) return 'bdtfx:v1.01';
343
		if(strpos(strtolower($referentiel), 'bdtxa') !== FALSE) return 'bdtxa:v1.00';
451
		if(strpos(strtolower($referentiel), 'bdtxa') !== FALSE) return 'bdtxa:v1.00';
344
		if(strpos(strtolower($referentiel), 'bdnff') !== FALSE) return 'bdnff:4.02';
452
		if(strpos(strtolower($referentiel), 'bdnff') !== FALSE) return 'bdnff:4.02';
345
		if(strpos(strtolower($referentiel), 'isfan') !== FALSE) return 'isfan:v1.00';
453
		if(strpos(strtolower($referentiel), 'isfan') !== FALSE) return 'isfan:v1.00';
-
 
454
 
-
 
455
		if($referentiel) {
-
 
456
			trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": Attention: référentiel inconnu", E_USER_NOTICE);
-
 
457
		}
346
		return NULL;
458
		return NULL;
347
		/* TODO: cf story,
459
		/* TODO: cf story,
348
		   En cas de NULL faire une seconde passe de détection à partir du nom saisie */
460
		   En cas de NULL faire une seconde passe de détection à partir du nom saisi
-
 
461
		   + accepter les n° de version */
349
	}
462
	}
-
 
463
 
-
 
464
	static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx:v1.01', $ligne) {
-
 
465
		// en CSV ces valeurs sont des string, avec séparateur en français (","; cf défauts dans ExportXLS)
-
 
466
		if($lon && is_string($lon)) $lon = str_replace(',', '.', $lon);
350
 
467
		if($lat && is_string($lat)) $lat = str_replace(',', '.', $lat);
351
	/* NON!
468
 
352
	   Un taxon d'un référentiel donné peut être théoriquement observé n'importe où sur le globe.
469
		// sprintf applique une précision à 5 décimale (comme le ferait MySQL)
-
 
470
		// tout en uniformisant le format de séparateur des décimales (le ".")
353
	   Il n'y a pas lieu d'effectuer des restriction ici.
471
		if($lon && is_numeric($lon) && $lon >= -180 && $lon <= 180) return sprintf('%.5F', $lon);
-
 
472
		if($lat && is_numeric($lat) && $lat >= -90 && $lat <= 90) return sprintf('%.5F', $lat);
354
	   Cependant des erreurs fréquentes (0,0 ou lon/lat inversées) peuvent être détectés ici.
473
 
355
	   TODO */
474
		if($lon || $lat) {
356
	static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx:v1.01') {
475
			trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": " .
357
		// verifier format decimal +
476
						  "Attention: longitude ou latitude erronée",
-
 
477
						  E_USER_NOTICE);
-
 
478
		}
-
 
479
		return NULL;
-
 
480
 
-
 
481
		/* limite france métropole si bdtfx ? ou bdtxa ? ...
-
 
482
		   NON!
-
 
483
		   Un taxon d'un référentiel donné peut être théoriquement observé n'importe où sur le globe.
-
 
484
		   Il n'y a pas lieu d'effectuer des restriction ici.
358
		// + limite france si bdtfx ou bdtxa
485
		   Cependant des erreurs fréquentes (0,0 ou lon/lat inversées) peuvent être détectés ici.
359
 
486
		   TODO */
360
		$bbox = self::getReferentielBBox($referentiel);
487
		$bbox = self::getReferentielBBox($referentiel);
361
		if(!$bbox) return NULL;
488
		if(!$bbox) return NULL;
362
 
489
 
363
		if($lon) {
490
		if($lon) {
364
			if($lon < $bbox['EST'] && $lon > $bbox['OUEST']) return is_numeric($lon) ? $lon : NULL;
491
			if($lon < $bbox['EST'] && $lon > $bbox['OUEST']) return is_numeric($lon) ? $lon : NULL;
365
			else return NULL;
492
			else return NULL;
366
		}
493
		}
367
		if($lat) {
494
		if($lat) {
368
			if($lat < $bbox['NORD'] && $lat > $bbox['SUD']) return is_numeric($lat) ? $lat : NULL;
495
			if($lat < $bbox['NORD'] && $lat > $bbox['SUD']) return is_numeric($lat) ? $lat : NULL;
369
			return NULL;
496
			return NULL;
370
		}
497
		}
371
	}
498
	}
372
 
499
 
373
 
500
 
374
	static function traiterEspece($ligne, Array &$espece, $cel) {
501
	static function traiterEspece($ligne, Array &$espece, $cel) {
-
 
502
		if(!$ligne[C_NOM_SEL]) return;
-
 
503
 
375
		$taxon_info_webservice = new RechercheInfosTaxonBeta($cel->config);
504
		$taxon_info_webservice = new RechercheInfosTaxonBeta($cel->config);
376
 
505
 
377
		$ascii = iconv('UTF-8', 'ASCII//TRANSLIT', $ligne[C_NOM_SEL]);
506
		$ascii = iconv('UTF-8', 'ASCII//TRANSLIT', $ligne[C_NOM_SEL]);
-
 
507
		// FALSE = recherche étendue (LIKE x%)
378
		$resultat_recherche_espece = $taxon_info_webservice->rechercherInfosSurTexteCodeOuNumTax($ligne[C_NOM_SEL]);
508
		$resultat_recherche_espece = $taxon_info_webservice->rechercherInfosSurTexteCodeOuNumTax($ligne[C_NOM_SEL]);
379
 
509
 
380
		// on supprime les noms retenus et renvoi tel quel
510
		// on supprime les noms retenus et renvoi tel quel
381
		// on réutilise les define pour les noms d'indexes, tant qu'à faire
511
		// on réutilise les define pour les noms d'indexes, tant qu'à faire
382
		if (empty($resultat_recherche_espece['en_id_nom'])) {
512
		if (empty($resultat_recherche_espece['en_id_nom'])) {
383
			$espece[C_NOM_SEL] = $ligne[C_NOM_SEL];
513
			$espece[C_NOM_SEL] = $cel->quoteNonNull(trim($ligne[C_NOM_SEL]));
384
			$espece[C_NOM_SEL_NN] = $ligne[C_NOM_SEL_NN];
-
 
-
 
514
 
385
 
515
			// le reste reste à NULL
-
 
516
			// TODO: si empty(C_NOM_SEL) et !empty(C_NOM_SEL_NN) : recherche info à partir de C_NOM_SEL_NN
386
			// TODO: si empty(C_NOM_SEL) et !empty(C_NOM_SEL_NN) : recherche info à partir de C_NOM_SEL_NN
517
			$espece[C_NOM_SEL_NN] = $ligne[C_NOM_SEL_NN];
387
			$espece[C_NOM_RET] = $ligne[C_NOM_RET];
518
			$espece[C_NOM_RET] = $ligne[C_NOM_RET];
388
			$espece[C_NOM_RET_NN] = $ligne[C_NOM_RET_NN];
519
			$espece[C_NOM_RET_NN] = $ligne[C_NOM_RET_NN];
389
			$espece[C_NT] = $ligne[C_NT];
520
			$espece[C_NT] = $ligne[C_NT];
390
			$espece[C_FAMILLE] = $ligne[C_FAMILLE];
521
			$espece[C_FAMILLE] = $ligne[C_FAMILLE];
391
 
522
 
392
			return;
523
			return;
393
		}
524
		}
394
 
525
 
395
		// succès de la détection, récupération des infos
526
		// succès de la détection, récupération des infos
396
		$espece[C_NOM_SEL] = $resultat_recherche_espece['nom_sel'];
527
		$espece[C_NOM_SEL] = $cel->quoteNonNull($resultat_recherche_espece['nom_sel']);
397
		$espece[C_NOM_SEL_NN] = $resultat_recherche_espece['en_id_nom'];
528
		$espece[C_NOM_SEL_NN] = $cel->quoteNonNull($resultat_recherche_espece['en_id_nom']);
398
 
529
 
399
		$complement = $taxon_info_webservice->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
530
		$complement = $taxon_info_webservice->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
400
		$espece[C_NOM_RET] = $complement['Nom_Retenu'];
531
		$espece[C_NOM_RET] = $cel->quoteNonNull($complement['Nom_Retenu']);
401
		$espece[C_NOM_RET_NN] = $complement['Num_Nom_Retenu'];
532
		$espece[C_NOM_RET_NN] = $cel->quoteNonNull($complement['Num_Nom_Retenu']);
402
		$espece[C_NT] = $complement['Num_Taxon'];
533
		$espece[C_NT] = $cel->quoteNonNull($complement['Num_Taxon']);
403
		$espece[C_FAMILLE] = $complement['Famille'];
534
		$espece[C_FAMILLE] = $cel->quoteNonNull($complement['Famille']);
404
	}
535
	}
405
 
536
 
406
 
537
 
-
 
538
	static function traiterLocalisation($ligne, Array &$localisation, $cel) {
-
 
539
	    $identifiant_commune = trim($ligne[C_ZONE_GEO]);
-
 
540
		if(!$identifiant_commune) {
-
 
541
			$departement = trim($ligne[C_CE_ZONE_GEO]);
-
 
542
			goto testdepartement;
-
 
543
		}
-
 
544
 
-
 
545
 
-
 
546
		$select = "SELECT DISTINCT nom, code  FROM cel_zones_geo";
-
 
547
	
-
 
548
		if (preg_match('/(.*) \((\d+)\)/', $identifiant_commune, $elements)) {
-
 
549
			// commune + departement : montpellier (34)
-
 
550
			$nom_commune=$elements[1];
-
 
551
			$code_commune=$elements[2];
-
 
552
	 	    $requete = sprintf("%s WHERE nom = %s AND code LIKE %s",
-
 
553
							   $select, $cel->quoteNonNull($nom_commune), $cel->quoteNonNull($code_commune.'%'));
-
 
554
		}
-
 
555
		elseif (preg_match('/^(\d+|(2[ab]\d+))$/i', $identifiant_commune, $elements)) {
-
 
556
			// Code insee seul  
-
 
557
			$code_insee_commune=$elements[1];
-
 
558
	 	    $requete = sprintf("%s WHERE code = %s", $select, $cel->quoteNonNull($code_insee_commune));
-
 
559
		}
-
 
560
		else {
-
 
561
			// Commune seule (le departement sera recupere dans la colonne departement si elle est presente)
-
 
562
			// on prend le risque ici de retourner une mauvaise Commune
-
 
563
			$nom_commune = str_replace(" ", "%", iconv('UTF-8', 'ASCII//TRANSLIT', $identifiant_commune));
-
 
564
	 	    $requete = sprintf("%s WHERE nom LIKE %s", $select, $cel->quoteNonNull($nom_commune.'%'));
-
 
565
		}
-
 
566
	
-
 
567
		$resultat_commune = $cel->requeter($requete);
-
 
568
		// TODO: levenstein sort ?
-
 
569
 
-
 
570
		// cas de la commune introuvable dans le référentiel
-
 
571
		// réinitialisation aux valeurs du fichier XLS
-
 
572
		if(! $resultat_commune) {
-
 
573
			$localisation[C_ZONE_GEO] = trim($ligne[C_ZONE_GEO]);
-
 
574
			$localisation[C_CE_ZONE_GEO] = trim($ligne[C_CE_ZONE_GEO]);
-
 
575
		} else {
-
 
576
			$localisation[C_ZONE_GEO] = $resultat_commune[0]['nom'];
-
 
577
			$localisation[C_CE_ZONE_GEO] = $resultat_commune[0]['code'];
-
 
578
		}
-
 
579
 
-
 
580
		$departement = &$localisation[C_CE_ZONE_GEO];
-
 
581
 
407
	static function traiterDepartement($departement) { 
582
	testdepartement:
-
 
583
		if(strpos($departement, "INSEE-C:", 0) === 0) goto protectloc;
408
		if(strpos($departement, "INSEE-C:", 0) === 0) return $departement;
584
 
409
		if(!is_numeric($departement)) return NULL; // TODO ?
585
		if(!is_numeric($departement)) goto protectloc; // TODO ?
410
		if(strlen($departement) == 4) return "INSEE-C:0" . $departement;
586
		if(strlen($departement) == 4) $departement = "INSEE-C:0" . $departement;
411
		if(strlen($departement) == 5) return "INSEE-C:" . $departement;
587
		if(strlen($departement) == 5) $departement = "INSEE-C:" . $departement;
-
 
588
		// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
412
		// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
589
 
-
 
590
		$departement = trim($departement); // TODO
-
 
591
 
-
 
592
	protectloc:
-
 
593
		$localisation[C_ZONE_GEO] = $cel->quoteNonNull($localisation[C_ZONE_GEO]);
413
		return trim($departement); // TODO
594
		$localisation[C_CE_ZONE_GEO] = $cel->quoteNonNull($localisation[C_CE_ZONE_GEO]);
414
	}
595
	}
415
 
596
 
-
 
597
 
416
 
598
 
417
	/* HELPERS */
599
	/* HELPERS */
418
 
600
 
419
	// http://stackoverflow.com/questions/348410/sort-an-array-based-on-another-array
601
	// http://stackoverflow.com/questions/348410/sort-an-array-based-on-another-array
420
	static function sortArrayByArray($array, $orderArray) {
602
	static function sortArrayByArray($array, $orderArray) {
421
		$ordered = array();
603
		$ordered = array();
422
		foreach($orderArray as $key) {
604
		foreach($orderArray as $key) {
423
			if(array_key_exists($key, $array)) {
605
			if(array_key_exists($key, $array)) {
424
				$ordered[$key] = $array[$key];
606
				$ordered[$key] = $array[$key];
425
				unset($array[$key]);
607
				unset($array[$key]);
426
			}
608
			}
427
		}
609
		}
428
		return $ordered + $array;
610
		return $ordered + $array;
429
	}
611
	}
430
 
612
 
431
	// retourne une BBox [N,S,E,O) pour un référentiel donné
613
	// retourne une BBox [N,S,E,O) pour un référentiel donné
432
	static function getReferentielBBox($referentiel) {
614
	static function getReferentielBBox($referentiel) {
433
		if($referentiel == 'bdtfx:v1.01') return Array(
615
		if($referentiel == 'bdtfx:v1.01') return Array(
434
			'NORD' => 51.2, // Dunkerque
616
			'NORD' => 51.2, // Dunkerque
435
			'SUD' => 41.3, // Bonifacio
617
			'SUD' => 41.3, // Bonifacio
436
			'EST' => 9.7, // Corse
618
			'EST' => 9.7, // Corse
437
			'OUEST' => -5.2); // Ouessan
619
			'OUEST' => -5.2); // Ouessan
438
		return FALSE;
620
		return FALSE;
439
	}
621
	}
440
 
622
 
441
 
623
 
442
	public function initialiser_colonnes_statiques($id_utisateur) {
624
	public function initialiser_colonnes_statiques() {
443
		$this->colonnes_statiques = array_merge($this->colonnes_statiques,
625
		$this->colonnes_statiques = array_merge($this->colonnes_statiques,
444
												Array(
626
												Array(
445
													"ce_utilisateur" => $id_utisateur,
627
													"ce_utilisateur" => $this->id_utilisateur,
446
													"prenom_utilisateur" => $this->utilisateur['prenom'],
628
													"prenom_utilisateur" => $this->quoteNonNull($this->utilisateur['prenom']),
447
													"nom_utilisateur" => $this->utilisateur['nom'],
629
													"nom_utilisateur" => $this->quoteNonNull($this->utilisateur['nom']),
448
													"courriel_utilisateur" => $this->utilisateur['courriel'],
-
 
449
 
-
 
450
													"date_creation" => date("Y-m-d H:i:s"),
-
 
451
													"date_modification" => date("Y-m-d H:i:s"),
630
													"courriel_utilisateur" => $this->quoteNonNull($this->utilisateur['courriel']),
452
												));
631
												));
453
 
632
 
454
	}
633
	}
-
 
634
 
-
 
635
	// équivalent à CEL->Bdd->proteger() (qui wrap PDO::quote),
-
 
636
	// sans transformer NULL en ""
-
 
637
	private function quoteNonNull($chaine) {
-
 
638
		if(is_null($chaine)) return "NULL";
-
 
639
		if(!is_string($chaine)) die("erreur __FILE__, __LINE__");
-
 
640
		return $this->bdd->quote($chaine);
-
 
641
	}
-
 
642
 
-
 
643
	public function erreurs_stock($errno, $errstr) {
-
 
644
		$this->bilan[] = $errstr;
-
 
645
	}
455
}
646
}