FieldMetadataBuilder::build()   D
last analyzed

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