String   D
last analyzed

Complexity

Total Complexity 160

Size/Duplication

Total Lines 1788
Duplicated Lines 9.12 %

Coupling/Cohesion

Components 2
Dependencies 0
Metric Value
wmc 160
lcom 2
cbo 0
dl 163
loc 1788
rs 4.4103

55 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A __clone() 0 3 1
A __wakeup() 0 3 1
A setDefaults() 0 4 1
A getEncoding() 0 4 1
B coalesce() 0 18 6
A prefixLines() 0 16 3
D filter() 0 29 17
D format() 0 106 28
C vardump() 0 52 14
A hash() 0 4 1
A generatePassword() 0 49 2
B generateUuid() 0 29 2
A generate() 0 11 2
B xss() 0 32 2
A strip() 8 15 3
A squote() 22 22 2
A dquote() 22 22 2
B squoteArray() 24 24 3
B dquoteArray() 24 24 3
A replaceBreaks() 0 4 1
A cut() 0 8 2
A encodeHtml() 8 8 1
A decodeHtml() 8 8 1
A escapeHtml() 0 4 1
A unescapeHtml() 0 4 1
A toLower() 0 4 1
A toUpper() 0 4 1
A capitalize() 0 4 1
A capitalizeWords() 0 21 4
A length() 0 5 1
A startsWith() 10 10 2
A endsWith() 10 10 2
A substr() 0 8 2
A strpos() 0 4 1
A strstr() 0 4 1
A sizeCalc() 9 9 2
A quantityCalc() 9 9 2
A timeCalc() 0 12 3
B removeAccent() 0 437 1
A removeInvisibles() 9 48 3
A slug() 0 10 1
A toBase() 0 17 2
A fromBase() 0 11 2
A toBase62() 0 4 1
A fromBase62() 0 4 1
A toBaseUrl() 0 4 1
A fromBaseUrl() 0 4 1
A shortenUuid() 0 19 2
A unshortenUuid() 0 23 3
B ordinalize() 0 17 5
A swap() 0 6 1
B sanitizeFilename() 0 55 6
A matchPaths() 0 17 4
A convertLinks() 0 8 1

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 String 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 String, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Scabbia2 Helpers Component
4
 * https://github.com/eserozvataf/scabbia2
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @link        https://github.com/eserozvataf/scabbia2-helpers for the canonical source repository
10
 * @copyright   2010-2016 Eser Ozvataf. (http://eser.ozvataf.com/)
11
 * @license     http://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0
12
 */
13
14
namespace Scabbia\Helpers;
15
16
/**
17
 * A bunch of utility methods for string manipulation
18
 *
19
 * @package     Scabbia\Helpers
20
 * @author      Eser Ozvataf <[email protected]>
21
 * @since       1.0.0
22
 *
23
 * @scabbia-compile
24
 *
25
 * @todo pluralize, singularize
26
 * @todo split Text functions into another file
27
 * @todo alternator, camel2underscore, underscore2camel
28
 */
29
class String
30
{
31
    /** @type string FILTER_VALIDATE_BOOLEAN a symbolic constant for boolean validation */
32
    const FILTER_VALIDATE_BOOLEAN = "scabbiaFilterValidateBoolean";
33
    /** @type string FILTER_SANITIZE_BOOLEAN a symbolic constant for boolean sanitization */
34
    const FILTER_SANITIZE_BOOLEAN = "scabbiaFilterSanitizeBoolean";
35
    /** @type string FILTER_SANITIZE_XSS   a symbolic constant for xss sanitization */
36
    const FILTER_SANITIZE_XSS = "scabbiaFilterSanitizeXss";
37
38
39
    /**
40
     * Constructor to prevent new instances of String class
41
     *
42
     * @return String
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
43
     */
44
    final private function __construct()
45
    {
46
    }
47
48
    /**
49
     * Clone method to prevent duplication of String class
50
     *
51
     * @return String
52
     */
53
    final private function __clone()
54
    {
55
    }
56
57
    /**
58
     * Unserialization method to prevent restoration of String class
59
     *
60
     * @return String
61
     */
62
    final private function __wakeup()
63
    {
64
    }
65
66
    /**
67
     * Default variables for Html utility set
68
     *
69
     * @type array $defaults array of default variables
70
     */
71
    public static $defaults = [
72
        "tab" => "\t",
73
        "eol" => PHP_EOL,
74
75
        "squote_replacement" => [["\\", "'"], ["\\\\", "\\'"]],
76
        "dquote_replacement" => [["\\", "\""], ["\\\\", "\\\""]],
77
78
        "baseconversion_url_chars" => "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:[]@!$'()*+,;",
79
        "baseconversion_base62_chars" => "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
80
    ];
81
82
83
    /**
84
     * Sets the default variables
85
     *
86
     * @param array $uDefaults variables to be set
87
     *
88
     * @return void
89
     */
90
    public static function setDefaults($uDefaults)
91
    {
92
        self::$defaults = $uDefaults + self::$defaults;
93
    }
94
95
    /**
96
     * Returns default encoding
97
     *
98
     * @return string name of the encoding
99
     */
100
    public static function getEncoding()
101
    {
102
        return ini_get("default_charset");
103
    }
104
105
    /**
106
     * Checks arguments in order and returns the value of the first expression that is not-null
107
     *
108
     * @param array $uValues values
109
     *
110
     * @return mixed first non-null expression in parameter list.
111
     */
112
    public static function coalesce(...$uValues)
113
    {
114
        foreach ($uValues as $tValue) {
115
            if ($tValue !== null) {
116
                if (is_array($tValue)) {
117
                    if (isset($tValue[0][$tValue[1]]) && $tValue[0][$tValue[1]] !== null) {
118
                        return $tValue[0][$tValue[1]];
119
                    }
120
121
                    continue;
122
                }
123
124
                return $tValue;
125
            }
126
        }
127
128
        return null;
129
    }
130
131
    /**
132
     * Prefixes all lines in the given string with the dashes or specified string
133
     *
134
     * @param string $uInput  original string
135
     * @param string $uPrefix the string will be added to beginning of all lines
136
     *
137
     * @return string prefixed string
138
     */
139
    public static function prefixLines($uInput, $uPrefix = "- ")
140
    {
141
        $tLines = explode(self::$defaults["eol"], $uInput);
142
143
        $tOutput = $tLines[0] . self::$defaults["eol"];
144
        $tCount = 0;
145
        foreach ($tLines as $tLine) {
146
            if ($tCount++ === 0) {
147
                continue;
148
            }
149
150
            $tOutput .= $uPrefix . $tLine . self::$defaults["eol"];
151
        }
152
153
        return $tOutput;
154
    }
155
156
    /**
157
     * Filters or sanitizes given value according to filter options
158
     *
159
     * @param mixed $uValue  original value
160
     * @param mixed $uFilter filter
161
     * @param array $uArgs   arguments
162
     *
163
     * @return mixed final output
164
     *
165
     * @todo recursive filtering option
166
     */
167
    public static function filter($uValue, $uFilter, ...$uArgs)
168
    {
169
        if ($uFilter === self::FILTER_VALIDATE_BOOLEAN) {
170
            if ($uValue === true || $uValue === "true" || $uValue === 1 || $uValue === "1" ||
171
                $uValue === false || $uValue === "false" || $uValue === 0 || $uValue === "0") {
172
                return true;
173
            }
174
175
            return false;
176
        }
177
178
        if ($uFilter === self::FILTER_SANITIZE_BOOLEAN) {
179
            if ($uValue === true || $uValue === "true" || $uValue === 1 || $uValue === "1") {
180
                return true;
181
            }
182
183
            return false;
184
        }
185
186
        if ($uFilter === self::FILTER_SANITIZE_XSS) {
187
            return self::xss($uValue);
188
        }
189
190
        if (is_callable($uFilter, true)) {
191
            return call_user_func($uFilter, $uValue, ...$uArgs);
192
        }
193
194
        return filter_var(...$uArgs);
195
    }
196
197
    /**
198
     * Replaces placeholders given in string and formats them
199
     *
200
     * @param string $uString original string with placeholders
201
     * @param array  $uArgs   arguments
202
     *
203
     * @return string final replaced output
204
     */
205
    public static function format($uString, ...$uArgs)
206
    {
207
        if (count($uArgs) > 0 && is_array($uArgs[0])) {
208
            $uArgs = $uArgs[0];
209
        }
210
211
        $tBrackets = [[null, ""]];
212
        $tQuoteChar = false;
213
        $tLastItem = 0;
214
        $tArrayItem = 1;
215
216
        for ($tPos = 0, $tLen = self::length($uString); $tPos < $tLen; $tPos++) {
217
            $tChar = self::substr($uString, $tPos, 1);
218
219
            if ($tChar === "\\") {
220
                $tBrackets[$tLastItem][$tArrayItem] .= self::substr($uString, ++$tPos, 1);
221
                continue;
222
            }
223
224
            if ($tQuoteChar === false && $tChar === "{") {
225
                ++$tLastItem;
226
                $tBrackets[$tLastItem] = [null, null];
227
                $tArrayItem = 1;
228
                continue;
229
            }
230
231
            if ($tLastItem > 0) {
232
                if ($tBrackets[$tLastItem][$tArrayItem] === null) {
233
                    if ($tChar === "'" || $tChar === "\"") {
234
                        $tQuoteChar = $tChar;
235
                        $tBrackets[$tLastItem][$tArrayItem] = "\""; // static text
236
                        $tChar = self::substr($uString, ++$tPos, 1);
237
                    } else {
238
                        if ($tChar === "!") {
239
                            $tBrackets[$tLastItem][$tArrayItem] = "!"; // dynamic text
240
                            $tChar = self::substr($uString, ++$tPos, 1);
241
                        } else {
242
                            if ($tChar === "@") {
243
                                $tBrackets[$tLastItem][$tArrayItem] = "@"; // parameter
244
                                $tChar = self::substr($uString, ++$tPos, 1);
245
                            } else {
246
                                $tBrackets[$tLastItem][$tArrayItem] = "@"; // parameter
247
                            }
248
                        }
249
                    }
250
                }
251
252
                if (self::substr($tBrackets[$tLastItem][$tArrayItem], 0, 1) === "\"") {
253
                    if ($tQuoteChar === $tChar) {
254
                        $tQuoteChar = false;
255
                        continue;
256
                    }
257
258
                    if ($tQuoteChar !== false) {
259
                        $tBrackets[$tLastItem][$tArrayItem] .= $tChar;
260
                        continue;
261
                    }
262
263
                    if ($tChar !== "," && $tChar !== "}") {
264
                        continue;
265
                    }
266
                }
267
268
                if ($tArrayItem === 1 && $tChar === "|" && $tBrackets[$tLastItem][0] === null) {
269
                    $tBrackets[$tLastItem][0] = $tBrackets[$tLastItem][1];
270
                    $tBrackets[$tLastItem][1] = null;
271
                    continue;
272
                }
273
274
                if ($tChar === ",") {
275
                    $tBrackets[$tLastItem][++$tArrayItem] = null;
276
                    continue;
277
                }
278
279
                if ($tChar === "}") {
280
                    $tFunc = array_shift($tBrackets[$tLastItem]);
281
                    foreach ($tBrackets[$tLastItem] as &$tItem) {
282
                        if ($tItem[0] === "\"") {
283
                            $tItem = self::substr($tItem, 1);
284
                        } elseif ($tItem[0] === "@") {
285
                            $tItem = $uArgs[self::substr($tItem, 1)];
286
                        } elseif ($tItem[0] === "!") {
287
                            $tItem = constant(self::substr($tItem, 1));
288
                        }
289
                    }
290
291
                    if ($tFunc !== null) {
292
                        $tString = call_user_func(self::substr($tFunc, 1), ...$tBrackets[$tLastItem]);
293
                    } else {
294
                        $tString = implode(", ", $tBrackets[$tLastItem]);
295
                    }
296
297
                    $tArrayItem = count($tBrackets[$tLastItem - 1]) - 1;
298
                    $tBrackets[$tLastItem - 1][$tArrayItem] .= $tString;
299
                    unset($tBrackets[$tLastItem]);
300
                    $tLastItem--;
301
302
                    continue;
303
                }
304
            }
305
306
            $tBrackets[$tLastItem][$tArrayItem] .= $tChar;
307
        }
308
309
        return $tBrackets[0][1];
310
    }
311
312
    /**
313
     * Displays structured information of given parameter in a fancy way
314
     *
315
     * @param mixed $uVariable variable
316
     * @param bool  $uOutput   whether return output as a function output or not
317
     *
318
     * @return string|null structure of given parameter
319
     */
320
    public static function vardump($uVariable, $uOutput = true)
321
    {
322
        $tVariable = $uVariable;
323
        $tType = gettype($tVariable);
324
        $tOut = "";
325
        static $sTabs = "";
326
327
        if ($tType === "boolean") {
328
            $tOut .= "<b>boolean</b>(" . (($tVariable) ? "true" : "false") . ")" . self::$defaults["eol"];
329
        } elseif ($tType === "double") {
330
            $tOut .= "<b>{$tType}</b>('" . number_format($tVariable, 22, ".", "") . "')" . self::$defaults["eol"];
331
        } elseif ($tType === "integer" || $tType === "string") {
332
            $tOut .= "<b>{$tType}</b>('{$tVariable}')" . self::$defaults["eol"];
333
        } elseif ($tType === "array" || $tType === "object") {
334
            if ($tType === "object") {
335
                $tType = get_class($tVariable);
336
                $tVariable = get_object_vars($tVariable);
337
            }
338
339
            $tCount = count($tVariable);
340
            $tOut .= "<b>{$tType}</b>({$tCount})";
341
342
            if ($tCount > 0) {
343
                $tOut .= " {" . self::$defaults["eol"];
344
345
                $sTabs .= self::$defaults["tab"];
346
                foreach ($tVariable as $tKey => $tVal) {
347
                    $tOut .= "{$sTabs}[{$tKey}] = ";
348
                    $tOut .= self::vardump($tVal, false);
349
                }
350
                $sTabs = substr($sTabs, 0, -1);
351
352
                $tOut .= "{$sTabs}}";
353
            }
354
355
            $tOut .= self::$defaults["eol"];
356
        } elseif ($tType === "resource") {
357
            $tOut .= "<b>resource</b>('" . get_resource_type($tVariable) . "')" . self::$defaults["eol"];
358
        } elseif ($tType === "NULL") {
359
            $tOut .= "<b><i>null</i></b>" . self::$defaults["eol"];
360
        } else {
361
            $tOut .= "<b>{$tType}</b>" . self::$defaults["eol"];
362
        }
363
364
        if ($uOutput) {
365
            echo "<pre>{$tOut}</pre>";
366
367
            return null;
368
        }
369
370
        return $tOut;
371
    }
372
373
    /**
374
     * A basic hash method
375
     *
376
     * @param mixed $uValue value is going to be hashed
377
     *
378
     * @return int hash in decimal representation
379
     */
380
    public static function hash($uValue)
381
    {
382
        return hexdec(hash("crc32", $uValue) . hash("crc32b", $uValue));
383
    }
384
385
    /**
386
     * Generates a random password in given length
387
     *
388
     * @param int $uLength password length
389
     *
390
     * @return string generated password
391
     */
392
    public static function generatePassword($uLength)
393
    {
394
        // mt_srand((int)(microtime(true) * 0xFFFF));
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
395
396
        static $sVowels = ["a", "e", "i", "o", "u"];
397
        static $sCons = [
398
            "b",
399
            "c",
400
            "d",
401
            "g",
402
            "h",
403
            "j",
404
            "k",
405
            "l",
406
            "m",
407
            "n",
408
            "p",
409
            "r",
410
            "s",
411
            "t",
412
            "u",
413
            "v",
414
            "w",
415
            "tr",
416
            "cr",
417
            "br",
418
            "fr",
419
            "th",
420
            "dr",
421
            "ch",
422
            "ph",
423
            "wr",
424
            "st",
425
            "sp",
426
            "sw",
427
            "pr",
428
            "sl",
429
            "cl"
430
        ];
431
432
        $tConsLen = count($sCons) - 1;
433
        $tVowelsLen = count($sVowels) - 1;
434
        for ($tOutput = ""; strlen($tOutput) < $uLength;) {
435
            $tOutput .= $sCons[mt_rand(0, $tConsLen)] . $sVowels[mt_rand(0, $tVowelsLen)];
436
        }
437
438
        // prevent overflow of size
439
        return substr($tOutput, 0, $uLength);
440
    }
441
442
    /**
443
     * Generates an unique-identifier and ensures it is in uuid format
444
     *
445
     * @return string generated uuid
446
     */
447
    public static function generateUuid()
448
    {
449
        if (function_exists("com_create_guid")) {
450
            return strtolower(trim(com_create_guid(), "{}"));
451
        }
452
453
        // mt_srand((int)(microtime(true) * 0xFFFF));
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
454
455
        // return md5(uniqid(mt_rand(), true));
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
456
        return sprintf(
457
            "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
458
            // 32 bits for "time_low"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
459
            mt_rand(0, 0xffff),
460
            mt_rand(0, 0xffff),
461
            // 16 bits for "time_mid"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
462
            mt_rand(0, 0xffff),
463
            // 16 bits for "time_hi_and_version",
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
464
            // four most significant bits holds version number 4
465
            mt_rand(0, 0x0fff) | 0x4000,
466
            // 16 bits, 8 bits for "clk_seq_hi_res",
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
467
            // 8 bits for "clk_seq_low",
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
468
            // two most significant bits holds zero and one for variant DCE1.1
469
            mt_rand(0, 0x3fff) | 0x8000,
470
            // 48 bits for "node"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
471
            mt_rand(0, 0xffff),
472
            mt_rand(0, 0xffff),
473
            mt_rand(0, 0xffff)
474
        );
475
    }
476
477
    /**
478
     * Generates a random string in given length
479
     *
480
     * @param int    $uLength  string length
481
     * @param string $uCharset set of chars are going to be used in generated string
482
     *
483
     * @return string generated string
484
     */
485
    public static function generate($uLength, $uCharset = "0123456789ABCDEF")
486
    {
487
        // mt_srand((int)(microtime(true) * 0xFFFF));
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
488
489
        $tCharsetLen = self::length($uCharset) - 1;
490
        for ($tOutput = ""; $uLength > 0; $uLength--) {
491
            $tOutput .= self::substr($uCharset, mt_rand(0, $tCharsetLen), 1);
492
        }
493
494
        return $tOutput;
495
    }
496
497
    /**
498
     * Filters the chars that occur XSS attacks
499
     *
500
     * @param string $uValue original value
501
     *
502
     * @return string filtered string
503
     */
504
    public static function xss($uValue)
505
    {
506
        if (!is_string($uValue)) {
507
            return $uValue;
508
        }
509
510
        return str_replace(
511
            [
512
                "<",
513
                ">",
514
                "\"",
515
                "'",
516
                "$",
517
                "(",
518
                ")",
519
                "%28",
520
                "%29"
521
            ],
522
            [
523
                "&#60;",
524
                "&#62;",
525
                "&#34;",
526
                "&#39;",
527
                "&#36;",
528
                "&#40;",
529
                "&#41;",
530
                "&#40;",
531
                "&#41;"
532
            ],
533
            $uValue
534
        ); // "&" => "&#38;"
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
535
    }
536
537
    /**
538
     * Strips given string and leaves only chars specified
539
     *
540
     * @param string $uString     original string
541
     * @param string $uValidChars set of chars are going to be allowed
542
     *
543
     * @return string stripped output
544
     */
545
    public static function strip($uString, $uValidChars)
546
    {
547
        $tOutput = "";
548
549 View Code Duplication
        for ($tCount = 0, $tLen = self::length($uString); $tCount < $tLen; $tCount++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
550
            $tChar = self::substr($uString, $tCount, 1);
551
            if (self::strpos($uValidChars, $tChar) === false) {
552
                continue;
553
            }
554
555
            $tOutput .= $tChar;
556
        }
557
558
        return $tOutput;
559
    }
560
561
    /**
562
     * Escapes single quotes in a string
563
     *
564
     * @param string $uString original string
565
     * @param bool   $uCover  whether cover output with single quotes or not
566
     *
567
     * @return string final output
568
     */
569 View Code Duplication
    public static function squote($uString, $uCover = false)
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...
570
    {
571
        // if ($uString === null) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
572
        //     return "null";
573
        // }
574
575
        if ($uCover) {
576
            return "'" .
577
                str_replace(
578
                    self::$defaults["squote_replacement"][0],
579
                    self::$defaults["squote_replacement"][1],
580
                    $uString
581
                ) .
582
                "'";
583
        }
584
585
        return str_replace(
586
            self::$defaults["squote_replacement"][0],
587
            self::$defaults["squote_replacement"][1],
588
            $uString
589
        );
590
    }
591
592
    /**
593
     * Escapes double quotes in a string
594
     *
595
     * @param string $uString original string
596
     * @param bool   $uCover  whether cover output with double quotes or not
597
     *
598
     * @return string final output
599
     */
600 View Code Duplication
    public static function dquote($uString, $uCover = false)
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...
601
    {
602
        // if ($uString === null) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
603
        //     return "null";
604
        // }
605
606
        if ($uCover) {
607
            return "'" .
608
            str_replace(
609
                self::$defaults["dquote_replacement"][0],
610
                self::$defaults["dquote_replacement"][1],
611
                $uString
612
            ) .
613
            "'";
614
        }
615
616
        return str_replace(
617
            self::$defaults["dquote_replacement"][0],
618
            self::$defaults["dquote_replacement"][1],
619
            $uString
620
        );
621
    }
622
623
    /**
624
     * Escapes single quotes in a set of strings
625
     *
626
     * @param string $uArray set of original strings
627
     * @param bool   $uCover whether cover output with single quotes or not
628
     *
629
     * @return array final output
630
     */
631 View Code Duplication
    public static function squoteArray($uArray, $uCover = false)
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...
632
    {
633
        $tArray = [];
634
        foreach ((array)$uArray as $tKey => $tValue) {
635
            if ($uCover) {
636
                $tArray[$tKey] = "'" .
637
                    str_replace(
638
                        self::$defaults["squote_replacement"][0],
639
                        self::$defaults["squote_replacement"][1],
640
                        $tValue
641
                    ) .
642
                    "'";
643
                continue;
644
            }
645
646
            $tArray[$tKey] = str_replace(
647
                self::$defaults["squote_replacement"][0],
648
                self::$defaults["squote_replacement"][1],
649
                $tValue
650
            );
651
        }
652
653
        return $tArray;
654
    }
655
656
    /**
657
     * Escapes double quotes in a set of strings
658
     *
659
     * @param string $uArray set of original strings
660
     * @param bool   $uCover whether cover output with double quotes or not
661
     *
662
     * @return array final output
663
     */
664 View Code Duplication
    public static function dquoteArray($uArray, $uCover = false)
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...
665
    {
666
        $tArray = [];
667
        foreach ((array)$uArray as $tKey => $tValue) {
668
            if ($uCover) {
669
                $tArray[$tKey] = "\"" .
670
                    str_replace(
671
                        self::$defaults["dquote_replacement"][0],
672
                        self::$defaults["dquote_replacement"][1],
673
                        $tValue
674
                    ) .
675
                    "\"";
676
                continue;
677
            }
678
679
            $tArray[$tKey] = str_replace(
680
                self::$defaults["dquote_replacement"][0],
681
                self::$defaults["dquote_replacement"][1],
682
                $tValue
683
            );
684
        }
685
686
        return $tArray;
687
    }
688
689
    /**
690
     * Replaces CRLF characters with given string
691
     *
692
     * @param string $uString original string
693
     * @param string $uBreaks string that breaks are replaced with.
694
     *
695
     * @return string final output
696
     */
697
    public static function replaceBreaks($uString, $uBreaks = "<br />")
698
    {
699
        return str_replace(["\r", "\n"], ["", $uBreaks], $uString);
700
    }
701
702
    /**
703
     * Cuts a string if it exceeds given length
704
     *
705
     * @param string $uString original string
706
     * @param int    $uLength maximum length
707
     * @param string $uSuffix a suffix that is going to be added to end of string if original string is cut
708
     *
709
     * @return string final output
710
     */
711
    public static function cut($uString, $uLength, $uSuffix = "...")
712
    {
713
        if (self::length($uString) <= $uLength) {
714
            return $uString;
715
        }
716
717
        return rtrim(self::substr($uString, 0, $uLength)) . $uSuffix;
718
    }
719
720
    /**
721
     * Encodes html characters
722
     *
723
     * @param string $uString original string that is going to be encoded
724
     *
725
     * @return string encoded string
726
     */
727 View Code Duplication
    public static function encodeHtml($uString)
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...
728
    {
729
        return str_replace(
730
            ["&", "\"", "<", ">"],
731
            ["&amp;", "&quot;", "&lt;", "&gt;"],
732
            $uString
733
        );
734
    }
735
736
    /**
737
     * Decodes encoded html characters
738
     *
739
     * @param string $uString original string that has encoded characters
740
     *
741
     * @return string decoded string
742
     */
743 View Code Duplication
    public static function decodeHtml($uString)
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...
744
    {
745
        return str_replace(
746
            ["&amp;", "&quot;", "&lt;", "&gt;"],
747
            ["&", "\"", "<", ">"],
748
            $uString
749
        );
750
    }
751
752
    /**
753
     * Escapes special html characters
754
     *
755
     * @param string $uString original string that is going to be escaped
756
     *
757
     * @return string escaped string
758
     */
759
    public static function escapeHtml($uString)
760
    {
761
        return htmlspecialchars($uString, ENT_COMPAT | ENT_HTML5);
762
    }
763
764
    /**
765
     * Unescapes escaped html characters
766
     *
767
     * @param string $uString original string that has escaped characters
768
     *
769
     * @return string unescaped string
770
     */
771
    public static function unescapeHtml($uString)
772
    {
773
        return htmlspecialchars_decode($uString, ENT_COMPAT | ENT_HTML5);
774
    }
775
776
    /**
777
     * Transforms the string to lowercase
778
     *
779
     * @param string $uString original string
780
     *
781
     * @return string lowercased string
782
     */
783
    public static function toLower($uString)
784
    {
785
        return mb_convert_case($uString, MB_CASE_LOWER);
786
    }
787
788
    /**
789
     * Transforms the string to uppercase
790
     *
791
     * @param string $uString original string
792
     *
793
     * @return string uppercased string
794
     */
795
    public static function toUpper($uString)
796
    {
797
        return mb_convert_case($uString, MB_CASE_UPPER);
798
    }
799
800
    /**
801
     * Capitalizes the first character of the given string
802
     *
803
     * @param string $uString original string
804
     *
805
     * @return string the string with the first character capitalized
806
     */
807
    public static function capitalize($uString)
808
    {
809
        return mb_convert_case($uString, MB_CASE_TITLE);
810
    }
811
812
    /**
813
     * Capitalizes all first characters of the words in the given string
814
     *
815
     * @param string $uString original string
816
     * @param string $uSpace  the space character
817
     *
818
     * @return string the string with the first characters of the words capitalized
819
     */
820
    public static function capitalizeWords($uString, $uSpace = " ")
821
    {
822
        $tOutput = "";
823
        $tCapital = true;
824
825
        for ($tPos = 0, $tLen = self::length($uString); $tPos < $tLen; $tPos++) {
826
            $tChar = self::substr($uString, $tPos, 1);
827
828
            if ($tChar === $uSpace) {
829
                $tCapital = true;
830
            } elseif ($tCapital) {
831
                $tOutput .= self::toUpper($tChar);
832
                $tCapital = false;
833
                continue;
834
            }
835
836
            $tOutput .= $tChar;
837
        }
838
839
        return $tOutput;
840
    }
841
842
    /**
843
     * Returns the length of the string
844
     *
845
     * @param string $uString the input string
846
     *
847
     * @return int string length
848
     */
849
    public static function length($uString)
850
    {
851
        // return mb_strlen($uString);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
852
        return strlen(utf8_decode($uString));
853
    }
854
855
    /**
856
     * Checks the string if it starts with another string.
857
     *
858
     * @param string $uString the input string
859
     * @param string $uNeedle another string
860
     *
861
     * @return bool true if first string starts with second one
862
     */
863 View Code Duplication
    public static function startsWith($uString, $uNeedle)
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...
864
    {
865
        // $tLength = mb_strlen($uNeedle);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
866
        $tLength = strlen(utf8_decode($uNeedle));
867
        if ($tLength === 0) {
868
            return true;
869
        }
870
871
        return (mb_substr($uString, 0, $tLength) === $uNeedle);
872
    }
873
874
    /**
875
     * Checks the string if it ends with another string
876
     *
877
     * @param string $uString the input string
878
     * @param string $uNeedle another string
879
     *
880
     * @return bool true if first string ends with second one
881
     */
882 View Code Duplication
    public static function endsWith($uString, $uNeedle)
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...
883
    {
884
        // $tLength = mb_strlen($uNeedle);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
885
        $tLength = strlen(utf8_decode($uNeedle));
886
        if ($tLength === 0) {
887
            return true;
888
        }
889
890
        return (mb_substr($uString, -$tLength) === $uNeedle);
891
    }
892
893
    /**
894
     * Returns part of the string
895
     *
896
     * @param string $uString original string
897
     * @param int    $uStart  start offset
898
     * @param int    $uLength length
899
     *
900
     * @return string sliced substring
901
     */
902
    public static function substr($uString, $uStart, $uLength = null)
903
    {
904
        if ($uLength === null) {
905
            return mb_substr($uString, $uStart);
906
        }
907
908
        return mb_substr($uString, $uStart, $uLength);
909
    }
910
911
    /**
912
     * Find the offset of the first occurrence of given string
913
     *
914
     * @param string $uString the input string
915
     * @param string $uNeedle another string
916
     * @param int    $uOffset start offset
917
     *
918
     * @return int position of first occurence
919
     */
920
    public static function strpos($uString, $uNeedle, $uOffset = 0)
921
    {
922
        return mb_strpos($uString, $uNeedle, $uOffset);
923
    }
924
925
    /**
926
     * Returns the substring starting from and including the first occurrence of given string
927
     *
928
     * @param string $uString       the input string
929
     * @param string $uNeedle       another string
930
     * @param bool   $uBeforeNeedle start offset
931
     *
932
     * @return string sliced substring, or false if string is not found
933
     */
934
    public static function strstr($uString, $uNeedle, $uBeforeNeedle = false)
935
    {
936
        return mb_strstr($uString, $uNeedle, $uBeforeNeedle);
937
    }
938
939
    /**
940
     * Returns the given bytes in short representation
941
     *
942
     * @param int $uSize      size
943
     * @param int $uPrecision precision
944
     *
945
     * @return string short representation
946
     */
947 View Code Duplication
    public static function sizeCalc($uSize, $uPrecision = 0)
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...
948
    {
949
        static $sSize = " KMGT";
950
        for ($tCount = 0; $uSize >= 1024; $uSize /= 1024, $tCount++) {
951
            ;
952
        }
953
954
        return round($uSize, $uPrecision) . " {$sSize[$tCount]}B";
955
    }
956
957
    /**
958
     * Returns the given number in short representation
959
     *
960
     * @param int $uSize      size
961
     * @param int $uPrecision precision
962
     *
963
     * @return string short representation
964
     */
965 View Code Duplication
    public static function quantityCalc($uSize, $uPrecision = 0)
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...
966
    {
967
        static $sSize = " KMGT";
968
        for ($tCount = 0; $uSize >= 1000; $uSize /= 1000, $tCount++) {
969
            ;
970
        }
971
972
        return round($uSize, $uPrecision) . $sSize[$tCount];
973
    }
974
975
    /**
976
     * Returns the given period in short representation
977
     *
978
     * @param int $uTime time period
979
     *
980
     * @return string short representation
981
     */
982
    public static function timeCalc($uTime)
983
    {
984
        if ($uTime >= 60) {
985
            return number_format($uTime / 60, 2, ".", "") . "m";
986
        }
987
988
        if ($uTime >= 1) {
989
            return number_format($uTime, 2, ".", "") . "s";
990
        }
991
992
        return number_format($uTime * 1000, 2, ".", "") . "ms";
993
    }
994
995
    /**
996
     * Removes accented characters in a string
997
     *
998
     * @param string $uString the input string
999
     *
1000
     * @return string unaccented string
1001
     */
1002
    public static function removeAccent($uString)
1003
    {
1004
        static $tAccented = [
1005
            'À',
1006
            'Á',
1007
            'Â',
1008
            'Ã',
1009
            'Ä',
1010
            'Å',
1011
            'Æ',
1012
            'Ç',
1013
            'È',
1014
            'É',
1015
            'Ê',
1016
            'Ë',
1017
            'Ì',
1018
            'Í',
1019
            'Î',
1020
            'Ï',
1021
            'Ð',
1022
            'Ñ',
1023
            'Ò',
1024
            'Ó',
1025
            'Ô',
1026
            'Õ',
1027
            'Ö',
1028
            'Ø',
1029
            'Ù',
1030
            'Ú',
1031
            'Û',
1032
            'Ü',
1033
            'Ý',
1034
            'ß',
1035
            'à',
1036
            'á',
1037
            'â',
1038
            'ã',
1039
            'ä',
1040
            'å',
1041
            'æ',
1042
            'ç',
1043
            'è',
1044
            'é',
1045
            'ê',
1046
            'ë',
1047
            'ì',
1048
            'í',
1049
            'î',
1050
            'ï',
1051
            'ñ',
1052
            'ò',
1053
            'ó',
1054
            'ô',
1055
            'õ',
1056
            'ö',
1057
            'ø',
1058
            'ù',
1059
            'ú',
1060
            'û',
1061
            'ü',
1062
            'ý',
1063
            'ÿ',
1064
            'Ā',
1065
            'ā',
1066
            'Ă',
1067
            'ă',
1068
            'Ą',
1069
            'ą',
1070
            'Ć',
1071
            'ć',
1072
            'Ĉ',
1073
            'ĉ',
1074
            'Ċ',
1075
            'ċ',
1076
            'Č',
1077
            'č',
1078
            'Ď',
1079
            'ď',
1080
            'Đ',
1081
            'đ',
1082
            'Ē',
1083
            'ē',
1084
            'Ĕ',
1085
            'ĕ',
1086
            'Ė',
1087
            'ė',
1088
            'Ę',
1089
            'ę',
1090
            'Ě',
1091
            'ě',
1092
            'Ĝ',
1093
            'ĝ',
1094
            'Ğ',
1095
            'ğ',
1096
            'Ġ',
1097
            'ġ',
1098
            'Ģ',
1099
            'ģ',
1100
            'Ĥ',
1101
            'ĥ',
1102
            'Ħ',
1103
            'ħ',
1104
            'Ĩ',
1105
            'ĩ',
1106
            'Ī',
1107
            'ī',
1108
            'Ĭ',
1109
            'ĭ',
1110
            'Į',
1111
            'į',
1112
            'İ',
1113
            'ı',
1114
            'IJ',
1115
            'ij',
1116
            'Ĵ',
1117
            'ĵ',
1118
            'Ķ',
1119
            'ķ',
1120
            'Ĺ',
1121
            'ĺ',
1122
            'Ļ',
1123
            'ļ',
1124
            'Ľ',
1125
            'ľ',
1126
            'Ŀ',
1127
            'ŀ',
1128
            'Ł',
1129
            'ł',
1130
            'Ń',
1131
            'ń',
1132
            'Ņ',
1133
            'ņ',
1134
            'Ň',
1135
            'ň',
1136
            'ʼn',
1137
            'Ō',
1138
            'ō',
1139
            'Ŏ',
1140
            'ŏ',
1141
            'Ő',
1142
            'ő',
1143
            'Œ',
1144
            'œ',
1145
            'Ŕ',
1146
            'ŕ',
1147
            'Ŗ',
1148
            'ŗ',
1149
            'Ř',
1150
            'ř',
1151
            'Ś',
1152
            'ś',
1153
            'Ŝ',
1154
            'ŝ',
1155
            'Ş',
1156
            'ş',
1157
            'Š',
1158
            'š',
1159
            'Ţ',
1160
            'ţ',
1161
            'Ť',
1162
            'ť',
1163
            'Ŧ',
1164
            'ŧ',
1165
            'Ũ',
1166
            'ũ',
1167
            'Ū',
1168
            'ū',
1169
            'Ŭ',
1170
            'ŭ',
1171
            'Ů',
1172
            'ů',
1173
            'Ű',
1174
            'ű',
1175
            'Ų',
1176
            'ų',
1177
            'Ŵ',
1178
            'ŵ',
1179
            'Ŷ',
1180
            'ŷ',
1181
            'Ÿ',
1182
            'Ź',
1183
            'ź',
1184
            'Ż',
1185
            'ż',
1186
            'Ž',
1187
            'ž',
1188
            'ſ',
1189
            'ƒ',
1190
            'Ơ',
1191
            'ơ',
1192
            'Ư',
1193
            'ư',
1194
            'Ǎ',
1195
            'ǎ',
1196
            'Ǐ',
1197
            'ǐ',
1198
            'Ǒ',
1199
            'ǒ',
1200
            'Ǔ',
1201
            'ǔ',
1202
            'Ǖ',
1203
            'ǖ',
1204
            'Ǘ',
1205
            'ǘ',
1206
            'Ǚ',
1207
            'ǚ',
1208
            'Ǜ',
1209
            'ǜ',
1210
            'Ǻ',
1211
            'ǻ',
1212
            'Ǽ',
1213
            'ǽ',
1214
            'Ǿ',
1215
            'ǿ',
1216
            'þ',
1217
            'Þ',
1218
            'ð'
1219
        ];
1220
        static $tStraight = [
1221
            'A',
1222
            'A',
1223
            'A',
1224
            'A',
1225
            'A',
1226
            'A',
1227
            'AE',
1228
            'C',
1229
            'E',
1230
            'E',
1231
            'E',
1232
            'E',
1233
            'I',
1234
            'I',
1235
            'I',
1236
            'I',
1237
            'D',
1238
            'N',
1239
            'O',
1240
            'O',
1241
            'O',
1242
            'O',
1243
            'O',
1244
            'O',
1245
            'U',
1246
            'U',
1247
            'U',
1248
            'U',
1249
            'Y',
1250
            's',
1251
            'a',
1252
            'a',
1253
            'a',
1254
            'a',
1255
            'a',
1256
            'a',
1257
            'ae',
1258
            'c',
1259
            'e',
1260
            'e',
1261
            'e',
1262
            'e',
1263
            'i',
1264
            'i',
1265
            'i',
1266
            'i',
1267
            'n',
1268
            'o',
1269
            'o',
1270
            'o',
1271
            'o',
1272
            'o',
1273
            'o',
1274
            'u',
1275
            'u',
1276
            'u',
1277
            'u',
1278
            'y',
1279
            'y',
1280
            'A',
1281
            'a',
1282
            'A',
1283
            'a',
1284
            'A',
1285
            'a',
1286
            'C',
1287
            'c',
1288
            'C',
1289
            'c',
1290
            'C',
1291
            'c',
1292
            'C',
1293
            'c',
1294
            'D',
1295
            'd',
1296
            'D',
1297
            'd',
1298
            'E',
1299
            'e',
1300
            'E',
1301
            'e',
1302
            'E',
1303
            'e',
1304
            'E',
1305
            'e',
1306
            'E',
1307
            'e',
1308
            'G',
1309
            'g',
1310
            'G',
1311
            'g',
1312
            'G',
1313
            'g',
1314
            'G',
1315
            'g',
1316
            'H',
1317
            'h',
1318
            'H',
1319
            'h',
1320
            'I',
1321
            'i',
1322
            'I',
1323
            'i',
1324
            'I',
1325
            'i',
1326
            'I',
1327
            'i',
1328
            'I',
1329
            'i',
1330
            'IJ',
1331
            'ij',
1332
            'J',
1333
            'j',
1334
            'K',
1335
            'k',
1336
            'L',
1337
            'l',
1338
            'L',
1339
            'l',
1340
            'L',
1341
            'l',
1342
            'L',
1343
            'l',
1344
            'l',
1345
            'l',
1346
            'N',
1347
            'n',
1348
            'N',
1349
            'n',
1350
            'N',
1351
            'n',
1352
            'n',
1353
            'O',
1354
            'o',
1355
            'O',
1356
            'o',
1357
            'O',
1358
            'o',
1359
            'OE',
1360
            'oe',
1361
            'R',
1362
            'r',
1363
            'R',
1364
            'r',
1365
            'R',
1366
            'r',
1367
            'S',
1368
            's',
1369
            'S',
1370
            's',
1371
            'S',
1372
            's',
1373
            'S',
1374
            's',
1375
            'T',
1376
            't',
1377
            'T',
1378
            't',
1379
            'T',
1380
            't',
1381
            'U',
1382
            'u',
1383
            'U',
1384
            'u',
1385
            'U',
1386
            'u',
1387
            'U',
1388
            'u',
1389
            'U',
1390
            'u',
1391
            'U',
1392
            'u',
1393
            'W',
1394
            'w',
1395
            'Y',
1396
            'y',
1397
            'Y',
1398
            'Z',
1399
            'z',
1400
            'Z',
1401
            'z',
1402
            'Z',
1403
            'z',
1404
            's',
1405
            'f',
1406
            'O',
1407
            'o',
1408
            'U',
1409
            'u',
1410
            'A',
1411
            'a',
1412
            'I',
1413
            'i',
1414
            'O',
1415
            'o',
1416
            'U',
1417
            'u',
1418
            'U',
1419
            'u',
1420
            'U',
1421
            'u',
1422
            'U',
1423
            'u',
1424
            'U',
1425
            'u',
1426
            'A',
1427
            'a',
1428
            'AE',
1429
            'ae',
1430
            'O',
1431
            'o',
1432
            'b',
1433
            'B',
1434
            'o'
1435
        ];
1436
1437
        return str_replace($tAccented, $tStraight, $uString);
1438
    }
1439
1440
    /**
1441
     * Removes invisible characters in a string
1442
     *
1443
     * @param string $uString the input string
1444
     *
1445
     * @return string string with invisible characters removed
1446
     */
1447
    public static function removeInvisibles($uString)
1448
    {
1449
        static $tInvisibles = [
1450
            0,
1451
            1,
1452
            2,
1453
            3,
1454
            4,
1455
            5,
1456
            6,
1457
            7,
1458
            8,
1459
            11,
1460
            12,
1461
            14,
1462
            15,
1463
            16,
1464
            17,
1465
            18,
1466
            19,
1467
            20,
1468
            21,
1469
            22,
1470
            23,
1471
            24,
1472
            25,
1473
            26,
1474
            27,
1475
            28,
1476
            29,
1477
            30,
1478
            31,
1479
            127
1480
        ];
1481
        $tOutput = "";
1482
1483 View Code Duplication
        for ($tCount = 0, $tLen = self::length($uString); $tCount < $tLen; $tCount++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1484
            $tChar = self::substr($uString, $tCount, 1);
1485
1486
            if (in_array(ord($tChar), $tInvisibles)) {
1487
                continue;
1488
            }
1489
1490
            $tOutput .= $tChar;
1491
        }
1492
1493
        return $tOutput;
1494
    }
1495
1496
    /**
1497
     * Returns a transformed string that can be used as unixname and url portion
1498
     *
1499
     * @param string $uString    the input string
1500
     * @param string $uSpaceChar char that is used for spacing
1501
     *
1502
     * @return string transformed string
1503
     */
1504
    public static function slug($uString, $uSpaceChar = "-")
1505
    {
1506
        $uString = self::removeInvisibles($uString);
1507
        $uString = self::removeAccent($uString);
1508
        $uString = strtolower(trim($uString));
1509
        $uString = preg_replace("/[^a-z0-9-]/", $uSpaceChar, $uString);
1510
        $uString = preg_replace("/-+/", $uSpaceChar, $uString);
1511
1512
        return $uString;
1513
    }
1514
1515
    /**
1516
     * Converts a number to specified base
1517
     *
1518
     * @param int    $uNumber    the input number
1519
     * @param string $uBaseChars charset available for target base
1520
     *
1521
     * @return string converted base
1522
     */
1523
    public static function toBase($uNumber, $uBaseChars)
1524
    {
1525
        $tBaseLength = strlen($uBaseChars);
1526
        $tResult = "";
1527
1528
        do {
1529
            $tIndex = $uNumber % $tBaseLength;
1530
            // if ($tIndex < 0) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1531
            //    $tIndex += $tBaseLength;
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1532
            // }
1533
1534
            $tResult = $uBaseChars[$tIndex] . $tResult;
1535
            $uNumber = ($uNumber - $tIndex) / $tBaseLength;
1536
        } while ($uNumber > 0);
1537
1538
        return $tResult;
1539
    }
1540
1541
    /**
1542
     * Converts a number from specified base
1543
     *
1544
     * @param int    $uNumber    the input number
1545
     * @param string $uBaseChars charset available for source base
1546
     *
1547
     * @return string converted base
1548
     */
1549
    public static function fromBase($uNumber, $uBaseChars)
1550
    {
1551
        $tBaseLength = strlen($uBaseChars);
1552
        $tResult = strpos($uBaseChars, $uNumber[0]);
1553
1554
        for ($i = 1, $tLength = strlen($uNumber); $i < $tLength; $i++) {
1555
            $tResult = ($tBaseLength * $tResult) + strpos($uBaseChars, $uNumber[$i]);
1556
        }
1557
1558
        return $tResult;
1559
    }
1560
1561
    /**
1562
     * Converts a number to base62
1563
     *
1564
     * @param int $uNumber the input number
1565
     *
1566
     * @return string converted base
1567
     */
1568
    public static function toBase62($uNumber)
1569
    {
1570
        return self::toBase($uNumber, self::$defaults["baseconversion_base62_chars"]);
1571
    }
1572
1573
    /**
1574
     * Converts a number from base62
1575
     *
1576
     * @param int $uNumber the input number
1577
     *
1578
     * @return string converted base
1579
     */
1580
    public static function fromBase62($uNumber)
1581
    {
1582
        return self::fromBase($uNumber, self::$defaults["baseconversion_base62_chars"]);
1583
    }
1584
1585
    /**
1586
     * Converts a number to url base
1587
     *
1588
     * @param int $uNumber the input number
1589
     *
1590
     * @return string converted base
1591
     */
1592
    public static function toBaseUrl($uNumber)
1593
    {
1594
        return self::toBase($uNumber, self::$defaults["baseconversion_url_chars"]);
1595
    }
1596
1597
    /**
1598
     * Converts a number from url base
1599
     *
1600
     * @param int $uNumber the input number
1601
     *
1602
     * @return string converted base
1603
     */
1604
    public static function fromBaseUrl($uNumber)
1605
    {
1606
        return self::fromBase($uNumber, self::$defaults["baseconversion_url_chars"]);
1607
    }
1608
1609
    /**
1610
     * Shortens a uuid to use it in compact format
1611
     *
1612
     * @param string $uString the input string
1613
     *
1614
     * @return string shortened uuid
1615
     */
1616
    public static function shortenUuid($uString)
1617
    {
1618
        $tParts = [
1619
            substr($uString, 0, 8),
1620
            substr($uString, 9, 4),
1621
            substr($uString, 14, 4),
1622
            substr($uString, 19, 4),
1623
            substr($uString, 24, 6),
1624
            substr($uString, 30, 6)
1625
        ];
1626
1627
        $tShortened = "";
1628
        foreach ($tParts as $tPart) {
1629
            $tEncoded = base_convert($tPart, 16, 10);
1630
            $tShortened .= self::toBase($tEncoded, self::$defaults["baseconversion_url_chars"]);
1631
        }
1632
1633
        return $tShortened;
1634
    }
1635
1636
    /**
1637
     * Unshortens a uuid to restore it in compact format
1638
     *
1639
     * @param string $uString the input string
1640
     *
1641
     * @return string unshortened uuid
1642
     */
1643
    public static function unshortenUuid($uString)
1644
    {
1645
        $tParts = [
1646
            substr($uString, 0, 5),
1647
            substr($uString, 5, 3),
1648
            substr($uString, 8, 3),
1649
            substr($uString, 11, 3),
1650
            substr($uString, 14, 4),
1651
            substr($uString, 18, 4)
1652
        ];
1653
1654
        $tUnshortened = "";
1655
        $tIndex = 0;
1656
        foreach ($tParts as $tPart) {
1657
            $tDecoded = self::fromBase($tPart, self::$defaults["baseconversion_url_chars"]);
1658
            $tUnshortened .= base_convert($tDecoded, 10, 16);
1659
            if ($tIndex++ <= 3) {
1660
                $tUnshortened .= "-";
1661
            }
1662
        }
1663
1664
        return $tUnshortened;
1665
    }
1666
1667
    /**
1668
     * Returns the ordinal pronounce of a number
1669
     *
1670
     * @param int $uNumber the input number
1671
     *
1672
     * @return string ordinal string
1673
     */
1674
    public static function ordinalize($uNumber)
1675
    {
1676
        if (in_array(($uNumber % 100), range(11, 13))) {
1677
            return $uNumber . "th";
1678
        }
1679
1680
        $tMod = $uNumber % 10;
1681
        if ($tMod === 1) {
1682
            return $uNumber . "st";
1683
        } elseif ($tMod === 2) {
1684
            return $uNumber . "nd";
1685
        } elseif ($tMod === 3) {
1686
            return $uNumber . "rd";
1687
        } else {
1688
            return $uNumber . "th";
1689
        }
1690
    }
1691
1692
    /**
1693
     * Swaps two variables in memory
1694
     *
1695
     * @param mixed $uVariable1 first variable
1696
     * @param mixed $uVariable2 second variable
1697
     *
1698
     * @return void
1699
     */
1700
    public static function swap(&$uVariable1, &$uVariable2)
1701
    {
1702
        $tTemp = $uVariable1;
1703
        $uVariable1 = $uVariable2;
1704
        $uVariable2 = $tTemp;
1705
    }
1706
1707
    /**
1708
     * Sanitize a filename to prevent filesystem vulnerabilities
1709
     *
1710
     * @param string $uFilename     the input filename
1711
     * @param bool   $uRemoveAccent whether accented characters are going to be removed or not
1712
     * @param bool   $uRemoveSpaces whether spacing is going to be replaced with dashes or not
1713
     *
1714
     * @return string sanitized filename
1715
     *
1716
     * @todo optionally explode by '/', sanitize between
1717
     */
1718
    public static function sanitizeFilename($uFilename, $uRemoveAccent = false, $uRemoveSpaces = false)
1719
    {
1720
        static $sReplaceChars = [
1721
            [
1722
                "\\",
1723
                "/",
1724
                ":",
1725
                "?",
1726
                "*",
1727
                "'",
1728
                "\"",
1729
                "<",
1730
                ">",
1731
                "|",
1732
                ".",
1733
                "+"
1734
            ],
1735
            [
1736
                "-",
1737
                "-",
1738
                "-",
1739
                "-",
1740
                "-",
1741
                "-",
1742
                "-",
1743
                "-",
1744
                "-",
1745
                "-",
1746
                "-",
1747
                "-"
1748
            ]
1749
        ];
1750
1751
        $tPathInfo = pathinfo($uFilename);
1752
        $tFilename = str_replace($sReplaceChars[0], $sReplaceChars[1], $tPathInfo["filename"]);
1753
1754
        if (isset($tPathInfo["extension"])) {
1755
            $tFilename .= "." . str_replace($sReplaceChars[0], $sReplaceChars[1], $tPathInfo["extension"]);
1756
        }
1757
1758
        $tFilename = self::removeInvisibles($tFilename);
1759
        if ($uRemoveAccent) {
1760
            $tFilename = self::removeAccent($tFilename);
1761
        }
1762
1763
        if ($uRemoveSpaces) {
1764
            $tFilename = str_replace(" ", "_", $tFilename);
1765
        }
1766
1767
        if (isset($tPathInfo["dirname"]) && $tPathInfo["dirname"] !== ".") {
1768
            return rtrim(str_replace("\\", "/", $tPathInfo["dirname"]), "/") . "/{$tFilename}";
1769
        }
1770
1771
        return $tFilename;
1772
    }
1773
1774
    /**
1775
     * Returns the best matching path among the alternatives
1776
     *
1777
     * @param array  $uPathList set of paths
1778
     * @param string $uFullPath the full path
1779
     *
1780
     * @return string|false the path if found, false otherwise
1781
     */
1782
    public function matchPaths($uPathList, $uFullPath)
1783
    {
1784
        $uFullPath = ltrim(str_replace("\\", "/", $uFullPath), "/");
1785
1786
        $tLastFound = [0, false];
1787
1788
        foreach ($uPathList as $tKey) {
1789
            $tKey = trim(str_replace("\\", "/", $tKey), "/") . "/";
1790
            $tKeyLength = strlen($tKey);
1791
1792
            if ($tLastFound[0] < $tKeyLength && strpos($uFullPath, $tKey) === 0) {
1793
                $tLastFound = [$tKeyLength, $tKey];
1794
            }
1795
        }
1796
1797
        return $tLastFound[1];
1798
    }
1799
1800
    /**
1801
     * Captures and replaces http links in a string
1802
     *
1803
     * @param string   $uString   the input string
1804
     * @param callable $uCallback closure that gets each url address as a parameter and outputs replaced string
1805
     *
1806
     * @return string updated string
1807
     */
1808
    public static function convertLinks($uString, /* callable */ $uCallback)
1809
    {
1810
        return preg_replace_callback(
1811
            "#((https?://)?([-\\w]+\\.[-\\w\\.]+)+\\w(:\\d+)?(/([-\\w/_\\.]*(\\?\\S+)?)?)*)#",
1812
            $uCallback,
1813
            $uString
1814
        );
1815
    }
1816
}
1817