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 ( dbbb5b...810b23 )
by joseph
13s queued 10s
created

FieldGenerator::setupClassProperties()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 5.0205

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 29
cts 32
cp 0.9063
rs 8.7143
c 0
b 0
f 0
cc 5
nc 10
nop 5
crap 5.0205

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FileCreationTransaction;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FindAndReplaceHelper;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\PathHelper;
11
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\TypeHelper;
12
use EdmondsCommerce\DoctrineStaticMeta\Config;
13
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\ApprovedFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...lean\ApprovedFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\DefaultFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...olean\DefaultFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\DefaultsDisabledFieldTrait;
16
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\DefaultsEnabledFieldTrait;
17
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\DefaultsNullFieldTrait;
18
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\DateTime\DateTimeSettableNoDefaultFieldTrait;
19
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\DateTime\DateTimeSettableOnceFieldTrait;
20
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\BusinessIdentifierCodeFieldTrait;
21
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\CountryCodeFieldTrait;
22
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\EmailAddressFieldTrait;
23
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\IpAddressFieldTrait;
24
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\IsbnFieldTrait;
25
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\LocaleIdentifierFieldTrait;
26
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\NullableStringFieldTrait;
27
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\SettableUuidFieldTrait;
28
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\UnicodeLanguageIdentifierFieldTrait;
29
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\UniqueStringFieldTrait;
30
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\UrlFieldTrait;
31
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\TimeStamp\ActionedDateFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...\ActionedDateFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\TimeStamp\ActivatedDateFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...ActivatedDateFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\TimeStamp\CompletedDateFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...CompletedDateFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\TimeStamp\CreationTimestampFieldTrait;
35
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\TimeStamp\DeactivatedDateFieldTrait;
0 ignored issues
show
Bug introduced by
The type EdmondsCommerce\Doctrine...activatedDateFieldTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
37
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
38
use Symfony\Component\Filesystem\Filesystem;
39
40
/**
41
 * Class FieldGenerator
42
 *
43
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator
44
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
45
 */
