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 (#106)
by joseph
20:31
created

EntityGenerator::createEntitySaver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 27
rs 9.7333
c 0
b 0
f 0
ccs 0
cts 16
cp 0
cc 1
nc 1
nop 1
crap 2
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->createEntityRepository($entityFqn);
59 4
            if (true === $generateSpecificEntitySaver) {
60
                $this->createEntitySaver($entityFqn);
61
            }
62
63 4
            $this->createInterface($entityFqn);
64
65 4
            return $this->createEntity($entityFqn);
66
        } catch (\Exception $e) {
67
            throw new DoctrineStaticMetaException(
68
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
69
                $e->getCode(),
70
                $e
71
            );
72
        }
73
    }
74
75
    /**
76
     * @param string $entityFullyQualifiedName
77
     *
78
     * @throws DoctrineStaticMetaException
79
     */
80
    protected function createEntityTest(string $entityFullyQualifiedName): void
81
    {
82
        try {
83
            $abstractTestPath = $this->pathToProjectRoot . '/'
84
                                . $this->testSubFolderName
85
                                . '/' . AbstractGenerator::ENTITIES_FOLDER_NAME
86
                                . '/AbstractEntityTest.php';
87
            if (!$this->getFilesystem()->exists($abstractTestPath)) {
88
                $this->getFilesystem()->copy(self::ABSTRACT_ENTITY_TEST_TEMPLATE_PATH, $abstractTestPath);
89
                $this->fileCreationTransaction::setPathCreated($abstractTestPath);
90
                $this->findAndReplaceHelper->findReplace(
91
                    self::FIND_PROJECT_NAMESPACE,
92
                    rtrim($this->projectRootNamespace, '\\'),
93
                    $abstractTestPath
94
                );
95
            }
96
97
            $phpunitBootstrapPath = $this->pathToProjectRoot . '/'
98
                                    . $this->testSubFolderName . '/bootstrap.php';
99
            if (!$this->getFilesystem()->exists($phpunitBootstrapPath)) {
100
                $this->getFilesystem()->copy(self::PHPUNIT_BOOTSTRAP_TEMPLATE_PATH, $phpunitBootstrapPath);
101
                $this->fileCreationTransaction::setPathCreated($phpunitBootstrapPath);
102
            }
103
104
            list($filePath, $className, $namespace) = $this->parseAndCreate(
105
                $entityFullyQualifiedName . 'Test',
106
                $this->testSubFolderName,
107
                self::ENTITY_TEST_TEMPLATE_PATH
108
            );
109
            $this->findAndReplaceHelper->findReplace(
110
                self::FIND_ENTITIES_NAMESPACE,
111
                $this->namespaceHelper->tidy($namespace),
112
                $filePath
113
            );
114
115
            $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Test');
116
            $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
117
            $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace($namespace, $filePath);
118
            $this->findAndReplaceHelper->findReplace(
119
                'use FQNFor\AbstractEntityTest;',
120
                'use ' . $this->namespaceHelper->tidy(
121
                    $this->projectRootNamespace
122
                    . '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME
123
                    . '\\AbstractEntityTest;'
124
                ),
125
                $filePath
126
            );
127
        } catch (\Exception $e) {
128
            throw new DoctrineStaticMetaException(
129
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
130
                $e->getCode(),
131
                $e
132
            );
133
        }
134
    }
135
136
    /**
137
     * @throws DoctrineStaticMetaException
138
     */
139
    protected function parseAndCreate(
140
        string $fullyQualifiedName,
141
        string $subDir,
142
        string $templatePath
143
    ): array {
144
        try {
145
            list($className, $namespace, $subDirectories) = $this->parseFullyQualifiedName(
146
                $fullyQualifiedName,
147
                $subDir
148
            );
149
            $filePath = $this->pathHelper->copyTemplateAndGetPath(
150
                $this->pathToProjectRoot,
151
                $templatePath,
152
                $className,
153
                $subDirectories
154
            );
155
156
            return [$filePath, $className, $this->namespaceHelper->tidy($namespace)];
157
        } catch (\Exception $e) {
158
            throw new DoctrineStaticMetaException(
159
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
160
                $e->getCode(),
161
                $e
162
            );
163
        }
164
    }
