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 (#57)
by joseph
16:59
created

EntityGenerator::generateEntity()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 7.7355

Importance

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