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 ( 0a6f96...b0c756 )
by Ross
12s queued 10s
created

EntityGenerator::createEntitySaver()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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