Subversion Repositories eFlore/Applications.coel

Rev

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

Rev Author Line No. Line
1855 delphine 1
<?php
2
/**
3
 * Exemple lancement:
4
 * /opt/lampp/bin/php -d memory_limit=3500M cli.php import -n
5
 */
6
class Import extends Script {
7
	private $bdd = null;
8
	private $auteurs = array();
9
	protected $parametres_autorises = array(
10
			'-n' => array(true, false, 'Nom du fichier à importer.'));
11
 
1856 aurelien 12
	protected $colonnes_obligatoires = array();
13
	protected $colonnes_acceptees = array();
1855 delphine 14
 
1856 aurelien 15
	protected $cache_auteur = array();
16
 
1855 delphine 17
	public function __construct($script_nom, $parametres) {
18
		parent::__construct($script_nom, $parametres);
19
		$this->bdd = new Bdd();
20
	}
21
 
22
	public function executer() {
23
		try {
24
			$this->initialiserScript();
25
			$cmd = $this->getParametre('a');
26
			$fichier = $this->getParametre('n');
27
			switch ($cmd) {
28
				case "import" :
29
					//testerauteur
30
					$this->charger($fichier); break;
31
				default :
32
					$this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
33
			}
34
		} catch (Exception $erreur) {
35
			$this->traiterErreur($erreur->getMessage());
36
		}
37
	}
38
 
39
	private function initialiserScript() {
40
		$fichierIni = $this->getScriptChemin().'import.ini';
41
		if (file_exists($fichierIni)) {
42
			Config::charger($fichierIni);
43
		} else {
1856 aurelien 44
			$erreur = "Veuillez configurer le projet en créant le fichier 'import.ini' ".
45
					"dans le dossier du module de script du projet à partir du fichier 'import.defaut.ini'.";
1855 delphine 46
			throw new Exception($erreur);
47
		}
1856 aurelien 48
 
49
		$this->colonnes_obligatoires= Config::get('champs_obligatoires');
50
		$this->colonnes_acceptees = Config::get('champs');
1855 delphine 51
	}
52
 
53
	private function charger($fichier) {
54
 
1856 aurelien 55
		// vérification existence fichier
56
		if(!file_exists(Config::get('dossiertmp').$fichier)) {
57
			$erreur = "Le fichier ".Config::get('dossiertmp').$fichier." n'existe pas.";
58
			throw new Exception($erreur);
59
		}
60
 
61
		$pointeur = fopen(Config::get('dossiertmp').$fichier, "r");
62
		// Chargement de la première colonne (qui contient les noms de colonnes à importer
63
		$colonnes = fgetcsv($pointeur, 0, ";");
64
 
65
		// Vérification des colonnes obligatoires et en même temps du séparateur
66
		if(count($colonnes) < 2 || !array_intersect(array_keys($this->colonnes_obligatoires), $colonnes)) {
67
			$erreur = "Le fichier ne contient pas les colonnes obligatoires : ".implode(',', array_keys($this->colonnes_obligatoires))."\n";
68
			$erreur .= "ou bien n'est pas séparé par le caractère ';' ";
69
			throw new Exception($erreur);
70
		}
71
 
72
		$index_colonnes_importees = array_intersect(array_keys($this->colonnes_acceptees), $colonnes);
73
		$colonnes_importees = array();
74
		foreach($index_colonnes_importees as $index_colonne_importee) {
75
			$colonnes_importees[] = $this->colonnes_acceptees[$index_colonne_importee];
76
		}
77
 
78
		$index_colonnes_refusees = array_keys(array_diff($colonnes, array_keys($this->colonnes_acceptees)));
79
		// Création d'un index associant chaque numéro de colonne importée à son rôle
80
		// pour y apporter des traitement spécifiques
81
		$index_colonnes_importees = $colonnes;
82
		foreach($index_colonnes_refusees as $colonne_refusee) {
83
			unset($index_colonnes_importees[$colonne_refusee]);
84
		}
85
 
86
		$lignes = array();
87
		while($ligne = fgetcsv($pointeur, 0, ";")) {
88
			$ligne_inseree = array();
89
			foreach($ligne as $index => &$valeur) {
90
				if(!in_array($index, $index_colonnes_refusees)) {
91
					$ligne_inseree[] = $this->traiterChamp($valeur, $index_colonnes_importees[$index]);
92
				}
93
			}
94
			// Ajout du nom complet formaté de la publication
95
			$ligne_inseree[] = $this->formaterNomComplet($ligne, $index_colonnes_importees);
96
			$lignes[] = "(".implode(",", $ligne_inseree).")";
97
		}
98
 
99
		// Ajout de la colonne nom complet aux champs de la requête
100
		$colonnes_importees[] = 'cpu_fmt_nom_complet';
101
		$this->insererPublications($colonnes_importees, $lignes);
1855 delphine 102
	}
1856 aurelien 103
 
104
	protected function formaterNomComplet($ligne, $roles) {
105
		// TODO: écrire la fonction
106
		return 'aaaaa';
107
	}
108
 
109
	private function insererPublications(&$colonnes, &$publications) {
110
		$requete = "INSERT INTO $table ".
111
				   	"(".implode(',', $colonnes).") ".
112
				   "VALUES ".implode(","."\n", $publications)."\n";
113
 
114
		echo $requete;exit;
115
	}
116
 
117
	private function traiterChamp($valeur, $role) {
118
		switch($role) {
119
			case 'auteur':
120
				$valeur = $this->obtenirInfosAuteur($valeur);
121
			break;
122
			case 'editeur':
123
				$valeur = 'AUTRES##'.$valeur;
124
			break;
125
		}
126
 
127
		return $this->bdd->proteger($valeur);
128
	}
129
 
130
	private function obtenirInfosAuteur($auteur) {
131
		$retour = $auteur;
132
		if(isset($cache_auteur[$auteur])) {
133
			$retour = $cache_auteur[$auteur];
134
		} else {
135
			$auteur = $this->fabriquerCombinaisonsAuteur($auteur);
136
			$auteur_req = "(".implode(', ', $auteur).")";
137
 
138
			$requete = "SELECT cp_id_personne FROM coel_personne WHERE cp_fmt_nom_complet IN ".$auteur_req;
139
			$infos_auteur = $this->bdd->recupererTous($requete);
140
 
141
			if(!empty($infos_auteur)) {
142
				$retour = $infos_auteur[0]['cp_id_personne'];
143
				$cache_auteur[$auteur] = $infos_auteur[0]['cp_id_personne'];
144
			} else {
145
				$cache_auteur[$auteur] = $auteur;
146
			}
147
		}
148
 
149
		return $retour;
150
	}
151
 
152
	private function fabriquerCombinaisonsAuteur($auteur) {
153
 
154
		$auteur = trim($auteur);
155
		$auteurs_formates = array($this->bdd->proteger($auteur));
156
 
157
		// Séparation des élements de l'auteur des espaces pour obtenir
158
		// les noms et prénoms (Ex. "Carl Von Linné" => "Carl", "Von", "Linné")
159
		$auteur_tab = explode(' ', $auteur);
160
		$auteur_tab = array_filter($auteur_tab);
161
 
162
		$combinaisons = array();
163
		foreach($auteur_tab as &$element_auteur) {
164
			$combinaisons[] = array(
165
								// élement tel quel (Ex: "Linné")
166
								$element_auteur,
167
								// possibilité de l'initiale seule (Ex: "L")
168
								substr($element_auteur, 0, 1),
169
								// possibilité de l'initiale avec un point du genre (Ex: "L.")
170
								substr($element_auteur, 0, 1)."."
171
							);
172
		}
173
 
174
		// Fabrication de toutes les combinaisons possibles des parties de noms ci-dessus
175
		// pour deux et trois élements en faisant plusieurs produits cartésiens
176
		// car le nom peut être combiné différement de celui en base de données
177
		// (Ex. : "Carl Von Linné" VS "C. Von Linné" ou "C. V. Linné" ou encore "Von Linné C." etc...)
178
 
179
		// C'est moche et pas très élégant mais bon ça marche dans 90% des cas
180
		// On ne teste pas plus que 3 combinaisons, car ça serait très très couteux
181
		// TODO: faire mieux et factoriser les appels ci dessous
182
		if(count($auteur_tab) > 2) {
183
			// Cas du nom à trois parties (genre "Carl Von Linné")
184
			$possibilites_auteurs = $this->cartesian(array($combinaisons[0], $combinaisons[1], $combinaisons[2]));
185
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[0], $combinaisons[2], $combinaisons[1])));
186
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[2], $combinaisons[0])));
187
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[0], $combinaisons[2])));
188
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[2], $combinaisons[1], $combinaisons[0])));
189
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[2], $combinaisons[0], $combinaisons[1])));
190
		} else {
191
			// Cas du nom à trois parties (genre "Carl Linné")
192
			$possibilites_auteurs = $this->cartesian(array($combinaisons[0], $combinaisons[1]));
193
			$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[0])));
