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 ( 149ff2...b9f286 )
by Ross
13s
created

EntityGenerator::createInterface()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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