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 ( 6a4e57...36c412 )
by joseph
26:54
created

TestCodeGenerator.php$0 ➔ setBuildHash()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Assets;
4
5
use Composer\Autoload\ClassLoader;
6
use EdmondsCommerce\DoctrineStaticMeta\Builder\Builder;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FindAndReplaceHelper;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
11
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
12
use Symfony\Component\Filesystem\Filesystem;
13
14
class TestCodeGenerator
15
{
16
17
    public const  TEST_PROJECT_ROOT_NAMESPACE = 'Test\\Code\\Generator';
18
19
    public const  TEST_ENTITY_NAMESPACE_BASE = self::TEST_PROJECT_ROOT_NAMESPACE
20
                                               . '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME;
21
22
    public const TEST_FIELD_NAMESPACE_BASE = self::TEST_PROJECT_ROOT_NAMESPACE . '\\Entity\\Fields';
23
24
    public const  TEST_FIELD_FQN_BASE = self::TEST_FIELD_NAMESPACE_BASE . '\\Traits';
25
26
    public const TEST_ENTITY_PERSON                      = '\\Person';
27
    public const TEST_ENTITY_ATTRIBUTES_ADDRESS          = '\\Attributes\\Address';
28
    public const TEST_ENTITY_EMAIL                       = '\\Attributes\\Email';
29
    public const TEST_ENTITY_COMPANY                     = '\\Company';
30
    public const TEST_ENTITY_DIRECTOR                    = '\\Company\\Director';
31
    public const TEST_ENTITY_ORDER                       = '\\Order';
32
    public const TEST_ENTITY_ORDER_ADDRESS               = '\\Order\\Address';
33
    public const TEST_ENTITY_NAME_SPACING_SOME_CLIENT    = '\\Some\\Client';
34
    public const TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT = '\\Another\\Deeply\\Nested\\Client';
35
    public const TEST_ENTITY_LARGE_DATA                  = '\\Large\\Data';
36
    public const TEST_ENTITY_LARGE_PROPERTIES            = '\\Large\\Property';
37
    public const TEST_ENTITY_LARGE_RELATIONS             = '\\Large\\Relation';
38
    public const TEST_ENTITY_ALL_ARCHETYPE_FIELDS        = '\\All\\StandardLibraryFields\\TestEntity';
39
    public const TEST_ENTITIES                           = [
40
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
41
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
42
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
43
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
44
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
45
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
46
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
47
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
48
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
49
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
50
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_PROPERTIES,
51
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
52
        self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ALL_ARCHETYPE_FIELDS,
53
    ];
54
55
56
    public const TEST_RELATIONS = [
57
        [
58
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
59
            RelationsGenerator::HAS_UNIDIRECTIONAL_MANY_TO_ONE,
60
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
61
        ],
62
        [
63
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
64
            RelationsGenerator::HAS_ONE_TO_MANY,
65
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
66
        ],
67
        [
68
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
69
            RelationsGenerator::HAS_MANY_TO_MANY,
70
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
71
        ],
72
        [
73
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
74
            RelationsGenerator::HAS_ONE_TO_MANY,
75
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
76
        ],
77
        [
78
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
79
            RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_MANY,
80
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
81
        ],
82
        [
83
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
84
            RelationsGenerator::HAS_ONE_TO_ONE,
85
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
86
        ],
87
        [
88
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
89
            RelationsGenerator::HAS_MANY_TO_ONE,
90
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
91
        ],
92
        [
93
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER,
94
            RelationsGenerator::HAS_ONE_TO_MANY,
95
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
96
        ],
97
        [
98
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
99
            RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_ONE,
100
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
101
        ],
102
        [
103
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
104
            RelationsGenerator::HAS_ONE_TO_ONE,
105
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
106
        ],
107
        [
108
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
109
            RelationsGenerator::HAS_ONE_TO_ONE,
110
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
111
        ],
112
        [
113
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
114
            RelationsGenerator::HAS_UNIDIRECTIONAL_MANY_TO_ONE,
115
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ATTRIBUTES_ADDRESS,
116
        ],
117
        [
118
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
119
            RelationsGenerator::HAS_ONE_TO_MANY,
120
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_EMAIL,
121
        ],
122
        [
123
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
124
            RelationsGenerator::HAS_MANY_TO_MANY,
125
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_DIRECTOR,
126
        ],
127
        [
128
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
129
            RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_MANY,
130
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
131
        ],
132
        [
133
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
134
            RelationsGenerator::HAS_ONE_TO_ONE,
135
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_PERSON,
136
        ],
137
        [
138
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
139
            RelationsGenerator::HAS_MANY_TO_ONE,
140
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_PROPERTIES,
141
        ],
142
        [
143
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
144
            RelationsGenerator::HAS_ONE_TO_MANY,
145
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ORDER_ADDRESS,
146
        ],
147
        [
148
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_RELATIONS,
149
            RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_ONE,
150
            self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_COMPANY,
151
        ],
152
    ];
153
154
    public const LARGE_DATA_FIELDS = [
155
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataOne',
156
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataTwo',
157
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataThree',
158
        self::TEST_FIELD_FQN_BASE . '\\Large\\Data\\LargeDataFour',
159
    ];
160
161
    public const LARGE_PROPERTIES_FIELDS = [
162
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData001',
163
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData002',
164
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData003',
165
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData004',
166
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData005',
167
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData006',
168
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData007',
169
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData008',
170
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData009',
171
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData010',
172
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData011',
173
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData012',
174
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData013',
175
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData014',
176
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData015',
177
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData016',
178
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData017',
179
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData018',
180
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData019',
181
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData020',
182
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData021',
183
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData022',
184
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData023',
185
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData024',
186
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData025',
187
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData026',
188
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData027',
189
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData028',
190
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData029',
191
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData030',
192
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData031',
193
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData032',
194
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData033',
195
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData034',
196
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData035',
197
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData036',
198
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData037',
199
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData038',
200
        self::TEST_FIELD_FQN_BASE . '\\Large\\Properties\\LargeData039',
201
    ];
202
203
    public const  BUILD_DIR       = AbstractTest::VAR_PATH . '/../testCode';
204
    private const BUILD_HASH_FILE = self::BUILD_DIR . '/.buildHash';
205
206
    /**
207
     * @var Builder
208
     */
209
    protected $builder;
210
    /**
211
     * @var Filesystem
212
     */
213
    protected $filesystem;
214
    /**
215
     * @var FindAndReplaceHelper
216
     */
217
    protected $findAndReplaceHelper;
218
219
    public function __construct(Builder $builder, Filesystem $filesystem, FindAndReplaceHelper $findAndReplaceHelper)
220
    {
221
        $this->filesystem = $filesystem;
222
        $this->initBuildDir();
223
        $this->builder = $builder->setProjectRootNamespace(self::TEST_PROJECT_ROOT_NAMESPACE)
224
                                 ->setPathToProjectRoot(self::BUILD_DIR);
225
        $this->buildOnce();
226
        $this->findAndReplaceHelper = $findAndReplaceHelper;
227
    }
228
229
    private function initBuildDir(): void
230
    {
231
232
        if (!is_dir(self::BUILD_DIR)) {
233
            $this->filesystem->mkdir(self::BUILD_DIR);
234
        }
235
    }
236
237
    public function buildOnce(): void
238
    {
239
        if ($this->isBuilt()) {
240
            return;
241
        }
242
        $this->filesystem->remove(self::BUILD_DIR);
243
        $this->filesystem->mkdir(self::BUILD_DIR);
244
        $this->extendAutoloader();
245
        $this->buildEntitiesAndAssignCommonFields($this->buildCommonTypeFields());
246
        $this->updateLargeDataEntity();
247
        $this->updateLargePropertiesEntity();
248
        $this->updateAllArchetypeFieldsEntity();
249
        $this->setRelations();
250
        $this->resetAutoloader();
251
        $this->setBuildHash();
252
    }
253
254
    /**
255
     * Check that a file exists in the build directory which contains the md5 hash of this class.
256
     *
257
     * This means that if we update this class, the hash changes and the built files are invalid and will be nuked
258
     *
259
     * @return bool
260
     */
261
    private function isBuilt(): bool
262
    {
263
        return file_exists(self::BUILD_HASH_FILE) && $this->validateBuildHash();
264
    }
265
266
    private function validateBuildHash(): bool
267
    {
268
        return md5(\ts\file_get_contents(__FILE__)) === \ts\file_get_contents(self::BUILD_HASH_FILE);
269
    }
270
271
    private function extendAutoloader(): void
272
    {
273
        $testLoader = new class(self::TEST_PROJECT_ROOT_NAMESPACE) extends ClassLoader
274
        {
275
            /**
276
             * @var string
277
             */
278
            protected $namespace;
279
280
            public function __construct(string $namespace)
281
            {
282
                $this->namespace = $namespace;
283
            }
284
285
            public function loadClass($class)
286
            {
287
                if (false === strpos($class, $this->namespace)) {
288
                    return false;
289
                }
290
                $found = parent::loadClass($class);
291
                if (false === $found || null === $found) {
0 ignored issues
show
introduced by
The condition null === $found is always false.
Loading history...
292
                    //good point to set a breakpoint
293
                    return $found;
294
                }
295
296
                return $found;
297
            }
298
        };
299
        $testLoader->addPsr4(self::TEST_PROJECT_ROOT_NAMESPACE . '\\', self::BUILD_DIR . '/src', true);
300
        $testLoader->addPsr4(self::TEST_PROJECT_ROOT_NAMESPACE . '\\', self::BUILD_DIR . '/tests', true);
301
        $testLoader->register();
302
    }
303
304
    private function buildEntitiesAndAssignCommonFields(array $fields): void
305
    {
306
307
        $entityGenerator = $this->builder->getEntityGenerator();
308
        $fieldSetter     = $this->builder->getFieldSetter();
309
310
        foreach (self::TEST_ENTITIES as $entityFqn) {
311
            $entityGenerator->generateEntity($entityFqn);
312
            foreach ($fields as $fieldFqn) {
313
                $fieldSetter->setEntityHasField($entityFqn, $fieldFqn);
314
            }
315
        }
316
    }
317
318
    /**
319
     * Build the fields and return an array of Field Trait FQNs
320
     *
321
     * @return array|string[]
322
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
323
     * @throws \ReflectionException
324
     */
325
    private function buildCommonTypeFields(): array
326
    {
327
        $fields         = [];
328
        $fieldGenerator = $this->builder->getFieldGenerator();
329
330
        foreach (MappingHelper::COMMON_TYPES as $type) {
331
            $fields[] = $fieldGenerator->generateField(
332
                self::TEST_FIELD_FQN_BASE . '\\' . ucwords($type),
333
                $type
334
            );
335
        }
336
337
        return $fields;
338
    }
339
340
    private function updateLargeDataEntity(): void
341
    {
342
        $fieldGenerator = $this->builder->getFieldGenerator();
343
        $fieldSetter    = $this->builder->getFieldSetter();
344
        foreach (self::LARGE_DATA_FIELDS as $field) {
345
            $fieldSetter->setEntityHasField(
346
                self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
347
                $fieldGenerator->generateField($field, MappingHelper::TYPE_TEXT)
348
            );
349
        }
350
    }
351
352
    private function updateLargePropertiesEntity(): void
353
    {
354
        $fieldGenerator = $this->builder->getFieldGenerator();
355
        $fieldSetter    = $this->builder->getFieldSetter();
356
        foreach (self::LARGE_PROPERTIES_FIELDS as $field) {
357
            $fieldSetter->setEntityHasField(
358
                self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_LARGE_DATA,
359
                $fieldGenerator->generateField($field, MappingHelper::TYPE_BOOLEAN)
360
            );
361
        }
362
    }
363
364
    private function updateAllArchetypeFieldsEntity(): void
365
    {
366
        $fieldSetter = $this->builder->getFieldSetter();
367
        foreach (FieldGenerator::STANDARD_FIELDS as $archetypeFieldFqn) {
368
            $fieldSetter->setEntityHasField(
369
                self::TEST_ENTITY_NAMESPACE_BASE . self::TEST_ENTITY_ALL_ARCHETYPE_FIELDS,
370
                $archetypeFieldFqn
371
            );
372
        }
373
    }
374
375
    private function setRelations(): void
376
    {
377
        $relationsGenerator = $this->builder->getRelationsGenerator();
378
379
        foreach (self::TEST_RELATIONS as $relation) {
380
            $relationsGenerator->setEntityHasRelationToEntity(...$relation);
381
        }
382
    }
383
384
    private function resetAutoloader(): void
385
    {
386
        $registered = \spl_autoload_functions();
387
        $loader     = array_pop($registered);
388
        \spl_autoload_unregister($loader);
389
    }
390
391
    private function setBuildHash(): void
392
    {
393
        \ts\file_put_contents(self::BUILD_HASH_FILE, md5(\ts\file_get_contents(__FILE__)));
394
    }
395
396
    public function copyTo(
397
        string $destinationPath,
398
        string $replaceNamespace = AbstractTest::TEST_PROJECT_ROOT_NAMESPACE
399
    ): void {
400
        $this->filesystem->mirror(self::BUILD_DIR, $destinationPath);
401
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($destinationPath));
402
403
        foreach ($iterator as $info) {
404
            /**
405
             * @var \SplFileInfo $info
406
             */
407
            if (false === $info->isFile()) {
408
                continue;
409
            }
410
            $contents = file_get_contents($info->getPathname());
411
412
            $updated = \preg_replace(
413
                '%(use|namespace)\s+?'
414
                . $this->findAndReplaceHelper->escapeSlashesForRegex(self::TEST_PROJECT_ROOT_NAMESPACE)
415
                . '\\\\%',
416
                '$1 ' . $replaceNamespace . '\\',
417
                $contents
418
            );
419
            file_put_contents($info->getPathname(), $updated);
420
        }
421
    }
422
}
423