GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#224)
by joseph
22:25
created

TestCodeGenerator.php$0 ➔ resetAutoloader()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Assets;
6
7
use Composer\Autoload\ClassLoader;
8
use EdmondsCommerce\DoctrineStaticMeta\Builder\Builder;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Creation\Src\Entity\Fields\Traits\FieldTraitCreator;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
11
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FindAndReplaceHelper;
12
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
13
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
14
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PostProcessor\FileOverrider;
15
use EdmondsCommerce\DoctrineStaticMeta\Entity\Embeddable\Traits\Attribute\HasWeightEmbeddableTrait;
16
use EdmondsCommerce\DoctrineStaticMeta\Entity\Embeddable\Traits\Financial\HasMoneyEmbeddableTrait;
17
use EdmondsCommerce\DoctrineStaticMeta\Entity\Embeddable\Traits\Geo\HasAddressEmbeddableTrait;
18
use EdmondsCommerce\DoctrineStaticMeta\Entity\Embeddable\Traits\Identity\HasFullNameEmbeddableTrait;
19
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\EmailAddressFieldTrait;
20
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
21
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
22
use ReflectionException;
23
use RuntimeException;
24
use Symfony\Component\Filesystem\Filesystem;
25
use function spl_autoload_functions;
26
use function spl_autoload_unregister;
27
28
/**
29
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30
 */
