Rev 1856 | Rev 1862 | 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 $table_publication = null;protected $table_auteur = null;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" :$resultat = $this->charger($fichier); break;default :$this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));}} catch (Exception $erreur) {$this->traiterErreur($erreur->getMessage());}// renvoi du résultat vers la sortie phpecho $resultat;}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');$tables = Config::get('tables');$this->table_publication = $tables['publication'];$this->table_auteur = $tables['auteur'];}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->bdd->proteger($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';// le script renvoie le nombre de publications importéesreturn $this->insererPublications($colonnes_importees, $lignes);}protected function formaterNomComplet($ligne, $roles) {$roles = array_flip($roles);// Intitulé de la publication complet : fmt_auteur, date_parution(année). titre. Editeur (nom), collection, fascicule, indication_nvt. pages.// indication_nvt = serie_tome$champs_nom_complet = array('auteur', 'annee', 'titre', 'editeur', 'intitule_revue', 'fascicule', 'serie_tome', 'pages');$champs_fmt = array();$fmt_nom_complet = "";foreach($champs_nom_complet as $champ) {$index = $roles[$champ];if(!isset($ligne[$index])) {$champs_fmt[$champ] = "";} else {$champs_fmt[$champ] = $ligne[$index];}}$indication_nvt_pages = array($champs_fmt['serie_tome'], $champs_fmt['pages']);$indication_nvt_pages = array_filter($indication_nvt_pages, 'strlen');$indication_nvt_pages = trim(implode(". ", $indication_nvt_pages));$indication_nvt_pages .= !empty($indication_nvt_pages) ? "." : "";$annee_titre_editeur = array($champs_fmt['annee'], $champs_fmt['titre'], $champs_fmt['editeur']);$annee_titre_editeur = array_filter($annee_titre_editeur, 'strlen');$annee_titre_editeur = trim(implode(". ", $annee_titre_editeur));$fmt_nom_complet = array($champs_fmt['auteur'],$annee_titre_editeur,$champs_fmt['intitule_revue'],$champs_fmt['fascicule'],$indication_nvt_pages);$fmt_nom_complet = array_filter($fmt_nom_complet, 'strlen');$fmt_nom_complet = implode(", ", $fmt_nom_complet);return $fmt_nom_complet;}private function insererPublications(&$colonnes, &$publications) {$requete = "INSERT INTO ".$this->table_publication." "."(".implode(',', $colonnes).") "."VALUES ".implode(","."\n", $publications)."\n";return $this->bdd->executer($requete);}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_intitule) {$retour = $auteur_intitule;if(isset($this->cache_auteur[$auteur_intitule])) {$retour = !empty($this->cache_auteur[$auteur_intitule]['cp_id_personne']) ?$this->cache_auteur[$auteur_intitule]['cp_id_personne'] :$this->cache_auteur[$auteur_intitule];} else {$auteur = $this->fabriquerCombinaisonsAuteur($auteur_intitule);$auteur_req = "(".implode(', ', $auteur).")";$requete = "SELECT cp_id_personne, cp_fmt_nom_complet FROM ".$this->table_auteur." 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'];$this->cache_auteur[$auteur_intitule] = $infos_auteur[0];} else {$retour = $auteur_intitule;$this->cache_auteur[$auteur_intitule] = $auteur_intitule;}}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])));}$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;}}?>