Test Failed
Push — uuid_annotation ( d6506f )
by David
06:37
created

ScalarBeanPropertyDescriptor::getColumnName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace TheCodingMachine\TDBM\Utils;
4
5
use Doctrine\DBAL\Schema\Column;
6
use Doctrine\DBAL\Schema\Table;
7
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
8
use Ramsey\Uuid\Uuid;
9
use TheCodingMachine\TDBM\Utils\Annotation\AnnotationParser;
10
11
/**
12
 * This class represent a property in a bean (a property has a getter, a setter, etc...).
13
 */
14
class ScalarBeanPropertyDescriptor extends AbstractBeanPropertyDescriptor
15
{
16
    /**
17
     * @var Column
18
     */
19
    private $column;
20
21
    /**
22
     * ScalarBeanPropertyDescriptor constructor.
23
     * @param Table $table
24
     * @param Column $column
25
     * @param NamingStrategyInterface $namingStrategy
26
     */
27
    public function __construct(Table $table, Column $column, NamingStrategyInterface $namingStrategy)
28
    {
29
        parent::__construct($table, $namingStrategy);
30
        $this->table = $table;
31
        $this->column = $column;
32
    }
33
34
    /**
35
     * Returns the foreign-key the column is part of, if any. null otherwise.
36
     *
37
     * @return ForeignKeyConstraint|null
38
     */
39
    public function getForeignKey()
40
    {
41
        return false;
42
    }
43
44
    /**
45
     * Returns the param annotation for this property (useful for constructor).
46
     *
47
     * @return string
48
     */
49
    public function getParamAnnotation()
50
    {
51
        $paramType = $this->getPhpType();
52
53
        $str = '     * @param %s %s';
54
55
        return sprintf($str, $paramType, $this->getVariableName());
56
    }
57
58
    /**
59
     * Returns the name of the class linked to this property or null if this is not a foreign key.
60
     *
61
     * @return null|string
62
     */
63
    public function getClassName(): ?string
64
    {
65
        return null;
66
    }
67
68
    /**
69
     * Returns the PHP type for the property (it can be a scalar like int, bool, or class names, like \DateTimeInterface, App\Bean\User....)
70
     *
71
     * @return string
72
     */
73
    public function getPhpType(): string
74
    {
75
        $type = $this->column->getType();
76
        return TDBMDaoGenerator::dbalTypeToPhpType($type);
77
    }
78
79
    /**
80
     * Returns true if the property is compulsory (and therefore should be fetched in the constructor).
81
     *
82
     * @return bool
83
     */
84
    public function isCompulsory()
85
    {
86
        return $this->column->getNotnull() && !$this->column->getAutoincrement() && $this->column->getDefault() === null && !$this->hasUuidAnnotation();
87
    }
88
89
    private function hasUuidAnnotation(): bool
90
    {
91
        $comment = $this->column->getComment();
92
        if ($comment === null) {
93
            return false;
94
        }
95
        $parser = new AnnotationParser();
96
        $annotations = $parser->parse($comment);
97
        $uuidAnnotation = $annotations->findAnnotation('UUID');
98
        return $uuidAnnotation !== null;
99
    }
100
101
    /**
102
     * Returns true if the property has a default value (or if the @UUID annotation is set for the column)
103
     *
104
     * @return bool
105
     */
106
    public function hasDefault()
107
    {
108
        return $this->column->getDefault() !== null || $this->hasUuidAnnotation();
109
    }
110
111
    /**
112
     * Returns the code that assigns a value to its default value.
113
     *
114
     * @return string
115
     */
116
    public function assignToDefaultCode()
117
    {
118
        $str = '        $this->%s(%s);';
119
120
        if ($this->hasUuidAnnotation()) {
121
            // We generate a UUID1 because it is always handy to have IDs sorted chronologically (UUID4 on the other had is completely random)
122
            $defaultCode = 'Uuid::uuid1()';
123
        } else {
124
            $default = $this->column->getDefault();
125
126
            if (strtoupper($default) === 'CURRENT_TIMESTAMP') {
127
                $defaultCode = 'new \DateTimeImmutable()';
128
            } else {
129
                $defaultCode = var_export($this->column->getDefault(), true);
130
            }
131
        }
132
133
        return sprintf($str, $this->getSetterName(), $defaultCode);
134
    }
135
136
    /**
137
     * Returns true if the property is the primary key.
138
     *
139
     * @return bool
140
     */
141
    public function isPrimaryKey()
142
    {
143
        return in_array($this->column->getName(), $this->table->getPrimaryKeyColumns());
144
    }
145
146
    /**
147
     * Returns the PHP code for getters and setters.
148
     *
149
     * @return string
150
     */
151
    public function getGetterSetterCode()
152
    {
153
        $normalizedType = $this->getPhpType();
154
155
        $columnGetterName = $this->getGetterName();
156
        $columnSetterName = $this->getSetterName();
157
158
        // A column type can be forced if it is not nullable and not auto-incrementable (for auto-increment columns, we can get "null" as long as the bean is not saved).
159
        $isNullable = !$this->column->getNotnull() || $this->column->getAutoincrement();
160
161
        $getterAndSetterCode = '    /**
162
     * The getter for the "%s" column.
163
     *
164
     * @return %s
165
     */
166
    public function %s() : %s%s
167
    {
168
        return $this->get(%s, %s);
169
    }
170
171
    /**
172
     * The setter for the "%s" column.
173
     *
174
     * @param %s $%s
175
     */
176
    public function %s(%s%s $%s) : void
177
    {
178
        $this->set(%s, $%s, %s);
179
    }
180
181
';
182
183
        return sprintf($getterAndSetterCode,
184
            // Getter
185
            $this->column->getName(),
186
            $normalizedType.($isNullable ? '|null' : ''),
187
            $columnGetterName,
188
            ($isNullable ? '?' : ''),
189
            $normalizedType,
190
            var_export($this->column->getName(), true),
191
            var_export($this->table->getName(), true),
192
            // Setter
193
            $this->column->getName(),
194
            $normalizedType,
195
            $this->column->getName(),
196
            $columnSetterName,
197
            $this->column->getNotnull() ? '' : '?',
198
            $normalizedType,
199
                //$castTo,
200
            $this->column->getName(),
201
            var_export($this->column->getName(), true),
202
            $this->column->getName(),
203
            var_export($this->table->getName(), true)
204
        );
205
    }
206
207
    /**
208
     * Returns the part of code useful when doing json serialization.
209
     *
210
     * @return string
211
     */
212
    public function getJsonSerializeCode()
213
    {
214
        $normalizedType = $this->getPhpType();
215
216
        if ($normalizedType == '\\DateTimeInterface') {
217
            return '        $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = ($this->'.$this->getGetterName().'() === null) ? null : $this->'.$this->getGetterName()."()->format('c');\n";
218
        } else {
219
            return '        $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = $this->'.$this->getGetterName()."();\n";
220
        }
221
    }
222
223
    /**
224
     * Returns the column name.
225
     *
226
     * @return string
227
     */
228
    public function getColumnName()
229
    {
230
        return $this->column->getName();
231
    }
232
}
233