Passed
Push — master ( d32d3d...0995a0 )
by Andrea Marco
02:44 queued 12s
created

DtoProperty::processRawValue()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 8
c 1
b 0
f 0
nc 8
nop 0
dl 0
loc 15
ccs 9
cts 9
cp 1
crap 6
rs 9.2222
1
<?php
2
3
namespace Cerbero\Dto;
4
5
use Cerbero\Dto\Manipulators\ArrayConverter;
6
use Cerbero\Dto\Exceptions\UnexpectedValueException;
7
8
/**
9
 * The DTO property.
10
 *
11
 */
12
class DtoProperty
13
{
14
    /**
15
     * The property name.
16
     *
17
     * @var string
18
     */
19
    protected $name;
20
21
    /**
22
     * The property raw value.
23
     *
24
     * @var mixed
25
     */
26
    protected $rawValue;
27
28
    /**
29
     * The property types.
30
     *
31
     * @var DtoPropertyTypes
32
     */
33
    protected $types;
34
35
    /**
36
     * The DTO flags.
37
     *
38
     * @var int
39
     */
40
    protected $flags;
41
42
    /**
43
     * The processed value.
44
     *
45
     * @var mixed
46
     */
47
    protected $processedValue;
48
49
    /**
50
     * Whether the value has been processed.
51
     *
52
     * @var bool
53
     */
54
    protected $valueIsProcessed = false;
55
56
    /**
57
     * Instantiate the class.
58
     *
59
     * @param string $name
60
     * @param mixed $rawValue
61
     * @param DtoPropertyTypes $types
62
     * @param int $flags
63
     */
64 219
    protected function __construct(string $name, $rawValue, DtoPropertyTypes $types, int $flags)
65
    {
66 219
        $this->name = $name;
67 219
        $this->rawValue = $rawValue;
68 219
        $this->types = $types;
69 219
        $this->flags = $flags;
70 219
    }
71
72
    /**
73
     * Retrieve a DTO property instance after validating it
74
     *
75
     * @param string $name
76
     * @param mixed $rawValue
77
     * @param DtoPropertyTypes $types
78
     * @param int $flags
79
     * @return self
80
     * @throws UnexpectedValueException
81
     */
82 219
    public static function create(string $name, $rawValue, DtoPropertyTypes $types, int $flags): self
83
    {
84 219
        $instance = new static($name, $rawValue, $types, $flags);
85
86 219
        return $instance->validate();
87
    }
88
89
    /**
90
     * Validate the current property value depending on types and flags
91
     *
92
     * @return self
93
     * @throws UnexpectedValueException
94
     */
95 219
    public function validate(): self
96
    {
97 219
        if ($this->rawValue === null) {
98 39
            if ($this->isNullable()) {
99 33
                return $this;
100
            }
101
102 6
            throw new UnexpectedValueException($this);
103
        }
104
105 192
        if ($this->types->match($this->value())) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->value() targeting Cerbero\Dto\DtoProperty::value() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
106 183
            return $this;
107
        }
108
109 9
        throw new UnexpectedValueException($this);
110
    }
111
112
    /**
113
     * Determine whether this property is nullable
114
     *
115
     * @return bool
116
     */
117 45
    public function isNullable(): bool
118
    {
119 45
        if ($this->flags & NOT_NULLABLE) {
120 6
            return false;
121
        }
122
123 39
        return ($this->flags & NULLABLE) || $this->types->includeNull;
124
    }
125
126
    /**
127
     * Retrieve the processed value
128
     *
129
     * @return void
130
     */
131 204
    public function value()
132
    {
133 204
        if ($this->valueIsProcessed) {
134 108
            return $this->processedValue;
135
        }
136
137 204
        $this->processedValue = $this->processRawValue();
138 204
        $this->valueIsProcessed = true;
139
140 204
        return $this->processedValue;
141
    }
142
143
    /**
144
     * Retrieve the processed raw value
145
     *
146
     * @return mixed
147
     */
148 204
    protected function processRawValue()
149
    {
150 204
        if ($this->rawValue === null) {
151 15
            return null;
152
        }
153
154 192
        foreach ($this->types->all as $type) {
155 192
            if (!class_exists($class = $type->name())) {
156 177
                continue;
157 66
            } elseif ($converter = ArrayConverter::instance()->getConverterByClass($class)) {
158 44
                return $converter->toDto($this->rawValue);
159
            }
160
        }
161
162 192
        return $this->types->expectedDto ? $this->castRawValueIntoDto() : $this->rawValue;
163
    }
164
165
    /**
166
     * Retrieve the raw value casted into a DTO or a collection of DTOs
167
     *
168
     * @return Dto|Dto[]|null
169
     */
170 66
    protected function castRawValueIntoDto()
171
    {
172 66
        $dto = $this->types->expectedDto;
173
174 66
        if (!$this->types->expectCollection) {
175 54
            return is_a($this->rawValue, $dto) ? $this->rawValue : $dto::make($this->rawValue, $this->flags);
176
        }
177
178
        return array_map(function ($data) use ($dto) {
179 9
            return is_a($data, $dto) ? $data : $dto::make($data, $this->flags);
180 15
        }, $this->rawValue);
181
    }
182
183
    /**
184
     * Retrieve the property name
185
     *
186
     * @return string
187
     */
188 30
    public function getName(): string
189
    {
190 30
        return $this->name;
191
    }
192
193
    /**
194
     * Retrieve the property raw value
195
     *
196
     * @return mixed
197
     */
198 42
    public function getRawValue()
199
    {
200 42
        return $this->rawValue;
201
    }
202
203
    /**
204
     * Retrieve the property types
205
     *
206
     * @return DtoPropertyTypes
207
     */
208 186
    public function getTypes(): DtoPropertyTypes
209
    {
210 186
        return $this->types;
211
    }
212
213
    /**
214
     * Retrieve the DTO flags
215
     *
216
     * @return int
217
     */
218 15
    public function getFlags(): int
219
    {
220 15
        return $this->flags;
221
    }
222
223
    /**
224
     * Set a new value to this property and validate it
225
     *
226
     * @param mixed $rawValue
227
     * @param int $flags
228
     * @return self
229
     */
230 24
    public function setValue($rawValue, int $flags): self
231
    {
232 24
        $this->rawValue = $rawValue;
233 24
        $this->flags = $flags;
234 24
        $this->valueIsProcessed = false;
235
236 24
        return $this->validate();
237
    }
238
239
    /**
240
     * Determine how to clone the DTO property
241
     *
242
     * @return void
243
     */
244 21
    public function __clone()
245
    {
246 21
        $this->types = clone $this->types;
247 21
    }
248
}
249