objectify()   B
last analyzed

Complexity

Conditions 7
Paths 12

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 10
nc 12
nop 1
dl 0
loc 21
ccs 10
cts 10
cp 1
crap 7
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Jasny;
6
7
/**
8
 * Check if variable is an associative array.
9
 *
10
 * @param array|mixed $var
11
 * @return bool
12
 */
13
function is_associative_array($var): bool
14
{
15 8
    if (!is_array($var)) {
16 2
        return false;
17
    }
18
    
19 6
    $keys = array_keys($var);
20 6
    return ($keys !== array_keys($keys));
21
}
22
23
/**
24
 * Check if variable is a numeric array.
25
 *
26
 * @param array|mixed $var
27
 * @return bool
28
 */
29
function is_numeric_array($var): bool
30
{
31 8
    if (!is_array($var)) {
32 2
        return false;
33
    }
34
    
35 6
    $keys = array_keys($var);
36 6
    return ($keys === array_keys($keys));
37
}
38
39
/**
40
 * Check if variable is a string or can be cast to a string.
41
 *
42
 * @param mixed $var
43
 * @return bool
44
 */
45
function is_stringable($var): bool
46
{
47 9
    return (is_scalar($var) && !is_bool($var)) || (is_object($var) && method_exists($var, '__toString'));
48
}
49
50
/**
51
 * Turn associated array into stdClass object recursively.
52
 *
53
 * @param array|mixed $var
54
 * @return \stdClass|mixed
55
 */
56
function objectify($var)
57
{
58 9
    $i = func_num_args() > 1 ? func_get_arg(1) : 100;
59
    
60 9
    if ($i <= 0) {
61 1
        throw new \OverflowException("Maximum recursion depth reached. Possible circular reference.");
62
    }
63
    
64 9
    if (!is_array($var) && !is_object($var)) {
65 8
        return $var;
66
    }
67
    
68 8
    if (is_associative_array($var)) {
69 5
        $var = (object)$var;
70
    }
71
    
72 8
    foreach ($var as &$value) {
73 7
        $value = objectify($value, $i - 1);
74
    }
75
    
76 7
    return $var;
77
}
78
79
/**
80
 * Turn stdClass object into associated array recursively.
81
 *
82
 * @param \stdClass|mixed $var
83
 * @return array|mixed
84
 */
85
function arrayify($var)
86
{
87 7
    $i = func_num_args() > 1 ? func_get_arg(1) : 100;
88
    
89 7
    if ($i <= 0) {
90 1
        throw new \OverflowException("Maximum recursion depth reached. Possible circular reference.");
91
    }
92
    
93 7
    if (!is_array($var) && !is_object($var)) {
94 6
        return $var;
95
    }
96
    
97 6
    if ($var instanceof \stdClass) {
98 6
        $var = (array)$var;
99
    }
100
    
101 6
    foreach ($var as &$value) {
102 5
        $value = arrayify($value, $i - 1);
103
    }
104
    
105 5
    return $var;
106
}
107
108
/**
109
 * Get the type of a variable in a descriptive way.
110
 *
111
 * @param mixed $var
112
 * @return string
113
 */
114
function get_type_description($var): string
115
{
116 8
    switch (gettype($var)) {
117 8
        case 'double':
118 1
            return 'float';
119 7
        case 'object':
120 2
            return get_class($var) . " object";
121 5
        case 'resource':
122 1
            return get_resource_type($var) . " resource";
123 4
        case 'unknown type':
124 1
            return "resource (closed)"; // BC PHP 7.1
125
        default:
126 3
            return gettype($var);
127
    }
128
}
129
130
/**
131
 * Check that an argument has a specific type, otherwise throw an exception.
132
 *
133
 * @param mixed           $var
134
 * @param string|string[] $type
135
 * @param string          $throwable  Class name
136
 * @param string          $message
137
 * @return void
138
 * @throws \InvalidArgumentException
139
 */
140
function expect_type($var, $type, string $throwable = \TypeError::class, string $message = null): void
141
{
142 20
    $types = is_scalar($type) ? [$type] : $type;
143
144 20
    foreach ($types as &$curType) {
145 20
        if (str_ends_with($curType, ' resource')) {
146 4
            $valid = is_resource($var) && get_resource_type($var) === substr($curType, 0, -9);
147
        } else {
148 17
            $fn = $curType === 'boolean' ? 'is_bool' : 'is_' . $curType;
149 17
            $internal = function_exists($fn);
150
151 17
            $valid = $internal ? $fn($var) : is_a($var, $curType);
152 17
            $curType .= $internal ? '' : ' object';
153
        }
154
155 20
        if ($valid) {
156 20
            return;
157
        }
158
    }
159
160 10
    $message = $message ?? 'Expected %2$s, %1$s given';
161 10
    $varType = get_type_description($var);
162
163 10
    throw new $throwable(sprintf($message, $varType, array_join_pretty(', ', ' or ', $types)));
164
}
165