Failed Conditions
Push — master ( dc3899...a0ee18 )
by
unknown
07:45
created

Importer::connectFileMaker()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 12
ccs 0
cts 10
cp 0
crap 6
rs 10
c 0
b 0
f 0
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