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 ( 0bd9a0...71ef0e )
by joseph
24:07 queued 20:47
created

Builder::generateFields()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 16
rs 9.9332
c 0
b 0
f 0
ccs 0
cts 10
cp 0
nc 3
nop 1
cc 3
crap 12
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 1
    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 1
        $this->entityGenerator              = $entityGenerator;
72 1
        $this->fieldGenerator               = $fieldGenerator;
73 1
        $this->fieldSetter                  = $fieldSetter;
74 1
        $this->relationsGenerator           = $relationsGenerator;
75 1
        $this->archetypeEmbeddableGenerator = $archetypeEmbeddableGenerator;
76 1
        $this->embeddableSetter             = $embeddableSetter;
77 1
        $this->codeHelper                   = $codeHelper;
78 1
        $this->unusedRelationsRemover       = $unusedRelationsRemover;
79 1
    }
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 1
    public function setEnumOptionsOnInterface(string $interfaceFqn, array $options): void
234
    {
235 1
        $pathToInterface = (new ReflectionClass($interfaceFqn))->getFileName();
236 1
        $basename        = basename($pathToInterface);
237 1
        $classy          = substr($basename, 0, strpos($basename, 'FieldInterface'));
238 1
        $consty          = $this->codeHelper->consty($classy);
239 1
        $interface       = PhpInterface::fromFile($pathToInterface);
240 1
        $constants       = $interface->getConstants();
241
        $constants->map(function (PhpConstant $constant) use ($interface, $consty) {
242 1
            if (0 === strpos($constant->getName(), $consty . '_OPTION')) {
243 1
                $interface->removeConstant($constant);
244
            }
245 1
            if (0 === strpos($constant->getName(), 'DEFAULT')) {
246 1
                $interface->removeConstant($constant);
247
            }
248 1
        });
249 1
        $optionConsts = [];
250 1
        foreach ($options as $option) {
251 1
            $name           = \str_replace(
252 1
                '__',
253 1
                '_',
254 1
                $consty . '_OPTION_' . $this->codeHelper->consty(
255 1
                    \str_replace(' ', '_', $option)
256
                )
257
            );
258 1
            $optionConsts[] = 'self::' . $name;
259 1
            $constant       = new PhpConstant($name, $option);
260 1
            $interface->setConstant($constant);
261
        }
262 1
        $interface->setConstant(
263 1
            new PhpConstant(
264 1
                $consty . '_OPTIONS',
265 1
                '[' . implode(",\n", $optionConsts) . ']',
266 1
                true
267
            )
268
        );
269 1
        $interface->setConstant(
270 1
            new PhpConstant(
271 1
                'DEFAULT_' . $consty,
272 1
                current($optionConsts),
273 1
                true
274
            )
275
        );
276 1
        $this->codeHelper->generate($interface, $pathToInterface);
277 1
    }
278
279
    public function injectTraitInToClass(string $traitFqn, string $classFqn): void
280
    {
281
        $classFilePath = $this->getFileName($classFqn);
282
        $class         = PhpClass::fromFile($classFilePath);
283
        $trait         = PhpTrait::fromFile($this->getFileName($traitFqn));
284
        $traits        = $class->getTraits();
285
        $exists        = array_search($traitFqn, $traits, true);
286
        if ($exists !== false) {
287
            return;
288
        }
289
        $class->addTrait($trait);
290
        $this->codeHelper->generate($class, $classFilePath);
291
    }
292
293
    public function extendInterfaceWithInterface(string $interfaceToExtendFqn, string $interfaceToAddFqn): void
294
    {
295
        $toExtendFilePath = $this->getFileName($interfaceToExtendFqn);
296
        $toExtend         = PhpInterface::fromFile($toExtendFilePath);
297
        $toAdd            = PhpInterface::fromFile($this->getFileName($interfaceToAddFqn));
298
        $exists           = $toExtend->getInterfaces()->contains($interfaceToAddFqn);
299
        if ($exists !== false) {
300
            return;
301
        }
302
        $toExtend->addInterface($toAdd);
303
        $this->codeHelper->generate($toExtend, $toExtendFilePath);
304
    }
305
306
    public function removeIdTraitFromClass(string $classFqn): void
307
    {
308
        $traitFqn = "DSM\\Fields\\Traits\\PrimaryKey\\IdFieldTrait";
309
        $this->removeTraitFromClass($classFqn, $traitFqn);
310
    }
311
312
    public function removeTraitFromClass(string $classFqn, string $traitFqn): void
313
    {
314
        $classPath = $this->getFileName($classFqn);
315
        $class     = PhpClass::fromFile($classPath);
316
        $traits    = $class->getTraits();
317
        if ($class->getUseStatements()->contains($traitFqn) === true) {
318
            $class->removeUseStatement($traitFqn);
319
        }
320
        $index = array_search($traitFqn, $traits, true);
321
        if ($index === false) {
322
            $shortNameParts = explode('\\', $traitFqn);
323
            $shortName      = (string)array_pop($shortNameParts);
324
            $index          = array_search($shortName, $traits, true);
325
        }
326
        if ($index === false) {
327
            return;
328
        }
329
        unset($traits[$index]);
330
        $reflectionClass = new ReflectionClass(PhpClass::class);
331
        $property        = $reflectionClass->getProperty('traits');
332
        $property->setAccessible(true);
333
        $property->setValue($class, $traits);
334
        $this->codeHelper->generate($class, $classPath);
335
    }
336
337
    private function getFileName(string $typeFqn): string
338
    {
339
        $reflectionClass = new ReflectionClass($typeFqn);
340
341
        return $reflectionClass->getFileName();
342
    }
343
344
    public function removeUnusedRelations(): void
345
    {
346
        $this->unusedRelationsRemover->run();
347
    }
348
}
349