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 (#126)
by joseph
28:55
created

EntityGenerator::createEntityTest()   A

Complexity

Conditions 4
Paths 38

Size

Total Lines 52
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 40
dl 0
loc 52
rs 9.28
c 0
b 0
f 0
ccs 0
cts 40
cp 0
cc 4
nc 38
nop 1
crap 20

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator;
4
5
use EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\AbstractEntityRepository;
6
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\AbstractEntitySpecificSaver;
7
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
8
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
9
use gossi\codegen\model\PhpClass;
10
use gossi\codegen\model\PhpInterface;
11
12
class EntityGenerator extends AbstractGenerator
13
{
14
    /**
15
     * Flag to determine if a UUID primary key should be used for this entity.
16
     *
17
     * @var bool
18
     */
19
    protected $useUuidPrimaryKey = false;
20
21
    /**
22
     * @param string $entityFqn
23
     *
24
     * @param bool   $generateSpecificEntitySaver
25
     *
26
     * @return string - absolute path to created file
27
     * @throws DoctrineStaticMetaException
28
     * @SuppressWarnings(PHPMD.StaticAccess)
29
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
30
     */
31 4
    public function generateEntity(
32
        string $entityFqn,
33
        bool $generateSpecificEntitySaver = false
34
    ): string {
35
        try {
36 4
            if (false === \ts\stringContains($entityFqn, '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\')) {
37
                throw new \RuntimeException(
38
                    'Fully qualified name [' . $entityFqn
39
                    . '] does not include the Entities folder name ['
40
                    . AbstractGenerator::ENTITIES_FOLDER_NAME
41
                    . ']. Please ensure you pass in the full namespace qualified entity name'
42
                );
43
            }
44
45 4
            $shortName = MappingHelper::getShortNameForFqn($entityFqn);
46 4
            $plural    = MappingHelper::getPluralForFqn($entityFqn);
47 4
            $singular  = MappingHelper::getSingularForFqn($entityFqn);
48
49 4
            if (\strtolower($shortName) === $plural) {
50
                throw new \RuntimeException(
51
                    'Plural entity name used [' . $plural . ']. '
52
                    . 'Only singular entity names are allowed. '
53
                    . 'Please update this to [' . $singular . ']'
54
                );
55
            }
56
57 4
            $this->createEntityTest($entityFqn);
58 4
            $this->createEntityFixture($entityFqn);
59 4
            $this->createEntityRepository($entityFqn);
60 4
            $this->createEntityFactory($entityFqn);
61 4
            if (true === $generateSpecificEntitySaver) {
62
                $this->createEntitySaver($entityFqn);
63
            }
64
65 4
            $this->createInterface($entityFqn);
66
67 4
            return $this->createEntity($entityFqn);
68
        } catch (\Exception $e) {
69
            throw new DoctrineStaticMetaException(
70
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
71
                $e->getCode(),
72
                $e
73
            );
74
        }
75
    }
76
77
    /**
78
     * @param string $entityFullyQualifiedName
79
     *
80
     * @throws DoctrineStaticMetaException
81
     */
82
    protected function createEntityTest(string $entityFullyQualifiedName): void
83
    {
84
        try {
85
            $abstractTestPath = $this->pathToProjectRoot . '/'
86
                                . $this->testSubFolderName
87
                                . '/' . AbstractGenerator::ENTITIES_FOLDER_NAME
88
                                . '/AbstractEntityTest.php';
89
            if (!$this->getFilesystem()->exists($abstractTestPath)) {
90
                $this->getFilesystem()->copy(self::ABSTRACT_ENTITY_TEST_TEMPLATE_PATH, $abstractTestPath);
91
                $this->fileCreationTransaction::setPathCreated($abstractTestPath);
92
                $this->findAndReplaceHelper->findReplace(
93
                    self::FIND_PROJECT_NAMESPACE,
94
                    rtrim($this->projectRootNamespace, '\\'),
95
                    $abstractTestPath
96
                );
97
            }
98
99
            $phpunitBootstrapPath = $this->pathToProjectRoot . '/'
100
                                    . $this->testSubFolderName . '/bootstrap.php';
101
            if (!$this->getFilesystem()->exists($phpunitBootstrapPath)) {
102
                $this->getFilesystem()->copy(self::PHPUNIT_BOOTSTRAP_TEMPLATE_PATH, $phpunitBootstrapPath);
103
                $this->fileCreationTransaction::setPathCreated($phpunitBootstrapPath);
104
            }
105
106
            list($filePath, $className, $namespace) = $this->parseAndCreate(
107
                $entityFullyQualifiedName . 'Test',
108
                $this->testSubFolderName,
109
                self::ENTITY_TEST_TEMPLATE_PATH
110
            );
111
            $this->findAndReplaceHelper->findReplace(
112
                self::FIND_ENTITIES_NAMESPACE,
113
                $this->namespaceHelper->tidy($namespace),
114
                $filePath
115
            );
116
117
            $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Test');
118
            $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
119
            $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace($namespace, $filePath);
120
            $this->findAndReplaceHelper->findReplace(
121
                'use FQNFor\AbstractEntityTest;',
122
                'use ' . $this->namespaceHelper->tidy(
123
                    $this->projectRootNamespace
124
                    . '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME
125
                    . '\\AbstractEntityTest;'
126
                ),
127
                $filePath
128
            );
129
        } catch (\Exception $e) {
130
            throw new DoctrineStaticMetaException(
131
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
132
                $e->getCode(),
133
                $e
134
            );
135
        }
136
    }
137
138
    /**
139
     * @throws DoctrineStaticMetaException
140
     */
141
    protected function parseAndCreate(
142
        string $fullyQualifiedName,
143
        string $subDir,
144
        string $templatePath
145
    ): array {
146
        try {
147
            list($className, $namespace, $subDirectories) = $this->parseFullyQualifiedName(
148
                $fullyQualifiedName,
149
                $subDir
150
            );
151
            $filePath = $this->pathHelper->copyTemplateAndGetPath(
152
                $this->pathToProjectRoot,
153
                $templatePath,
154
                $className,
155
                $subDirectories
156
            );
157
158
            return [$filePath, $className, $this->namespaceHelper->tidy($namespace)];
159
        } catch (\Exception $e) {
160
            throw new DoctrineStaticMetaException(
161
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
162
                $e->getCode(),
163
                $e
164
            );
165
        }
166
    }
167
168
    protected function createEntityFixture(string $entityFullyQualifiedName): void
169
    {
170
171
        list($filePath, $className, $namespace) = $this->parseAndCreate(
172
            $this->namespaceHelper->getFixtureFqnFromEntityFqn($entityFullyQualifiedName),
173
            $this->testSubFolderName,
174
            self::ENTITY_FIXTURE_TEMPLATE_PATH
175
        );
176
        $this->findAndReplaceHelper->findReplace(
177
            'TemplateNamespace\Assets\EntityFixtures',
178
            $this->namespaceHelper->tidy($namespace),
179
            $filePath
180
        );
181
        $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Fixture');
182
        $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
183
    }
184
185
    /**
186
     * @param string $entityFullyQualifiedName
187
     *
188
     * @throws DoctrineStaticMetaException
189
     */
190
    protected function createEntityRepository(string $entityFullyQualifiedName): void
191
    {
192
        try {
193
            $abstractRepositoryPath = $this->pathToProjectRoot
194
                                      . '/' . $this->srcSubFolderName
195
                                      . '/' . AbstractGenerator::ENTITY_REPOSITORIES_FOLDER_NAME
196
                                      . '/AbstractEntityRepository.php';
197
            if (!$this->getFilesystem()->exists($abstractRepositoryPath)) {
198
                $this->getFilesystem()->copy(
199
                    self::ABSTRACT_ENTITY_REPOSITORY_TEMPLATE_PATH,
200
                    $abstractRepositoryPath
201
                );
202
                $this->fileCreationTransaction::setPathCreated($abstractRepositoryPath);
203
                $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace(
204
                    $this->projectRootNamespace . '\\'
205
                    . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE,
206
                    $abstractRepositoryPath
207
                );
208
            }
209
            $entityRepositoryFqn = \str_replace(
210
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
211
                '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE . '\\',
212
                $entityFullyQualifiedName
213
            ) . 'Repository';
214
215
            list($filePath, $className, $namespace) = $this->parseAndCreate(
216
                $entityRepositoryFqn,
217
                $this->srcSubFolderName,
218
                self::REPOSITORIES_TEMPLATE_PATH
219
            );
220
            $this->findAndReplaceHelper->findReplace(
221
                self::FIND_ENTITY_REPOSITORIES_NAMESPACE,
222
                $this->namespaceHelper->tidy($namespace),
223
                $filePath
224
            );
225
            $classInterfaceNamespace = \str_replace(
226
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
227
                '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE . '\\',
228
                $entityFullyQualifiedName
229
            ) . 'Interface';
230
            $classInterface          = preg_replace('#Repository$#', 'Interface', $className);
231
232
            $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($classInterfaceNamespace, $filePath);
233
            $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Repository');
234
            $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
235
            $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace($namespace, $filePath);
236
            $this->findAndReplaceHelper->replaceName($classInterface, $filePath, self::FIND_ENTITY_NAME . 'Interface');
237
            $this->findAndReplaceHelper->findReplace(
238
                'use FQNFor\AbstractEntityRepository;',
239
                'use ' . $this->namespaceHelper->tidy(
240
                    $this->projectRootNamespace
241
                    . '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE
242
                    . '\\AbstractEntityRepository;'
243
                ),
244
                $filePath
245
            );
246
        } catch (\Exception $e) {
247
            throw new DoctrineStaticMetaException(
248
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
249
                $e->getCode(),
250
                $e
251
            );
252
        }
253
    }
254
255
    /**
256
     * @param string $entityFullyQualifiedName
257
     *
258
     * @throws DoctrineStaticMetaException
259
     */
260
    protected function createEntityFactory(string $entityFullyQualifiedName): void
261
    {
262
        try {
263
            $abstractFactoryPath = $this->pathToProjectRoot
264
                                   . '/' . $this->srcSubFolderName
265
                                   . '/' . AbstractGenerator::ENTITY_FACTORIES_FOLDER_NAME
266
                                   . '/AbstractEntityFactory.php';
267
            if (!$this->getFilesystem()->exists($abstractFactoryPath)) {
268
                $this->getFilesystem()->copy(
269
                    self::ABSTRACT_ENTITY_FACTORY_TEMPLATE_PATH,
270
                    $abstractFactoryPath
271
                );
272
                $this->fileCreationTransaction::setPathCreated($abstractFactoryPath);
273
                $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace(
274
                    $this->projectRootNamespace . '\\'
275
                    . AbstractGenerator::ENTITY_FACTORIES_NAMESPACE,
276
                    $abstractFactoryPath
277
                );
278
            }
279
            $entityFactoryFqn = \str_replace(
280
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
281
                '\\' . AbstractGenerator::ENTITY_FACTORIES_NAMESPACE . '\\',
282
                $entityFullyQualifiedName
283
            ) . 'Factory';
284
285
            list($filePath, $className, $namespace) = $this->parseAndCreate(
286
                $entityFactoryFqn,
287
                $this->srcSubFolderName,
288
                self::FACTORIES_TEMPLATE_PATH
289
            );
290
            list($entityShortName, ,) = $this->parseFullyQualifiedName($entityFullyQualifiedName);
291
            $this->findAndReplaceHelper->findReplace(
292
                self::FIND_ENTITY_FACTORIES_NAMESPACE,
293
                $this->namespaceHelper->tidy($namespace),
294
                $filePath
295
            );
296
            $classInterfaceNamespace = \str_replace(
297
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
298
                '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE . '\\',
299
                $entityFullyQualifiedName
300
            ) . 'Interface';
301
            $classInterface          = preg_replace('#Factory$#', 'Interface', $className);
302
            $this->findAndReplaceHelper->replaceEntitiesNamespace($entityFullyQualifiedName, $filePath);
303
            $this->findAndReplaceHelper->findReplace('EntityFqn', $entityFullyQualifiedName, $filePath);
304
            $this->findAndReplaceHelper->replaceName($entityShortName, $filePath, self::FIND_ENTITY_NAME);
305
            $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($classInterfaceNamespace, $filePath);
306
            $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Factory');
307
            $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
308
            $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace($namespace, $filePath);
309
            $this->findAndReplaceHelper->replaceName($classInterface, $filePath, self::FIND_ENTITY_NAME . 'Interface');
310
            $this->findAndReplaceHelper->findReplace(
311
                'use FQNFor\AbstractEntityFactory;',
312
                'use ' . $this->namespaceHelper->tidy(
313
                    $this->projectRootNamespace
314
                    . '\\' . AbstractGenerator::ENTITY_FACTORIES_NAMESPACE
315
                    . '\\AbstractEntityFactory;'
316
                ),
317
                $filePath
318
            );
319
        } catch (\Exception $e) {
320
            throw new DoctrineStaticMetaException(
321
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
322
                $e->getCode(),
323
                $e
324
            );
325
        }
326
    }
327
328
    /**
329
     * Create an entity saver
330
     *
331
     * @param string $entityFqn
332
     *
333
     * @throws DoctrineStaticMetaException
334
     * @SuppressWarnings(PHPMD.StaticAccess)
335
     */
336
    protected function createEntitySaver(string $entityFqn): void
337
    {
338
        $entitySaverFqn = \str_replace(
339
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
340
            AbstractGenerator::ENTITY_SAVERS_NAMESPACE . '\\',
341
            $entityFqn
342
        ) . 'Saver';
343
344
345
        $entitySaver = new PhpClass();
346
        $entitySaver
347
            ->setQualifiedName($entitySaverFqn)
348
            ->setParentClassName('\\' . AbstractEntitySpecificSaver::class)
349
            ->setInterfaces(
350
                [
351
                    PhpInterface::fromFile(__DIR__ . '/../../Entity/Savers/EntitySaverInterface.php'),
352
                ]
353
            );
354
355
        list($className, , $subDirectories) = $this->parseFullyQualifiedName(
356
            $entitySaverFqn,
357
            $this->srcSubFolderName
358
        );
359
360
        $filePath = $this->createSubDirectoriesAndGetPath($subDirectories);
361
362
        $this->codeHelper->generate($entitySaver, $filePath . '/' . $className . '.php');
363
    }
364
365
    /**
366
     * @param string $entityFullyQualifiedName
367
     *
368
     * @throws DoctrineStaticMetaException
369
     */
370
    protected function createInterface(string $entityFullyQualifiedName): void
371
    {
372
        $entityInterfaceFqn = \str_replace(
373
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
374
            '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE . '\\',
375
            $entityFullyQualifiedName
376
        ) . 'Interface';
377
378
        list($className, $namespace, $subDirectories) = $this->parseFullyQualifiedName(
379
            $entityInterfaceFqn,
380
            $this->srcSubFolderName
381
        );
382
383
        $filePath = $this->pathHelper->copyTemplateAndGetPath(
384
            $this->pathToProjectRoot,
385
            self::ENTITY_INTERFACE_TEMPLATE_PATH,
386
            $className,
387
            $subDirectories
388
        );
389
390
        $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Interface');
391
        $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($namespace, $filePath);
392
    }
393
394
    protected function createEntity(
395
        string $entityFullyQualifiedName
396
    ): string {
397
        list($filePath, $className, $namespace) = $this->parseAndCreate(
398
            $entityFullyQualifiedName,
399
            $this->srcSubFolderName,
400
            self::ENTITY_TEMPLATE_PATH
401
        );
402
        $this->findAndReplaceHelper->replaceName($className, $filePath, static::FIND_ENTITY_NAME);
403
        $this->findAndReplaceHelper->replaceEntitiesNamespace($namespace, $filePath);
404
        $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace(
405
            \str_replace(
406
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME,
407
                '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE,
408
                $namespace
409
            ),
410
            $filePath
411
        );
412
413
        if ($this->getUseUuidPrimaryKey()) {
414
            $this->findAndReplaceHelper->findReplace(
415
                'IdFieldTrait',
416
                'UuidFieldTrait',
417
                $filePath
418
            );
419
        }
420
421
        $interfaceNamespace = \str_replace(
422
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME,
423
            '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE,
424
            $namespace
425
        );
426
427
        $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($interfaceNamespace, $filePath);
428
429
        return $filePath;
430
    }
431
432
    public function getUseUuidPrimaryKey(): bool
433
    {
434
        return $this->useUuidPrimaryKey;
435
    }
436
437
    public function setUseUuidPrimaryKey(bool $useUuidPrimaryKey): self
438
    {
439
        $this->useUuidPrimaryKey = $useUuidPrimaryKey;
440
441
        return $this;
442
    }
443
444
    /**
445
     * Create the abstract entity repository factory if it doesn't currently exist
446
     */
447
    protected function createAbstractEntityRepositoryFactory(): void
448
    {
449
        $abstractRepositoryFactoryPath = $this->pathToProjectRoot
450
                                         . '/' . $this->srcSubFolderName
451
                                         . '/' . AbstractGenerator::ENTITY_REPOSITORIES_FOLDER_NAME
452
                                         . '/AbstractEntityRepositoryFactory.php';
453
454
        if ($this->getFilesystem()->exists($abstractRepositoryFactoryPath)) {
455
            return;
456
        }
457
458
        $abstractFactoryFqn = $this->projectRootNamespace
459
                              . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE
460
                              . '\\AbstractEntityRepositoryFactory';
461
462
        $abstractFactory = new PhpClass();
463
        $abstractFactory
464
            ->setUseStatements([AbstractEntityRepository::class . ' as DSMRepositoryFactory'])
465
            ->setQualifiedName($abstractFactoryFqn)
466
            ->setParentClassName('DSMRepositoryFactory');
467
468
        $this->codeHelper->generate($abstractFactory, $abstractRepositoryFactoryPath);
469
    }
470
}
471