Passed
Pull Request — master (#34)
by David
02:55
created

assignToDefaultCode()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 34
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

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