Passed
Push — main ( c84275...1d7014 )
by Gabriel
03:41
created

CastableTrait::addCast()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
namespace ByTIC\DataObjects\Behaviors\Castable;
4
5
use ByTIC\DataObjects\ValueCaster;
6
7
/**
8
 * Trait CastableTrait
9
 * @package ByTIC\DataObjects\Behaviors\Castable
10
 */
11
trait CastableTrait
12
{
13
    /**
14
     * The attributes that should be cast.
15
     *
16
     * @var array
17
     */
18
    protected $casts = [];
19
20
    /**
21
     * @param $key
22
     * @param $value
23
     * @return mixed
24
     */
25 6
    public function transformValue($key, $value)
26
    {
27
        // If the attribute exists within the cast array, we will convert it to
28
        // an appropriate native PHP type dependent upon the associated value
29
        // given with the key in the pair. Dayle made this comment line up.
30 6
        if ($this->hasCast($key)) {
31 1
            return $this->castValue($key, $value);
32
        }
33
34 5
        return $value;
35
    }
36
37
    /**
38
     * @param $key
39
     * @param $value
40
     * @return mixed
41
     */
42
    public function transformInboundValue($key, $value)
43
    {
44 1
        if ($value && $this->isDateCastable($key)) {
45
            return ValueCaster::asDateTime($value)->format('Y-m-d H:i:s');
46 1
        }
47
        return $value;
48 1
    }
49
50
    /**
51
     * Determine whether an attribute should be cast to a native type.
52 1
     *
53
     * @param string $key
54
     * @param array|string|null $types
55
     * @return bool
56
     */
57
    public function hasCast($key, $types = null): bool
58
    {
59
        if (array_key_exists($key, $this->getCasts())) {
60
            return $types ? in_array($this->getCastType($key), (array)$types, true) : true;
61 1
        }
62
63 1
        return false;
64
    }
65
66
67 1
    /**
68
     * Get the casts array.
69
     *
70
     * @return array
71 1
     */
72
    public function getCasts(): array
73
    {
74
        return $this->casts;
75
    }
76
77
    /**
78
     * @param $attribute
79
     * @param $cast
80 1
     * @return self
81
     */
82 1
    public function addCast($attribute, $cast): self
83 1
    {
84
        $this->casts[$attribute] = $cast;
85
        return $this;
86
    }
87
88
    /**
89
     * Cast an attribute to a native PHP type.
90
     *
91
     * @param string $key
92 1
     * @param mixed $value
93
     * @return mixed
94 1
     */
95
    protected function castValue(string $key, $value)
96
    {
97
        $castType = $this->getCastType($key);
98
99
        if (is_null($value) && in_array($castType, ValueCaster::$primitiveTypes)) {
100
            return $value;
101
        }
102
103
        return ValueCaster::as($value, $castType);
104 6
    }
105
106 6
    /**
107 1
     * Get the type of cast for a model attribute.
108
     *
109
     * @param string $key
110 5
     * @return string
111
     */
112
    protected function getCastType($key)
113
    {
114
        if ($this->isCustomDateTimeCast($this->getCasts()[$key])) {
115
            return 'custom_datetime';
116
        }
117
118
        if ($this->isDecimalCast($this->getCasts()[$key])) {
119 6
            return 'decimal';
120
        }
121 6
122
        return trim(strtolower($this->getCasts()[$key]));
123
    }
124
125
    /**
126
     * Determine if the cast type is a custom date time cast.
127
     *
128
     * @param string $cast
129
     * @return bool
130
     */
131
    protected function isCustomDateTimeCast($cast)
132
    {
133
        return strncmp($cast, 'date:', 5) === 0 ||
134
            strncmp($cast, 'datetime:', 9) === 0;
135
    }
136
137
    /**
138
     * Determine if the cast type is a decimal cast.
139
     *
140
     * @param string $cast
141
     * @return bool
142
     */
143
    protected function isDecimalCast($cast): bool
144
    {
145
        return strncmp($cast, 'decimal:', 8) === 0;
146
    }
147
148
    /**
149
     * Determine whether a value is Date / DateTime castable for inbound manipulation.
150
     *
151
     * @param string $key
152
     * @return bool
153
     */
154
    protected function isDateCastable($key)
155
    {
156
        return $this->hasCast($key, ['date', 'datetime']);
157
    }
158
159
    /**
160
     * Determine whether a value is JSON castable for inbound manipulation.
161
     *
162
     * @param string $key
163
     * @return bool
164
     */
165
    protected function isJsonCastable($key)
166
    {
167
        return $this->hasCast(
168
            $key,
169
            [
170
                'array',
171
                'json',
172
                'object',
173
                'collection',
174
                'encrypted:array',
175
                'encrypted:collection',
176
                'encrypted:json',
177
                'encrypted:object'
178
            ]
179
        );
180
    }
181
}
182