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 ( 810b23...1b23c8 )
by joseph
12s
created

DbalFieldGenerator::generateTrait()   A

Complexity

Conditions 2
Paths 12

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 2.041

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 18
cts 23
cp 0.7826
rs 9.472
c 0
b 0
f 0
cc 2
nc 12
nop 0
crap 2.041
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field;
4
5
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FileCreationTransaction;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FindAndReplaceHelper;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PathHelper;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\TypeHelper;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\UsesPHPMetaDataInterface;
12
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
13
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
14
use gossi\codegen\model\PhpMethod;
15
use gossi\codegen\model\PhpParameter;
16
use gossi\codegen\model\PhpTrait;
17
use gossi\docblock\Docblock;
18
use gossi\docblock\tags\UnknownTag;
19
use Symfony\Component\Filesystem\Filesystem;
20
21
/**
22
 * Class DbalFieldGenerator
23
 *
24
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field
25
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26
 * @SuppressWarnings(PHPMD.TooManyFields)
27
 */
28
class DbalFieldGenerator
29
{
30
    /**
31
     * @var string
32
     */
33
    protected $traitPath;
34
    /**
35
     * @var string
36
     */
37
    protected $interfacePath;
38
    /**
39
     * @var null|string
40
     */
41
    protected $phpType;
42
    /**
43
     * @var null
44
     */
45
    protected $defaultValue;
46
    /**
47
     * @var bool
48
     */
49
    protected $isUnique;
50
    /**
51
     * @var bool
52
     */
53
    protected $isNullable;
54
    /**
55
     * @var string
56
     */
57
    protected $dbalType;
58
    /**
59
     * @var Filesystem
60
     */
61
    protected $fileSystem;
62
    /**
63
     * @var CodeHelper
64
     */
65
    protected $codeHelper;
66
    /**
67
     * @var FileCreationTransaction
68
     */
69
    protected $fileCreationTransaction;
70
    /**
71
     * @var FindAndReplaceHelper
72
     */
73
    protected $findAndReplaceHelper;
74
    /**
75
     * @var string
76
     */
77
    protected $className;
78
    /**
79
     * @var TypeHelper
80
     */
81
    protected $typeHelper;
82
    /**
83
     * @var string
84
     */
85
    protected $traitNamespace;
86
    /**
87
     * @var string
88
     */
89
    protected $interfaceNamespace;
90
    /**
91
     * @var PathHelper
92
     */
93
    protected $pathHelper;
94
95 29
    public function __construct(
96
        Filesystem $fileSystem,
97
        CodeHelper $codeHelper,
98
        FileCreationTransaction $fileCreationTransaction,
99
        FindAndReplaceHelper $findAndReplaceHelper,
100
        TypeHelper $typeHelper,
101
        PathHelper $pathHelper
102
    ) {
103 29
        $this->fileSystem              = $fileSystem;
104 29
        $this->codeHelper              = $codeHelper;
105 29
        $this->fileCreationTransaction = $fileCreationTransaction;
106 29
        $this->findAndReplaceHelper    = $findAndReplaceHelper;
107 29
        $this->typeHelper              = $typeHelper;
108 29
        $this->pathHelper              = $pathHelper;
109 29
    }
110
111
    /**
112
     * @param string      $className
113
     * @param string      $traitPath
114
     * @param string      $interfacePath
115
     * @param string      $dbalType
116
     * @param null        $defaultValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $defaultValue is correct as it would always require null to be passed?
Loading history...
117
     * @param bool        $isUnique
118
     * @param null|string $phpType
119
     *
120
     * @param string      $traitNamespace
121
     * @param string      $interfaceNamespace
122
     *
123
     * @return string
124
     * @throws DoctrineStaticMetaException
125
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
126
     */
127 29
    public function create(
128
        string $className,
129
        string $traitPath,
130
        string $interfacePath,
131
        string $dbalType,
132
        $defaultValue = null,
133
        bool $isUnique = false,
134
        ?string $phpType = null,
135
        string $traitNamespace,
136
        string $interfaceNamespace
137
    ): string {
138 29
        $this->traitPath          = $traitPath;
139 29
        $this->interfacePath      = $interfacePath;
140 29
        $this->phpType            = $phpType;
141 29
        $this->defaultValue       = $defaultValue;
142 29
        $this->isUnique           = $isUnique;
143 29
        $this->isNullable         = (null === $defaultValue);
144 29
        $this->dbalType           = $dbalType;
145 29
        $this->className          = $className;
146 29
        $this->traitNamespace     = $traitNamespace;
147 29
        $this->interfaceNamespace = $interfaceNamespace;
148 29
        $this->generateInterface();
149
150 29
        return $this->generateTrait();
151
    }
152
153
    /**
154
     * @throws DoctrineStaticMetaException
155
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
156
     */
157 29
    protected function generateInterface(): void
158
    {
159
        try {
160 29
            $this->fileSystem->copy(
161 29
                $this->pathHelper->resolvePath(FieldGenerator::FIELD_INTERFACE_TEMPLATE_PATH),
162 29
                $this->interfacePath
163
            );
164 29
            $this->interfacePostCopy($this->interfacePath);
165 29
            $this->codeHelper->replaceTypeHintsInFile(
166 29
                $this->interfacePath,
167 29
                $this->phpType,
0 ignored issues
show
Bug introduced by
It seems like $this->phpType can also be of type null; however, parameter $type of EdmondsCommerce\Doctrine...eplaceTypeHintsInFile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

167
                /** @scrutinizer ignore-type */ $this->phpType,
Loading history...
168 29
                $this->dbalType,
169 29
                $this->isNullable
170
            );
171
        } catch (\Exception $e) {
172
            throw new DoctrineStaticMetaException(
173
                'Error in '.__METHOD__.': '.$e->getMessage(),
174
                $e->getCode(),
175
                $e
176
            );
177
        }
178 29
    }
179
180
    /**
181
     * @param string $filePath
182
     *
183
     * @throws \RuntimeException
184
     * @throws DoctrineStaticMetaException
185
     */
186 29
    protected function postCopy(
187
        string $filePath
188
    ): void {
189 29
        $this->fileCreationTransaction::setPathCreated($filePath);
190 29
        $this->findAndReplaceHelper->replaceName(
191 29
            $this->codeHelper->classy($this->className),
192 29
            $filePath,
193 29
            FieldGenerator::FIND_ENTITY_FIELD_NAME
194
        );
195 29
        $this->findAndReplaceHelper->findReplace(
196 29
            $this->codeHelper->consty(FieldGenerator::FIND_ENTITY_FIELD_NAME),
197 29
            $this->codeHelper->consty($this->className),
198 29
            $filePath
199
        );
200 29
        $this->codeHelper->tidyNamespacesInFile($filePath);
201 29
        $this->setGetterToIsForBools($filePath);
202 29
    }
203
204
205 29
    protected function setGetterToIsForBools(
206
        string $filePath
207
    ): void {
208 29
        if ($this->phpType !== 'bool') {
209 29
            return;
210
        }
211 17
        $replaceName = $this->codeHelper->getGetterMethodNameForBoolean($this->codeHelper->classy($this->className));
212 17
        $findName    = 'get'.$this->codeHelper->classy($this->className);
213 17
        $this->findAndReplaceHelper->findReplace($findName, $replaceName, $filePath);
214 17
    }
215
216
217
    /**
218
     * @param string $filePath
219
     *
220
     * @throws \RuntimeException
221
     * @throws DoctrineStaticMetaException
222
     */
223 29
    protected function traitPostCopy(
224
        string $filePath
225
    ): void {
226 29
        $this->findAndReplaceHelper->replaceFieldTraitNamespace($this->traitNamespace, $filePath);
227 29
        $this->findAndReplaceHelper->replaceFieldInterfaceNamespace($this->interfaceNamespace, $filePath);
228 29
        $this->postCopy($filePath);
229 29
    }
230
231
    /**
232
     * @param string $filePath
233
     *
234
     * @throws DoctrineStaticMetaException
235
     */
236 29
    protected function interfacePostCopy(
237
        string $filePath
238
    ): void {
239 29
        $this->findAndReplaceHelper->replaceFieldInterfaceNamespace($this->interfaceNamespace, $filePath);
240 29
        $this->replaceDefaultValueInInterface($filePath);
241 29
        $this->postCopy($filePath);
242 29
    }
243
244
    /**
245
     * @param string $filePath
246
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
247
     */
248 29
    protected function replaceDefaultValueInInterface(
249
        string $filePath
250
    ): void {
251 29
        $defaultType = $this->typeHelper->getType($this->defaultValue);
252
        switch (true) {
253 29
            case $defaultType === 'null':
254 28
                $replace = 'null';
255 28
                break;
256 1
            case $this->phpType === 'string':
257
                $replace = "'$this->defaultValue'";
258
                break;
259 1
            case $this->phpType === 'bool':
260 1
                $replace = true === $this->defaultValue ? 'true' : 'false';
261 1
                break;
262 1
            case $this->phpType === 'float':
263 1
                $replace = (string)$this->defaultValue;
264 1
                if (false === strpos($replace, '.')) {
265 1
                    $replace .= '.0';
266
                }
267 1
                break;
268 1
            case $this->phpType === 'int':
269 1
                $replace = (string)$this->defaultValue;
270 1
                break;
271
            case $this->phpType === 'DateTime':
272
                if ($this->defaultValue !== null) {
273
                    throw new \InvalidArgumentException(
274
                        'Invalid default value '.$this->defaultValue
275
                        .'Currently we only support null as a default for DateTime'
276
                    );
277
                }
278
                $replace = 'null';
279
                break;
280
            default:
281
                throw new \RuntimeException(
282
                    'failed to calculate replace based on defaultType '.$defaultType
283
                    .' and phpType '.$this->phpType.' in '.__METHOD__
284
                );
285
        }
286 29
        $this->findAndReplaceHelper->findReplace("'defaultValue'", $replace, $filePath);
287 29
    }
288
289
290
    /**
291
     * @return string
292
     * @throws DoctrineStaticMetaException
293
     * @SuppressWarnings(PHPMD.StaticAccess)
294
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
295
     */
296 29
    protected function generateTrait(): string
297
    {
298
        try {
299 29
            $this->fileSystem->copy(
300 29
                $this->pathHelper->resolvePath(FieldGenerator::FIELD_TRAIT_TEMPLATE_PATH),
301 29
                $this->traitPath
302
            );
303 29
            $this->fileCreationTransaction::setPathCreated($this->traitPath);
304 29
            $this->traitPostCopy($this->traitPath);
305 29
            $trait = PhpTrait::fromFile($this->traitPath);
306 29
            $trait->setMethod($this->getPropertyMetaMethod());
307 29
            $trait->addUseStatement('\\'.MappingHelper::class);
308 29
            $trait->addUseStatement('\\'.ClassMetadataBuilder::class);
309 29
            $this->codeHelper->generate($trait, $this->traitPath);
310 29
            $this->codeHelper->replaceTypeHintsInFile(
311 29
                $this->traitPath,
312 29
                $this->phpType,
0 ignored issues
show
Bug introduced by
It seems like $this->phpType can also be of type null; however, parameter $type of EdmondsCommerce\Doctrine...eplaceTypeHintsInFile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

312
                /** @scrutinizer ignore-type */ $this->phpType,
Loading history...
313 29
                $this->dbalType,
314 29
                $this->isNullable
315
            );
316 29
            $this->breakUpdateCallOntoMultipleLines();
317
318 29
            return $trait->getQualifiedName();
319
        } catch (\Exception $e) {
320
            throw new DoctrineStaticMetaException(
321
                'Error in '.__METHOD__.': '.$e->getMessage(),
322
                $e->getCode(),
323
                $e
324
            );
325
        }
326
    }
327
328 29
    private function breakUpdateCallOntoMultipleLines()
329
    {
330 29
        $contents = \file_get_contents($this->traitPath);
331 29
        $indent='            ';
332 29
        $updated  = \preg_replace(
333
            [
334 29
                '%updatePropertyValueThenValidateAndNotify\((.+?),(.+?)\)%',
335
            ],
336
            [
337 29
                "updatePropertyValueThenValidateAndNotify(\n$indent\$1,\n$indent\$2\n        )",
338
            ],
339 29
            $contents
340
        );
341 29
        \file_put_contents($this->traitPath, $updated);
342 29
    }
343
344
    /**
345
     * @return PhpMethod
346
     * @SuppressWarnings(PHPMD.StaticAccess)
347
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
348
     */
349 29
    protected function getPropertyMetaMethod(): PhpMethod
350
    {
351 29
        $classy = $this->codeHelper->classy($this->className);
352 29
        $consty = $this->codeHelper->consty($this->className);
353 29
        $name   = UsesPHPMetaDataInterface::METHOD_PREFIX_GET_PROPERTY_DOCTRINE_META.$classy;
354 29
        $method = PhpMethod::create($name);
355 29
        $method->setStatic(true);
356 29
        $method->setVisibility('public');
357 29
        $method->setParameters(
358 29
            [PhpParameter::create('builder')->setType('ClassMetadataBuilder')]
359
        );
360 29
        $mappingHelperMethodName = 'setSimple'.ucfirst(strtolower($this->dbalType)).'Fields';
361
362
        $methodBody = "
363 29
        MappingHelper::$mappingHelperMethodName(
364 29
            [{$classy}FieldInterface::PROP_{$consty}],
365
            \$builder,
366 29
            {$classy}FieldInterface::DEFAULT_{$consty}
367
        );                        
368
";
369 29
        if (\in_array($this->dbalType, MappingHelper::UNIQUEABLE_TYPES, true)) {
370 29
            $isUniqueString = $this->isUnique ? 'true' : 'false';
371
            $methodBody     = "
372 29
        MappingHelper::$mappingHelperMethodName(
373 29
            [{$classy}FieldInterface::PROP_{$consty}],
374
            \$builder,
375 29
            {$classy}FieldInterface::DEFAULT_{$consty},
376 29
            $isUniqueString
377
        );                        
378
";
379
        }
380 29
        $method->setBody($methodBody);
381 29
        $method->setDocblock(
382 29
            Docblock::create()
383 29
                    ->appendTag(
384 29
                        UnknownTag::create('SuppressWarnings(PHPMD.StaticAccess)')
385
                    )
386
        );
387
388 29
        return $method;
389
    }
390
391
    /**
392
     * @return PhpMethod
393
     * @SuppressWarnings(PHPMD.StaticAccess)
394
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
395
     */
396
    protected function getPropertyMetaMethodForDatetime(): PhpMethod
397
    {
398
        $classy = $this->codeHelper->classy($this->className);
399
        $consty = $this->codeHelper->consty($this->className);
400
        $name   = UsesPHPMetaDataInterface::METHOD_PREFIX_GET_PROPERTY_DOCTRINE_META.$classy;
401
        $method = PhpMethod::create($name);
402
        $method->setStatic(true);
403
        $method->setVisibility('public');
404
        $method->setParameters(
405
            [PhpParameter::create('builder')->setType('ClassMetadataBuilder')]
406
        );
407
        $mappingHelperMethodName = 'setSimple'.ucfirst(strtolower($this->dbalType)).'Fields';
408
409
        $methodBody = "
410
        MappingHelper::$mappingHelperMethodName(
411
            [{$classy}FieldInterface::PROP_{$consty}],
412
            \$builder,
413
            {$classy}FieldInterface::DEFAULT_{$consty}
414
        );                        
415
";
416
        if (\in_array($this->dbalType, MappingHelper::UNIQUEABLE_TYPES, true)) {
417
            $isUniqueString = $this->isUnique ? 'true' : 'false';
418
            $methodBody     = "
419
        MappingHelper::$mappingHelperMethodName(
420
            [{$classy}FieldInterface::PROP_{$consty}],
421
            \$builder,
422
            {$classy}FieldInterface::DEFAULT_{$consty},
423
            $isUniqueString
424
        );                        
425
";
426
        }
427
        $method->setBody($methodBody);
428
        $method->setDocblock(
429
            Docblock::create()
430
                    ->appendTag(
431
                        UnknownTag::create('SuppressWarnings(PHPMD.StaticAccess)')
432
                    )
433
        );
434
435
        return $method;
436
    }
437
}
438