Rev 1855 | Rev 1857 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*** Exemple lancement:* /opt/lampp/bin/php -d memory_limit=3500M cli.php import -n*/class Import extends Script {private $bdd = null;private $auteurs = array();protected $parametres_autorises = array('-n' => array(true, false, 'Nom du fichier à importer.'));protected $colonnes_obligatoires = array();protected $colonnes_acceptees = array();protected $cache_auteur = array();public function __construct($script_nom, $parametres) {parent::__construct($script_nom, $parametres);$this->bdd = new Bdd();}public function executer() {try {$this->initialiserScript();$cmd = $this->getParametre('a');$fichier = $this->getParametre('n');switch ($cmd) {case "import" ://testerauteur$this->charger($fichier); break;default :$this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));}} catch (Exception $erreur) {$this->traiterErreur($erreur->getMessage());}}private function initialiserScript() {$fichierIni = $this->getScriptChemin().'import.ini';if (file_exists($fichierIni)) {Config::charger($fichierIni);} else {$erreur = "Veuillez configurer le projet en créant le fichier 'import.ini' "."dans le dossier du module de script du projet à partir du fichier 'import.defaut.ini'.";throw new Exception($erreur);}$this->colonnes_obligatoires= Config::get('champs_obligatoires');$this->colonnes_acceptees = Config::get('champs');}private function charger($fichier) {// vérification existence fichierif(!file_exists(Config::get('dossiertmp').$fichier)) {$erreur = "Le fichier ".Config::get('dossiertmp').$fichier." n'existe pas.";throw new Exception($erreur);}$pointeur = fopen(Config::get('dossiertmp').$fichier, "r");// Chargement de la première colonne (qui contient les noms de colonnes à importer$colonnes = fgetcsv($pointeur, 0, ";");// Vérification des colonnes obligatoires et en même temps du séparateurif(count($colonnes) < 2 || !array_intersect(array_keys($this->colonnes_obligatoires), $colonnes)) {$erreur = "Le fichier ne contient pas les colonnes obligatoires : ".implode(',', array_keys($this->colonnes_obligatoires))."\n";$erreur .= "ou bien n'est pas séparé par le caractère ';' ";throw new Exception($erreur);}$index_colonnes_importees = array_intersect(array_keys($this->colonnes_acceptees), $colonnes);$colonnes_importees = array();foreach($index_colonnes_importees as $index_colonne_importee) {$colonnes_importees[] = $this->colonnes_acceptees[$index_colonne_importee];}$index_colonnes_refusees = array_keys(array_diff($colonnes, array_keys($this->colonnes_acceptees)));// Création d'un index associant chaque numéro de colonne importée à son rôle// pour y apporter des traitement spécifiques$index_colonnes_importees = $colonnes;foreach($index_colonnes_refusees as $colonne_refusee) {unset($index_colonnes_importees[$colonne_refusee]);}$lignes = array();while($ligne = fgetcsv($pointeur, 0, ";")) {$ligne_inseree = array();foreach($ligne as $index => &$valeur) {if(!in_array($index, $index_colonnes_refusees)) {$ligne_inseree[] = $this->traiterChamp($valeur, $index_colonnes_importees[$index]);}}// Ajout du nom complet formaté de la publication$ligne_inseree[] = $this->formaterNomComplet($ligne, $index_colonnes_importees);$lignes[] = "(".implode(",", $ligne_inseree).")";}// Ajout de la colonne nom complet aux champs de la requête$colonnes_importees[] = 'cpu_fmt_nom_complet';$this->insererPublications($colonnes_importees, $lignes);}protected function formaterNomComplet($ligne, $roles) {// TODO: écrire la fonctionreturn 'aaaaa';}private function insererPublications(&$colonnes, &$publications) {$requete = "INSERT INTO $table "."(".implode(',', $colonnes).") "."VALUES ".implode(","."\n", $publications)."\n";echo $requete;exit;}private function traiterChamp($valeur, $role) {switch($role) {case 'auteur':$valeur = $this->obtenirInfosAuteur($valeur);break;case 'editeur':$valeur = 'AUTRES##'.$valeur;break;}return $this->bdd->proteger($valeur);}private function obtenirInfosAuteur($auteur) {$retour = $auteur;if(isset($cache_auteur[$auteur])) {$retour = $cache_auteur[$auteur];} else {$auteur = $this->fabriquerCombinaisonsAuteur($auteur);$auteur_req = "(".implode(', ', $auteur).")";$requete = "SELECT cp_id_personne FROM coel_personne WHERE cp_fmt_nom_complet IN ".$auteur_req;$infos_auteur = $this->bdd->recupererTous($requete);if(!empty($infos_auteur)) {$retour = $infos_auteur[0]['cp_id_personne'];$cache_auteur[$auteur] = $infos_auteur[0]['cp_id_personne'];} else {$cache_auteur[$auteur] = $auteur;}}return $retour;}private function fabriquerCombinaisonsAuteur($auteur) {$auteur = trim($auteur);$auteurs_formates = array($this->bdd->proteger($auteur));// Séparation des élements de l'auteur des espaces pour obtenir// les noms et prénoms (Ex. "Carl Von Linné" => "Carl", "Von", "Linné")$auteur_tab = explode(' ', $auteur);$auteur_tab = array_filter($auteur_tab);$combinaisons = array();foreach($auteur_tab as &$element_auteur) {$combinaisons[] = array(// élement tel quel (Ex: "Linné")$element_auteur,// possibilité de l'initiale seule (Ex: "L")substr($element_auteur, 0, 1),// possibilité de l'initiale avec un point du genre (Ex: "L.")substr($element_auteur, 0, 1).".");}// Fabrication de toutes les combinaisons possibles des parties de noms ci-dessus// pour deux et trois élements en faisant plusieurs produits cartésiens// car le nom peut être combiné différement de celui en base de données// (Ex. : "Carl Von Linné" VS "C. Von Linné" ou "C. V. Linné" ou encore "Von Linné C." etc...)// C'est moche et pas très élégant mais bon ça marche dans 90% des cas// On ne teste pas plus que 3 combinaisons, car ça serait très très couteux// TODO: faire mieux et factoriser les appels ci dessousif(count($auteur_tab) > 2) {// Cas du nom à trois parties (genre "Carl Von Linné")$possibilites_auteurs = $this->cartesian(array($combinaisons[0], $combinaisons[1], $combinaisons[2]));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[0], $combinaisons[2], $combinaisons[1])));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[2], $combinaisons[0])));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[0], $combinaisons[2])));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[2], $combinaisons[1], $combinaisons[0])));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[2], $combinaisons[0], $combinaisons[1])));} else {// Cas du nom à trois parties (genre "Carl Linné")$possibilites_auteurs = $this->cartesian(array($combinaisons[0], $combinaisons[1]));$possibilites_auteurs = array_merge($possibilites_auteurs, $this->cartesian(array($combinaisons[1], $combinaisons[0])));}// Elimination d'éventuels doublonsarray_unique($possibilites_auteurs);$auteurs_formates = array();foreach($possibilites_auteurs as &$possibilite) {$initiales = true;// Suppression des possibilités ne contenant que des initiales avec ou sans pointforeach($possibilite as &$chars) {$initiales = $initiales && mb_strlen($chars) <= 2;}if(!$initiales) {$auteurs_formates[] = $this->bdd->proteger(implode(" ", $possibilite));}}return $auteurs_formates;}// http://stackoverflow.com/questions/6311779/finding-cartesian-product-with-php-associative-arraysfunction cartesian($input) {// filter out empty values$input = array_filter($input);$result = array(array());foreach ($input as $key => $values) {$append = array();foreach($result as $product) {foreach($values as $item) {$product[$key] = $item;$append[] = $product;}}$result = $append;}return $result;}}?>