46
class FieldGenerator extends AbstractGenerator
47
{
48
    public const FIELD_TRAIT_SUFFIX = 'FieldTrait';
49
50
    /**
51
     * @var string
52
     */
53
    protected $fieldsPath;
54
55
    /**
56
     * @var string
57
     */
58
    protected $fieldsInterfacePath;
59
60
    /**
61
     * @var string
62
     */
63
    protected $phpType;
64
65
    /**
66
     * @var string
67
     */
68
    protected $fieldType;
69
70
    /**
71
     * Are we currently generating an archetype based field?
72
     *
73
     * @var bool
74
     */
75
    protected $isArchetype = false;
76
77
    /**
78
     * @var bool
79
     */
80
    protected $isNullable;
81
82
    /**
83
     * @var bool
84
     */
85
    protected $isUnique;
86
87
    /**
88
     * @var mixed
89
     */
90
    protected $defaultValue;
91
92
    /**
93
     * @var string
94
     */
95
    protected $traitNamespace;
96
97
    /**
98
     * @var string
99
     */
100
    protected $interfaceNamespace;
101
102
    public const STANDARD_FIELDS = [
103
        DefaultsDisabledFieldTrait::class,
104
        DefaultsEnabledFieldTrait::class,
105
        DefaultsNullFieldTrait::class,
106
        DateTimeSettableNoDefaultFieldTrait::class,
107
        DateTimeSettableOnceFieldTrait::class,
108
        BusinessIdentifierCodeFieldTrait::class,
109
        CountryCodeFieldTrait::class,
110
        EmailAddressFieldTrait::class,
111
        IpAddressFieldTrait::class,
112
        IsbnFieldTrait::class,
113
        LocaleIdentifierFieldTrait::class,
114
        NullableStringFieldTrait::class,
115
        SettableUuidFieldTrait::class,
116
        UnicodeLanguageIdentifierFieldTrait::class,
117
        UniqueStringFieldTrait::class,
118
        UrlFieldTrait::class,
119
        CreationTimestampFieldTrait::class,
120
    ];
121
122
    /**
123
     * @var TypeHelper
124
     */
125
    protected $typeHelper;
126
    /**
127
     * @var ArchetypeFieldGenerator
128
     */
129
    protected $archetypeFieldCopier;
130
    /**
131
     * @var string
132
     */
133
    protected $fieldFqn;
134
    /**
135
     * @var string
136
     */
137
    protected $className;
138
139
140 36
    public function __construct(
141
        Filesystem $filesystem,
142
        FileCreationTransaction $fileCreationTransaction,
143
        NamespaceHelper $namespaceHelper,
144
        Config $config,
145
        CodeHelper $codeHelper,
146
        PathHelper $pathHelper,
147
        FindAndReplaceHelper $findAndReplaceHelper,
148
        TypeHelper $typeHelper
149
    ) {
150 36
        parent::__construct(
151 36
            $filesystem,
152 36
            $fileCreationTransaction,
153 36
            $namespaceHelper,
154 36
            $config,
155 36
            $codeHelper,
156 36
            $pathHelper,
157 36
            $findAndReplaceHelper
158
        );
159 36
        $this->typeHelper = $typeHelper;
160 36
    }
161
162
163
    /**
164
     * Generate a new Field based on a property name and Doctrine Type or Archetype field FQN
165
     *
166
     * @see MappingHelper::ALL_DBAL_TYPES for the full list of Dbal Types
167
     *
168
     * @param string      $fieldFqn
169
     * @param string      $fieldType
170
     * @param null|string $phpType
171
     *
172
     * @param mixed       $defaultValue
173
     * @param bool        $isUnique
174
     *
175
     * @return string - The Fully Qualified Name of the generated Field Trait
176
     *
177
     * @throws DoctrineStaticMetaException
178
     * @throws \ReflectionException
179
     * @SuppressWarnings(PHPMD.StaticAccess)
180
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
181
     */
182 35
    public function generateField(
183
        string $fieldFqn,
184
        string $fieldType,
185
        ?string $phpType = null,
186
        $defaultValue = null,
187
        bool $isUnique = false
188
    ): string {
189 35
        $this->validateArguments($fieldFqn, $fieldType, $phpType);
190 31
        $this->setupClassProperties($fieldFqn, $fieldType, $phpType, $defaultValue, $isUnique);
191
192 31
        $this->pathHelper->ensurePathExists($this->fieldsPath);
193 31
        $this->pathHelper->ensurePathExists($this->fieldsInterfacePath);
194
195 31
        $this->assertFileDoesNotExist($this->getTraitPath(), 'Trait');
196 31
        $this->assertFileDoesNotExist($this->getInterfacePath(), 'Interface');
197
198 31
        if (true === $this->isArchetype) {
199 4
            return $this->createFieldFromArchetype();
200
        }
201
202 29
        return $this->createDbalField();
203
    }
204
205 31
    protected function getTraitPath(): string
206
    {
207 31
        return $this->fieldsPath.'/'.$this->codeHelper->classy($this->className).'FieldTrait.php';
208
    }
209
210
211 31
    protected function getInterfacePath(): string
212
    {
213 31
        return $this->fieldsInterfacePath.'/'.$this->codeHelper->classy($this->className).'FieldInterface.php';
214
    }
215
216
    /**
217
     * @return string
218
     * @throws DoctrineStaticMetaException
219
     */
220 29
    protected function createDbalField(): string
221
    {
222 29
        $creator = new DbalFieldGenerator(
223 29
            $this->fileSystem,
224 29
            $this->codeHelper,
225 29
            $this->fileCreationTransaction,
226 29
            $this->findAndReplaceHelper,
227 29
            $this->typeHelper,
228 29
            $this->pathHelper
229
        );
230
231 29
        return $creator->create(
232 29
            $this->className,
233 29
            $this->getTraitPath(),
234 29
            $this->getInterfacePath(),
235 29
            $this->fieldType,
236 29
            $this->defaultValue,
237 29
            $this->isUnique,
238 29
            $this->phpType,
239 29
            $this->traitNamespace,
240 29
            $this->interfaceNamespace
241
        );
242
    }
243
244
    /**
245
     * @return string
246
     * @throws \ReflectionException
247
     */
248 4
    protected function createFieldFromArchetype(): string
249
    {
250 4
        $copier = new ArchetypeFieldGenerator(
251 4
            $this->fileSystem,
252 4
            $this->namespaceHelper,
253 4
            $this->codeHelper,
254 4
            $this->findAndReplaceHelper
255
        );
256
257 4
        return $copier->createFromArchetype(
258 4
                $this->fieldFqn,
259 4
                $this->getTraitPath(),
260 4
                $this->getInterfacePath(),
261 4
                '\\'.$this->fieldType,
262 4
                $this->projectRootNamespace
263 4
            ).self::FIELD_TRAIT_SUFFIX;
264
    }
265
266 35
    protected function validateArguments(
267
        string $fieldFqn,
268
        string $fieldType,
269
        ?string $phpType
270
    ): void {
271
        //Check for a correct looking field FQN
272 35
        if (false === \strpos($fieldFqn, AbstractGenerator::ENTITY_FIELD_TRAIT_NAMESPACE)) {
273 1
            throw new \InvalidArgumentException(
274 1
                'Fully qualified name [ '.$fieldFqn.' ]'
275 1
                .' does not include [ '.AbstractGenerator::ENTITY_FIELD_TRAIT_NAMESPACE.' ].'."\n"
276 1
                .'Please ensure you pass in the full namespace qualified field name'
277
            );
278
        }
279
        //Check that the field type is either a Dbal Type or a Field Archetype FQN
280 34
        if (false === \in_array(\strtolower($fieldType), MappingHelper::ALL_DBAL_TYPES, true)
281 34
            && false === \in_array($fieldType, self::STANDARD_FIELDS, true)
282 34
            && false === $this->traitFqnLooksLikeField($fieldType)
283
        ) {
284
            throw new \InvalidArgumentException(
285
                'fieldType '.$fieldType.' is not a valid field type'
286
            );
287
        }
288
        //Check the phpType is valid
289 33
        if ((null !== $phpType)
290 33
            && (false === \in_array($phpType, MappingHelper::PHP_TYPES, true))
291
        ) {
292 2
            throw new \InvalidArgumentException(
293 2
                'phpType must be either null or one of MappingHelper::PHP_TYPES'
294
            );
295
        }
296 31
    }
297
298
    /**
299
     * Does the specified trait FQN look like a field trait?
300
     *
301
     * @param string $traitFqn
302
     *
303
     * @return bool
304
     * @throws \ReflectionException
305
     */
306 2
    protected function traitFqnLooksLikeField(string $traitFqn): bool
307
    {
308
        try {
309 2
            $reflection = new \ReflectionClass($traitFqn);
310 1
        } catch (\ReflectionException $e) {
311 1
            throw new \InvalidArgumentException(
312 1
                'invalid traitFqn '.$traitFqn.' does not seem to exist',
313 1
                $e->getCode(),
314 1
                $e
315
            );
316
        }
317 1
        if (true !== $reflection->isTrait()) {
318
            throw new \InvalidArgumentException('field type is not a trait FQN');
319
        }
320 1
        if ('FieldTrait' !== \substr($traitFqn, -\strlen('FieldTrait'))) {
321
            throw new \InvalidArgumentException('traitFqn does not end in FieldTrait');
322
        }
323
324 1
        return true;
325
    }
326
327
    /**
328
     * Defining the properties for the field to be generated
329
     *
330
     * @param string      $fieldFqn
331
     * @param string      $fieldType
332
     * @param null|string $phpType
333
     * @param mixed       $defaultValue
334
     * @param bool        $isUnique
335
     *
336
     * @throws DoctrineStaticMetaException
337
     * @SuppressWarnings(PHPMD.StaticAccess)
338
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
339
     */
340 31
    protected function setupClassProperties(
341
        string $fieldFqn,
342
        string $fieldType,
343
        ?string $phpType,
344
        $defaultValue,
345
        bool $isUnique
346
    ): void {
347 31
        $this->isArchetype = false;
348 31
        $this->fieldType   = \strtolower($fieldType);
349 31
        if (true !== \in_array($this->fieldType, MappingHelper::COMMON_TYPES, true)) {
350 4
            $this->isArchetype = true;
351 4
            $this->fieldType   = $fieldType;
352
        }
353 31
        $this->phpType      = $phpType ?? $this->getPhpTypeForDbalType();
354 31
        $this->defaultValue = $this->typeHelper->normaliseValueToType($defaultValue, $this->phpType);
355
356 31
        if (null !== $this->defaultValue) {
357 1
            $defaultValueType = $this->typeHelper->getType($this->defaultValue);
358 1
            if ($defaultValueType !== $this->phpType) {
359
                throw new \InvalidArgumentException(
360
                    'default value '.$this->defaultValue.' has the type: '.$defaultValueType
361
                    .' whereas the phpType for this field has been set as '.$this->phpType.', these do not match up'
362
                );
363
            }
364
        }
365 31
        $this->isNullable = (null === $defaultValue);
366 31
        $this->isUnique   = $isUnique;
367
368 31
        if (\substr($fieldFqn, -\strlen(self::FIELD_TRAIT_SUFFIX)) === self::FIELD_TRAIT_SUFFIX) {
369 4
            $fieldFqn = \substr($fieldFqn, 0, -\strlen(self::FIELD_TRAIT_SUFFIX));
370
        }
371 31
        $this->fieldFqn = $fieldFqn;
372
373 31
        list($className, $traitNamespace, $traitSubDirectories) = $this->parseFullyQualifiedName(
374 31
            $fieldFqn,
375 31
            $this->srcSubFolderName
376
        );
377 31
        $this->className = $className;
378 31
        list(, $interfaceNamespace, $interfaceSubDirectories) = $this->parseFullyQualifiedName(
379 31
            \str_replace('Traits', 'Interfaces', $fieldFqn),
380 31
            $this->srcSubFolderName
381
        );
382
383 31
        $this->fieldsPath = $this->pathHelper->resolvePath(
384 31
            $this->pathToProjectRoot.'/'.\implode('/', $traitSubDirectories)
385
        );
386
387 31
        $this->fieldsInterfacePath = $this->pathHelper->resolvePath(
388 31
            $this->pathToProjectRoot.'/'.\implode('/', $interfaceSubDirectories)
389
        );
390
391 31
        $this->traitNamespace     = $traitNamespace;
392 31
        $this->interfaceNamespace = $interfaceNamespace;
393 31
    }
394
395 31
    private function assertFileDoesNotExist(string $filePath, string $type): void
396
    {
397 31
        if (file_exists($filePath)) {
398 1
            throw new \RuntimeException("Field $type already exists at $filePath");
399
        }
400 31
    }
401
402
    /**
403
     * @return string
404
     * @throws DoctrineStaticMetaException
405
     *
406
     */
407 31
    protected function getPhpTypeForDbalType(): string
408
    {
409 31
        if (true === $this->isArchetype) {
410 4
            return '';
411
        }
412 29
        if (!\in_array($this->fieldType, MappingHelper::COMMON_TYPES, true)) {
413
            throw new DoctrineStaticMetaException(
414
                'Field type of '.$this->fieldType.' is not one of MappingHelper::COMMON_TYPES'
415
                ."\n\nYou can only use this fieldType type if you pass in the explicit phpType as well "
416
                ."\n\nAlternatively, suggest you set the type as string and then edit the generated code as you see fit"
417
            );
418
        }
419
420 29
        return MappingHelper::COMMON_TYPES_TO_PHP_TYPES[$this->fieldType];
421
    }
422
}
423