Completed
Push — master ( 57233c...a38405 )
by Arnold
02:36
created

TypeCast::getValueTypeDescription()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 12
cts 12
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 12
nc 5
nop 0
crap 5
1
<?php
2
3
namespace Jasny;
4
5
use Jasny\TypeCast;
6
7
/**
8
 * Class for type casting
9
 *
10
 *     $string = TypeCast::value($myValue)->to('string');
11
 *     $foo = TypeCast::value($data)->to('Foo');
12
 * 
13
 * When casting to an object of a class, the `__set_state()` method is used if available and the value is an array or a
14
 * stdClass object.
15
 */
16
class TypeCast
17
{
18
    use TypeCast\ToMixed,
19
        TypeCast\ToNumber,
20
        TypeCast\ToString,
21
        TypeCast\ToBoolean,
22
        TypeCast\ToArray,
23
        TypeCast\ToObject,
24
        TypeCast\ToResource,
25
        TypeCast\ToClass,
26
        TypeCast\ToMultiple;
27
    
28
    /**
29
     * @var mixed
30
     */
31
    protected $value;
32
    
33
    /**
34
     * The display name
35
     * @var string
36
     */
37
    protected $name;
38
    
39
    /**
40
     * Type aliases
41
     * @var string[]
42
     */
43
    protected $aliases = [
44
        'bool' => 'boolean',
45
        'int' => 'integer',
46
        'mixed[]' => 'array'
47
    ];
48
    
49
    
50
    /**
51
     * Class constructor
52
     *
53
     * @param mixed $value
54
     */
55 56
    public function __construct($value)
56
    {
57 56
        $this->value = $value;
58 56
    }
59
    
60
    /**
61
     * Factory method
62
     *
63
     * @param mixed $value
64
     */
65 55
    public static function value($value)
66
    {
67 55
        return new static($value);
68
    }
69
    
70
    /**
71
     * Create a clone of this typecast object for a different value
72
     * 
73
     * @param mixed $value
74
     * @return static
75
     */
76 10
    protected function forValue($value)
77
    {
78 10
        $cast = clone $this;
79 10
        $cast->value = $value;
80
        
81 10
        return $cast;
82
    }
83
    
84
    
85
    /**
86
     * Get the value
87
     * 
88
     * @return mixed
89
     */
90 54
    public function getValue()
91
    {
92 54
        return $this->value;
93
    }
94
    
95
    /**
96
     * Set the display name.
97
     * This is used in notices.
98
     * 
99
     * @param string $name
100
     * @return $this
101
     */
102 1
    public function setName($name)
103
    {
104 1
        $this->name = $name;
105 1
        return $this;
106
    }
107
    
108
    /**
109
     * Add a custom alias
110
     * 
111
     * @param string $alias
112
     * @param string $type
113
     */
114 1
    public function alias($alias, $type)
115
    {
116 1
        $this->aliases[$alias] = $type;
117 1
    }
118
119
    /**
120
     * Replace alias type with full type
121
     * 
122
     * @param string $type
123
     */
124 19
    public function normalizeType(&$type)
125
    {
126 19
        if (substr($type, -2) === '[]') {
127 10
            $subtype = substr($type, 0, -2);
128 10
            $this->normalizeType($subtype);
129
            
130 10
            $type = $subtype . '[]';
131 10
            return;
132
        }
133
        
134 19
        if (isset($this->aliases[$type])) {
135 16
            $type = $this->aliases[$type];
136 16
        }
137 19
    }
138
    
139
    /**
140
     * Get the internal types
141
     * 
142
     * @return array
143
     */
144 13
    protected function getInternalTypes()
145
    {
146 13
        return ['string', 'boolean', 'integer', 'float', 'array', 'object', 'resource', 'mixed'];
147
    }
148
    
149
    /**
150
     * Cast value
151
     *
152
     * @param string $type
153
     * @return mixed
154
     */
155 13
    public function to($type)
156
    {
157 13
        if (strstr($type, '|')) {
158 1
            return $this->toMultiple(explode('|', $type));
159
        }
160
        
161 13
        $this->normalizeType($type);
162
        
163
        // Cast internal types
164 13
        if (in_array($type, $this->getInternalTypes())) {
165 12
            return call_user_func([$this, 'to' . ucfirst($type)]);
166
        }
167
168
        // Cast to class
169 5
        return substr($type, -2) === '[]'
170 5
            ? $this->toArray(substr($type, 0, -2))
171 4
            : $this->toClass($type);
172
    }
173
    
174
175
    /**
176
     * Get a descript of the type of the value
177
     *
178
     * @return string
179
     */
180 28
    protected function getValueTypeDescription()
181
    {
182 28
        if (is_resource($this->getValue())) {
183 6
            $valueType = "a " . get_resource_type($this->getValue()) . " resource";
184 28
        } elseif (is_array($this->getValue())) {
185 4
            $valueType = "an array";
186 22
        } elseif (is_object($this->getValue())) {
187 6
            $valueType = "a " . get_class($this->getValue()) . " object";
188 18
        } elseif (is_string($this->getValue())) {
189 10
            $valueType = "string \"{$this->getValue()}\"";
190 10
        } else {
191 2
            $valueType = "a " . gettype($this->getValue());
192
        }
193
194 28
        return $valueType;
195
    }
196
    
197
    /**
198
     * Trigger a warning that the value can't be casted and return $value
199
     * 
200
     * @param string $type
201
     * @param string $explain  Additional message
202
     * @return mixed
203
     */
204 28
    public function dontCastTo($type, $explain = null)
205
    {
206 28
        $valueType = $this->getValueTypeDescription();
207
        
208 28
        if (!strstr($type, '|')) {
209 24
            $type = (in_array($type, ['array', 'object']) ? 'an ' : 'a ') . $type;
210 24
        }
211
        
212 28
        $name = isset($this->name) ? " {$this->name} from" : '';
213
        
214 28
        $message = "Unable to cast" . $name . " $valueType to $type" . (isset($explain) ? ": $explain" : '');
215 28
        trigger_error($message, E_USER_NOTICE);
216
        
217 1
        return $this->getValue();
218
    }
219
}
220