Failed Conditions
Push — master ( 4f8027...fa7802 )
by Guilherme
09:14
created

FieldMetadataBuilder::withColumnAnnotation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 Mapping\ClassMetadata */
19
    private $componentMetadata;
20
21
    /** @var string */
22
    private $fieldName;
23
24
    /** @var Annotation\Column */
25
    private $columnAnnotation;
26
27
    /** @var Annotation\Id|null */
28
    private $idAnnotation;
29
30
    /** @var Annotation\Version|null */
31
    private $versionAnnotation;
32
33 401
    public function __construct(Mapping\ClassMetadataBuildingContext $metadataBuildingContext)
34
    {
35 401
        $this->metadataBuildingContext = $metadataBuildingContext;
36 401
    }
37
38 401
    public function withComponentMetadata(Mapping\ClassMetadata $componentMetadata) : FieldMetadataBuilder
39
    {
40 401
        $this->componentMetadata = $componentMetadata;
41
42 401
        return $this;
43
    }
44
45 397
    public function withFieldName(string $fieldName) : FieldMetadataBuilder
46
    {
47 397
        $this->fieldName = $fieldName;
48
49 397
        return $this;
50
    }
51
52 397
    public function withColumnAnnotation(Annotation\Column $columnAnnotation) : FieldMetadataBuilder
53
    {
54 397
        $this->columnAnnotation = $columnAnnotation;
55
56 397
        return $this;
57
    }
58
59 397
    public function withIdAnnotation(?Annotation\Id $idAnnotation) : FieldMetadataBuilder
60
    {
61 397
        $this->idAnnotation = $idAnnotation;
62
63 397
        return $this;
64
    }
65
66 397
    public function withVersionAnnotation(?Annotation\Version $versionAnnotation) : FieldMetadataBuilder
67
    {
68 397
        $this->versionAnnotation = $versionAnnotation;
69
70 397
        return $this;
71
    }
72
73 397
    public function build() : Mapping\FieldMetadata
74
    {
75
        // Validate required fields
76 397
        assert($this->componentMetadata !== null);
77 397
        assert($this->columnAnnotation !== null);
78 397
        assert($this->fieldName !== null);
79
80 397
        $componentClassName = $this->componentMetadata->getClassName();
81 397
        $namingStrategy     = $this->metadataBuildingContext->getNamingStrategy();
82 397
        $columnName         = $this->columnAnnotation->name
83 397
            ?? $namingStrategy->propertyToColumnName($this->fieldName, $componentClassName);
84 397
        $fieldMetadata      = new Mapping\FieldMetadata($this->fieldName);
85
86
        // For PHP 7.4+, we could potentially infer from property type
87 397
        if ($this->columnAnnotation->type === null) {
88
            throw Mapping\MappingException::propertyTypeIsRequired($componentClassName, $this->fieldName);
89
        }
90
91 397
        $fieldType    = Type::getType($this->columnAnnotation->type);
92 397
        $fieldOptions = $this->columnAnnotation->options ?? [];
93
94
        // Check for primary key
95 397
        if ($this->idAnnotation !== null) {
96 391
            $fieldMetadata->setPrimaryKey(true);
97
98 391
            if ($fieldType->canRequireSQLConversion()) {
99
                throw Mapping\MappingException::sqlConversionNotAllowedForPrimaryKeyProperties(
100
                    $componentClassName,
101
                    $this->fieldName,
102
                    $fieldType->getName()
103
                );
104
            }
105
        }
106
107
        // Check for version
108 397
        if ($this->versionAnnotation !== null) {
109
            // Determine default option for versioned field
110 20
            switch ($fieldType->getName()) {
111 20
                case 'integer':
112 2
                case 'bigint':
113 2
                case 'smallint':
114 19
                    $fieldOptions = array_merge(['default' => 1], $fieldOptions);
115 19
                    break;
116
117 2
                case 'datetime':
118 1
                case 'datetime_immutable':
119
                case 'datetimetz':
120
                case 'datetimetz_immutable':
121 2
                    $fieldOptions = array_merge(['default' => 'CURRENT_TIMESTAMP'], $fieldOptions);
122 2
                    break;
123
124
                default:
125
                    if (! isset($fieldOptions['default'])) {
126
                        throw Mapping\MappingException::unsupportedOptimisticLockingType($fieldType);
127
                    }
128
129
                    break;
130
            }
131
132 20
            $fieldMetadata->setVersioned(true);
133
        }
134
135
        // Prevent PK and version on same field
136 397
        if ($fieldMetadata->isPrimaryKey() && $fieldMetadata->isVersioned()) {
137
            throw Mapping\MappingException::cannotVersionIdField($componentClassName, $this->fieldName);
138
        }
139
140 397
        $fieldMetadata->setColumnName($columnName);
141 397
        $fieldMetadata->setType($fieldType);
142 397
        $fieldMetadata->setOptions($fieldOptions);
143 397
        $fieldMetadata->setScale($this->columnAnnotation->scale);
144 397
        $fieldMetadata->setPrecision($this->columnAnnotation->precision);
145 397
        $fieldMetadata->setNullable($this->columnAnnotation->nullable);
146 397
        $fieldMetadata->setUnique($this->columnAnnotation->unique);
147
148 397
        if (! $this->componentMetadata->isMappedSuperclass) {
149 388
            $fieldMetadata->setTableName($this->componentMetadata->getTableName());
150
        }
151
152 397
        if (! empty($this->columnAnnotation->columnDefinition)) {
153 8
            $fieldMetadata->setColumnDefinition($this->columnAnnotation->columnDefinition);
154
        }
155
156 397
        if (! empty($this->columnAnnotation->length)) {
157 397
            $fieldMetadata->setLength($this->columnAnnotation->length);
158
        }
159
160 397
        return $fieldMetadata;
161
    }
162
}
163