Completed
Branch 09branch (1e97b6)
by Anton
02:49
created

Strings::normalizeIndents()   B

Complexity

Conditions 8
Paths 17

Size

Total Lines 53
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 27
nc 17
nop 2
dl 0
loc 53
rs 7.1199
c 0
b 0
f 0

How to fix   Long Method   

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
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Support;
9
10
use Cocur\Slugify\SlugifyInterface;
11
12
/**
13
 * Set of helper methods to simplify working with string values.
14
 */
15
class Strings
16
{
17
    /**
18
     * Create a random string with desired length.
19
     *
20
     * @param int $length String length. 32 symbols by default.
21
     *
22
     * @return string
23
     */
24
    public static function random(int $length = 32): string
25
    {
26
        if (empty($string = openssl_random_pseudo_bytes($length))) {
27
            throw new \RuntimeException("Unable to generate random string");
28
        }
29
30
        return substr(base64_encode($string), 0, $length);
31
    }
32
33
    /**
34
     * Return a URL safe version of a string.
35
     *
36
     * @param string $string
37
     * @param string $separator
38
     *
39
     * @return string
40
     */
41
    public static function slug(string $string, string $separator = '-'): string
42
    {
43
        return spiral(SlugifyInterface::class)->slugify($string, $separator);
44
    }
45
46
    /**
47
     * Applies htmlentities() and strip_tags() to string (if enabled). Can be used to clean up
48
     * data before rendering it in HTML.
49
     *
50
     * @param string $string    String to be escaped.
51
     * @param bool   $stripTags Will remove all tags using strip_tags(). Disabled by default.
52
     *
53
     * @return string
54
     */
55
    public static function escape($string, bool $stripTags = false)
56
    {
57
        if (is_array($string) || is_object($string)) {
58
            return '';
59
        }
60
61
        if ($stripTags) {
62
            $string = strip_tags($string);
63
        }
64
65
        return htmlentities($string, ENT_QUOTES, 'UTF-8', false);
66
    }
67
68
    /**
69
     * Shorter string with specified limit. UTF8 encoding will be used to support non English
70
     * strings.
71
     *
72
     * @param string $string
73
     * @param int    $limit The max string length, 300 by default.
74
     *
75
     * @return string
76
     */
77
    public static function shorter(string $string, int $limit = 300): string
78
    {
79
        if (mb_strlen($string) + 3 > $limit) {
80
            return trim(mb_substr($string, 0, $limit - 3, 'UTF-8')) . '...';
81
        }
82
83
        return $string;
84
    }
85
86
    /**
87
     * Format bytes to human-readable format.
88
     *
89
     * @param int $bytes    Size in bytes.
90
     * @param int $decimals The number of decimals include to output. Set to 1 by default.
91
     *
92
     * @return string
93
     */
94
    public static function bytes(int $bytes, int $decimals = 1): string
95
    {
96
        $pows = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
97
        for ($unit = 0; $bytes > 1024; $unit++) {
98
            $bytes /= 1024;
99
        }
100
101
        return number_format($bytes, $unit ? $decimals : 0) . " " . $pows[$unit];
102
    }
103
104
    /**
105
     * Normalize string endings to avoid EOL problem. Replace \n\r and multiply new lines with
106
     * single \n.
107
     *
108
     * @param string $string       String to be normalized.
109
     * @param bool   $joinMultiple Join multiple new lines into one.
110
     *
111
     * @return string
112
     */
113
    public static function normalizeEndings(string $string, bool $joinMultiple = true): string
114
    {
115
        if (!$joinMultiple) {
116
            return str_replace("\r\n", "\n", $string);
117
        }
118
119
        return preg_replace('/[\n\r]+/', "\n", $string);
120
    }
121
122
    /**
123
     * Shift all string lines to have minimum indent size set to 0.
124
     *
125
     * Example:
126
     * |-a
127
     * |--b
128
     * |--c
129
     * |---d
130
     *
131
     * Output:
132
     * |a
133
     * |-b
134
     * |-c
135
     * |--d
136
     *
137
     * @param string $string         Input string with multiple lines.
138
     * @param string $tabulationCost How to treat \t symbols relatively to spaces. By default, this
139
     *                               is set to 4 spaces.
140
     *
141
     * @return string
142
     */
143
    public static function normalizeIndents(string $string, string $tabulationCost = "   "): string
144
    {
145
        $string = self::normalizeEndings($string, false);
146
        $lines = explode("\n", $string);
147
148
        $minIndent = null;
149
        foreach ($lines as $line) {
150
            if (!trim($line)) {
151
                continue;
152
            }
153
154
            $line = str_replace("\t", $tabulationCost, $line);
155
156
            //Getting indent size
157
            if (!preg_match("/^( +)/", $line, $matches)) {
158
                //Some line has no indent
159
                return $string;
160
            }
161
162
            if ($minIndent === null) {
163
                $minIndent = strlen($matches[1]);
164
            }
165
166
            $minIndent = min($minIndent, strlen($matches[1]));
167
        }
168
169
        //Fixing indent
170
        foreach ($lines as &$line) {
171
            if (empty($line)) {
172
                continue;
173
            }
174
175
            //Getting line indent
176
            preg_match("/^([ \t]+)/", $line, $matches);
177
            $indent = $matches[1];
178
179
            if (!trim($line)) {
180
                $line = '';
181
                continue;
182
            }
183
184
            //Getting new indent
185
            $useIndent = str_repeat(
186
                " ",
187
                strlen(str_replace("\t", $tabulationCost, $indent)) - $minIndent
188
            );
189
190
            $line = $useIndent . substr($line, strlen($indent));
191
            unset($line);
192
        }
193
194
        return join("\n", $lines);
195
    }
196
}