Str   B
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 380
Duplicated Lines 5.26 %

Test Coverage

Coverage 96.39%

Importance

Changes 0
Metric Value
wmc 41
dl 20
loc 380
ccs 80
cts 83
cp 0.9639
rs 8.2769
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A macro() 0 3 1
A camel() 0 3 1
A ascii() 0 3 1
A finish() 0 5 1
A contains() 9 9 4
A is() 0 14 2
A quickRandom() 0 5 1
A singular() 0 3 1
A studly() 0 5 1
A startsWith() 9 9 4
A parseCallback() 0 3 2
A title() 0 3 1
A slug() 0 16 2
A random() 0 13 3
A snake() 0 5 2
A limit() 0 7 2
A lower() 0 3 1
A __callStatic() 0 7 2
A upper() 0 3 1
A endsWith() 0 9 3
A plural() 0 3 1
A length() 0 3 1
A words() 0 13 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Str 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 Str, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Trucker\Support;
4
5
/*
6
 * Attribution: This file is part of the Laravel Framework, see Illuminate\Support\Str
7
 *
8
 * @see https://github.com/laravel/framework/blob/master/src/Illuminate/Support/Str.php
9
 */
10
use Illuminate\Support\Pluralizer;
11
use Patchwork\Utf8;
12
13
class Str
14
{
15
    /**
16
     * The registered string macros.
17
     *
18
     * @var array
19
     */
20
    protected static $macros = [];
21
22
    /**
23
     * Transliterate a UTF-8 value to ASCII.
24
     *
25
     * @param string $value
26
     *
27
     * @return string
28
     */
29 1
    public static function ascii($value)
30
    {
31 1
        return Utf8::toAscii($value);
32
    }
33
34
    /**
35
     * Convert a value to camel case.
36
     *
37
     * @param string $value
38
     *
39
     * @return string
40
     */
41 1
    public static function camel($value)
42
    {
43 1
        return lcfirst(static::studly($value));
44
    }
45
46
    /**
47
     * Determine if a given string contains a given substring.
48
     *
49
     * @param string       $haystack
50
     * @param string|array $needles
51
     *
52
     * @return bool
53
     */
54 2 View Code Duplication
    public static function contains($haystack, $needles)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
    {
56 2
        foreach ((array) $needles as $needle) {
57 2
            if ('' != $needle && false !== strpos($haystack, $needle)) {
58 2
                return true;
59
            }
60
        }
61
62 2
        return false;
63
    }
64
65
    /**
66
     * Determine if a given string ends with a given substring.
67
     *
68
     * @param string       $haystack
69
     * @param string|array $needles
70
     *
71
     * @return bool
72
     */
73 1
    public static function endsWith($haystack, $needles)
74
    {
75 1
        foreach ((array) $needles as $needle) {
76 1
            if ($needle == substr($haystack, -strlen($needle))) {
77 1
                return true;
78
            }
79
        }
80
81 1
        return false;
82
    }
83
84
    /**
85
     * Cap a string with a single instance of a given value.
86
     *
87
     * @param string $value
88
     * @param string $cap
89
     *
90
     * @return string
91
     */
92 1
    public static function finish($value, $cap)
93
    {
94 1
        $quoted = preg_quote($cap, '/');
95
96 1
        return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap;
97
    }
98
99
    /**
100
     * Determine if a given string matches a given pattern.
101
     *
102
     * @param string $pattern
103
     * @param string $value
104
     *
105
     * @return bool
106
     */
107 24
    public static function is($pattern, $value)
108
    {
109 24
        if ($pattern == $value) {
110 15
            return true;
111
        }
112
113 16
        $pattern = preg_quote($pattern, '#');
114
115
        // Asterisks are translated into zero-or-more regular expression wildcards
116
        // to make it convenient to check if the strings starts with the given
117
        // pattern such as "library/*", making any string check convenient.
118 16
        $pattern = str_replace('\*', '.*', $pattern) . '\z';
119
120 16
        return (bool) preg_match('#^' . $pattern . '#', $value);
121
    }
122
123
    /**
124
     * Return the length of the given string.
125
     *
126
     * @param string $value
127
     *
128
     * @return int
129
     */
130 1
    public static function length($value)
131
    {
132 1
        return mb_strlen($value);
133
    }
134
135
    /**
136
     * Limit the number of characters in a string.
137
     *
138
     * @param string $value
139
     * @param int    $limit
140
     * @param string $end
141
     *
142
     * @return string
143
     */
144 1
    public static function limit($value, $limit = 100, $end = '...')
145
    {
146 1
        if (mb_strlen($value) <= $limit) {
147 1
            return $value;
148
        }
149
150 1
        return rtrim(mb_substr($value, 0, $limit, 'UTF-8')) . $end;
151
    }
152
153
    /**
154
     * Convert the given string to lower-case.
155
     *
156
     * @param string $value
157
     *
158
     * @return string
159
     */
160 1
    public static function lower($value)
161
    {
162 1
        return mb_strtolower($value);
163
    }
164
165
    /**
166
     * Limit the number of words in a string.
167
     *
168
     * @param string $value
169
     * @param int    $words
170
     * @param string $end
171
     *
172
     * @return string
173
     */
174 3
    public static function words($value, $words = 100, $end = '...')
175
    {
176 3
        preg_match('/^\s*+(?:\S++\s*+){1,' . $words . '}/u', $value, $matches);
177
178 3
        if (!isset($matches[0])) {
179 1
            return $value;
180
        }
181
182 2
        if (strlen($value) == strlen($matches[0])) {
183 2
            return $value;
184
        }
185
186 2
        return rtrim($matches[0]) . $end;
187
    }
188
189
    /**
190
     * Parse a Class method style callback into class and method.
191
     *
192
     * @param string $callback
193
     * @param string $default
194
     *
195
     * @return array
196
     */
197 1
    public static function parseCallback($callback, $default)
198
    {
199 1
        return static::contains($callback, '@') ? explode('@', $callback, 2) : [$callback, $default];
200
    }
201
202
    /**
203
     * Get the plural form of an English word.
204
     *
205
     * @param string $value
206
     * @param int    $count
207
     *
208
     * @return string
209
     */
210 1
    public static function plural($value, $count = 2)
211
    {
212 1
        return Pluralizer::plural($value, $count);
213
    }
214
215
    /**
216
     * Generate a more truly "random" alpha-numeric string.
217
     *
218
     * @param int $length
219
     *
220
     * @return string
221
     *
222
     * @throws \RuntimeException
223
     */
224 1
    public static function random($length = 16)
225
    {
226 1
        if (function_exists('openssl_random_pseudo_bytes')) {
227 1
            $bytes = openssl_random_pseudo_bytes($length * 2);
228
229 1
            if (false === $bytes) {
230
                throw new \RuntimeException('Unable to generate random string.');
231
            }
232
233 1
            return substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $length);
0 ignored issues
show
Bug Best Practice introduced by
The expression return substr(str_replac...e($bytes)), 0, $length) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
234
        }
