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 (#153)
by joseph
22:27
created

Builder::getEntityGenerator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Builder;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Action\CreateDtosForAllEntitiesAction;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Embeddable\ArchetypeEmbeddableGenerator;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Embeddable\EntityEmbeddableSetter;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\EntityGenerator;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\EntityFieldSetter;
11
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator;
12
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
13
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
14
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PostProcessor\CopyPhpstormMeta;
15
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PostProcessor\EntityFormatter;
16
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\UnusedRelationsRemover;
17
use EdmondsCommerce\DoctrineStaticMeta\Config;
18
use gossi\codegen\model\PhpClass;
19
use gossi\codegen\model\PhpConstant;
20
use gossi\codegen\model\PhpInterface;
21
use gossi\codegen\model\PhpTrait;
22
use ts\Reflection\ReflectionClass;
23
24
/**
25
 * Class Builder
26
 *
27
 * @package EdmondsCommerce\DoctrineStaticMeta\Builder
28
 * @SuppressWarnings(PHPMD)
29
 */
30
class Builder
31
{
32
33
    /**
34
     * @var EntityGenerator
35
     */
36
    protected $entityGenerator;
37
    /**
38
     * @var FieldGenerator
39
     */
40
    protected $fieldGenerator;
41
    /**
42
     * @var EntityFieldSetter
43
     */
44
    protected $fieldSetter;
45
    /**
46
     * @var RelationsGenerator
47
     */
48
    protected $relationsGenerator;
49
    /**
50
     * @var ArchetypeEmbeddableGenerator
51
     */
52
    protected $archetypeEmbeddableGenerator;
53
    /**
54
     * @var EntityEmbeddableSetter
55
     */
56
    protected $embeddableSetter;
57
    /**
58
     * @var CodeHelper
59
     */
60
    protected $codeHelper;
61
    /**
62
     * @var UnusedRelationsRemover
63
     */
64
    protected $unusedRelationsRemover;
65
    /**
66
     * @var CreateDtosForAllEntitiesAction
67
     */
68
    private $dataTransferObjectsForAllEntitiesAction;
69
    /**
70
     * @var EntityFormatter
71
     */
72
    private $entityFormatter;
73
    /**
74
     * @var CopyPhpstormMeta
75
     */
76
    private $copyPhpstormMeta;
77
    /**
78
     * @var NamespaceHelper
79
     */
80
    private $namespaceHelper;
81
82
    public function __construct(
83
        EntityGenerator $entityGenerator,
84
        FieldGenerator $fieldGenerator,
85
        EntityFieldSetter $fieldSetter,
86
        RelationsGenerator $relationsGenerator,
87
        ArchetypeEmbeddableGenerator $archetypeEmbeddableGenerator,
88
        EntityEmbeddableSetter $embeddableSetter,
89
        CodeHelper $codeHelper,
90
        UnusedRelationsRemover $unusedRelationsRemover,
91
        CreateDtosForAllEntitiesAction $dataTransferObjectsForAllEntitiesAction,
92
        EntityFormatter $entityFormatter,
93
        Config $config,
94
        CopyPhpstormMeta $copyPhpstormMeta,
95
        NamespaceHelper $namespaceHelper
96
    ) {
97
        $this->entityGenerator                         = $entityGenerator;
98
        $this->fieldGenerator                          = $fieldGenerator;
99
        $this->fieldSetter                             = $fieldSetter;
100
        $this->relationsGenerator                      = $relationsGenerator;
101
        $this->archetypeEmbeddableGenerator            = $archetypeEmbeddableGenerator;
102
        $this->embeddableSetter                        = $embeddableSetter;
103
        $this->codeHelper                              = $codeHelper;
104
        $this->unusedRelationsRemover                  = $unusedRelationsRemover;
105
        $this->dataTransferObjectsForAllEntitiesAction = $dataTransferObjectsForAllEntitiesAction;
106
        $this->entityFormatter                         = $entityFormatter;
107
        $this->copyPhpstormMeta                        = $copyPhpstormMeta;
108
        $this->namespaceHelper                         = $namespaceHelper;
109
110
        $this->setPathToProjectRoot($config::getProjectRootDirectory());
111
    }
112
113
    public function setPathToProjectRoot(string $pathToProjectRoot): self
114
    {
115
        $this->entityGenerator->setPathToProjectRoot($pathToProjectRoot);
116
        $this->fieldGenerator->setPathToProjectRoot($pathToProjectRoot);
117
        $this->fieldSetter->setPathToProjectRoot($pathToProjectRoot);
118
        $this->relationsGenerator->setPathToProjectRoot($pathToProjectRoot);
119
        $this->archetypeEmbeddableGenerator->setPathToProjectRoot($pathToProjectRoot);
120
        $this->unusedRelationsRemover->setPathToProjectRoot($pathToProjectRoot);
121
        $this->dataTransferObjectsForAllEntitiesAction->setProjectRootDirectory($pathToProjectRoot);
122
        $this->embeddableSetter->setPathToProjectRoot($pathToProjectRoot);
123
        $this->entityFormatter->setPathToProjectRoot($pathToProjectRoot);
124
        $this->copyPhpstormMeta->setPathToProjectRoot($pathToProjectRoot);
125
126
        return $this;
127
    }
128
129
    /**
130
     * @return EntityGenerator
131
     */
132
    public function getEntityGenerator(): EntityGenerator
133
    {
134
        return $this->entityGenerator;
135
    }
136
137
    /**
138
     * @return FieldGenerator
139
     */
140
    public function getFieldGenerator(): FieldGenerator
141
    {
142
        return $this->fieldGenerator;
143
    }
144
145
    /**
146
     * @return EntityFieldSetter
147
     */
148
    public function getFieldSetter(): EntityFieldSetter
149
    {
150
        return $this->fieldSetter;
151
    }
152
153
    /**
154
     * @return RelationsGenerator
155
     */
156
    public function getRelationsGenerator(): RelationsGenerator
157
    {
158
        return $this->relationsGenerator;
159
    }
160
161
    /**
162
     * @return ArchetypeEmbeddableGenerator
163
     */
164
    public function getArchetypeEmbeddableGenerator(): ArchetypeEmbeddableGenerator
165
    {
166
        return $this->archetypeEmbeddableGenerator;
167
    }
168
169
    /**
170
     * @return EntityEmbeddableSetter
171
     */
172
    public function getEmbeddableSetter(): EntityEmbeddableSetter
173
    {
174
        return $this->embeddableSetter;
175
    }
176
177
    /**
178
     * Finalise build - run various steps to wrap up the build and tidy up the codebase
179
     *
180
     * @return Builder
181
     */
182
    public function finaliseBuild(): self
183
    {
184
        $this->dataTransferObjectsForAllEntitiesAction->run();
185
        $this->entityFormatter->run();
186
        $this->removeUnusedRelations();
187
        $this->copyPhpstormMeta->run();
188
189
        return $this;
190
    }
191
192
    public function removeUnusedRelations(): void
193
    {
194
        $this->unusedRelationsRemover->run();
195
    }
196
197
    /**
198
     * @param array $entityFqns
199
     *
200
     * @return Builder
201
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
202
     */
203
    public function generateEntities(array $entityFqns): self
204
    {
205
        $this->setProjectRootNamespace(
206
            $this->namespaceHelper->getProjectNamespaceRootFromEntityFqn(
207
                current($entityFqns)
208
            )
209
        );
210
        foreach ($entityFqns as $entityFqn) {
211
            $this->entityGenerator->generateEntity($entityFqn);
212
        }
213
214
        return $this;
215
    }
216
217
    public function setProjectRootNamespace(string $projectRootNamespace): self
218
    {
219
        $this->entityGenerator->setProjectRootNamespace($projectRootNamespace);
220
        $this->fieldGenerator->setProjectRootNamespace($projectRootNamespace);
221
        $this->fieldSetter->setProjectRootNamespace($projectRootNamespace);
222
        $this->relationsGenerator->setProjectRootNamespace($projectRootNamespace);
223
        $this->archetypeEmbeddableGenerator->setProjectRootNamespace($projectRootNamespace);
224
        $this->dataTransferObjectsForAllEntitiesAction->setProjectRootNamespace($projectRootNamespace);
225
        $this->embeddableSetter->setProjectRootNamespace($projectRootNamespace);
226
        $this->unusedRelationsRemover->setProjectRootNamespace($projectRootNamespace);
227
228
        return $this;
229
    }
230
231
    /**
232
     * @param array $entityRelationEntity
233
     *
234
     * @return Builder
235
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
236
     */
237
    public function setEntityRelations(array $entityRelationEntity): self
238
    {
239
        foreach ($entityRelationEntity as list($owningEntityFqn, $hasType, $ownedEntityFqn)) {
240
            $this->relationsGenerator->setEntityHasRelationToEntity($owningEntityFqn, $hasType, $ownedEntityFqn);
241
        }
242
243
        return $this;
244
    }
245
246
    /**
247
     * @param array $fields
248
     *
249
     * @return array $traitFqns
250
     */
251
    public function generateFields(array $fields): array
252
    {
253
        $traitFqns = [];
254
        foreach ($fields as list($fieldFqn, $fieldType)) {
255
            try {
256
                $traitFqns[] = $this->fieldGenerator->generateField($fieldFqn, $fieldType);
257
            } catch (\Exception $e) {
258
                throw new \RuntimeException(
259
                    'Failed building field with $fieldFqn: ' . $fieldFqn . ' and $fieldType ' . $fieldType,
260
                    $e->getCode(),
261
                    $e
262
                );
263
            }
264
        }
265
266
        return $traitFqns;
267
    }
268
269
    /**
270
     * @param string $entityFqn
271
     * @param array  $fieldFqns
272
     *
273
     * @return Builder
274
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
275
     */
276
    public function setFieldsToEntity(string $entityFqn, array $fieldFqns): self
277
    {
278
        foreach ($fieldFqns as $fieldFqn) {
279
            $this->fieldSetter->setEntityHasField($entityFqn, $fieldFqn);
280
        }
281
282
        return $this;
283
    }
284
285
    /**
286
     * @param array $embeddables
287
     *
288
     * @return array $traitFqns
289
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
290
     * @throws \ReflectionException
291
     */
292
    public function generateEmbeddables(array $embeddables): array
293
    {
294
        $traitFqns = [];
295
        foreach ($embeddables as list($archetypeEmbeddableObjectFqn, $newEmbeddableObjectClassName)) {
296
            $traitFqns[] = $this->archetypeEmbeddableGenerator->createFromArchetype(
297
                $archetypeEmbeddableObjectFqn,
298
                $newEmbeddableObjectClassName
299
            );
300
        }
301
302
        return $traitFqns;
303
    }
304
305
    /**
306
     * @param string $entityFqn
307
     * @param array  $embeddableTraitFqns
308
     *
309
     * @return Builder
310
     */
311
    public function setEmbeddablesToEntity(string $entityFqn, array $embeddableTraitFqns): self
312
    {
313
        foreach ($embeddableTraitFqns as $embeddableTraitFqn) {
314
            $this->embeddableSetter->setEntityHasEmbeddable($entityFqn, $embeddableTraitFqn);
315
        }
316
317
        return $this;
318
    }
319
320
    public function setEnumOptionsOnInterface(string $interfaceFqn, array $options): void
321
    {
322
        $pathToInterface = (new ReflectionClass($interfaceFqn))->getFileName();
323
        $basename        = basename($pathToInterface);
324
        $classy          = substr($basename, 0, strpos($basename, 'FieldInterface'));
325
        $consty          = $this->codeHelper->consty($classy);
326
        $interface       = PhpInterface::fromFile($pathToInterface);
327
        $constants       = $interface->getConstants();
328
        $constants->map(function (PhpConstant $constant) use ($interface, $consty) {
329
            if (0 === strpos($constant->getName(), $consty . '_OPTION')) {
330
                $interface->removeConstant($constant);
331
            }
332
            if (0 === strpos($constant->getName(), 'DEFAULT')) {
333
                $interface->removeConstant($constant);
334
            }
335
        });
336
        $optionConsts = [];
337
        foreach ($options as $option) {
338
            $name           = \str_replace(
339
                '__',
340
                '_',
341
                $consty . '_OPTION_' . $this->codeHelper->consty(
342
                    \str_replace(' ', '_', $option)
343
                )
344
            );
345
            $optionConsts[] = 'self::' . $name;
346
            $constant       = new PhpConstant($name, $option);
347
            $interface->setConstant($constant);
348
        }
349
        $interface->setConstant(
350
            new PhpConstant(
351
                $consty . '_OPTIONS',
352
                '[' . implode(",\n", $optionConsts) . ']',
353
                true
354
            )
355
        );
356
        $interface->setConstant(
357
            new PhpConstant(
358
                'DEFAULT_' . $consty,
359
                current($optionConsts),
360
                true
361
            )
362
        );
363
        $this->codeHelper->generate($interface, $pathToInterface);
364
    }
365
366
    public function injectTraitInToClass(string $traitFqn, string $classFqn): void
367
    {
368
        $classFilePath = $this->getFileName($classFqn);
369
        $class         = PhpClass::fromFile($classFilePath);
370
        $trait         = PhpTrait::fromFile($this->getFileName($traitFqn));
371
        $traits        = $class->getTraits();
372
        $exists        = array_search($traitFqn, $traits, true);
373
        if ($exists !== false) {
374
            return;
375
        }
376
        $class->addTrait($trait);
377
        $this->codeHelper->generate($class, $classFilePath);
378
    }
379
380
    private function getFileName(string $typeFqn): string
381
    {
382
        $reflectionClass = new ReflectionClass($typeFqn);
383
384
        return $reflectionClass->getFileName();
385
    }
386
387
    public function extendInterfaceWithInterface(string $interfaceToExtendFqn, string $interfaceToAddFqn): void
388
    {
389
        $toExtendFilePath = $this->getFileName($interfaceToExtendFqn);
390
        $toExtend         = PhpInterface::fromFile($toExtendFilePath);
391
        $toAdd            = PhpInterface::fromFile($this->getFileName($interfaceToAddFqn));
392
        $exists           = $toExtend->getInterfaces()->contains($interfaceToAddFqn);
393
        if ($exists !== false) {
394
            return;
395
        }
396
        $toExtend->addInterface($toAdd);
397
        $this->codeHelper->generate($toExtend, $toExtendFilePath);
398
    }
399
400
    public function removeIdTraitFromClass(string $classFqn): void
401
    {
402
        $traitFqn = "DSM\\Fields\\Traits\\PrimaryKey\\IdFieldTrait";
403
        $this->removeTraitFromClass($classFqn, $traitFqn);
404
    }
405
406
    public function removeTraitFromClass(string $classFqn, string $traitFqn): void
407
    {
408
        $classPath = $this->getFileName($classFqn);
409
        $class     = PhpClass::fromFile($classPath);
410
        $traits    = $class->getTraits();
411
        if ($class->getUseStatements()->contains($traitFqn) === true) {
412
            $class->removeUseStatement($traitFqn);
413
        }
414
        $index = array_search($traitFqn, $traits, true);
415
        if ($index === false) {
416
            $shortNameParts = explode('\\', $traitFqn);
417
            $shortName      = (string)array_pop($shortNameParts);
418
            $index          = array_search($shortName, $traits, true);
419
        }
420
        if ($index === false) {
421
            return;
422
        }
423
        unset($traits[$index]);
424
        $reflectionClass = new ReflectionClass(PhpClass::class);
425
        $property        = $reflectionClass->getProperty('traits');
426
        $property->setAccessible(true);
427
        $property->setValue($class, $traits);
428
        $this->codeHelper->generate($class, $classPath);
429
    }
430
}
431