4 * Copyright © 2003-2024 The Galette Team
6 * This file is part of Galette (https://galette.eu).
8 * Galette is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * Galette is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
22 namespace Galette\IO\test\units
;
24 use Galette\Entity\FieldsConfig
;
25 use PHPUnit\Framework\TestCase
;
26 use Galette\Entity\Adherent
;
27 use Galette\DynamicFields\DynamicField
;
28 use Galette\GaletteTestCase
;
33 * @author Johan Cwiklinski <johan@x-tnd.be>
35 class CsvIn
extends GaletteTestCase
37 private ?
string $contents_table = null;
44 public function setUp(): void
47 $this->contents_table
= null;
55 public function tearDown(): void
59 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
60 $this->zdb
->execute($delete);
61 $delete = $this->zdb
->delete(\Galette\Entity\DynamicFieldsHandle
::TABLE
);
62 $this->zdb
->execute($delete);
63 $delete = $this->zdb
->delete(DynamicField
::TABLE
);
64 $this->zdb
->execute($delete);
65 //cleanup dynamic translations
66 $delete = $this->zdb
->delete(\Galette\Core\L10n
::TABLE
);
69 'Dynamic choice field',
74 $this->zdb
->execute($delete);
76 if ($this->contents_table
!== null) {
77 $this->zdb
->drop($this->contents_table
);
82 * Import text CSV file
84 * @param array $fields Fields name to use at import
85 * @param string $file_name File name
86 * @param array $flash_messages Expected flash messages from doImport route
87 * @param array $members_list List of faked members data
88 * @param integer $count_before Count before insertions. Defaults to 0 if null.
89 * @param integer $count_after Count after insertions. Default to $count_before + count $members_list
90 * @param array $values Textual values for dynamic choices fields
94 private function doImportFileTest(
97 array $flash_messages,
99 int $count_before = null,
100 int $count_after = null,
103 if ($count_before === null) {
106 if ($count_after === null) {
107 $count_after = $count_before +
count($members_list);
110 $members = new \Galette\Repository\
Members();
111 $list = $members->getList();
115 print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS
, 1), true)
118 $model = $this->getModel($fields);
120 //get csv model file to add data in
121 $controller = new \Galette\Controllers\
CsvController($this->container
);
122 $this->container
->injectOn($controller);
124 $rfactory = new \Slim\Psr7\Factory\
RequestFactory();
125 $request = $rfactory->createRequest('GET', 'http://localhost/models/csv');
126 $response = new \Slim\Psr7\
Response();
128 $response = $controller->getImportModel($request, $response);
129 $csvin = new \Galette\IO\
CsvIn($this->container
->get('zdb'));
131 $this->assertSame(200, $response->getStatusCode());
132 $headers = $response->getHeaders();
133 $this->assertIsArray($headers);
134 $this->assertSame(['text/csv'], $headers['Content-Type']);
136 ['attachment;filename="galette_import_model.csv"'],
137 $headers['Content-Disposition']
140 $csvfile_model = $response->getBody()->__toString();
142 "\"" . implode("\";\"", $fields) . "\"\r\n",
146 $contents = $csvfile_model;
147 foreach ($members_list as $member) {
149 foreach ($fields as $field) {
150 $amember[$field] = $member[$field];
152 $contents .= "\"" . implode("\";\"", $amember) . "\"\r\n";
155 $path = GALETTE_CACHE_DIR
. $file_name;
156 $this->assertIsInt(file_put_contents($path, $contents));
157 $_FILES['new_file'] = [
158 'error' => UPLOAD_ERR_OK
,
159 'name' => $file_name,
161 'size' => filesize($path)
163 $this->assertTrue($csvin->store($_FILES['new_file'], true));
164 $this->assertTrue(file_exists($csvin->getDestDir() . $csvin->getFileName()));
167 'import_file' => $file_name
170 $request = clone $request;
171 $request = $request->withParsedBody($post);
173 $response = $controller->doImports($request, $response);
174 $this->assertSame(301, $response->getStatusCode());
175 $this->assertSame($flash_messages, $this->flash_data
['slimFlash']);
176 $this->flash
->clearMessages();
178 $members = new \Galette\Repository\
Members();
179 $list = $members->getList();
180 $this->assertSame($count_after, $list->count());
182 if ($count_before != $count_after) {
183 foreach ($list as $member) {
184 $created = $members_list[$member->fingerprint
];
185 foreach ($fields as $field) {
186 if (property_exists($member, $field)) {
187 $this->assertEquals($created[$field], $member->$field);
189 //manage dynamic fields
191 if (preg_match('/^dynfield_(\d+)/', $field, $matches)) {
192 $adh = new Adherent($this->zdb
, (int)$member->id_adh
, ['dynamics' => true]);
195 'item_id' => $adh->id
,
196 'field_form' => 'adh',
198 'field_val' => $created[$field]
202 $dfield = $adh->getDynamicFields()->getValues($matches[1]);
203 if (isset($dfield[0]['text_val'])) {
204 //choice, add textual value
205 $expected[0]['text_val'] = $values[$created[$field]];
210 $adh->getDynamicFields()->getValues($matches[1])
213 throw new \
RuntimeException("Unknown field $field");
222 * Test CSV import loading
226 public function testImport(): void
228 $fields = ['nom_adh', 'ville_adh', 'bool_exempt_adh', 'fingerprint'];
229 $file_name = 'test-import-atoum.csv';
231 'success_detected' => ["File '$file_name' has been successfully imported :)"]
233 $members_list = $this->getMemberData1();
237 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
240 $file_name = 'test-import-atoum-noname.csv';
242 'error_detected' => [
243 'File does not comply with requirements.',
244 'Field nom_adh is required, but missing in row 3'
248 $members_list = $this->getMemberData2NoName();
252 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
256 * Get CSV import model
258 * @param array $fields Fields list
260 * @return \Galette\Entity\ImportModel
262 protected function getModel(array $fields): \Galette\Entity\ImportModel
264 $model = new \Galette\Entity\
ImportModel();
265 $this->assertTrue($model->remove($this->zdb
));
267 $this->assertInstanceOf(\Galette\Entity\ImportModel
::class, $model->setFields($fields));
268 $this->assertTrue($model->store($this->zdb
));
269 $this->assertTrue($model->load());
274 * Test dynamic translation has been added properly
276 * @param string $text_orig Original text
277 * @param string $lang Lang text has been added in
281 protected function checkDynamicTranslation(string $text_orig, string $lang = 'fr_FR.utf8'): void
283 $langs = array_keys($this->i18n
->getArrayList());
284 $select = $this->zdb
->select(\Galette\Core\L10n
::TABLE
);
290 $select->where(['text_orig' => $text_orig]);
291 $results = $this->zdb
->execute($select);
292 $this->assertSame(count($langs), $results->count());
294 foreach ($results as $result) {
295 $this->assertTrue(in_array(str_replace('.utf8', '', $result['text_locale']), $langs));
296 $this->assertSame(1, (int)$result['text_nref']);
298 ($result['text_locale'] == 'en_US' ?
$text_orig : ''),
299 $result['text_trans']
305 * Test import with dynamic fields
309 public function testImportDynamics(): void
313 'form_name' => 'adh',
314 'field_name' => 'Dynamic text field',
315 'field_perm' => FieldsConfig
::USER_WRITE
,
316 'field_type' => DynamicField
::TEXT
,
317 'field_required' => 1,
321 $df = DynamicField
::getFieldType($this->zdb
, $field_data['field_type']);
323 $stored = $df->store($field_data);
324 $error_detected = $df->getErrors();
325 $warning_detected = $df->getWarnings();
330 $df->getErrors() +
$df->getWarnings()
333 $this->assertEmpty($error_detected, implode(' ', $df->getErrors()));
334 $this->assertEmpty($warning_detected, implode(' ', $df->getWarnings()));
335 //check if dynamic translation has been added
336 $this->checkDynamicTranslation($field_data['field_name']);
338 $select = $this->zdb
->select(DynamicField
::TABLE
);
339 $select->columns(array('num' => new \Laminas\Db\Sql\
Expression('COUNT(1)')));
340 $result = $this->zdb
->execute($select)->current();
341 $this->assertSame(1, (int)$result->num
);
343 $fields = ['nom_adh', 'ville_adh', 'dynfield_' . $df->getId(), 'fingerprint'];
344 $file_name = 'test-import-atoum-dyn.csv';
346 'success_detected' => ["File '$file_name' has been successfully imported :)"]
348 $members_list = $this->getMemberData1();
349 foreach ($members_list as $fingerprint => &$data) {
350 $data['dynfield_' . $df->getId()] = 'Dynamic field value for ' . $data['fingerprint'];
355 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
358 //$fields does not change from previous
359 $file_name = 'test-import-atoum-dyn-noname.csv';
361 'error_detected' => [
362 'File does not comply with requirements.',
363 'Field nom_adh is required, but missing in row 3'
366 $members_list = $this->getMemberData2NoName();
367 foreach ($members_list as $fingerprint => &$data) {
368 $data['dynfield_' . $df->getId()] = 'Dynamic field value for ' . $data['fingerprint'];
374 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
376 //missing required dynamic field
377 //$fields does not change from previous
378 $file_name = 'test-import-atoum-dyn-nodyn.csv';
380 'error_detected' => [
381 'File does not comply with requirements.',
382 'Missing required field Dynamic text field'
385 $members_list = $this->getMemberData2();
387 foreach ($members_list as $fingerprint => &$data) {
388 //two lines without required dynamic field.
389 $data['dynfield_' . $df->getId()] = (($i == 2 ||
$i == 5) ?
'' :
390 'Dynamic field value for ' . $data['fingerprint']);
397 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
399 //cleanup members and dynamic fields values
400 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
401 $this->zdb
->execute($delete);
402 $delete = $this->zdb
->delete(\Galette\Entity\DynamicFieldsHandle
::TABLE
);
403 $this->zdb
->execute($delete);
405 //new dynamic field, of type choice.
412 'form_name' => 'adh',
413 'field_name' => 'Dynamic choice field',
414 'field_perm' => FieldsConfig
::USER_WRITE
,
415 'field_type' => DynamicField
::CHOICE
,
416 'field_required' => 0,
418 'fixed_values' => implode("\n", $values)
421 $cdf = DynamicField
::getFieldType($this->zdb
, $cfield_data['field_type']);
423 $stored = $cdf->store($cfield_data);
424 $error_detected = $cdf->getErrors();
425 $warning_detected = $cdf->getWarnings();
430 $cdf->getErrors() +
$cdf->getWarnings()
433 $this->assertEmpty($error_detected, implode(' ', $cdf->getErrors()));
434 $this->assertEmpty($warning_detected, implode(' ', $cdf->getWarnings()));
435 //check if dynamic translation has been added
436 $this->checkDynamicTranslation($cfield_data['field_name']);
438 $select = $this->zdb
->select(DynamicField
::TABLE
);
439 $select->columns(array('num' => new \Laminas\Db\Sql\
Expression('COUNT(1)')));
440 $result = $this->zdb
->execute($select)->current();
441 $this->assertSame(2, (int)$result->num
);
443 $this->assertSame($values, $cdf->getValues());
445 $fields = ['nom_adh', 'ville_adh', 'dynfield_' . $cdf->getId(), 'fingerprint'];
446 $file_name = 'test-import-atoum-dyn-cdyn.csv';
448 'success_detected' => ["File '$file_name' has been successfully imported :)"]
450 $members_list = $this->getMemberData1();
451 foreach ($members_list as $fingerprint => &$data) {
452 //two lines without required dynamic field.
453 $data['dynfield_' . $cdf->getId()] = rand(0, 2);
459 $this->doImportFileTest(
469 //cleanup members and dynamic fields values
470 $delete = $this->zdb
->delete(\Galette\Entity\Adherent
::TABLE
);
471 $this->zdb
->execute($delete);
472 $delete = $this->zdb
->delete(\Galette\Entity\DynamicFieldsHandle
::TABLE
);
473 $this->zdb
->execute($delete);
474 //cleanup dynamic choices table
475 $this->contents_table
= $cdf->getFixedValuesTableName($cdf->getId());
477 //new dynamic field, of type date.
479 'form_name' => 'adh',
480 'field_name' => 'Dynamic date field',
481 'field_perm' => FieldsConfig
::USER_WRITE
,
482 'field_type' => DynamicField
::DATE
,
483 'field_required' => 0,
487 $cdf = DynamicField
::getFieldType($this->zdb
, $cfield_data['field_type']);
489 $stored = $cdf->store($cfield_data);
490 $error_detected = $cdf->getErrors();
491 $warning_detected = $cdf->getWarnings();
496 $cdf->getErrors() +
$cdf->getWarnings()
499 $this->assertEmpty($error_detected, implode(' ', $cdf->getErrors()));
500 $this->assertEmpty($warning_detected, implode(' ', $cdf->getWarnings()));
501 //check if dynamic translation has been added
502 $this->checkDynamicTranslation($cfield_data['field_name']);
504 $select = $this->zdb
->select(DynamicField
::TABLE
);
505 $select->columns(array('num' => new \Laminas\Db\Sql\
Expression('COUNT(1)')));
506 $result = $this->zdb
->execute($select)->current();
507 $this->assertSame(3, (int)$result->num
);
510 $fields = ['nom_adh', 'ville_adh', 'dynfield_' . $cdf->getId(), 'fingerprint'];
511 $file_name = 'test-import-atoum-cdyn-date.csv';
513 'success_detected' => ["File '$file_name' has been successfully imported :)"]
515 $members_list = $this->getMemberData1();
516 foreach ($members_list as $fingerprint => &$data) {
517 //two lines without required dynamic field.
518 $data['dynfield_' . $cdf->getId()] = $data['date_crea_adh'];
524 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
526 //Test with a bad date
527 //$fields does not change from previous
528 $file_name = 'test-import-atoum-cdyn-baddate.csv';
530 'error_detected' => [
531 'File does not comply with requirements.',
532 '- Wrong date format (Y-m-d) for Dynamic date field!'
535 $members_list = $this->getMemberData2();
537 foreach ($members_list as $fingerprint => &$data) {
538 //two lines without required dynamic field.
539 $data['dynfield_' . $cdf->getId()] = (($i == 2 ||
$i == 5) ?
'20200513' : $data['date_crea_adh']);
546 $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
550 * Get first set of member data
554 private function getMemberData1(): array
558 'nom_adh' => 'Boucher',
559 'prenom_adh' => 'Roland',
560 'ville_adh' => 'Dumas',
562 'adresse_adh' => '5, chemin de Meunier',
563 'email_adh' => 'remy44@lopez.net',
564 'login_adh' => 'jean36',
565 'mdp_adh' => 'HM~OCSl[]UkZp%Y',
566 'mdp_adh2' => 'HM~OCSl[]UkZp%Y',
567 'bool_admin_adh' => false,
568 'bool_exempt_adh' => true,
569 'bool_display_info' => false,
571 'prof_adh' => 'Technicien géomètre',
573 'ddn_adh' => '1914-03-22',
574 'lieu_naissance' => 'Laurent-sur-Guyot',
575 'pseudo_adh' => 'tgonzalez',
577 'tel_adh' => '+33 8 93 53 99 52',
578 'activite_adh' => true,
580 'date_crea_adh' => '2020-03-09',
582 'fingerprint' => 'FAKER_0',
585 'nom_adh' => 'Lefebvre',
586 'prenom_adh' => 'François',
587 'ville_adh' => 'Laine',
589 'adresse_adh' => '311, rue de Costa',
590 'email_adh' => 'astrid64@masse.fr',
591 'login_adh' => 'olivier.pierre',
592 'mdp_adh' => '.4y/J>yN_QUh7Bw@NW>)',
593 'mdp_adh2' => '.4y/J>yN_QUh7Bw@NW>)',
594 'bool_admin_adh' => false,
595 'bool_exempt_adh' => false,
596 'bool_display_info' => false,
598 'prof_adh' => 'Conseiller relooking',
600 'ddn_adh' => '1989-10-31',
601 'lieu_naissance' => 'Collet',
602 'pseudo_adh' => 'agnes.evrard',
604 'tel_adh' => '0288284193',
605 'activite_adh' => true,
607 'date_crea_adh' => '2019-11-29',
609 'fingerprint' => 'FAKER_1',
612 'nom_adh' => 'Lemaire',
613 'prenom_adh' => 'Georges',
614 'ville_adh' => 'Teixeira-sur-Mer',
616 'adresse_adh' => 'place Guillaume',
617 'email_adh' => 'lefort.vincent@club-internet.fr',
618 'login_adh' => 'josette46',
619 'mdp_adh' => '(IqBaAIR',
620 'mdp_adh2' => '(IqBaAIR',
621 'bool_admin_adh' => false,
622 'bool_exempt_adh' => false,
623 'bool_display_info' => true,
625 'prof_adh' => 'Assistant logistique',
627 'ddn_adh' => '1935-09-07',
628 'lieu_naissance' => 'Ponsboeuf',
629 'pseudo_adh' => 'fgay',
631 'tel_adh' => '+33 7 45 45 19 81',
632 'activite_adh' => true,
634 'date_crea_adh' => '2019-02-03',
636 'fingerprint' => 'FAKER_2',
640 'prenom_adh' => 'Thibaut',
641 'ville_adh' => 'Mallet-sur-Prevost',
643 'adresse_adh' => '246, boulevard Daniel Mendes',
644 'email_adh' => 'ihamel@pinto.fr',
645 'login_adh' => 'josephine.fabre',
646 'mdp_adh' => '`2LrQcb9Utgm=Y\\S$',
647 'mdp_adh2' => '`2LrQcb9Utgm=Y\\S$',
648 'bool_admin_adh' => false,
649 'bool_exempt_adh' => false,
650 'bool_display_info' => true,
652 'prof_adh' => 'Aide à domicile',
654 'ddn_adh' => '1961-09-17',
655 'lieu_naissance' => 'Gomez',
656 'pseudo_adh' => 'chauvin.guillaume',
657 'pays_adh' => 'Hong Kong',
658 'tel_adh' => '+33 5 48 57 32 28',
659 'activite_adh' => true,
661 'date_crea_adh' => '2017-11-20',
662 'pref_lang' => 'nb_NO',
663 'fingerprint' => 'FAKER_3',
664 'societe_adh' => 'Jacques',
665 'is_company' => true,
668 'nom_adh' => 'Pascal',
669 'prenom_adh' => 'Isaac',
670 'ville_adh' => 'Jourdanboeuf',
672 'adresse_adh' => '5, boulevard de Boucher',
673 'email_adh' => 'valerie.becker@gmail.com',
674 'login_adh' => 'lucie08',
675 'mdp_adh' => '|%+wtMW{l',
676 'mdp_adh2' => '|%+wtMW{l',
677 'bool_admin_adh' => false,
678 'bool_exempt_adh' => false,
679 'bool_display_info' => true,
681 'prof_adh' => 'Bruiteur',
683 'ddn_adh' => '1953-12-11',
684 'lieu_naissance' => 'Foucher',
685 'pseudo_adh' => 'sauvage.dorothee',
686 'pays_adh' => 'Bangladesh',
687 'tel_adh' => '+33 4 75 14 66 56',
688 'activite_adh' => false,
690 'date_crea_adh' => '2018-08-16',
691 'pref_lang' => 'en_US',
692 'fingerprint' => 'FAKER_4',
695 'nom_adh' => 'Morvan',
696 'prenom_adh' => 'Joseph',
697 'ville_adh' => 'Noel',
699 'adresse_adh' => 'place de Barthelemy',
700 'email_adh' => 'claunay@tele2.fr',
701 'login_adh' => 'marthe.hoarau',
702 'mdp_adh' => '\'C?}vJAU>:-iE',
703 'mdp_adh2' => '\'C?}vJAU>:-iE',
704 'bool_admin_adh' => false,
705 'bool_exempt_adh' => false,
706 'bool_display_info' => true,
708 'prof_adh' => 'Opérateur du son',
710 'ddn_adh' => '1938-05-11',
711 'lieu_naissance' => 'Beguedan',
712 'pseudo_adh' => 'andre.guillou',
714 'tel_adh' => '09 26 70 06 55',
715 'activite_adh' => true,
717 'date_crea_adh' => '2018-09-28',
719 'fingerprint' => 'FAKER_5',
722 'nom_adh' => 'Lebreton',
723 'prenom_adh' => 'Emmanuelle',
724 'ville_adh' => 'Lefevre',
726 'adresse_adh' => '98, rue Moulin',
727 'email_adh' => 'zacharie77@ruiz.fr',
728 'login_adh' => 'marianne.collin',
729 'mdp_adh' => '=jG{wyE',
730 'mdp_adh2' => '=jG{wyE',
731 'bool_admin_adh' => false,
732 'bool_exempt_adh' => false,
733 'bool_display_info' => true,
735 'prof_adh' => 'Galeriste',
737 'ddn_adh' => '2001-02-01',
738 'lieu_naissance' => 'Berthelot',
739 'pseudo_adh' => 'ferreira.rene',
740 'pays_adh' => 'Tuvalu',
741 'tel_adh' => '+33 (0)7 47 56 89 70',
742 'activite_adh' => true,
744 'date_crea_adh' => '2018-01-13',
746 'fingerprint' => 'FAKER_6',
749 'nom_adh' => 'Maurice',
750 'prenom_adh' => 'Capucine',
751 'ville_adh' => 'Renaultdan',
752 'cp_adh' => '59 348',
753 'adresse_adh' => '56, avenue Grenier',
754 'email_adh' => 'didier.emmanuel@tiscali.fr',
755 'login_adh' => 'william.herve',
756 'mdp_adh' => '#7yUz#qToZ\'',
757 'mdp_adh2' => '#7yUz#qToZ\'',
758 'bool_admin_adh' => false,
759 'bool_exempt_adh' => false,
760 'bool_display_info' => true,
762 'prof_adh' => 'Cintrier-machiniste',
764 'ddn_adh' => '1984-04-17',
765 'lieu_naissance' => 'Rolland',
766 'pseudo_adh' => 'roger27',
767 'pays_adh' => 'Antilles néerlandaises',
768 'tel_adh' => '0922523762',
769 'activite_adh' => true,
771 'date_crea_adh' => '2020-02-13',
773 'fingerprint' => 'FAKER_7',
774 'societe_adh' => 'Mace',
775 'is_company' => true,
778 'nom_adh' => 'Hubert',
779 'prenom_adh' => 'Lucy',
780 'ville_adh' => 'Lagarde',
781 'cp_adh' => '22 829',
782 'adresse_adh' => '3, rue Pénélope Marie',
783 'email_adh' => 'zoe02@morvan.com',
784 'login_adh' => 'bernard.agathe',
785 'mdp_adh' => '@9di}eJyc"0s_d(',
786 'mdp_adh2' => '@9di}eJyc"0s_d(',
787 'bool_admin_adh' => false,
788 'bool_exempt_adh' => false,
789 'bool_display_info' => true,
791 'prof_adh' => 'Facteur',
793 'ddn_adh' => '2008-01-13',
794 'lieu_naissance' => 'Ribeiro',
795 'pseudo_adh' => 'julien.isabelle',
796 'pays_adh' => 'Mexique',
797 'tel_adh' => '0809527977',
798 'activite_adh' => true,
800 'date_crea_adh' => '2019-06-26',
801 'pref_lang' => 'de_DE',
802 'fingerprint' => 'FAKER_8',
805 'nom_adh' => 'Goncalves',
806 'prenom_adh' => 'Corinne',
807 'ville_adh' => 'LesageVille',
809 'adresse_adh' => '18, rue de Pinto',
810 'email_adh' => 'julien.clement@dbmail.com',
811 'login_adh' => 'xavier.nicolas',
812 'mdp_adh' => '<W0XdOj2Gp|@;W}gWh]',
813 'mdp_adh2' => '<W0XdOj2Gp|@;W}gWh]',
814 'bool_admin_adh' => false,
815 'bool_exempt_adh' => false,
816 'bool_display_info' => true,
818 'prof_adh' => 'Eleveur de volailles',
820 'ddn_adh' => '2013-09-12',
821 'lieu_naissance' => 'Breton',
822 'pseudo_adh' => 'louis.pruvost',
824 'tel_adh' => '+33 (0)6 80 24 46 58',
825 'activite_adh' => true,
827 'date_crea_adh' => '2020-08-09',
829 'fingerprint' => 'FAKER_9',
835 * Get second set of member data
836 * two lines without name.
840 private function getMemberData2(): array
844 'nom_adh' => 'Goncalves',
845 'prenom_adh' => 'Margot',
846 'ville_adh' => 'Alves',
848 'adresse_adh' => '43, impasse Maurice Imbert',
849 'email_adh' => 'guillou.richard@yahoo.fr',
850 'login_adh' => 'suzanne.mathieu',
851 'mdp_adh' => 'Thihk2z0',
852 'mdp_adh2' => 'Thihk2z0',
853 'bool_admin_adh' => false,
854 'bool_exempt_adh' => false,
855 'bool_display_info' => true,
857 'prof_adh' => 'Cueilleur de cerises',
859 'ddn_adh' => '2020-04-24',
860 'lieu_naissance' => 'Poulain-les-Bains',
861 'pseudo_adh' => 'olivier.roux',
862 'pays_adh' => 'République Dominicaine',
863 'tel_adh' => '08 95 04 73 14',
864 'activite_adh' => true,
866 'date_crea_adh' => '2020-07-31',
868 'fingerprint' => 'FAKER_0',
871 'nom_adh' => 'Da Silva',
872 'prenom_adh' => 'Augustin',
873 'ville_adh' => 'Perrin-sur-Masson',
875 'adresse_adh' => '154, place Boulay',
876 'email_adh' => 'marc60@moreno.fr',
877 'login_adh' => 'hoarau.maryse',
878 'mdp_adh' => '\\9Si%r/FAmz.HE4!{Q\\',
879 'mdp_adh2' => '\\9Si%r/FAmz.HE4!{Q\\',
880 'bool_admin_adh' => false,
881 'bool_exempt_adh' => false,
882 'bool_display_info' => true,
884 'prof_adh' => 'Séismologue',
886 'ddn_adh' => '1988-06-26',
887 'lieu_naissance' => 'Martel',
888 'pseudo_adh' => 'hchevalier',
889 'pays_adh' => 'Kiribati',
890 'tel_adh' => '04 55 49 80 92',
891 'activite_adh' => true,
893 'date_crea_adh' => '2020-06-02',
894 'pref_lang' => 'fr_FR',
895 'fingerprint' => 'FAKER_1',
899 'prenom_adh' => 'Laetitia',
900 'ville_adh' => 'SimonBourg',
902 'adresse_adh' => '147, chemin de Chauvet',
903 'email_adh' => 'jean.joseph@pinto.fr',
904 'login_adh' => 'marianne.bourgeois',
905 'mdp_adh' => '[oT:"ExE',
906 'mdp_adh2' => '[oT:"ExE',
907 'bool_admin_adh' => false,
908 'bool_exempt_adh' => false,
909 'bool_display_info' => true,
911 'prof_adh' => 'Porteur de hottes',
913 'ddn_adh' => '2010-03-13',
914 'lieu_naissance' => 'Gallet',
915 'pseudo_adh' => 'abarre',
916 'pays_adh' => 'Kirghizistan',
917 'tel_adh' => '07 47 63 11 31',
918 'activite_adh' => true,
920 'date_crea_adh' => '2020-10-28',
922 'fingerprint' => 'FAKER_2',
925 'nom_adh' => 'Cordier',
926 'prenom_adh' => 'Olivier',
927 'ville_adh' => 'Lacroixboeuf',
928 'cp_adh' => '58 787',
929 'adresse_adh' => '77, place Gilbert Perrier',
930 'email_adh' => 'adelaide07@yahoo.fr',
931 'login_adh' => 'riou.sebastien',
932 'mdp_adh' => '%"OC/UniE46',
933 'mdp_adh2' => '%"OC/UniE46',
934 'bool_admin_adh' => false,
935 'bool_exempt_adh' => false,
936 'bool_display_info' => false,
938 'prof_adh' => 'Oenologue',
940 'ddn_adh' => '2010-10-08',
941 'lieu_naissance' => 'Leger',
942 'pseudo_adh' => 'frederique.bernier',
944 'tel_adh' => '+33 2 50 03 01 12',
945 'activite_adh' => true,
947 'date_crea_adh' => '2020-08-14',
949 'fingerprint' => 'FAKER_3',
952 'nom_adh' => 'Robert',
953 'prenom_adh' => 'Grégoire',
954 'ville_adh' => 'Delannoy-sur-Mer',
956 'adresse_adh' => '15, boulevard de Pierre',
957 'email_adh' => 'normand.matthieu@orange.fr',
958 'login_adh' => 'guilbert.louis',
959 'mdp_adh' => 'y(,HodJF*j',
960 'mdp_adh2' => 'y(,HodJF*j',
961 'bool_admin_adh' => false,
962 'bool_exempt_adh' => false,
963 'bool_display_info' => true,
965 'prof_adh' => 'Mannequin détail',
967 'ddn_adh' => '1974-05-14',
968 'lieu_naissance' => 'Barbe-sur-Laurent',
969 'pseudo_adh' => 'stoussaint',
970 'pays_adh' => 'Îles Mineures Éloignées des États-Unis',
971 'tel_adh' => '+33 (0)1 30 50 01 54',
972 'activite_adh' => true,
974 'date_crea_adh' => '2018-12-05',
975 'pref_lang' => 'it_IT',
976 'fingerprint' => 'FAKER_4',
977 'societe_adh' => 'Chretien Martineau S.A.',
978 'is_company' => true,
982 'prenom_adh' => 'Charles',
983 'ville_adh' => 'Charpentier-sur-Lebrun',
985 'adresse_adh' => '817, chemin de Bonnin',
986 'email_adh' => 'guillou.augustin@live.com',
987 'login_adh' => 'dominique80',
988 'mdp_adh' => '~g??E0HE$A>2"e*C7+Kw',
989 'mdp_adh2' => '~g??E0HE$A>2"e*C7+Kw',
990 'bool_admin_adh' => true,
991 'bool_exempt_adh' => false,
992 'bool_display_info' => true,
994 'prof_adh' => 'Commandant de police',
996 'ddn_adh' => '2007-03-26',
997 'lieu_naissance' => 'Boutin',
998 'pseudo_adh' => 'virginie.jacquet',
1000 'tel_adh' => '0393209420',
1001 'activite_adh' => true,
1003 'date_crea_adh' => '2018-02-17',
1004 'pref_lang' => 'fr_FR',
1005 'fingerprint' => 'FAKER_5',
1007 'FAKER_6' => array (
1008 'nom_adh' => 'Thierry',
1009 'prenom_adh' => 'Louis',
1010 'ville_adh' => 'Henry',
1011 'cp_adh' => '98 144',
1012 'adresse_adh' => '383, avenue Éléonore Bouchet',
1013 'email_adh' => 'bernard.elodie@orange.fr',
1014 'login_adh' => 'ubreton',
1015 'mdp_adh' => 'lTBT@,hsE`co?C2=',
1016 'mdp_adh2' => 'lTBT@,hsE`co?C2=',
1017 'bool_admin_adh' => false,
1018 'bool_exempt_adh' => false,
1019 'bool_display_info' => false,
1021 'prof_adh' => 'Endocrinologue',
1022 'titre_adh' => null,
1023 'ddn_adh' => '1994-07-19',
1024 'lieu_naissance' => 'Pagesdan',
1025 'pseudo_adh' => 'diallo.sebastien',
1027 'tel_adh' => '+33 5 72 28 24 81',
1028 'activite_adh' => true,
1030 'date_crea_adh' => '2020-03-16',
1031 'pref_lang' => 'en_US',
1032 'fingerprint' => 'FAKER_6',
1034 'FAKER_7' => array (
1035 'nom_adh' => 'Delattre',
1036 'prenom_adh' => 'Susanne',
1037 'ville_adh' => 'Roche-les-Bains',
1038 'cp_adh' => '37 104',
1039 'adresse_adh' => '44, rue Suzanne Guilbert',
1040 'email_adh' => 'tmartel@wanadoo.fr',
1041 'login_adh' => 'lebreton.alexandre',
1042 'mdp_adh' => '{(3mCWC7[YL]n',
1043 'mdp_adh2' => '{(3mCWC7[YL]n',
1044 'bool_admin_adh' => false,
1045 'bool_exempt_adh' => false,
1046 'bool_display_info' => true,
1048 'prof_adh' => 'Gérant d\'hôtel',
1049 'titre_adh' => null,
1050 'ddn_adh' => '1914-05-16',
1051 'lieu_naissance' => 'Traore',
1052 'pseudo_adh' => 'helene59',
1054 'tel_adh' => '0383453389',
1055 'activite_adh' => true,
1057 'date_crea_adh' => '2020-02-03',
1058 'pref_lang' => 'oc',
1059 'fingerprint' => 'FAKER_7',
1061 'FAKER_8' => array (
1062 'nom_adh' => 'Peltier',
1063 'prenom_adh' => 'Inès',
1064 'ville_adh' => 'Thierry-sur-Carre',
1065 'cp_adh' => '80690',
1066 'adresse_adh' => '43, impasse Texier',
1067 'email_adh' => 'qdubois@mendes.fr',
1068 'login_adh' => 'julie.carlier',
1069 'mdp_adh' => '.ATai-E6%LIxE{',
1070 'mdp_adh2' => '.ATai-E6%LIxE{',
1071 'bool_admin_adh' => false,
1072 'bool_exempt_adh' => false,
1073 'bool_display_info' => true,
1075 'prof_adh' => 'Gynécologue',
1076 'titre_adh' => null,
1077 'ddn_adh' => '1988-05-29',
1078 'lieu_naissance' => 'Dijoux-sur-Michaud',
1079 'pseudo_adh' => 'wpierre',
1081 'tel_adh' => '01 32 14 47 74',
1082 'activite_adh' => true,
1084 'date_crea_adh' => '2020-03-28',
1085 'pref_lang' => 'ar',
1086 'fingerprint' => 'FAKER_8',
1088 'FAKER_9' => array (
1089 'nom_adh' => 'Marchand',
1090 'prenom_adh' => 'Audrey',
1091 'ville_adh' => 'Lenoirdan',
1092 'cp_adh' => '06494',
1093 'adresse_adh' => '438, place de Carre',
1094 'email_adh' => 'luc42@yahoo.fr',
1095 'login_adh' => 'margot.bousquet',
1096 'mdp_adh' => 'FH,q5udclwM(',
1097 'mdp_adh2' => 'FH,q5udclwM(',
1098 'bool_admin_adh' => false,
1099 'bool_exempt_adh' => false,
1100 'bool_display_info' => true,
1102 'prof_adh' => 'Convoyeur garde',
1103 'titre_adh' => null,
1104 'ddn_adh' => '1977-09-02',
1105 'lieu_naissance' => 'Arnaud-sur-Antoine',
1106 'pseudo_adh' => 'gerard66',
1108 'tel_adh' => '+33 1 46 04 81 87',
1109 'activite_adh' => true,
1111 'date_crea_adh' => '2019-05-16',
1112 'pref_lang' => 'fr_FR',
1113 'fingerprint' => 'FAKER_9',
1119 * Get second set of member data but two lines without name.
1123 private function getMemberData2NoName(): array
1125 $data = $this->getMemberData2();
1126 $data['FAKER_2']['nom_adh'] = '';
1127 $data['FAKER_5']['nom_adh'] = '';