Passed
Push — master ( 9d7ef7...af08db )
by Andrea Marco
01:42 queued 11s
created

DtoPropertyTypes::getExpectedPrimitive()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 14
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 20
ccs 6
cts 6
cp 1
crap 3
rs 9.7998
1
<?php
2
3
namespace Cerbero\Dto;
4
5
use Cerbero\Dto\Manipulators\ArrayConverter;
6
use Cerbero\Dto\Manipulators\ValueConverter;
7
8
/**
9
 * The wrapper for DTO property types.
10
 *
11
 * @property DtoPropertyType[] $all
12
 * @property bool $includeNull
13
 * @property bool $includeArray
14
 * @property bool $includeBool
15
 * @property bool $expectCollection
16
 * @property string|null $expectedDto
17
 * @property ValueConverter|null $expectedConverter
18
 * @property string|null $expectedPrimitive
19
 * @property string[] $declaredNames
20
 */
21
class DtoPropertyTypes
22
{
23
    /**
24
     * The DTO property types.
25
     *
26
     * @var DtoPropertyType[]
27
     */
28
    protected $all = [];
29
30
    /**
31
     * Whether one of the types is 'null'.
32
     *
33
     * @var bool
34
     */
35
    protected $includeNull = false;
36
37
    /**
38
     * Whether one of the types is 'array'.
39
     *
40
     * @var bool
41
     */
42
    protected $includeArray = false;
43
44
    /**
45
     * Whether one of the types is 'bool'.
46
     *
47
     * @var bool
48
     */
49
    protected $includeBool = false;
50
51
    /**
52
     * Whether the types expect a collection.
53
     *
54
     * @var bool
55
     */
56
    protected $expectCollection = false;
57
58
    /**
59
     * The expected DTO.
60
     *
61
     * @var string
62
     */
63
    protected $expectedDto;
64
65
    /**
66
     * The expected value converter.
67
     *
68
     * @var ValueConverter
69
     */
70
    protected $expectedConverter;
71
72
    /**
73
     * The expected primitive type.
74
     *
75
     * @var string
76
     */
77
    protected $expectedPrimitive;
78
79
    /**
80
     * The types name with the [] suffix if collections.
81
     *
82
     * @var array
83
     */
84
    protected $declaredNames = [];
85
86
    /**
87
     * Add the given DTO property type
88
     *
89
     * @param DtoPropertyType $type
90
     * @return self
91
     */
92 318
    public function addType(DtoPropertyType $type): self
93
    {
94 318
        $this->all[] = $type;
95 318
        $this->includeNull = $this->includeNull || $type->name() == 'null';
96 318
        $this->includeArray = $this->includeArray || $type->name() == 'array';
97 318
        $this->includeBool = $this->includeBool || $type->name() == 'bool';
98 318
        $this->expectCollection = $this->expectCollection || $type->isCollection();
99 318
        $this->expectedDto = $this->getExpectedDto($type);
100 318
        $this->expectedConverter = $this->getExpectedConverter($type);
101 318
        $this->expectedPrimitive = $this->getExpectedPrimitive($type);
102 318
        $this->declaredNames[] = $type->declaredName();
103
104 318
        return $this;
105
    }
106
107
    /**
108
     * Retrieve the expected DTO if any
109
     *
110
     * @param DtoPropertyType $type
111
     * @return string|null
112
     */
113 318
    protected function getExpectedDto(DtoPropertyType $type): ?string
114
    {
115 318
        if ($this->expectedDto) {
116 6
            return $this->expectedDto;
117
        }
118
119 318
        return $type->isDto() ? $type->name() : null;
120
    }
121
122
    /**
123
     * Retrieve the expected value converter
124
     *
125
     * @param DtoPropertyType $type
126
     * @return ValueConverter|null
127
     */
128 318
    protected function getExpectedConverter(DtoPropertyType $type): ?ValueConverter
129
    {
130 318
        if ($this->expectedConverter) {
131
            return $this->expectedConverter;
132
        }
133
134 318
        return ArrayConverter::instance()->getConverterByClass($type->name());
135
    }
136
137
    /**
138
     * Retrieve the expected primitive type
139
     *
140
     * @param DtoPropertyType $type
141
     * @return string|null
142
     */
143 318
    protected function getExpectedPrimitive(DtoPropertyType $type): ?string
144
    {
145 318
        if ($this->expectedPrimitive) {
146 222
            return $this->expectedPrimitive;
147
        }
148
149 318
        $typeName = $type->name();
150
        $casts = [
151 318
            'int' => true,
152
            'integer' => true,
153
            'bool' => true,
154
            'boolean' => true,
155
            'float' => true,
156
            'double' => true,
157
            'string' => true,
158
            'array' => true,
159
            'object' => true,
160
        ];
161
162 318
        return isset($casts[$typeName]) ? $typeName : null;
163
    }
164
165
    /**
166
     * Determine whether the given value matches at least one of the property types
167
     *
168
     * @param mixed $value
169
     * @return bool
170
     */
171 228
    public function match($value): bool
172
    {
173 228
        foreach ($this->all as $type) {
174 228
            if ($type->matches($value)) {
175 220
                return true;
176
            }
177
        }
178
179 24
        return false;
180
    }
181
182
    /**
183
     * Determine whether the types have a default value depending on the given flags
184
     *
185
     * @param int $flags
186
     * @return mixed
187
     */
188 222
    public function haveDefaultValue(int $flags)
189
    {
190 222
        return $this->arraysHaveDefault($flags) ||
191 222
            ($this->includeBool && ($flags & BOOL_DEFAULT_TO_FALSE)) ||
192 222
            ($this->includeNull && ($flags & NULLABLE_DEFAULT_TO_NULL));
193
    }
194
195
    /**
196
     * Determine whether array types have a default value
197
     *
198
     * @param int $flags
199
     * @return bool
200
     */
201 222
    protected function arraysHaveDefault(int $flags): bool
202
    {
203 222
        $includeArray = $this->includeArray || $this->expectCollection;
204
205 222
        return $includeArray && ($flags & ARRAY_DEFAULT_TO_EMPTY_ARRAY);
206
    }
207
208
    /**
209
     * Retrieve the types default value depending on the given flags
210
     *
211
     * @param int $flags
212
     * @return mixed
213
     */
214 15
    public function getDefaultValue(int $flags)
215
    {
216
        switch (true) {
217 15
            case ($this->includeArray || $this->expectCollection) && ($flags & ARRAY_DEFAULT_TO_EMPTY_ARRAY):
218 9
                return [];
219 12
            case $this->includeBool && ($flags & BOOL_DEFAULT_TO_FALSE):
220 6
                return false;
221
        }
222 12
    }
223
224
    /**
225
     * Retrieve the given property
226
     *
227
     * @param string $name
228
     * @return mixed
229
     */
230 285
    public function __get(string $name)
231
    {
232 285
        return $this->{$name};
233
    }
234
}
235