Overview
Comment: | Suppression de l'import de Galette, remplacé par un import de CSV générique, permettant de s'adapter à n'importe quel format de CSV |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dev |
Files: | files | file ages | folders |
SHA1: |
7af44a178e434ee14a42a54f55976970 |
User & Date: | bohwaz on 2018-08-22 19:49:49 |
Other Links: | branch diff | manifest | tags |
Context
2018-08-26
| ||
00:43 | Ménage : les versions inférieures à 0.7 (3 ans et demi) devront faire une mise à jour intermédiaire pour pouvoir passer à une nouvelle version. check-in: b0063b95ef user: bohwaz tags: dev | |
2018-08-22
| ||
19:49 | Suppression de l'import de Galette, remplacé par un import de CSV générique, permettant de s'adapter à n'importe quel format de CSV check-in: 7af44a178e user: bohwaz tags: dev | |
2018-08-21
| ||
00:56 | Améliore aspect messages d'erreur check-in: 2ddd23337c user: bohwaz tags: dev | |
Changes
Modified src/include/lib/Garradin/Membres/Import.php from [032b787733] to [6fc6eacc71].
︙ | ︙ | |||
8 9 10 11 12 13 14 | use Garradin\Utils; use Garradin\UserException; use KD2\ODSWriter; class Import { | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < | < | < < < < < < < < < | < > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > | > | > > | > > | > > > > > > > > | > > > > > > | > < < | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | use Garradin\Utils; use Garradin\UserException; use KD2\ODSWriter; class Import { public function getCSVAsArray($path) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : '.$path); } $fp = fopen($path, 'r'); if (!$fp) { return false; } $delim = Utils::find_csv_delim($fp); Utils::skip_bom($fp); $line = 0; $out = []; $nb_columns = null; while (!feof($fp)) { $row = fgetcsv($fp, 4096, $delim); $line++; if (empty($row)) { continue; } if (null === $nb_columns) { $nb_columns = count($row); } if (count($row) != $nb_columns) { throw new UserException('Erreur sur la ligne ' . $line . ' : incohérence dans le nombre de colonnes avec la première ligne.'); } $out[$line] = $row; } fclose($fp); return $out; } /** * Importer un CSV générique * @param string $path Chemin vers le CSV * @param array $translation_table Tableau indiquant la correspondance à effectuer entre les colonnes * du CSV et les champs de Garradin. Par exemple : ['Date création fiche' => 'date_inscription'] * @return boolean TRUE en cas de succès */ public function fromArray(array $table, $translation_table, $skip_lines = 0) { $db = DB::getInstance(); $db->begin(); $membres = new Membres; $champs = Config::getInstance()->get('champs_membres'); $nb_columns = count($translation_table); if ($skip_lines) { $table = array_slice($table, $skip_lines, null, true); } foreach ($table as $line => $row) { if (empty($row)) { continue; } if (count($row) != $nb_columns) { $db->rollback(); throw new UserException('Erreur sur la ligne ' . $line . ' : le nombre de colonnes est incorrect.'); } $data = []; foreach ($translation_table as $column_index => $garradin_field) { // Champs qu'on ne veut pas importer if (empty($garradin_field)) { continue; } // Concaténer plusieurs champs, si on choisit d'indiquer plusieurs fois // le même champ pour plusieurs colonnes (par exemple pour mettre nom et prénom // dans un seul champ) if (isset($data[$garradin_field])) { $champ = $champs->get($garradin_field); if ($champ->type == 'text') { $data[$garradin_field] .= ' ' . $row[$column_index]; } elseif ($champ->type == 'textarea') { $data[$garradin_field] .= "\n" . $row[$column_index]; } else { throw new UserException(sprintf('Erreur sur la ligne %d : impossible de concaténer des colonnes avec le champ %s : n\'est pas un champ de type texte', $line, $champ->title)); } } else { $data[$garradin_field] = $row[$column_index]; } } try { $membres->add($data, false); } catch (UserException $e) { $db->rollback(); throw new UserException('Erreur sur la ligne ' . $line . ' : ' . $e->getMessage()); } } $db->commit(); return true; } /** * Importer un CSV de la liste des membres depuis un export Garradin * @param string $path Chemin vers le CSV * @param int $current_user_id * @return boolean TRUE en cas de succès */ public function fromGarradinCSV($path, $current_user_id) { if (!file_exists($path) || !is_readable($path)) { throw new \RuntimeException('Fichier inconnu : '.$path); } $fp = fopen($path, 'r'); |
︙ | ︙ |
Modified src/templates/admin/membres/import.tpl from [239f90c5ba] to [f967ae9cb7].
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | {if $ok} <p class="confirm"> L'import s'est bien déroulé. </p> {/if} <form method="post" action="{$self_url}" enctype="multipart/form-data"> <fieldset> <legend>Importer depuis un fichier</legend> <dl> <dt><label for="f_file">Fichier à importer</label> <b title="(Champ obligatoire)">obligatoire</b></dt> <dd><input type="file" name="upload" id="f_file" required="required" /></dd> <dt><label for="f_type">Type de fichier</label> <b title="(Champ obligatoire)">obligatoire</b></dt> <dd> <input type="radio" name="type" id="f_type" value="garradin" {form_field name=type checked="garradin" default="garradin"} /> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < < < < | < | < < < < < < < < < < < < < < < < > > < < < < < < < < < < < < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | {if $ok} <p class="confirm"> L'import s'est bien déroulé. </p> {/if} <form method="post" action="{$self_url}" enctype="multipart/form-data"> {if $csv_file} <fieldset> <legend>Importer depuis un fichier CSV générique</legend> <p class="help">{$csv_file|count} lignes trouvées dans le fichier</p> <dl> <dt><label><input type="checkbox" name="skip_first_line" value="1" checked="checked" /> Ne pas importer la première ligne</label></dt> <dd class="help">Décocher cette case si la première ligne ne contient pas l'intitulé des colonnes mais des données.</dd> <dt><label>Correspondance des champs</label></dt> <dd class="help">Indiquer la correspondance entre colonnes du CSV et champs des fiches membre.</dd> <dd> <table class="list auto"> <tbody> {foreach from=$csv_first_line key="index" item="csv_field"} <tr> <th>{$csv_field}</th> <td> <select name="csv_translate[{$index}]"> <option value="">-- Ne pas importer ce champ</option> {foreach from=$garradin_champs item="champ" key="name"} {if $champ.type == 'multiple' || $champ.type == 'file' || $name == 'passe'}{continue}{/if} <option value="{$name}">{$champ.title}</option> {/foreach} </select> </td> </tr> {/foreach} </tbody> </table> </dd> <dd class="help">Pour fusionner des colonnes, il suffit d'indiquer le même nom de champ pour plusieurs colonnes.</dd> </dl> </fieldset> <input type="hidden" name="csv_encoded" value="{$csv_file|escape:'json'|escape}" /> {else} <fieldset> <legend>Importer depuis un fichier</legend> <dl> <dt><label for="f_file">Fichier à importer</label> <b title="(Champ obligatoire)">obligatoire</b></dt> <dd><input type="file" name="upload" id="f_file" required="required" /></dd> <dt><label for="f_type">Type de fichier</label> <b title="(Champ obligatoire)">obligatoire</b></dt> <dd> <input type="radio" name="type" id="f_type" value="garradin" {form_field name=type checked="garradin" default="garradin"} /> <label for="f_type">Fichier CSV de Garradin</label> </dd> <dd class="help"> Export de la liste des membres au format CSV provenant de Garradin. Les lignes comportant un numéro de membre mettront à jour les fiches des membres ayant ce numéro (si le numéro existe), les lignes sans numéro ou avec un numéro inexistant créeront de nouveaux membres. </dd> <dd> <input type="radio" name="type" id="f_type_csv" value="csv" {form_field name=type checked="csv"} /> <label for="f_type_csv">Fichier CSV générique</label> </dd> <dd class="help"> Vous pourrez choisir la correspondance entre colonnes du CSV et champs des fiches membres dans le prochain écran. </dd> </dl> </fieldset> {/if} <p class="submit"> {csrf_field key="membres_import"} <input type="submit" name="import" value="Importer →" /> </p> </form> {include file="admin/_foot.tpl"} |
Modified src/www/admin/membres/import.php from [414da74c86] to [87bae42958].
︙ | ︙ | |||
23 24 25 26 27 28 29 | $import->toODS(); exit; } $champs = $config->get('champs_membres')->getAll(); $champs->date_inscription = (object) ['title' => 'Date inscription', 'type' => 'date']; | > > > > > > > > > > > > > > > > > > > > > > > > > | | < | | > | | < < > > > < < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | $import->toODS(); exit; } $champs = $config->get('champs_membres')->getAll(); $champs->date_inscription = (object) ['title' => 'Date inscription', 'type' => 'date']; $csv_file = false; if (f('csv_encoded')) { $form->check('membres_import', [ 'csv_encoded' => 'required|json', 'csv_translate' => 'required|array', 'skip_first_line' => 'boolean', ]); $csv_file = json_decode(f('csv_encoded'), true); if (!$form->hasErrors()) { try { $import->fromArray($csv_file, f('csv_translate'), f('skip_first_line') ? 1 : 0); Utils::redirect(ADMIN_URL . 'membres/import.php?ok'); } catch (UserException $e) { $form->addError($e->getMessage()); } } } elseif (f('import')) { $form->check('membres_import', [ 'upload' => 'file|required', 'type' => 'required|in:csv,garradin', ]); if (!$form->hasErrors()) { try { if (f('type') == 'garradin') { $import->fromGarradinCSV($_FILES['upload']['tmp_name'], $user->id); Utils::redirect(ADMIN_URL . 'membres/import.php?ok'); } elseif (f('type') == 'csv') { $csv_file = $import->getCSVAsArray($_FILES['upload']['tmp_name']); } else { throw new UserException('Import inconnu.'); } } catch (UserException $e) { $form->addError($e->getMessage()); } } } $tpl->assign('ok', null !== qg('ok') ? true : false); $tpl->assign('csv_file', $csv_file); $tpl->assign('csv_first_line', $csv_file ? reset($csv_file) : null); $tpl->assign('garradin_champs', $champs); $tpl->display('admin/membres/import.tpl'); |