Failed Conditions
Push — master ( fa7802...d60694 )
by Guilherme
09:27
created

FieldMetadataBuilder::build()   D

Complexity

Conditions 18
Paths 166

Size

Total Lines 100
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 51
CRAP Score 19.8088

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 18
eloc 62
c 2
b 0
f 0
nc 166
nop 0
dl 0
loc 100
ccs 51
cts 62
cp 0.8226
crap 19.8088
rs 4.3166

How to fix   Long Method    Complexity   

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
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping\Builder;
6
7
use Doctrine\DBAL\Types\Type;
8
use Doctrine\ORM\Annotation;
9
use Doctrine\ORM\Mapping;
10
use function array_merge;
11
use function assert;
12
13
class FieldMetadataBuilder
14
{
15
    /** @var Mapping\ClassMetadataBuildingContext */
16
    private $metadataBuildingContext;
17
18
    /** @var ValueGeneratorMetadataBuilder */
19
    private $valueGeneratorMetadataBuilder;
20
21
    /** @var Mapping\ClassMetadata */
22
    private $componentMetadata;
23
24
    /** @var string */
25
    private $fieldName;
26
27
    /** @var Annotation\Column */
28
    private $columnAnnotation;
29
30
    /** @var Annotation\Id|null */
31
    private $idAnnotation;
32
33
    /** @var Annotation\Version|null */
34
    private $versionAnnotation;
35
36
    /** @var Annotation\GeneratedValue|null */
37
    private $generatedValueAnnotation;
38
39
    /** @var Annotation\SequenceGenerator|null */
40
    private $sequenceGeneratorAnnotation;
41
42
    /** @var Annotation\CustomIdGenerator|null */
43
    private $customIdGeneratorAnnotation;
44
45 401
    public function __construct(
46
        Mapping\ClassMetadataBuildingContext $metadataBuildingContext,
47
        ?ValueGeneratorMetadataBuilder $valueGeneratorMetadataBuilder = null
48
    ) {
49 401
        $this->metadataBuildingContext       = $metadataBuildingContext;
50 401
        $this->valueGeneratorMetadataBuilder = $valueGeneratorMetadataBuilder ?: new ValueGeneratorMetadataBuilder($metadataBuildingContext);
51 401
    }
52
53 401
    public function withComponentMetadata(Mapping\ClassMetadata $componentMetadata) : FieldMetadataBuilder
54
    {
55 401
        $this->componentMetadata = $componentMetadata;
56
57 401
        return $this;
58
    }
59
60 397
    public function withFieldName(string $fieldName) : FieldMetadataBuilder
61
    {
62 397
        $this->fieldName = $fieldName;
63
64 397
        return $this;
65
    }
66
67 397
    public function withColumnAnnotation(Annotation\Column $columnAnnotation) : FieldMetadataBuilder
68
    {
69 397
        $this->columnAnnotation = $columnAnnotation;
70
71 397
        return $this;
72
    }
73
74 397
    public function withIdAnnotation(?Annotation\Id $idAnnotation) : FieldMetadataBuilder
75
    {
76 397
        $this->idAnnotation = $idAnnotation;
77
78 397
        return $this;
79
    }
80
81 397
    public function withVersionAnnotation(?Annotation\Version $versionAnnotation) : FieldMetadataBuilder
82
    {
83 397
        $this->versionAnnotation = $versionAnnotation;
84
85 397
        return $this;
86
    }
87
88 395
    public function withGeneratedValueAnnotation(
89
        ?Annotation\GeneratedValue $generatedValueAnnotation
90
    ) : FieldMetadataBuilder {
91 395
        $this->generatedValueAnnotation = $generatedValueAnnotation;
92
93 395
        return $this;
94
    }
95
96 395
    public function withSequenceGeneratorAnnotation(
97
        ?Annotation\SequenceGenerator $sequenceGeneratorAnnotation
98
    ) : FieldMetadataBuilder {
99 395
        $this->sequenceGeneratorAnnotation = $sequenceGeneratorAnnotation;
100
101 395
        return $this;
102
    }
103
104 395
    public function withCustomIdGeneratorAnnotation(
105
        ?Annotation\CustomIdGenerator $customIdGeneratorAnnotation
106
    ) : FieldMetadataBuilder {
107 395
        $this->customIdGeneratorAnnotation = $customIdGeneratorAnnotation;
108
109 395
        return $this;
110
    }
111
112 397
    public function build() : Mapping\FieldMetadata
113
    {
114
        // Validate required fields
115 397
        assert($this->componentMetadata !== null);
116 397
        assert($this->columnAnnotation !== null);
117 397
        assert($this->fieldName !== null);
118
119 397
        $componentClassName = $this->componentMetadata->getClassName();
120 397
        $namingStrategy     = $this->metadataBuildingContext->getNamingStrategy();
121 397
        $columnName         = $this->columnAnnotation->name
122 397
            ?? $namingStrategy->propertyToColumnName($this->fieldName, $componentClassName);
123 397
        $fieldMetadata      = new Mapping\FieldMetadata($this->fieldName);
124
125
        // For PHP 7.4+, we could potentially infer from property type
126 397
        if ($this->columnAnnotation->type === null) {
127
            throw Mapping\MappingException::propertyTypeIsRequired($componentClassName, $this->fieldName);
128
        }
129
130 397
        $fieldType    = Type::getType($this->columnAnnotation->type);
131 397
        $fieldOptions = $this->columnAnnotation->options ?? [];
132
133
        // Check for primary key
134 397
        if ($this->idAnnotation !== null) {
135 391
            $fieldMetadata->setPrimaryKey(true);
136
137 391
            if ($fieldType->canRequireSQLConversion()) {
138
                throw Mapping\MappingException::sqlConversionNotAllowedForPrimaryKeyProperties(
139
                    $componentClassName,
140
                    $this->fieldName,
141
                    $fieldType->getName()
142
                );
143
            }
144
145
            // Check for value generator
146 391
            $valueGeneratorMetadata = $this->valueGeneratorMetadataBuilder
147 391
                ->withComponentMetadata($this->componentMetadata)
148 391
                ->withFieldName($this->fieldName)
149 391
                ->withFieldType($fieldType)
150 391
                ->withGeneratedValueAnnotation($this->generatedValueAnnotation)
151 391
                ->withSequenceGeneratorAnnotation($this->sequenceGeneratorAnnotation)
152 391
                ->withCustomIdGeneratorAnnotation($this->customIdGeneratorAnnotation)
153 391
                ->build();
154
155 391
            $fieldMetadata->setValueGenerator($valueGeneratorMetadata);
156
        }
157
158
        // Check for version
159 397
        if ($this->versionAnnotation !== null) {
160
            // Determine default option for versioned field
161 20
            switch ($fieldType->getName()) {
162 20
                case 'integer':
163 2
                case 'bigint':
164 2
                case 'smallint':
165 19
                    $fieldOptions = array_merge(['default' => 1], $fieldOptions);
166 19
                    break;
167
168 2
                case 'datetime':
169 1
                case 'datetime_immutable':
170
                case 'datetimetz':
171
                case 'datetimetz_immutable':
172 2
                    $fieldOptions = array_merge(['default' => 'CURRENT_TIMESTAMP'], $fieldOptions);
173 2
                    break;
174
175
                default:
176
                    if (! isset($fieldOptions['default'])) {
177
                        throw Mapping\MappingException::unsupportedOptimisticLockingType($fieldType);
178
                    }
179
180
                    break;
181
            }
182
183 20
            $fieldMetadata->setVersioned(true);
184
        }
185
186
        // Prevent PK and version on same field
187 397
        if ($fieldMetadata->isPrimaryKey() && $fieldMetadata->isVersioned()) {
188
            throw Mapping\MappingException::cannotVersionIdField($componentClassName, $this->fieldName);
189
        }
190
191 397
        $fieldMetadata->setColumnName($columnName);
192 397
        $fieldMetadata->setType($fieldType);
193 397
        $fieldMetadata->setOptions($fieldOptions);
194 397
        $fieldMetadata->setScale($this->columnAnnotation->scale);
195 397
        $fieldMetadata->setPrecision($this->columnAnnotation->precision);
196 397
        $fieldMetadata->setNullable($this->columnAnnotation->nullable);
197 397
        $fieldMetadata->setUnique($this->columnAnnotation->unique);
198
199 397
        if (! $this->componentMetadata->isMappedSuperclass) {
200 390
            $fieldMetadata->setTableName($this->componentMetadata->getTableName());
201
        }
202
203 397
        if (! empty($this->columnAnnotation->columnDefinition)) {
204 8
            $fieldMetadata->setColumnDefinition($this->columnAnnotation->columnDefinition);
205
        }
206
207 397
        if (! empty($this->columnAnnotation->length)) {
208 397
            $fieldMetadata->setLength($this->columnAnnotation->length);
209
        }
210
211 397
        return $fieldMetadata;
212
    }
213
}
214