Passed
Push — master ( ba645d...9eba8c )
by Michael
07:09 queued 43s
created

Utils   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 92
c 1
b 0
f 0
dl 0
loc 203
rs 8.8
wmc 45

10 Methods

Rating   Name   Duplication   Size   Complexity  
C composerGetExtras() 0 40 12
A isSequential() 0 3 1
A truncateString() 0 14 3
A __construct() 0 2 1
B isTrace() 0 39 9
A composerSkipFlags() 0 10 5
A traceFrameIsListed() 0 9 2
A getTypeString() 0 7 2
B normalizeAliases() 0 34 9
A getHumanReadableBytes() 0 10 1

How to fix   Complexity   

Complex Class

Complex classes like Utils often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Utils, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2013 Jonathan Vollebregt ([email protected]), Rokas Šleinius ([email protected])
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
9
 * this software and associated documentation files (the "Software"), to deal in
10
 * the Software without restriction, including without limitation the rights to
11
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12
 * the Software, and to permit persons to whom the Software is furnished to do so,
13
 * subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in all
16
 * copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
26
namespace Kint;
27
28
use InvalidArgumentException;
29
use Kint\Object\BlobObject;
30
use ReflectionNamedType;
31
use ReflectionType;
32
33
/**
34
 * A collection of utility methods. Should all be static methods with no dependencies.
35
 */
36
final class Utils
37
{
38
    /**
39
     * @codeCoverageIgnore
40
     */
41
    private function __construct()
42
    {
43
    }
44
45
    /**
46
     * Turns a byte value into a human-readable representation.
47
     *
48
     * @param int $value Amount of bytes
49
     *
50
     * @return array Human readable value and unit
51
     */
52
    public static function getHumanReadableBytes($value)
53
    {
54
        static $unit = array('B', 'KB', 'MB', 'GB', 'TB');
55
56
        $i = \floor(\log($value, 1024));
57
        $i = \min($i, 4); // Only go up to TB
58
59
        return array(
60
            'value' => (float) ($value / \pow(1024, $i)),
61
            'unit' => $unit[$i],
62
        );
63
    }
64
65
    public static function isSequential(array $array)
66
    {
67
        return \array_keys($array) === \range(0, \count($array) - 1);
68
    }
69
70
    public static function composerGetExtras($key = 'kint')
71
    {
72
        $extras = array();
73
74
        if (0 === \strpos(KINT_DIR, 'phar://')) {
75
            // Only run inside phar file, so skip for code coverage
76
            return $extras; // @codeCoverageIgnore
77
        }
78
79
        $folder = KINT_DIR.'/vendor';
80
81
        for ($i = 0; $i < 4; ++$i) {
82
            $installed = $folder.'/composer/installed.json';
83
84
            if (\file_exists($installed) && \is_readable($installed)) {
85
                $packages = \json_decode(\file_get_contents($installed), true);
86
87
                foreach ($packages as $package) {
88
                    if (isset($package['extra'][$key]) && \is_array($package['extra'][$key])) {
89
                        $extras = \array_replace($extras, $package['extra'][$key]);
90
                    }
91
                }
92
93
                $folder = \dirname($folder);
94
95
                if (\file_exists($folder.'/composer.json') && \is_readable($folder.'/composer.json')) {
96
                    $composer = \json_decode(\file_get_contents($folder.'/composer.json'), true);
97
98
                    if (isset($composer['extra'][$key]) && \is_array($composer['extra'][$key])) {
99
                        $extras = \array_replace($extras, $composer['extra'][$key]);
100
                    }
101
                }
102
103
                break;
104
            }
105
106
            $folder = \dirname($folder);
107
        }
108
109
        return $extras;
110
    }
111
112
    /**
113
     * @codeCoverageIgnore
114
     */
115
    public static function composerSkipFlags()
116
    {
117
        $extras = self::composerGetExtras();
118
119
        if (!empty($extras['disable-facade']) && !\defined('KINT_SKIP_FACADE')) {
120
            \define('KINT_SKIP_FACADE', true);
121
        }
122
123
        if (!empty($extras['disable-helpers']) && !\defined('KINT_SKIP_HELPERS')) {
124
            \define('KINT_SKIP_HELPERS', true);
125
        }
126
    }
127
128
    public static function isTrace(array $trace)
129
    {
130
        if (!self::isSequential($trace)) {
131
            return false;
132
        }
133
134
        static $bt_structure = array(
135
            'function' => 'string',
136
            'line' => 'integer',
137
            'file' => 'string',
138
            'class' => 'string',
139
            'object' => 'object',
140
            'type' => 'string',
141
            'args' => 'array',
142
        );
143
144
        $file_found = false;
145
146
        foreach ($trace as $frame) {
147
            if (!\is_array($frame) || !isset($frame['function'])) {
148
                return false;
149
            }
150
151
            foreach ($frame as $key => $val) {
152
                if (!isset($bt_structure[$key])) {
153
                    return false;
154
                }
155
156
                if (\gettype($val) !== $bt_structure[$key]) {
157
                    return false;
158
                }
159
160
                if ('file' === $key) {
161
                    $file_found = true;
162
                }
163
            }
164
        }
165
166
        return $file_found;
167
    }
168
169
    public static function traceFrameIsListed(array $frame, array $matches)
170
    {
171
        if (isset($frame['class'])) {
172
            $called = array(\strtolower($frame['class']), \strtolower($frame['function']));
173
        } else {
174
            $called = \strtolower($frame['function']);
175
        }
176
177
        return \in_array($called, $matches, true);
178
    }
179
180
    public static function normalizeAliases(array &$aliases)
181
    {
182
        static $name_regex = '[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*';
183
184
        foreach ($aliases as $index => &$alias) {
185
            if (\is_array($alias) && 2 === \count($alias)) {
186
                $alias = \array_values(\array_filter($alias, 'is_string'));
187
188
                if (2 === \count($alias) &&
189
                    \preg_match('/^'.$name_regex.'$/', $alias[1]) &&
190
                    \preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias[0])
191
                ) {
192
                    $alias = array(
193
                        \strtolower(\ltrim($alias[0], '\\')),
194
                        \strtolower($alias[1]),
195
                    );
196
                } else {
197
                    unset($aliases[$index]);
198
                    continue;
199
                }
200
            } elseif (\is_string($alias)) {
201
                if (\preg_match('/^\\\\?('.$name_regex.'\\\\)*'.$name_regex.'$/', $alias)) {
202
                    $alias = \explode('\\', \strtolower($alias));
203
                    $alias = \end($alias);
204
                } else {
205
                    unset($aliases[$index]);
206
                    continue;
207
                }
208
            } else {
209
                unset($aliases[$index]);
210
            }
211
        }
212
213
        $aliases = \array_values($aliases);
214
    }
215
216
    public static function truncateString($input, $length = PHP_INT_MAX, $end = '...', $encoding = false)
217
    {
218
        $length = (int) $length;
219
        $endlength = BlobObject::strlen($end);
220
221
        if ($endlength >= $length) {
222
            throw new InvalidArgumentException('Can\'t truncate a string to '.$length.' characters if ending with string '.$endlength.' characters long');
223
        }
224
225
        if (BlobObject::strlen($input, $encoding) > $length) {
226
            return BlobObject::substr($input, 0, $length - $endlength, $encoding).$end;
227
        }
228
229
        return $input;
230
    }
231
232
    public static function getTypeString(ReflectionType $type)
233
    {
234
        if ($type instanceof ReflectionNamedType) {
235
            return $type->getName();
236
        }
237
238
        return (string) $type; // @codeCoverageIgnore
239
    }
240
}
241