Utils::stringifyValue()   D
last analyzed

Complexity

Conditions 22
Paths 35

Size

Total Lines 62
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 38
CRAP Score 22.0081

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 22
eloc 40
c 2
b 0
f 0
nc 35
nop 2
dl 0
loc 62
ccs 38
cts 39
cp 0.9744
crap 22.0081
rs 4.1666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Murtukov\PHPCodeGenerator;
6
7
use Error;
8
use Exception;
9
use Murtukov\PHPCodeGenerator\Exception\UnrecognizedValueTypeException;
10
use function get_class;
11
use function is_int;
12
use function json_encode;
13
use function rtrim;
14
use function str_replace;
15
use function substr;
16
use function var_export;
17
18
class Utils
19
{
20
    const TYPE_STRING = 'string';
21
    const TYPE_INT = 'integer';
22
    const TYPE_BOOL = 'boolean';
23
    const TYPE_DOUBLE = 'double';
24
    const TYPE_OBJECT = 'object';
25
    const TYPE_ARRAY = 'array';
26
27
    /**
28
     * @var bool whether arrays should be split into multiple lines
29
     */
30
    private static ?bool $multiline = false;
31
32
    /**
33
     * @var bool defines whether arrays should be rendered with keys
34
     */
35
    private static ?bool $withKeys = false;
36
37
    /**
38
     * @var bool if true, null values are not rendered
39
     */
40
    public static bool $skipNullValues = false;
41
42
    /**
43
     * @var array custom converters registered by users
44
     */
45
    private static array $customConverters = [];
46
47
    /**
48
     * @param mixed $value
49
     *
50
     * @throws UnrecognizedValueTypeException
51
     */
52 25
    public static function stringify($value, ?bool $multiline = null, ?bool $withKeys = null, array $converters = []): string
53
    {
54
        // Common options to avoid passing them recursively
55 25
        self::$multiline = $multiline;
56 25
        self::$withKeys = $withKeys;
57 25
        self::$customConverters = $converters;
58
59 25
        return self::stringifyValue($value, true);
60
    }
61
62
    /**
63
     * @param mixed $value
64
     *
65
     * @throws UnrecognizedValueTypeException
66
     * @throws Exception
67
     */
68 25
    private static function stringifyValue($value, bool $topLevel = false): string
69
    {
70 25
        $type = gettype($value);
71
72
        // Custom converters
73 25
        if (!empty(self::$customConverters)) {
74 1
            foreach (Config::getConverterClasses($type) as $fqcn) {
75 1
                $converter = Config::getConverter($fqcn);
76 1
                if ($converter && $converter->check($value)) {
77 1
                    return (string) $converter->convert($value);
78
                }
79
            }
80
        }
81
82
        // Default converters
83 25
        switch ($type) {
84 25
            case 'boolean':
85 24
            case 'integer':
86 24
            case 'double':
87 8
                return json_encode($value);
88 24
            case 'string':
89 14
                if ('' === $value) {
90 2
                    return "''";
91
                }
92
93 12
                return var_export($value, true);
94 21
            case 'array':
95 15
                if (empty($value)) {
96 7
                    return '[]';
97
                }
98
99 9
                if (null !== self::$withKeys && true === $topLevel) {
100 5
                    return self::$withKeys
101 5
                        ? self::stringifyAssocArray($value, self::$multiline)
102 5
                        : self::stringifyNumericArray($value, self::$multiline);
103
                }
104
105 7
                return isset($value[0])
106 5
                    ? self::stringifyNumericArray($value)
107 7
                    : self::stringifyAssocArray($value);
108
109 13
            case 'object':
110 6
                if (!$value instanceof GeneratorInterface) {
111
                    try {
112 1
                        $result = json_encode($value->__toString());
113
114 1
                        return false !== $result ? $result : '[object]';
115 1
                    } catch (Error $e) {
116 1
                        $class = get_class($value);
117 1
                        throw new Exception("Cannot stringify object of class: '$class'.");
118
                    }
119
                }
120
121 5
                return (string) $value;
122 9
            case 'NULL':
123 9
                if (self::$skipNullValues) {
124 1
                    return '';
125
                }
126
127 8
                return 'null';
128
            default:
129
                throw new UnrecognizedValueTypeException('Cannot stringify value of unrecognized type.');
130
        }
131
    }
132
133
    /**
134
     * @throws UnrecognizedValueTypeException
135
     */
136 7
    private static function stringifyAssocArray(array $items, ?bool $multiline = true): string
137
    {
138 7
        $code = '';
139
140 7
        if ($multiline) {
141 7
            $code .= "\n";
142
143 7
            foreach ($items as $key => $value) {
144 7
                $key = is_int($key) ? $key : "'$key'";
145 7
                $value = self::stringifyValue($value);
146 7
                $code .= "$key => $value,\n";
147
            }
148
149 7
            $code = Utils::indent($code, false);
150
        } else {
151 2
            foreach ($items as $key => $value) {
152 2
                $key = is_int($key) ? $key : "'$key'";
153 2
                $value = self::stringifyValue($value);
154 2
                $code .= "$key => $value, ";
155
            }
156
        }
157
158
        // Remove last comma
159 7
        $code = rtrim($code, ', ');
160
161 7
        return "[$code]";
162
    }
163
164
    /**
165
     * @throws UnrecognizedValueTypeException
166
     */
167 5
    private static function stringifyNumericArray(array $items, ?bool $multiline = false): string
168
    {
169 5
        $code = '';
170
171 5
        if ($multiline) {
172 2
            $code .= "\n";
173
174 2
            foreach ($items as $value) {
175 2
                $value = self::stringifyValue($value);
176 2
                $code .= "$value,\n";
177
            }
178
179 2
            $code = Utils::indent($code, false);
180
        } else {
181 5
            foreach ($items as $value) {
182 5
                $value = self::stringifyValue($value);
183 5
                $code .= "$value, ";
184
            }
185
        }
186
187
        // Remove last comma and space
188 5
        $code = rtrim($code, ', ');
189
190 5
        return "[$code]";
191
    }
192
193 26
    public static function indent(string $code, bool $leadingIndent = true): string
194
    {
195 26
        $indent = Config::$indent;
196 26
        $code = str_replace("\n", "\n$indent", $code);
197
198 26
        if (true === $leadingIndent) {
199 19
            $code = $indent.$code;
200
        }
201
202 26
        return $code;
203
    }
204
205 25
    public static function resolveQualifier(string $path)
206
    {
207 25
        if ($portion = strrchr($path, '\\')) {
208 4
            return substr($portion, 1);
209
        }
210
211 22
        return false;
212
    }
213
}
214