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 (#118)
by joseph
21:38
created

Builder::getRelationsGenerator()   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 2
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\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
    public function setPathToProjectRoot(string $pathToProjectRoot): self
82
    {
83
        $this->entityGenerator->setPathToProjectRoot($pathToProjectRoot);
84
        $this->fieldGenerator->setPathToProjectRoot($pathToProjectRoot);
85
        $this->fieldSetter->setPathToProjectRoot($pathToProjectRoot);
86
        $this->relationsGenerator->setPathToProjectRoot($pathToProjectRoot);
87
        $this->archetypeEmbeddableGenerator->setPathToProjectRoot($pathToProjectRoot);
88
89
        return $this;
90
    }
91
92
    public function setProjectRootNamespace(string $projectRootNamespace): self
93
    {
94
        $this->entityGenerator->setProjectRootNamespace($projectRootNamespace);
95
        $this->fieldGenerator->setProjectRootNamespace($projectRootNamespace);
96
        $this->fieldSetter->setProjectRootNamespace($projectRootNamespace);
97
        $this->relationsGenerator->setProjectRootNamespace($projectRootNamespace);
98
        $this->archetypeEmbeddableGenerator->setProjectRootNamespace($projectRootNamespace);
99
100
        return $this;
101
    }
102
103
    /**
104
     * @return EntityGenerator
105
     */
106
    public function getEntityGenerator(): EntityGenerator
107
    {
108
        return $this->entityGenerator;
109
    }
110
111
    /**
112
     * @return FieldGenerator
113
     */
114
    public function getFieldGenerator(): FieldGenerator
115
    {
116
        return $this->fieldGenerator;
117
    }
118
119
    /**
120
     * @return EntityFieldSetter
121
     */
122
    public function getFieldSetter(): EntityFieldSetter
123
    {
124
        return $this->fieldSetter;
125
    }
126
127
    /**
128
     * @return RelationsGenerator
129
     */
130
    public function getRelationsGenerator(): RelationsGenerator
131
    {
132
        return $this->relationsGenerator;
133
    }
134
135
    /**
136
     * @return ArchetypeEmbeddableGenerator
137
     */
138
    public function getArchetypeEmbeddableGenerator(): ArchetypeEmbeddableGenerator
139
    {
140
        return $this->archetypeEmbeddableGenerator;
141
    }
142
143
    /**
144
     * @return EntityEmbeddableSetter
145
     */
146
    public function getEmbeddableSetter(): EntityEmbeddableSetter
147
    {
148
        return $this->embeddableSetter;
149
    }
150
151
    /**
152
     * @param array $entityFqns
153
     *
154
     * @return Builder
155
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
156
     */
157
    public function generateEntities(array $entityFqns): self
158
    {
159
        foreach ($entityFqns as $entityFqn) {
160
            $this->entityGenerator->generateEntity($entityFqn);
161
        }
162
163
        return $this;
164
    }
165
166
    /**
167
     * @param array $entityRelationEntity
168
     *
169
     * @return Builder
170
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
171
     */
172
    public function setEntityRelations(array $entityRelationEntity): self
173
    {
174
        foreach ($entityRelationEntity as list($owningEntityFqn, $hasType, $ownedEntityFqn)) {
175
            $this->relationsGenerator->setEntityHasRelationToEntity($owningEntityFqn, $hasType, $ownedEntityFqn);
176
        }
177
178
        return $this;
179
    }
180
181
    /**
182
     * @param array $fields
183
     *
184
     * @return array $traitFqns
185
     */
186
    public function generateFields(array $fields): array
187
    {
188
        $traitFqns = [];
189
        foreach ($fields as list($fieldFqn, $fieldType)) {
190
            try {
191
                $traitFqns[] = $this->fieldGenerator->generateField($fieldFqn, $fieldType);
192
            } catch (\Exception $e) {
193
                throw new \RuntimeException(
194
                    'Failed building field with $fieldFqn: ' . $fieldFqn . ' and $fieldType ' . $fieldType,
195
                    $e->getCode(),
196
                    $e
197
                );
198
            }
199
        }
200
201
        return $traitFqns;
202
    }
203
204
    /**
205
     * @param string $entityFqn
206
     * @param array  $fieldFqns
207
     *
208
     * @return Builder
209
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
210
     */
211
    public function setFieldsToEntity(string $entityFqn, array $fieldFqns): self
212
    {
213
        foreach ($fieldFqns as $fieldFqn) {
214
            $this->fieldSetter->setEntityHasField($entityFqn, $fieldFqn);
215
        }
216
217
        return $this;
218
    }
219
220
    /**
221
     * @param array $embeddables
222
     *
223
     * @return array $traitFqns
224
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
225
     * @throws \ReflectionException
226
     */
227
    public function generateEmbeddables(array $embeddables): array
228
    {
229
        $traitFqns = [];
230
        foreach ($embeddables as list($archetypeEmbeddableObjectFqn, $newEmbeddableObjectClassName)) {
231
            $traitFqns[] = $this->archetypeEmbeddableGenerator->createFromArchetype(
232
                $archetypeEmbeddableObjectFqn,
233
                $newEmbeddableObjectClassName
234
            );
235
        }
236
237
        return $traitFqns;
238
    }
239
240
    /**
241
     * @param string $entityFqn
242
     * @param array  $embeddableTraitFqns
243
     *
244
     * @return Builder
245
     */
246
    public function setEmbeddablesToEntity(string $entityFqn, array $embeddableTraitFqns): self
247
    {
248
        foreach ($embeddableTraitFqns as $embeddableTraitFqn) {
249
            $this->embeddableSetter->setEntityHasEmbeddable($entityFqn, $embeddableTraitFqn);
250
        }
251
252
        return $this;
253
    }
254
255 1
    public function setEnumOptionsOnInterface(string $interfaceFqn, array $options): void
256
    {
257 1
        $pathToInterface = (new ReflectionClass($interfaceFqn))->getFileName();
258 1
        $basename        = basename($pathToInterface);
259 1
        $classy          = substr($basename, 0, strpos($basename, 'FieldInterface'));
260 1
        $consty          = $this->codeHelper->consty($classy);
261 1
        $interface       = PhpInterface::fromFile($pathToInterface);
262 1
        $constants       = $interface->getConstants();
263
        $constants->map(function (PhpConstant $constant) use ($interface, $consty) {
264 1
            if (0 === strpos($constant->getName(), $consty . '_OPTION')) {
265 1
                $interface->removeConstant($constant);
266
            }
267 1
            if (0 === strpos($constant->getName(), 'DEFAULT')) {
268 1
                $interface->removeConstant($constant);
269
            }
270 1
        });
271 1
        $optionConsts = [];
272 1
        foreach ($options as $option) {
273 1
            $name           = \str_replace(
274 1
                '__',
275 1
                '_',
276 1
                $consty . '_OPTION_' . $this->codeHelper->consty(
277 1
                    \str_replace(' ', '_', $option)
278
                )
279
            );
280 1
            $optionConsts[] = 'self::' . $name;
281 1
            $constant       = new PhpConstant($name, $option);
282 1
            $interface->setConstant($constant);
283
        }
284 1
        $interface->setConstant(
285 1
            new PhpConstant(
286 1
                $consty . '_OPTIONS',
287 1
                '[' . implode(",\n", $optionConsts) . ']',
288 1
                true
289
            )
290
        );
291 1
        $interface->setConstant(
292 1
            new PhpConstant(
293 1
                'DEFAULT_' . $consty,
294 1
                current($optionConsts),
295 1
                true
296
            )
297
        );
298 1
        $this->codeHelper->generate($interface, $pathToInterface);
299 1
    }
300
301
    public function injectTraitInToClass(string $traitFqn, string $classFqn): void
302
    {
303
        $classFilePath = $this->getFileName($classFqn);
304
        $class         = PhpClass::fromFile($classFilePath);
305
        $trait         = PhpTrait::fromFile($this->getFileName($traitFqn));
306
        $traits        = $class->getTraits();
307
        $exists        = array_search($traitFqn, $traits, true);
308
        if ($exists !== false) {
309
            return;
310
        }
311
        $class->addTrait($trait);
312
        $this->codeHelper->generate($class, $classFilePath);
313
    }
314
315
    public function extendInterfaceWithInterface(string $interfaceToExtendFqn, string $interfaceToAddFqn): void
316
    {
317
        $toExtendFilePath = $this->getFileName($interfaceToExtendFqn);
318
        $toExtend         = PhpInterface::fromFile($toExtendFilePath);
319
        $toAdd            = PhpInterface::fromFile($this->getFileName($interfaceToAddFqn));
320
        $exists           = $toExtend->getInterfaces()->contains($interfaceToAddFqn);
321
        if ($exists !== false) {
322
            return;
323
        }
324
        $toExtend->addInterface($toAdd);
325
        $this->codeHelper->generate($toExtend, $toExtendFilePath);
326
    }
327
328
    public function removeIdTraitFromClass(string $classFqn): void
329
    {
330
        $traitFqn = "DSM\\Fields\\Traits\\PrimaryKey\\IdFieldTrait";
331
        $this->removeTraitFromClass($classFqn, $traitFqn);
332
    }
333
334
    public function removeTraitFromClass(string $classFqn, string $traitFqn): void
335
    {
336
        $classPath = $this->getFileName($classFqn);
337
        $class     = PhpClass::fromFile($classPath);
338
        $traits    = $class->getTraits();
339
        if ($class->getUseStatements()->contains($traitFqn) === true) {
340
            $class->removeUseStatement($traitFqn);
341
        }
342
        $index = array_search($traitFqn, $traits, true);
343
        if ($index === false) {
344
            $shortNameParts = explode('\\', $traitFqn);
345
            $shortName      = (string)array_pop($shortNameParts);
346
            $index          = array_search($shortName, $traits, true);
347
        }
348
        if ($index === false) {
349
            return;
350
        }
351
        unset($traits[$index]);
352
        $reflectionClass = new ReflectionClass(PhpClass::class);
353
        $property        = $reflectionClass->getProperty('traits');
354
        $property->setAccessible(true);
355
        $property->setValue($class, $traits);
356
        $this->codeHelper->generate($class, $classPath);
357
    }
358
359
    private function getFileName(string $typeFqn): string
360
    {
361
        $reflectionClass = new ReflectionClass($typeFqn);
362
363
        return $reflectionClass->getFileName();
364
    }
365
366
    public function removeUnusedRelations(): void
367
    {
368
        $this->unusedRelationsRemover->run();
369
    }
370
}
371