194
		}
195
		// Elimination d'éventuels doublons
196
		array_unique($possibilites_auteurs);
197
 
198
		$auteurs_formates = array();
199
		foreach($possibilites_auteurs as &$possibilite) {
200
			$initiales = true;
201
			// Suppression des possibilités ne contenant que des initiales avec ou sans point
202
			foreach($possibilite as &$chars) {
203
				$initiales = $initiales && mb_strlen($chars) <= 2;
204
			}
1855 delphine 205
 
1856 aurelien 206
			if(!$initiales) {
207
				$auteurs_formates[] = $this->bdd->proteger(implode(" ", $possibilite));
208
			}
209
		}
210
 
211
		return $auteurs_formates;
212
	}
213
 
214
	// http://stackoverflow.com/questions/6311779/finding-cartesian-product-with-php-associative-arrays
215
	function cartesian($input) {
216
		// filter out empty values
217
		$input = array_filter($input);
218
 
219
		$result = array(array());
220
 
221
		foreach ($input as $key => $values) {
222
			$append = array();
223
 
224
			foreach($result as $product) {
225
				foreach($values as $item) {
226
					$product[$key] = $item;
227
					$append[] = $product;
228
				}
229
			}
230
 
231
			$result = $append;
232
		}
233
 
234
		return $result;
235
	}
1855 delphine 236
}
237
?>