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 (#51)
by joseph
06:58
created

EntityGenerator::parseAndCreate()   A

Complexity

Conditions 2
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.0185

Importance

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