init
[garradin.git] / include / class.membres_import.php
1 <?php
2
3 namespace Garradin;
4
5 class Membres_Import
6 {
7 /**
8 * Champs du CSV de Galette
9 * les lignes vides ('') ne seront pas proposées à l'import
10 * @var array
11 */
12 public $galette_fields = [
13 'Numéro',
14 1,
15 'Nom',
16 'Prénom',
17 'Pseudo',
18 'Société',
19 2,
20 'Date de naissance',
21 3,
22 'Adresse, ligne 1',
23 'Adresse, ligne 2',
24 'Code postal',
25 'Ville',
26 'Pays',
27 'Téléphone fixe',
28 'Téléphone mobile',
29 'E-Mail',
30 'Site web',
31 'ICQ',
32 'MSN',
33 'Jabber',
34 'Infos (réservé administrateur)',
35 'Infos (public)',
36 'Profession',
37 'Identifiant',
38 'Mot de passe',
39 'Date création fiche',
40 'Date modification fiche',
41 4, // activite_adh
42 5, // bool_admin_adh
43 6, // bool_exempt_adh
44 7, // bool_display_info
45 8, // date_echeance
46 9, // pref_lang
47 'Lieu de naissance',
48 10, // GPG id
49 11 // Fingerprint
50 ];
51
52 /**
53 * Importer un CSV de la liste des membres depuis Galette
54 * @param string $path Chemin vers le CSV
55 * @param array $translation_table Tableau indiquant la correspondance à effectuer entre les champs
56 * de Galette et ceux de Garradin. Par exemple : ['Date création fiche' => 'date_inscription']
57 * @return boolean TRUE en cas de succès
58 */
59 public function fromGalette($path, $translation_table)
60 {
61 if (!file_exists($path) || !is_readable($path))
62 {
63 throw new \RuntimeException('Fichier inconnu : '.$path);
64 }
65
66 $fp = fopen($path, 'r');
67
68 if (!$fp)
69 {
70 return false;
71 }
72
73 $db = DB::getInstance();
74 $db->exec('BEGIN;');
75 $membres = new Membres;
76
77 $columns = array_flip($this->galette_fields);
78
79 $col = function($column) use (&$row, &$columns)
80 {
81 if (!isset($columns[$column]))
82 return null;
83
84 if (!isset($row[$columns[$column]]))
85 return null;
86
87 return $row[$columns[$column]];
88 };
89
90 $line = 0;
91 $delim = utils::find_csv_delim($fp);
92
93 while (!feof($fp))
94 {
95 $row = fgetcsv($fp, 4096, $delim);
96 $line++;
97
98 if (empty($row))
99 {
100 continue;
101 }
102
103 if (count($row) != count($columns))
104 {
105 $db->exec('ROLLBACK;');
106 throw new UserException('Erreur sur la ligne ' . $line . ' : le nombre de colonnes est incorrect.');
107 }
108
109 $data = [];
110
111 foreach ($translation_table as $galette=>$garradin)
112 {
113 // Champs qu'on ne veut pas importer
114 if (empty($garradin))
115 continue;
116
117 // Concaténer plusieurs champs
118 if (isset($data[$garradin]))
119 $data[$garradin] .= "\n" . $col($galette);
120 else
121 $data[$garradin] = $col($galette);
122 }
123
124 try {
125 $membres->add($data);
126 }
127 catch (UserException $e)
128 {
129 $db->exec('ROLLBACK;');
130 throw new UserException('Erreur sur la ligne ' . $line . ' : ' . $e->getMessage());
131 }
132 }
133
134 $db->exec('END;');
135
136 fclose($fp);
137 return true;
138 }
139
140 /**
141 * Importer un CSV de la liste des membres depuis un export Garradin
142 * @param string $path Chemin vers le CSV
143 * @return boolean TRUE en cas de succès
144 */
145 public function fromCSV($path)
146 {
147 if (!file_exists($path) || !is_readable($path))
148 {
149 throw new \RuntimeException('Fichier inconnu : '.$path);
150 }
151
152 $fp = fopen($path, 'r');
153
154 if (!$fp)
155 {
156 return false;
157 }
158
159 $db = DB::getInstance();
160 $db->exec('BEGIN;');
161 $membres = new Membres;
162
163 // On récupère les champs qu'on peut importer
164 $champs = Config::getInstance()->get('champs_membres')->getAll();
165 $champs = array_keys($champs);
166 $champs[] = 'date_inscription';
167 $champs[] = 'date_connexion';
168 $champs[] = 'id';
169 $champs[] = 'id_categorie';
170
171 $line = 0;
172 $delim = utils::find_csv_delim($fp);
173
174 while (!feof($fp))
175 {
176 $row = fgetcsv($fp, 4096, $delim);
177
178 $line++;
179
180 if (empty($row))
181 {
182 continue;
183 }
184
185 if ($line == 1)
186 {
187 if (is_numeric($row[0]))
188 {
189 throw new UserException('Erreur sur la ligne 1 : devrait contenir l\'en-tête des colonnes.');
190 }
191
192 $columns = array_flip($row);
193 continue;
194 }
195
196 if (count($row) != count($columns))
197 {
198 $db->exec('ROLLBACK;');
199 throw new UserException('Erreur sur la ligne ' . $line . ' : le nombre de colonnes est incorrect.');
200 }
201
202 $data = [];
203
204 foreach ($columns as $name=>$id)
205 {
206 $name = trim($name);
207
208 // Champs qui n'existent pas dans le schéma actuel
209 if (!in_array($name, $champs))
210 continue;
211
212 if (trim($row[$id]) !== '')
213 $data[$name] = $row[$id];
214 }
215
216 if (!empty($data['id']))
217 {
218 $id = (int)$data['id'];
219 unset($data['id']);
220 }
221 else
222 {
223 $id = false;
224 }
225
226 try {
227 if ($id)
228 $membres->edit($id, $data);
229 else
230 $membres->add($data);
231 }
232 catch (UserException $e)
233 {
234 $db->exec('ROLLBACK;');
235 throw new UserException('Erreur sur la ligne ' . $line . ' : ' . $e->getMessage());
236 }
237 }
238
239 $db->exec('END;');
240
241 fclose($fp);
242 return true;
243 }
244
245 public function toCSV()
246 {
247 $db = DB::getInstance();
248
249 $res = $db->prepare('SELECT m.id, c.nom AS categorie, m.* FROM membres AS m
250 LEFT JOIN membres_categories AS c ON m.id_categorie = c.id ORDER BY c.id;')->execute();
251
252 $fp = fopen('php://output', 'w');
253 $header = false;
254
255 while ($row = $res->fetchArray(SQLITE3_ASSOC))
256 {
257 unset($row['passe']);
258
259 if (!$header)
260 {
261 fputcsv($fp, array_keys($row));
262 $header = true;
263 }
264
265 fputcsv($fp, $row);
266 }
267
268 fclose($fp);
269
270 return true;
271 }
272 }