235
236
        return static::quickRandom($length);
237
    }
238
239
    /**
240
     * Generate a "random" alpha-numeric string.
241
     *
242
     * Should not be considered sufficient for cryptography, etc.
243
     *
244
     * @param int $length
245
     *
246
     * @return string
247
     */
248 1
    public static function quickRandom($length = 16)
249
    {
250 1
        $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
251
252 1
        return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
0 ignored issues
show
Bug Best Practice introduced by
The expression return substr(str_shuffl...$pool, 5)), 0, $length) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
253
    }
254
255
    /**
256
     * Convert the given string to upper-case.
257
     *
258
     * @param string $value
259
     *
260
     * @return string
261
     */
262 1
    public static function upper($value)
263
    {
264 1
        return mb_strtoupper($value);
265
    }
266
267
    /**
268
     * Convert the given string to title case.
269
     *
270
     * @param string $value
271
     *
272
     * @return string
273
     */
274 1
    public static function title($value)
275
    {
276 1
        return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
277
    }
278
279
    /**
280
     * Get the singular form of an English word.
281
     *
282
     * @param string $value
283
     *
284
     * @return string
285
     */
286 1
    public static function singular($value)
287
    {
288 1
        return Pluralizer::singular($value);
289
    }
290
291
    /**
292
     * Generate a URL friendly "slug" from a given string.
293
     *
294
     * @param string $title
295
     * @param string $separator
296
     *
297
     * @return string
298
     */
299 1
    public static function slug($title, $separator = '-')
300
    {
301 1
        $title = static::ascii($title);
302
303
        // Convert all dashes/undescores into separator
304 1
        $flip = '-' == $separator ? '_' : '-';
305
306 1
        $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
307
308
        // Remove all characters that are not the separator, letters, numbers, or whitespace.
309 1
        $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', mb_strtolower($title));
310
311
        // Replace all separator characters and whitespace by a single separator
312 1
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
313
314 1
        return trim($title, $separator);
315
    }
316
317
    /**
318
     * Convert a string to snake case.
319
     *
320
     * @param string $value
321
     * @param string $delimiter
322
     *
323
     * @return string
324
     */
325 1
    public static function snake($value, $delimiter = '_')
326
    {
327 1
        $replace = '$1' . $delimiter . '$2';
328
329 1
        return ctype_lower($value) ? $value : strtolower(preg_replace('/(.)([A-Z])/', $replace, $value));
330
    }
331
332
    /**
333
     * Determine if a given string starts with a given substring.
334
     *
335
     * @param string       $haystack
336
     * @param string|array $needles
337
     *
338
     * @return bool
339
     */
340 1 View Code Duplication
    public static function startsWith($haystack, $needles)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
341
    {
342 1
        foreach ((array) $needles as $needle) {
343 1
            if ('' != $needle && 0 === strpos($haystack, $needle)) {
344 1
                return true;
345
            }
346
        }
347
348 1
        return false;
349
    }
350
351
    /**
352
     * Convert a value to studly caps case.
353
     *
354
     * @param string $value
355
     *
356
     * @return string
357
     */
358 55
    public static function studly($value)
359
    {
360 55
        $value = ucwords(str_replace(['-', '_'], ' ', $value));
361
362 55
        return str_replace(' ', '', $value);
363
    }
364
365
    /**
366
     * Register a custom string macro.
367
     *
368
     * @param string   $name
369
     * @param callable $macro
370
     */
371 1
    public static function macro($name, $macro)
372
    {
373 1
        static::$macros[$name] = $macro;
374 1
    }
375
376
    /**
377
     * Dynamically handle calls to the string class.
378
     *
379
     * @param string $method
380
     * @param array  $parameters
381
     *
382
     * @return mixed
383
     *
384
     * @throws \BadMethodCallException
385
     */
386 1
    public static function __callStatic($method, $parameters)
387
    {
388 1
        if (isset(static::$macros[$method])) {
389 1
            return call_user_func_array(static::$macros[$method], $parameters);
390
        }
391
392
        throw new \BadMethodCallException("Method {$method} does not exist.");
393
    }
394
}
395