Completed
Push — uuid_annotation ( ce334a )
by David
02:50
created

assignToDefaultCode()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 30
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 6
nop 0
dl 0
loc 30
rs 8.439
c 0
b 0
f 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\TDBMException;
10
use TheCodingMachine\TDBM\Utils\Annotation\Annotation;
11
use TheCodingMachine\TDBM\Utils\Annotation\AnnotationParser;
12
13
/**
14
 * This class represent a property in a bean (a property has a getter, a setter, etc...).
15
 */
16
class ScalarBeanPropertyDescriptor extends AbstractBeanPropertyDescriptor
17
{
18
    /**
19
     * @var Column
20
     */
21
    private $column;
22
23
    /**
24
     * ScalarBeanPropertyDescriptor constructor.
25
     * @param Table $table
26
     * @param Column $column
27
     * @param NamingStrategyInterface $namingStrategy
28
     */
29
    public function __construct(Table $table, Column $column, NamingStrategyInterface $namingStrategy)
30
    {
31
        parent::__construct($table, $namingStrategy);
32
        $this->table = $table;
33
        $this->column = $column;
34
    }
35
36
    /**
37
     * Returns the foreign-key the column is part of, if any. null otherwise.
38
     *
39
     * @return ForeignKeyConstraint|null
40
     */
41
    public function getForeignKey()
42
    {
43
        return false;
44
    }
45
46
    /**
47
     * Returns the param annotation for this property (useful for constructor).
48
     *
49
     * @return string
50
     */
51
    public function getParamAnnotation()
52
    {
53
        $paramType = $this->getPhpType();
54
55
        $str = '     * @param %s %s';
56
57
        return sprintf($str, $paramType, $this->getVariableName());
58
    }
59
60
    /**
61
     * Returns the name of the class linked to this property or null if this is not a foreign key.
62
     *
63
     * @return null|string
64
     */
65
    public function getClassName(): ?string
66
    {
67
        return null;
68
    }
69
70
    /**
71
     * Returns the PHP type for the property (it can be a scalar like int, bool, or class names, like \DateTimeInterface, App\Bean\User....)
72
     *
73
     * @return string
74
     */
75
    public function getPhpType(): string
76
    {
77
        $type = $this->column->getType();
78
        return TDBMDaoGenerator::dbalTypeToPhpType($type);
79
    }
80
81
    /**
82
     * Returns true if the property is compulsory (and therefore should be fetched in the constructor).
83
     *
84
     * @return bool
85
     */
86
    public function isCompulsory()
87
    {
88
        return $this->column->getNotnull() && !$this->column->getAutoincrement() && $this->column->getDefault() === null && !$this->hasUuidAnnotation();
89
    }
90
91
    private function hasUuidAnnotation(): bool
92
    {
93
        return $this->getUuidAnnotation() !== null;
94
    }
95
96
    private function getUuidAnnotation(): ?Annotation
97
    {
98
        $comment = $this->column->getComment();
99
        if ($comment === null) {
100
            return null;
101
        }
102
        $parser = new AnnotationParser();
103
        $annotations = $parser->parse($comment);
104
        return $annotations->findAnnotation('UUID');
105
    }
106
107
    /**
108
     * Returns true if the property has a default value (or if the @UUID annotation is set for the column)
109
     *
110
     * @return bool
111
     */
112
    public function hasDefault()
113
    {
114
        return $this->column->getDefault() !== null || $this->hasUuidAnnotation();
115
    }
116
117
    /**
118
     * Returns the code that assigns a value to its default value.
119
     *
120
     * @return string
121
     */
122
    public function assignToDefaultCode()
123
    {
124
        $str = '        $this->%s(%s);';
125
126
        $uuidAnnotation = $this->getUuidAnnotation();
127
        if ($uuidAnnotation !== null) {
128
            $comment = trim($uuidAnnotation->getAnnotationComment(), '\'"');
129
            switch ($comment) {
130
                case '':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
131
                case 'v1':
132
                    $defaultCode = 'Uuid::uuid1()';
133
                    break;
134
                case 'v4':
135
                    $defaultCode = 'Uuid::uuid4()';
136
                    break;
137
                default:
138
                    throw new TDBMException('@UUID annotation accepts either "v1" or "v4" parameter. Unexpected parameter: '.$comment);
139
            }
140
        } else {
141
            $default = $this->column->getDefault();
142
143
            if (strtoupper($default) === 'CURRENT_TIMESTAMP') {
144
                $defaultCode = 'new \DateTimeImmutable()';
145
            } else {
146
                $defaultCode = var_export($this->column->getDefault(), true);
147
            }
148
        }
149
150
        return sprintf($str, $this->getSetterName(), $defaultCode);
151
    }
152
153
    /**
154
     * Returns true if the property is the primary key.
155
     *
156
     * @return bool
157
     */
158
    public function isPrimaryKey()
159
    {
160
        return in_array($this->column->getName(), $this->table->getPrimaryKeyColumns());
161
    }
162
163
    /**
164
     * Returns the PHP code for getters and setters.
165
     *
166
     * @return string
167
     */
168
    public function getGetterSetterCode()
169
    {
170
        $normalizedType = $this->getPhpType();
171
172
        $columnGetterName = $this->getGetterName();
173
        $columnSetterName = $this->getSetterName();
174
175
        // 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).
176
        $isNullable = !$this->column->getNotnull() || $this->column->getAutoincrement();
177
178
        $getterAndSetterCode = '    /**
179
     * The getter for the "%s" column.
180
     *
181
     * @return %s
182
     */
183
    public function %s() : %s%s
184
    {
185
        return $this->get(%s, %s);
186
    }
187
188
    /**
189
     * The setter for the "%s" column.
190
     *
191
     * @param %s $%s
192
     */
193
    public function %s(%s%s $%s) : void
194
    {
195
        $this->set(%s, $%s, %s);
196
    }
197
198
';
199
200
        return sprintf($getterAndSetterCode,
201
            // Getter
202
            $this->column->getName(),
203
            $normalizedType.($isNullable ? '|null' : ''),
204
            $columnGetterName,
205
            ($isNullable ? '?' : ''),
206
            $normalizedType,
207
            var_export($this->column->getName(), true),
208
            var_export($this->table->getName(), true),
209
            // Setter
210
            $this->column->getName(),
211
            $normalizedType,
212
            $this->column->getName(),
213
            $columnSetterName,
214
            $this->column->getNotnull() ? '' : '?',
215
            $normalizedType,
216
                //$castTo,
217
            $this->column->getName(),
218
            var_export($this->column->getName(), true),
219
            $this->column->getName(),
220
            var_export($this->table->getName(), true)
221
        );
222
    }
223
224
    /**
225
     * Returns the part of code useful when doing json serialization.
226
     *
227
     * @return string
228
     */
229
    public function getJsonSerializeCode()
230
    {
231
        $normalizedType = $this->getPhpType();
232
233
        if ($normalizedType == '\\DateTimeInterface') {
234
            return '        $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = ($this->'.$this->getGetterName().'() === null) ? null : $this->'.$this->getGetterName()."()->format('c');\n";
235
        } else {
236
            return '        $array['.var_export($this->namingStrategy->getJsonProperty($this), true).'] = $this->'.$this->getGetterName()."();\n";
237
        }
238
    }
239
240
    /**
241
     * Returns the column name.
242
     *
243
     * @return string
244
     */
245
    public function getColumnName()
246
    {
247
        return $this->column->getName();
248
    }
249
}
250