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
Push — master ( 0d82f1...4042bf )
by joseph
20s queued 14s
created

TestCodeGenerator.php$0 ➔ applyOverrides()   A

Complexity

Conditions 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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