165
166
    /**
167
     * @param string $entityFullyQualifiedName
168
     *
169
     * @throws DoctrineStaticMetaException
170
     */
171
    protected function createEntityRepository(string $entityFullyQualifiedName): void
172
    {
173
        try {
174
            $abstractRepositoryPath = $this->pathToProjectRoot
175
                                      . '/' . $this->srcSubFolderName
176
                                      . '/' . AbstractGenerator::ENTITY_REPOSITORIES_FOLDER_NAME
177
                                      . '/AbstractEntityRepository.php';
178
            if (!$this->getFilesystem()->exists($abstractRepositoryPath)) {
179
                $this->getFilesystem()->copy(
180
                    self::ABSTRACT_ENTITY_REPOSITORY_TEMPLATE_PATH,
181
                    $abstractRepositoryPath
182
                );
183
                $this->fileCreationTransaction::setPathCreated($abstractRepositoryPath);
184
                $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace(
185
                    $this->projectRootNamespace . '\\'
186
                    . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE,
187
                    $abstractRepositoryPath
188
                );
189
            }
190
            $entityRepositoryFqn = \str_replace(
191
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
192
                '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE . '\\',
193
                $entityFullyQualifiedName
194
            ) . 'Repository';
195
196
            list($filePath, $className, $namespace) = $this->parseAndCreate(
197
                $entityRepositoryFqn,
198
                $this->srcSubFolderName,
199
                self::REPOSITORIES_TEMPLATE_PATH
200
            );
201
            $this->findAndReplaceHelper->findReplace(
202
                self::FIND_ENTITY_REPOSITORIES_NAMESPACE,
203
                $this->namespaceHelper->tidy($namespace),
204
                $filePath
205
            );
206
            $classInterfaceNamespace = \str_replace(
207
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
208
                '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE . '\\',
209
                $entityFullyQualifiedName
210
            );
211
            $classInterface = preg_replace('#Repository$#', 'Interface', $className);
212
213
            $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Repository');
214
            $this->findAndReplaceHelper->replaceProjectNamespace($this->projectRootNamespace, $filePath);
215
            $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace($namespace, $filePath);
216
            $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($classInterfaceNamespace, $filePath);
217
            $this->findAndReplaceHelper->replaceName($classInterface, $filePath, self::FIND_ENTITY_NAME . 'Interface');
218
            $this->findAndReplaceHelper->findReplace(
219
                'use FQNFor\AbstractEntityRepository;',
220
                'use ' . $this->namespaceHelper->tidy(
221
                    $this->projectRootNamespace
222
                    . '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE
223
                    . '\\AbstractEntityRepository;'
224
                ),
225
                $filePath
226
            );
227
        } catch (\Exception $e) {
228
            throw new DoctrineStaticMetaException(
229
                'Exception in ' . __METHOD__ . ': ' . $e->getMessage(),
230
                $e->getCode(),
231
                $e
232
            );
233
        }
234
    }
235
236
    /**
237
     * Create an entity saver
238
     *
239
     * @param string $entityFqn
240
     *
241
     * @throws DoctrineStaticMetaException
242
     * @SuppressWarnings(PHPMD.StaticAccess)
243
     */
244
    protected function createEntitySaver(string $entityFqn): void
245
    {
246
        $entitySaverFqn = \str_replace(
247
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
248
            AbstractGenerator::ENTITY_SAVERS_NAMESPACE . '\\',
249
            $entityFqn
250
        ) . 'Saver';
251
252
253
        $entitySaver = new PhpClass();
254
        $entitySaver
255
            ->setQualifiedName($entitySaverFqn)
256
            ->setParentClassName('\\' . AbstractEntitySpecificSaver::class)
257
            ->setInterfaces(
258
                [
259
                    PhpInterface::fromFile(__DIR__ . '/../../Entity/Savers/EntitySaverInterface.php'),
260
                ]
261
            );
262
263
        list($className, , $subDirectories) = $this->parseFullyQualifiedName(
264
            $entitySaverFqn,
265
            $this->srcSubFolderName
266
        );
267
268
        $filePath = $this->createSubDirectoriesAndGetPath($subDirectories);
269
270
        $this->codeHelper->generate($entitySaver, $filePath . '/' . $className . '.php');
271
    }
