1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Application; |
6
|
|
|
|
7
|
|
|
use Doctrine\DBAL\Driver\PDOConnection; |
8
|
|
|
|
9
|
|
|
class Importer |
10
|
|
|
{ |
11
|
|
|
/** |
12
|
|
|
* @var PDOConnection |
13
|
|
|
*/ |
14
|
|
|
private $filemaker; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var PDOConnection |
18
|
|
|
*/ |
19
|
|
|
private $typo3; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var array |
23
|
|
|
*/ |
24
|
|
|
private $members = []; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var array |
28
|
|
|
*/ |
29
|
|
|
private $users = []; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Import constructor |
33
|
|
|
*/ |
34
|
|
|
public function __construct() |
35
|
|
|
{ |
36
|
|
|
$this->loadMembers(); |
37
|
|
|
$this->loadPeople(); |
38
|
|
|
$this->deleteTestUsers(); |
39
|
|
|
$this->insertUsers(); |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @return PDOConnection |
44
|
|
|
*/ |
45
|
|
|
private function connectFileMaker(): PDOConnection |
46
|
|
|
{ |
47
|
|
|
global $container; |
48
|
|
|
if ($this->filemaker) { |
49
|
|
|
return $this->filemaker; |
50
|
|
|
} |
51
|
|
|
$config = $container->get('config'); |
52
|
|
|
|
53
|
|
|
$dsn = sprintf('odbc:Driver={%s};Server=%s;Database=%s;charset=UTF-8', $config['filemaker']['driver'], $config['filemaker']['host'], $config['filemaker']['dbname']); |
54
|
|
|
$this->filemaker = new PDOConnection($dsn, $config['filemaker']['user'], $config['filemaker']['password']); |
55
|
|
|
|
56
|
|
|
return $this->filemaker; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @return PDOConnection |
61
|
|
|
*/ |
62
|
|
|
private function connectTypo3(): PDOConnection |
63
|
|
|
{ |
64
|
|
|
global $container; |
65
|
|
|
if ($this->typo3) { |
66
|
|
|
return $this->typo3; |
67
|
|
|
} |
68
|
|
|
$config = $container->get('config'); |
69
|
|
|
|
70
|
|
|
$this->typo3 = new PDOConnection(sprintf('mysql:host=%s;port=%u;dbname=%s', $config['typo3']['host'], $config['typo3']['port'], $config['typo3']['dbname']), $config['typo3']['user'], $config['typo3']['password']); |
71
|
|
|
|
72
|
|
|
return $this->typo3; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Load members from FileMaker "ichtus" table into memory |
77
|
|
|
*/ |
78
|
|
|
private function loadMembers(): void |
79
|
|
|
{ |
80
|
|
|
$this->connectFileMaker(); |
81
|
|
|
$query = <<<EOT |
82
|
|
|
SELECT ID_membre, |
83
|
|
|
"nom_prénom", |
84
|
|
|
"date_entrée ichtus", |
85
|
|
|
remarques, |
86
|
|
|
"liens de famille", |
87
|
|
|
"date_séance d'accueil", |
88
|
|
|
"date_formulaire_adhésion", |
89
|
|
|
membre_new, |
90
|
|
|
membre_actif, |
91
|
|
|
membre_suspension, |
92
|
|
|
"membre_archivé", |
93
|
|
|
assurances, |
94
|
|
|
envoi_papier |
95
|
|
|
FROM ichtus |
96
|
|
|
WHERE ((membre_new>0 AND "date_formulaire_adhésion">=DATE '2018-10-01') OR membre_actif>0 OR membre_suspension>0) AND "membre_archivé"=0 AND remarques NOT LIKE '%Ignorer%' |
97
|
|
|
EOT; |
98
|
|
|
$statement = $this->filemaker->prepare(trim($query)); |
99
|
|
|
if ($statement->execute()) { |
100
|
|
|
echo sprintf('%u membres à importer...', $statement->rowCount()) . PHP_EOL; |
101
|
|
|
foreach ($statement->fetchAll(\PDO::FETCH_ASSOC) as $member) { |
102
|
|
|
foreach ($member as $fieldName => $fieldValue) { |
103
|
|
|
$member[$fieldName] = $this->fromMacRoman($fieldValue); |
104
|
|
|
} |
105
|
|
|
$this->members[$member['ID_membre']] = $member; |
106
|
|
|
echo sprintf('Membre %u importé', $member['ID_membre']) . PHP_EOL; |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Load people from TYPO3 fe_users into memory |
113
|
|
|
*/ |
114
|
|
|
private function loadPeople(): void |
115
|
|
|
{ |
116
|
|
|
$this->connectTypo3(); |
117
|
|
|
$query = <<<EOT |
118
|
|
|
SELECT * |
119
|
|
|
FROM fe_users |
120
|
|
|
WHERE FIND_IN_SET(CAST(family_uid as char), :members) AND status_archived=0 AND disable=0; |
121
|
|
|
EOT; |
122
|
|
|
$statement = $this->typo3->prepare($query); |
123
|
|
|
$statement->bindValue('members', implode(',', array_keys($this->members))); |
124
|
|
|
|
125
|
|
|
if ($statement->execute()) { |
126
|
|
|
echo sprintf('%u individus à importer...', $statement->rowCount()) . PHP_EOL; |
127
|
|
|
$withoutLoginCount = 0; |
128
|
|
|
foreach ($statement->fetchAll(\PDO::FETCH_ASSOC) as $user) { |
129
|
|
|
if (($user['family_status'] === 'chef de famille' || $user['family_status'] === 'chef(fe) de famille') && $user['uid'] !== $user['family_uid']) { |
130
|
|
|
echo sprintf('WARN: utilisateur %u ne devrait pas être de chef de la famille %u', $user['uid'], $user['family_uid']) . PHP_EOL; |
131
|
|
|
} |
132
|
|
|
if (empty($user['new_username'])) { |
133
|
|
|
echo sprintf("WARN: utilisateur %u (%s %s) n'a pas de login MyIchtus", $user['uid'], $user['first_name'], $user['last_name']) . PHP_EOL; |
134
|
|
|
++$withoutLoginCount; |
135
|
|
|
} |
136
|
|
|
$this->users[$user['uid']] = $user; |
137
|
|
|
echo sprintf('Individu %u importé', $user['uid']) . PHP_EOL; |
138
|
|
|
} |
139
|
|
|
if ($withoutLoginCount > 0) { |
140
|
|
|
echo sprintf('%u individus sans login MyIchtus', $withoutLoginCount) . PHP_EOL; |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Create users |
147
|
|
|
*/ |
148
|
|
|
private function insertUsers(): void |
149
|
|
|
{ |
150
|
|
|
$conn = _em()->getConnection(); |
151
|
|
|
foreach ($this->users as $user) { |
152
|
|
|
echo sprintf('Insert user %u (%s %s)', $user['uid'], $user['first_name'], $user['last_name']) . PHP_EOL; |
153
|
|
|
$insert = <<<EOT |
154
|
|
|
REPLACE INTO user( |
155
|
|
|
id, |
156
|
|
|
login, |
157
|
|
|
first_name, |
158
|
|
|
last_name, |
159
|
|
|
birthday, |
160
|
|
|
sex, |
161
|
|
|
email, |
162
|
|
|
street, |
163
|
|
|
postcode, |
164
|
|
|
locality, |
165
|
|
|
country_id, |
166
|
|
|
mobile_phone, |
167
|
|
|
phone, |
168
|
|
|
remarks, |
169
|
|
|
iban, |
170
|
|
|
has_insurance, |
171
|
|
|
swiss_sailing, |
172
|
|
|
swiss_sailing_type, |
173
|
|
|
swiss_windsurf_type, |
174
|
|
|
receives_newsletter, |
175
|
|
|
family_relationship, |
176
|
|
|
billing_type, |
177
|
|
|
welcome_session_date, |
178
|
|
|
status |
179
|
|
|
) VALUES ( |
180
|
|
|
:id, |
181
|
|
|
:login, |
182
|
|
|
:first_name, |
183
|
|
|
:last_name, |
184
|
|
|
:birthday, |
185
|
|
|
:sex, |
186
|
|
|
:email, |
187
|
|
|
:street, |
188
|
|
|
:postcode, |
189
|
|
|
:locality, |
190
|
|
|
:country_id, |
191
|
|
|
:mobile_phone, |
192
|
|
|
:phone, |
193
|
|
|
:remarks, |
194
|
|
|
:iban, |
195
|
|
|
:has_insurance, |
196
|
|
|
:swiss_sailing, |
197
|
|
|
:swiss_sailing_type, |
198
|
|
|
:swiss_windsurf_type, |
199
|
|
|
:receives_newsletter, |
200
|
|
|
:family_relationship, |
201
|
|
|
:billing_type, |
202
|
|
|
:welcome_session_date, |
203
|
|
|
:status |
204
|
|
|
) |
205
|
|
|
EOT; |
206
|
|
|
|
207
|
|
|
$insert = $conn->prepare($insert); |
208
|
|
|
$insert->bindValue('id', $user['uid']); |
209
|
|
|
$insert->bindValue('login', $user['new_username']); |
210
|
|
|
$insert->bindValue('first_name', $user['first_name']); |
211
|
|
|
$insert->bindValue('last_name', $user['last_name']); |
212
|
|
|
$insert->bindValue('birthday', $user['date_birth'] !== null && $user['date_birth'] !== '0000-00-00' ? $user['date_birth'] : null); |
213
|
|
|
$insert->bindValue('sex', $user['sexe'] === 'F' ? 2 : 1); |
214
|
|
|
$insert->bindValue('email', !empty($user['email']) ? $user['email'] : null); |
215
|
|
|
$insert->bindValue('street', $user['address']); |
216
|
|
|
$insert->bindValue('postcode', $user['zip']); |
217
|
|
|
$insert->bindValue('locality', $user['city']); |
218
|
|
|
|
219
|
|
|
switch ($user['country']) { |
220
|
|
|
case 'CH': $country_id = 1; |
221
|
|
|
|
222
|
|
|
break; |
223
|
|
|
case 'FR': $country_id = 2; |
224
|
|
|
|
225
|
|
|
break; |
226
|
|
|
case 'DE': $country_id = 10; |
227
|
|
|
|
228
|
|
|
break; |
229
|
|
|
case 'CA': $country_id = 6; |
230
|
|
|
|
231
|
|
|
break; |
232
|
|
|
case 'NL': $country_id = 19; |
233
|
|
|
|
234
|
|
|
break; |
235
|
|
|
default: |
236
|
|
|
$country_id = null; |
237
|
|
|
echo sprintf("WARN: pas de correspondance pour le code pays %s de l\\'individu %u (%s &s)", $user['country'], $user['uid'], $user['first_name'], $user['last_name']) . PHP_EOL; |
238
|
|
|
} |
239
|
|
|
$insert->bindValue('country_id', $country_id); |
240
|
|
|
|
241
|
|
|
$insert->bindValue('mobile_phone', !empty($user['natel']) ? $user['natel'] : ''); |
242
|
|
|
$insert->bindValue('phone', $user['telephone']); |
243
|
|
|
|
244
|
|
|
if ($user['uid'] === $user['family_uid']) { |
245
|
|
|
// Si responsable de l'adhésion, fusionne les notes au niveau du membre et de l'individu |
246
|
|
|
$remarks = implode(PHP_EOL, [$this->members[$user['family_uid']]['remarques'], $user['notes']]); |
247
|
|
|
} else { |
248
|
|
|
$remarks = !empty($user['notes']) ? $user['notes'] : ''; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
$insert->bindValue('remarks', $remarks); |
252
|
|
|
$insert->bindValue('iban', !empty($user['IBAN']) ? $user['IBAN'] : ''); |
253
|
|
|
$insert->bindValue('has_insurance', !empty($this->members[$user['family_uid']]['assurances']) ? 1 : 0); |
254
|
|
|
|
255
|
|
|
$insert->bindValue('swiss_sailing', !empty($user['ichtus_swiss_sailing']) ? $user['ichtus_swiss_sailing'] : ''); |
256
|
|
|
switch ($user['ichtus_swiss_sailing_type']) { |
257
|
|
|
case 'A': $swissSailingType = 'active'; |
258
|
|
|
|
259
|
|
|
break; |
260
|
|
|
case 'P': $swissSailingType = 'passive'; |
261
|
|
|
|
262
|
|
|
break; |
263
|
|
|
case 'J': $swissSailingType = 'junior'; |
264
|
|
|
|
265
|
|
|
break; |
266
|
|
|
default: $swissSailingType = null; |
267
|
|
|
} |
268
|
|
|
$insert->bindValue('swiss_sailing_type', $swissSailingType); |
269
|
|
|
|
270
|
|
|
switch ($user['ichtus_swiss_windsurf_type']) { |
271
|
|
|
case 'A': $swissWindsurfType = 'active'; |
272
|
|
|
|
273
|
|
|
break; |
274
|
|
|
case 'P': $swissWindsurfType = 'passive'; |
275
|
|
|
|
276
|
|
|
break; |
277
|
|
|
default: $swissWindsurfType = null; |
278
|
|
|
} |
279
|
|
|
$insert->bindValue('swiss_windsurf_type', $swissWindsurfType); |
280
|
|
|
|
281
|
|
|
$insert->bindValue('receives_newsletter', !empty($user['email']) ? 1 : 0); |
282
|
|
|
|
283
|
|
|
switch ($user['family_status']) { |
284
|
|
|
case 'chef de famille': $relationship = 'householder'; |
285
|
|
|
|
286
|
|
|
break; |
287
|
|
|
case 'chef(fe) de famille': $relationship = 'householder'; |
288
|
|
|
|
289
|
|
|
break; |
290
|
|
|
case 'conjoint': $relationship = 'partner'; |
291
|
|
|
|
292
|
|
|
break; |
293
|
|
|
case 'enfant': $relationship = 'child'; |
294
|
|
|
|
295
|
|
|
break; |
296
|
|
|
case 'parent': $relationship = 'parent'; |
297
|
|
|
|
298
|
|
|
break; |
299
|
|
|
case 'soeur': $relationship = 'sister'; |
300
|
|
|
|
301
|
|
|
break; |
302
|
|
|
case 'frère': $relationship = 'brother'; |
303
|
|
|
|
304
|
|
|
break; |
305
|
|
|
case 'beau-frère': $relationship = 'brother'; |
306
|
|
|
|
307
|
|
|
break; |
308
|
|
|
default: |
309
|
|
|
$relationship = 'householder'; |
310
|
|
|
echo sprintf("WARN: individu %u (%s %s) n'a pas de statut familial", $user['uid'], $user['first_name'], $user['last_name']) . PHP_EOL; |
311
|
|
|
} |
312
|
|
|
$insert->bindValue('family_relationship', $relationship); |
313
|
|
|
|
314
|
|
|
if ($this->members[$user['family_uid']]['envoi_papier'] && empty($user['email'])) { |
315
|
|
|
$insert->bindValue('billing_type', 'paper'); |
316
|
|
|
} else { |
317
|
|
|
$insert->bindValue('billing_type', 'electronic'); |
318
|
|
|
} |
319
|
|
|
$insert->bindValue('welcome_session_date', $this->members[$user['family_uid']]["date_séance d'accueil"]); |
320
|
|
|
|
321
|
|
|
$userStatus = 'new'; |
322
|
|
|
if ($user['status_new'] + $user['status_actif'] + $user['status_archived'] > 1) { |
323
|
|
|
echo sprintf('WARN individu %u (%s %s) a plus d\' un statut actif à la fois', $user['uid'], $user['first_name'], $user['last_name']) . PHP_EOL; |
324
|
|
|
} |
325
|
|
|
if ($user['status_actif']) { |
326
|
|
|
$userStatus = 'active'; |
327
|
|
|
} elseif ($user['status_archived']) { |
328
|
|
|
$userStatus = 'archived'; |
329
|
|
|
} |
330
|
|
|
$insert->bindValue('status', $userStatus); |
331
|
|
|
|
332
|
|
|
$insert->execute(); |
333
|
|
|
} |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Convert MacRoman string to UTF-8 |
338
|
|
|
* |
339
|
|
|
* @param mixed $string |
340
|
|
|
* |
341
|
|
|
* @return string |
342
|
|
|
*/ |
343
|
|
|
private function fromMacRoman($string): ?string |
344
|
|
|
{ |
345
|
|
|
return !empty($string) ? iconv('MacRoman', 'UTF-8', $string) : $string; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
/** |
349
|
|
|
* Delete existing test users prior importing to prevent an ID collision |
350
|
|
|
*/ |
351
|
|
|
private function deleteTestUsers(): void |
352
|
|
|
{ |
353
|
|
|
$conn = _em()->getConnection(); |
354
|
|
|
$result = $conn->executeQuery('SELECT id FROM account a where a.owner_id >= 1000 AND a.owner_id <= 1011'); |
355
|
|
|
$accounts = $result->fetchAll(\PDO::FETCH_COLUMN); |
356
|
|
|
print_r($accounts); |
357
|
|
|
$stmt = $conn->prepare('DELETE tl, t FROM transaction_line tl JOIN transaction t ON tl.transaction_id = t.id WHERE FIND_IN_SET(CAST(tl.debit_id as char), :accounts) OR FIND_IN_SET(CAST(tl.credit_id as char), :accounts)'); |
358
|
|
|
$stmt->bindValue('accounts', implode(',', $accounts)); |
359
|
|
|
$stmt->execute(); |
360
|
|
|
$stmt = $conn->prepare('DELETE FROM account WHERE FIND_IN_SET(CAST(id as char), :accounts)'); |
361
|
|
|
$stmt->bindValue('accounts', implode(',', $accounts)); |
362
|
|
|
$stmt->execute(); |
363
|
|
|
$stmt = $conn->prepare('DELETE FROM message WHERE (creator_id >= 1000 AND creator_id <= 1011) OR (owner_id >= 1000 AND owner_id <= 1011)'); |
364
|
|
|
$stmt->execute(); |
365
|
|
|
$stmt = $conn->prepare('DELETE FROM user_tag WHERE (creator_id >= 1000 AND creator_id <= 1011) OR (owner_id >= 1000 AND owner_id <= 1011)'); |
366
|
|
|
$stmt->execute(); |
367
|
|
|
$stmt = $conn->prepare('DELETE FROM user_tag WHERE (creator_id >= 1000 AND creator_id <= 1011) OR (owner_id >= 1000 AND owner_id <= 1011)'); |
368
|
|
|
$stmt->execute(); |
369
|
|
|
$stmt = $conn->prepare('DELETE FROM expense_claim WHERE (creator_id >= 1000 AND creator_id <= 1011) OR (owner_id >= 1000 AND owner_id <= 1011)'); |
370
|
|
|
$stmt->execute(); |
371
|
|
|
$stmt = $conn->prepare('DELETE FROM booking WHERE (creator_id >= 1000 AND creator_id <= 1011) OR (owner_id >= 1000 AND owner_id <= 1011)'); |
372
|
|
|
$stmt->execute(); |
373
|
|
|
$stmt = $conn->prepare('SET FOREIGN_KEY_CHECKS=0; DELETE FROM user WHERE id >= 1000 AND id <= 1011; SET FOREIGN_KEY_CHECKS=1;'); |
374
|
|
|
$stmt->execute(); |
375
|
|
|
} |
376
|
|
|
} |
377
|
|
|
|