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.
Passed
Pull Request — master (#105)
by joseph
21:10
created

Builder::generateEntities()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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