31
class TestCodeGenerator
32
{
33
34
    public const   TEST_PROJECT_ROOT_NAMESPACE = 'Test\\Code\\Generator';
35
    public const   TEST_ENTITY_NAMESPACE_BASE  = '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME;
36
    private const  TEST_FIELD_NAMESPACE_BASE   = '\\Entity\\Fields';
37
    private const  TEST_FIELD_FQN_BASE         = self::TEST_FIELD_NAMESPACE_BASE . '\\Traits';
38
39
    public const TEST_ENTITY_PERSON                      = '\\Person';
40
    public const TEST_ENTITY_ATTRIBUTES_ADDRESS          = '\\Attributes\\Address';
41
    public const TEST_ENTITY_EMAIL                       = '\\Attributes\\Email';
42
    public const TEST_ENTITY_COMPANY                     = '\\Company';
43
    public const TEST_ENTITY_DIRECTOR                    = '\\Company\\Director';
44
    public const TEST_ENTITY_ORDER                       = '\\Order';
45
    public const TEST_ENTITY_ORDER_ADDRESS               = '\\Order\\Address';
46
    public const TEST_ENTITY_NAME_SPACING_SOME_CLIENT    = '\\Some\\Client';
47
    public const TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT = '\\Another\\Deeply\\Nested\\Client';
48
    public const TEST_ENTITY_LARGE_DATA                  = '\\Large\\Data';
49
    public const TEST_ENTITY_LARGE_PROPERTIES            = '\\Large\\Property';
50
    public const TEST_ENTITY_LARGE_RELATIONS             = '\\Large\\Relation';
51
    public const TEST_ENTITY_ALL_ARCHETYPE_FIELDS        = '\\All\\StandardLibraryFields\\TestEntity';
52
    public const TEST_ENTITY_ALL_EMBEDDABLES             = '\\AllEmbeddable';
53
    public const TEST_ENTITY_SIMPLE                      = '\\Simple';
54
    public const TEST_ENTITY_CUSTOM_RELATION             = '\\CustomRelation';
55
56
    public const TEST_ENTITIES = [
57
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
58
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
59
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
60
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
61
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
62
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
63
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
64
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
65
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
66
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
67
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_PROPERTIES,
68
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
69
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ALL_ARCHETYPE_FIELDS,
70
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ALL_EMBEDDABLES,
71
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_SIMPLE,
72
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_CUSTOM_RELATION,
73
    ];
74
75
76
    private const TEST_RELATIONS = [
77
        [
78
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
79
            RelationsGenerator::HAS_UNIDIRECTIONAL_MANY_TO_ONE,
80
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
81
            false,
82
        ],
83
        [
84
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
85
            RelationsGenerator::HAS_ONE_TO_MANY,
86
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
87
            false,
88
        ],
89
        [
90
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
91
            RelationsGenerator::HAS_REQUIRED_MANY_TO_MANY,
92
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
93
            true,
94
        ],
95
        [
96
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
97
            RelationsGenerator::HAS_REQUIRED_ONE_TO_MANY,
98
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
99
            false,
100
        ],
101
        [
102
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
103
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_ONE_TO_MANY,
104
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
105
            false,
106
        ],
107
        [
108
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
109
            RelationsGenerator::HAS_REQUIRED_ONE_TO_ONE,
110
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
111
            false,
112
        ],
113
        [
114
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
115
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_MANY_TO_ONE,
116
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
117
            false,
118
        ],
119
        [
120
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
121
            RelationsGenerator::HAS_REQUIRED_ONE_TO_MANY,
122
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
123
            true,
124
        ],
125
        [
126
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
127
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_ONE_TO_ONE,
128
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
129
            false,
130
        ],
131
        [
132
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
133
            RelationsGenerator::HAS_ONE_TO_ONE,
134
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
135
            false,
136
        ],
137
        [
138
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
139
            RelationsGenerator::HAS_ONE_TO_ONE,
140
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
141
            false,
142
        ],
143
        [
144
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
145
            RelationsGenerator::HAS_UNIDIRECTIONAL_MANY_TO_ONE,
146
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
147
            false,
148
        ],
149
        [
150
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
151
            RelationsGenerator::HAS_REQUIRED_ONE_TO_MANY,
152
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
153
            false,
154
        ],
155
        [
156
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
157
            RelationsGenerator::HAS_MANY_TO_MANY,
158
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
159
            false,
160
        ],
161
        [
162
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
163
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_ONE_TO_MANY,
164
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
165
            false,
166
        ],
167
        [
168
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
169
            RelationsGenerator::HAS_ONE_TO_ONE,
170
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
171
            false,
172
        ],
173
        [
174
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
175
            RelationsGenerator::HAS_REQUIRED_MANY_TO_ONE,
176
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_PROPERTIES,
177
            true,
178
        ],
179
        [
180
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
181
            RelationsGenerator::HAS_ONE_TO_MANY,
182
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
183
            false,
184
        ],
185
        [
186
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
187
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_ONE_TO_ONE,
188
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
189
            false,
190
        ],
191
        [
192
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_CUSTOM_RELATION,
193
            RelationsGenerator::HAS_REQUIRED_UNIDIRECTIONAL_ONE_TO_ONE,
194
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
195
            false,
196
        ],
197
    ];
198
199
    private const LARGE_DATA_FIELDS = [
200
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataOne',
201
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataTwo',
202
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataThree',
203
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataFour',
204
    ];
205
206
    private const LARGE_PROPERTIES_FIELDS = [
207
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData001',
208
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData002',
209
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData003',
210
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData004',
211
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData005',
212
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData006',
213
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData007',
214
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData008',
215
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData009',
216
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData010',
217
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData011',
218
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData012',
219
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData013',
220
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData014',
221
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData015',
222
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData016',
223
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData017',
224
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData018',
225
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData019',
226
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData020',
227
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData021',
228
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData022',
229
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData023',
230
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData024',
231
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData025',
232
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData026',
233
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData027',
234
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData028',
235
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData029',
236
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData030',
237
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData031',
238
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData032',
239
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData033',
240
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData034',
241
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData035',
242
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData036',
243
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData037',
244
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData038',
245
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData039',
246
    ];
247
248
    private const  BUILD_DIR                      = AbstractTest::VAR_PATH . '/../testCode';
249
    private const  BUILD_DIR_TMP_B1               = AbstractTest::VAR_PATH . '/../testCodeTmp1';
250
    private const  BUILD_DIR_TMP_B2               = AbstractTest::VAR_PATH . '/../testCodeTmp2';
251
    private const  TEST_PROJECT_ROOT_NAMESPACE_B1 = self::TEST_PROJECT_ROOT_NAMESPACE . '\\Tmp1';
252
    private const  TEST_ENTITY_NAMESPACE_BASE_B1  = self::TEST_PROJECT_ROOT_NAMESPACE_B1 .
253
                                                    self::TEST_ENTITY_NAMESPACE_BASE;
254
    private const  TEST_PROJECT_ROOT_NAMESPACE_B2 = self::TEST_PROJECT_ROOT_NAMESPACE . '\\Tmp2';
255
    private const  BUILD_HASH_FILE                = self::BUILD_DIR . '/.buildHash';
256
257
    /**
258
     * @var Builder
259
     */
260
    protected $builder;
261
    /**
262
     * @var Filesystem
263
     */
264
    protected $filesystem;
265
    /**
266
     * @var FindAndReplaceHelper
267
     */
268
    protected $findAndReplaceHelper;
269
    /**
270
     * @var CodeCopier
271
     */
272
    private $codeCopier;
273
    /**
274
     * @var NamespaceHelper
275
     */
276
    private $namespaceHelper;
277
278
    public function __construct(
279
        Builder $builder,
280
        Filesystem $filesystem,
281
        FindAndReplaceHelper $findAndReplaceHelper,
282
        NamespaceHelper $namespaceHelper
283
    ) {
284
        $this->builder         = $builder;
285
        $this->filesystem      = $filesystem;
286
        $this->codeCopier      = new CodeCopier($this->filesystem, $findAndReplaceHelper);
287
        $this->namespaceHelper = $namespaceHelper;
288
        $this->initBuildDir();
289
        $this->buildOnce();
290
    }
291
292
    private function initBuildDir(): void
293
    {
294
295
        if (!is_dir(self::BUILD_DIR)) {
296
            $this->filesystem->mkdir(self::BUILD_DIR);
297
        }
298
    }
299
300
    private function buildOnce(): void
301
    {
302
        if ($this->isBuilt()) {
303
            return;
304
        }
305
        $this->firstBuild();
306
        $this->secondBuild();
307
        $this->thirdBuild();
308
        $this->filesystem->remove(self::BUILD_DIR_TMP_B1);
309
        $this->filesystem->remove(self::BUILD_DIR_TMP_B2);
310
        $this->setBuildHash();
311
    }
312
313
    /**
314
     * Check that a file exists in the build directory which contains the md5 hash of this class.
315
     *
316
     * This means that if we update this class, the hash changes and the built files are invalid and will be nuked
317
     *
318
     * @return bool
319
     */
320
    private function isBuilt(): bool
321
    {
322
        return file_exists(self::BUILD_HASH_FILE) && $this->validateBuildHash();
323
    }
324
325
    private function validateBuildHash(): bool
326
    {
327
        return md5(\ts\file_get_contents(__FILE__)) === \ts\file_get_contents(self::BUILD_HASH_FILE);
328
    }
329
330
    private function firstBuild(): void
331
    {
332
        $this->emptyDir(self::BUILD_DIR_TMP_B1);
333
        $this->builder->setProjectRootNamespace(self::TEST_PROJECT_ROOT_NAMESPACE_B1)
334
                      ->setPathToProjectRoot(self::BUILD_DIR_TMP_B1);
335
        $this->filesystem->remove(self::BUILD_DIR_TMP_B1);
336
        $this->filesystem->mkdir(self::BUILD_DIR_TMP_B1);
337
        $this->extendAutoloader(self::TEST_PROJECT_ROOT_NAMESPACE_B1, self::BUILD_DIR_TMP_B1);
338
        $fields = $this->buildCommonTypeFields();
339
        $this->buildEntitiesAndAssignCommonFields($fields);
340
        $this->updateLargeDataEntity();
341
        $this->updateLargePropertiesEntity();
342
        $this->addArchetypeFieldsToEntities();
343
        $this->updateEmailEntity();
344
        $this->updateAllEmbeddablesEntity();
345
        $this->setRelations();
346
        $this->resetAutoloader();
347
    }
348
349
    private function emptyDir(string $path): void
350
    {
351
        $this->filesystem->remove($path);
352
        $this->filesystem->mkdir($path);
353
    }
354
355
    private function extendAutoloader(string $namespace, string $buildDir): void
356
    {
357
        $testLoader = new class ($namespace) extends ClassLoader
358
        {
359
            /**
360
             * @var string
361
             */
362
            protected $namespace;
363
364
            public function __construct(string $namespace)
365
            {
366
                $this->namespace = $namespace;
367
            }
368
369
            public function loadClass($class)
370
            {
371
                if (false === strpos($class, $this->namespace)) {
372
                    return false;
373
                }
374
                $found = parent::loadClass($class);
375
                if (false === $found || null === $found) {
0 ignored issues
show
introduced by
The condition null === $found is always false.
Loading history...
376
                    //good point to set a breakpoint
377
                    return $found;
378
                }
379
380
                return $found;
381
            }
382
        };
383
        $testLoader->addPsr4($namespace . '\\', $buildDir . '/src', true);
384
        $testLoader->addPsr4($namespace . '\\', $buildDir . '/tests', true);
385
        $testLoader->register();
386
    }
387
388
    /**
389
     * Build the fields and return an array of Field Trait FQNs
390
     *
391
     * @return array|string[]
392
     * @throws DoctrineStaticMetaException
393
     * @throws ReflectionException
394
     */
395
    private function buildCommonTypeFields(): array
396
    {
397
        $fields         = [];
398
        $fieldGenerator = $this->builder->getFieldGenerator();
399
400
        foreach (MappingHelper::COMMON_TYPES as $type) {
401
            $fields[] = $fieldGenerator->generateField(
402
                self::TEST_PROJECT_ROOT_NAMESPACE_B1
403
                . self::TEST_FIELD_FQN_BASE . '\\' . ucwords($type) . FieldTraitCreator::SUFFIX,
404
                $type
405
            );
406
        }
407
408
        return $fields;
409
    }
410
411
    private function buildEntitiesAndAssignCommonFields(array $fields): void
412
    {
413
414
        $entityGenerator = $this->builder->getEntityGenerator();
415
        $fieldSetter     = $this->builder->getFieldSetter();
416
417
        foreach (self::TEST_ENTITIES as $entityFqn) {
418
            $entityGenerator->generateEntity(self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $entityFqn);
419
            foreach ($fields as $fieldFqn) {
420
                $fieldSetter->setEntityHasField(
421
                    self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $entityFqn,
422
                    $fieldFqn
423
                );
424
            }
425
        }
426
    }
427
428
    private function updateLargeDataEntity(): void
429
    {
430
        $fieldGenerator = $this->builder->getFieldGenerator();
431
        $fieldSetter    = $this->builder->getFieldSetter();
432
        foreach (self::LARGE_DATA_FIELDS as $field) {
433
            $fieldSetter->setEntityHasField(
434
                self::TEST_ENTITY_NAMESPACE_BASE_B1 . self::TEST_ENTITY_LARGE_DATA,
435
                $fieldGenerator->generateField(
436
                    self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $field,
437
                    MappingHelper::TYPE_TEXT
438
                )
439
            );
440
        }
441
    }
442
443
    private function updateLargePropertiesEntity(): void
444
    {
445
        $fieldGenerator = $this->builder->getFieldGenerator();
446
        $fieldSetter    = $this->builder->getFieldSetter();
447
        foreach (self::LARGE_PROPERTIES_FIELDS as $field) {
448
            $fieldSetter->setEntityHasField(
449
                self::TEST_ENTITY_NAMESPACE_BASE_B1 . self::TEST_ENTITY_LARGE_DATA,
450
                $fieldGenerator->generateField(
451
                    self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $field,
452
                    MappingHelper::TYPE_BOOLEAN
453
                )
454
            );
455
        }
456
    }
457
458
    private function addArchetypeFieldsToEntities(): void
459
    {
460
        $archetypeFqns = $this->namespaceHelper->getAllArchetypeFieldFqns();
461
        $fieldSetter   = $this->builder->getFieldSetter();
462
        foreach ($archetypeFqns as $archetypeFieldFqn) {
463
            $fieldSetter->setEntityHasField(
464
                self::TEST_ENTITY_NAMESPACE_BASE_B1 . self::TEST_ENTITY_ALL_ARCHETYPE_FIELDS,
465
                $archetypeFieldFqn
466
            );
467
        }
468
    }
469
470
    private function updateEmailEntity(): void
471
    {
472
        $emailEntityFqn = self::TEST_ENTITY_NAMESPACE_BASE_B1 . self::TEST_ENTITY_EMAIL;
473
        $this->builder->getFieldSetter()->setEntityHasField($emailEntityFqn, EmailAddressFieldTrait::class);
474
    }
475
476
    private function updateAllEmbeddablesEntity(): void
477
    {
478
        $this->builder->setEmbeddablesToEntity(
479
            self::TEST_ENTITY_NAMESPACE_BASE_B1 . self::TEST_ENTITY_ALL_EMBEDDABLES,
480
            [
481
                HasMoneyEmbeddableTrait::class,
482
                HasAddressEmbeddableTrait::class,
483
                HasFullNameEmbeddableTrait::class,
484
                HasWeightEmbeddableTrait::class,
485
            ]
486
        );
487
    }
488
489
    private function setRelations(): void
490
    {
491
        $relationsGenerator = $this->builder->getRelationsGenerator();
492
        foreach (self::TEST_RELATIONS as $relation) {
493
            $relationsGenerator->setEntityHasRelationToEntity(
494
                self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $relation[0],
495
                (string)$relation[1],
496
                self::TEST_PROJECT_ROOT_NAMESPACE_B1 . $relation[2],
497
                (bool)$relation[3]
498
            );
499
        }
500
    }
501
502
    private function resetAutoloader(): void
503
    {
504
        $registered = spl_autoload_functions();
505
        $loader     = array_pop($registered);
506
        spl_autoload_unregister($loader);
507
    }
508
509
    private function secondBuild(): void
510
    {
511
        $this->emptyDir(self::BUILD_DIR_TMP_B2);
512
        $this->codeCopier->copy(
513
            self::BUILD_DIR_TMP_B1,
514
            self::BUILD_DIR_TMP_B2,
515
            self::TEST_PROJECT_ROOT_NAMESPACE_B1,
516
            self::TEST_PROJECT_ROOT_NAMESPACE_B2
517
        );
518
        $this->createCustomDataFiller();
519
        $this->extendAutoloader(self::TEST_PROJECT_ROOT_NAMESPACE_B2, self::BUILD_DIR_TMP_B2);
520
        $this->builder->setPathToProjectRoot(self::BUILD_DIR_TMP_B2)
521
                      ->setProjectRootNamespace(self::TEST_PROJECT_ROOT_NAMESPACE_B2)
522
                      ->finaliseBuild();
523
        $this->emptyDir(self::BUILD_DIR);
524
        $this->codeCopier->copy(
525
            self::BUILD_DIR_TMP_B2,
526
            self::BUILD_DIR,
527
            self::TEST_PROJECT_ROOT_NAMESPACE_B2,
528
            self::TEST_PROJECT_ROOT_NAMESPACE
529
        );
530
    }
531
532
    private function createCustomDataFiller(): void
533
    {
534
535
        $dataFiller = <<<'PHP'
536
<?php declare(strict_types=1);
537
538
namespace Test\Code\Generator\Assets\Entity\FakerDataFillers;
539
540
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
541
use EdmondsCommerce\DoctrineStaticMeta\DoctrineStaticMeta;
542
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\DataTransferObjectInterface;
543
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityGenerator\FakerDataFiller;
544
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityGenerator\FakerDataFillerFactory;
545
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityGenerator\FakerDataFillerInterface;
546
use Test\Code\Generator\Entity\DataTransferObjects\SimpleDto;
547
548
class SimpleFakerDataFiller implements FakerDataFillerInterface
549
{
550
    /**
551
     * @var FakerDataFiller
552
     */
553
    private $wrappedFiller;
554
555
    public function __construct(
556
        FakerDataFillerFactory $fakerDataFillerFactory,
557
        DoctrineStaticMeta $testedEntityDsm,
558
        NamespaceHelper $namespaceHelper,
559
        array $fakerDataProviderClasses,
560
        ?float $seed = null
561
    ) {
562
        $this->wrappedFiller =
563
            new FakerDataFiller(
564
                $fakerDataFillerFactory,
565
                $testedEntityDsm,
566
                $namespaceHelper,
567
                $fakerDataProviderClasses,
568
                $seed
569
            );
570
    }
571
572
    public function updateDtoWithFakeData(DataTransferObjectInterface $dto): void
573
    {
574
        $this->wrappedFiller->updateDtoWithFakeData($dto);
575
        $this->updateDtoWithKnownData($dto);
576
    }
577
    
578
    public function update(DataTransferObjectInterface $dto, $isRootDto = false): void
579
    {
580
        $this->wrappedFiller->update($dto, $isRootDto);
581
        $this->updateDtoWithKnownData($dto);
582
    }
583
    
584
    private function updateDtoWithKnownData(DataTransferObjectInterface $dto): void
585
    {
586
        if (!$dto instanceof SimpleDto) {
587
            throw new \RuntimeException(sprintf('Expected %s got %s', SimpleDto::class, get_class($dto)));
588
        }
589
        $dto->setString('Set from a custom Faker Data Filler');
590
    }
591
}
592
PHP;
593
        $dirPath    = self::BUILD_DIR_TMP_B2 . '/tests/Assets/Entity/FakerDataFillers/';
594
        $filePath   = $dirPath . 'SimpleFakerDataFiller.php';
595
        if (!is_dir($dirPath)) {
596
            mkdir($dirPath);
597
        }
598
        \ts\file_put_contents($filePath, $dataFiller);
599
    }
600
601
    private function thirdBuild(): void
602
    {
603
        $this->applyOverrides();
604
        $this->extendAutoloader(self::TEST_PROJECT_ROOT_NAMESPACE, self::BUILD_DIR);
605
        $this->builder->setPathToProjectRoot(self::BUILD_DIR)
606
                      ->setProjectRootNamespace(self::TEST_PROJECT_ROOT_NAMESPACE)
607
                      ->finaliseBuild();
608
    }
609
610
    private function applyOverrides(): void
611
    {
612
        $this->filesystem->mirror(
613
            __DIR__ . '/../Assets/overrides',
614
            self::BUILD_DIR . '/' . FileOverrider::OVERRIDES_PATH
615
        );
616
        $overrider        = new FileOverrider(
617
            self::BUILD_DIR
618
        );
619
        $invalidOverrides = $overrider->getInvalidOverrides();
620
        if ($invalidOverrides !== []) {
621
            throw new RuntimeException('Invaild Overrides: ' . \ts\print_r($invalidOverrides, true));
622
        }
623
        $overrider->applyOverrides();
624
    }
625
626
    private function setBuildHash(): void
627
    {
628
        \ts\file_put_contents(self::BUILD_HASH_FILE, md5(\ts\file_get_contents(__FILE__)));
629
    }
630
631
    public function copyTo(
632
        string $destinationPath,
633
        string $replaceNamespace = AbstractTest::TEST_PROJECT_ROOT_NAMESPACE
634
    ): void {
635
        $this->codeCopier->copy(
636
            self::BUILD_DIR,
637
            $destinationPath,
638
            self::TEST_PROJECT_ROOT_NAMESPACE,
639
            $replaceNamespace
640
        );
641
    }
642
}
643