272
273
    /**
274
     * @param string $entityFullyQualifiedName
275
     *
276
     * @throws DoctrineStaticMetaException
277
     */
278
    protected function createInterface(string $entityFullyQualifiedName): void
279
    {
280
        $entityInterfaceFqn = \str_replace(
281
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\',
282
            '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE . '\\',
283
            $entityFullyQualifiedName
284
        ) . 'Interface';
285
286
        list($className, $namespace, $subDirectories) = $this->parseFullyQualifiedName(
287
            $entityInterfaceFqn,
288
            $this->srcSubFolderName
289
        );
290
291
        $filePath = $this->pathHelper->copyTemplateAndGetPath(
292
            $this->pathToProjectRoot,
293
            self::ENTITY_INTERFACE_TEMPLATE_PATH,
294
            $className,
295
            $subDirectories
296
        );
297
298
        $this->findAndReplaceHelper->replaceName($className, $filePath, self::FIND_ENTITY_NAME . 'Interface');
299
        $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($namespace, $filePath);
300
    }
301
302
    protected function createEntity(
303
        string $entityFullyQualifiedName
304
    ): string {
305
        list($filePath, $className, $namespace) = $this->parseAndCreate(
306
            $entityFullyQualifiedName,
307
            $this->srcSubFolderName,
308
            self::ENTITY_TEMPLATE_PATH
309
        );
310
        $this->findAndReplaceHelper->replaceName($className, $filePath, static::FIND_ENTITY_NAME);
311
        $this->findAndReplaceHelper->replaceEntitiesNamespace($namespace, $filePath);
312
        $this->findAndReplaceHelper->replaceEntityRepositoriesNamespace(
313
            \str_replace(
314
                '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME,
315
                '\\' . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE,
316
                $namespace
317
            ),
318
            $filePath
319
        );
320
321
        if ($this->getUseUuidPrimaryKey()) {
322
            $this->findAndReplaceHelper->findReplace(
323
                'IdFieldTrait',
324
                'UuidFieldTrait',
325
                $filePath
326
            );
327
        }
328
329
        $interfaceNamespace = \str_replace(
330
            '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME,
331
            '\\' . AbstractGenerator::ENTITY_INTERFACE_NAMESPACE,
332
            $namespace
333
        );
334
335
        $this->findAndReplaceHelper->replaceEntityInterfaceNamespace($interfaceNamespace, $filePath);
336
337
        return $filePath;
338
    }
339
340
    public function getUseUuidPrimaryKey(): bool
341
    {
342
        return $this->useUuidPrimaryKey;
343
    }
344
345
    public function setUseUuidPrimaryKey(bool $useUuidPrimaryKey): self
346
    {
347
        $this->useUuidPrimaryKey = $useUuidPrimaryKey;
348
349
        return $this;
350
    }
351
352
    /**
353
     * Create the abstract entity repository factory if it doesn't currently exist
354
     */
355
    protected function createAbstractEntityRepositoryFactory(): void
356
    {
357
        $abstractRepositoryFactoryPath = $this->pathToProjectRoot
358
                                         . '/' . $this->srcSubFolderName
359
                                         . '/' . AbstractGenerator::ENTITY_REPOSITORIES_FOLDER_NAME
360
                                         . '/AbstractEntityRepositoryFactory.php';
361
362
        if ($this->getFilesystem()->exists($abstractRepositoryFactoryPath)) {
363
            return;
364
        }
365
366
        $abstractFactoryFqn = $this->projectRootNamespace
367
                              . AbstractGenerator::ENTITY_REPOSITORIES_NAMESPACE
368
                              . '\\AbstractEntityRepositoryFactory';
369
370
        $abstractFactory = new PhpClass();
371
        $abstractFactory
372
            ->setUseStatements([AbstractEntityRepository::class . ' as DSMRepositoryFactory'])
373
            ->setQualifiedName($abstractFactoryFqn)
374
            ->setParentClassName('DSMRepositoryFactory');
375
376
        $this->codeHelper->generate($abstractFactory, $abstractRepositoryFactoryPath);
377
    }
378
}
379