Completed
Push — master ( 1efa22...d57925 )
by Lorenzo
02:40
created

string.php ➔ str_contains()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 10
nc 5
nop 2
dl 0
loc 18
rs 7.756
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Generate random string (password) from a different charset based on $secLevel.
5
 * $secLevel=0 [a-z] charset.
6
 * $secLevel=1 [a-z0-9] charset.
7
 * $secLevel=2 [A-Za-z0-9] charset.
8
 * $secLevel=3 [A-Za-z0-9-_$!+&%?=*#@] charset.
9
 * @param int $length
10
 * @param int $secLevel
11
 * @return string
12
 */
13
function generateRandomPassword(int $length = 10, int $secLevel = 2) : string
14
{
15
    $charset = 'abcdefghijklmnopqrstuvwxyz';
16
    if ($secLevel == 1) {
17
        $charset = 'abcdefghijklmnopqrstuvwxyz1234567890';
18
    } elseif ($secLevel == 2) {
19
        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';
20
    } elseif ($secLevel >= 3) {
21
        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_$!+&%?=*#@';
22
    }
23
24
    return generateRandomString($length, '', $charset);
25
}
26
27
/**
28
 * Generate random string from [0-9A-Za-z] charset.
29
 * You may extend charset by passing $extChars (i.e. add these chars to existing).
30
 * Ex.: $extChars='-_$!' implies that the final charset is [0-9A-Za-z-_$!]
31
 * If $newChars is set, the default charset are replaced by this and $extChars was ignored.
32
 * Ex.: $newChars='0123456789' implies that the final charset is [0123456789]
33
 * @param int $length
34
 * @param string $extChars
35
 * @param string $newChars
36
 * @return string
37
 */
38
function generateRandomString(int $length = 10, string $extChars = '', string $newChars = '') : string
39
{
40
    if ($length < 1) {
41
        $length = 1;
42
    }
43
44
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
45
    if ($newChars !== null && $newChars != '') {
46
        $characters = $newChars;
47
    } elseif ($extChars !== null && $extChars != '') {
48
        $characters .= $extChars;
49
    }
50
51
    $charactersLength = strlen($characters);
52
    $randomString = '';
53
54
    for ($i = 0; $i < $length; $i++) {
55
        $randomString .= $characters[random_int(0, $charactersLength - 1)];
56
    }
57
58
    return $randomString;
59
}
60
61
/**
62
 * *****************************************************
63
 * LARAVEL STRING HELPERS
64
 * With some adjustments
65
 * *****************************************************
66
 */
67
68
if (!function_exists('preg_replace_sub')) {
69
    /**
70
     * Replace a given pattern with each value in the array in sequentially.
71
     *
72
     * @param  string $pattern
73
     * @param  array $replacements
74
     * @param  string $subject
75
     * @return string
76
     */
77
    function preg_replace_sub($pattern, &$replacements, $subject)
78
    {
79
        return preg_replace_callback($pattern, function () use (&$replacements) {
80
            return array_shift($replacements);
81
        }, $subject);
82
    }
83
}
84
85
if (!function_exists('snake_case')) {
86
    /**
87
     * Convert a string to snake case.
88
     *
89
     * @param  string $value
90
     * @param  string $delimiter
91
     * @return string
92
     */
93
    function snake_case($value, $delimiter = '_')
94
    {
95
        $snakeCache = [];
96
        $key = $value . $delimiter;
97
        if (isset($snakeCache[$key])) {
98
            return $snakeCache[$key];
99
        }
100
        if (!ctype_lower($value)) {
101
            $value = strtolower(preg_replace('/(.)(?=[A-Z])/', '$1' . $delimiter, $value));
102
        }
103
        return $snakeCache[$key] = $value;
104
    }
105
}
106
107
if (!function_exists('str_random')) {
108
    /**
109
     * Generate a more truly "random" alpha-numeric string with openssl.
110
     * If openssl_random_pseudo_bytes not exists, use simple legacy function
111
     *
112
     * @param  int $length
113
     * @return string
114
     *
115
     * @throws \RuntimeException
116
     */
117
    function str_random(int $length = 16)
118
    {
119
        if ($length < 0) {
120
            $length = 16;
121
        }
122
123
        if (!function_exists('openssl_random_pseudo_bytes')) {
124
            return generateRandomString($length);
125
        }
126
        $bytes = openssl_random_pseudo_bytes($length * 2);
127
        if ($bytes === false) {
128
            throw new RuntimeException('Unable to generate random string.');
129
        }
130
        return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
131
    }
132
}
133
134
if (!function_exists('ends_with')) {
135
    /**
136
     * Determine if a given string ends with a given substring.
137
     *
138
     * @param  string $haystack
139
     * @param  string|array $needles
140
     * @return bool
141
     */
142
    function ends_with($haystack, $needles)
143
    {
144
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
145
            return false;
146
        }
147
148
        foreach ((array)$needles as $needle) {
149
            if ((string)$needle === substr($haystack, -strlen($needle))) {
150
                return true;
151
            }
152
        }
153
        return false;
154
    }
155
}
156
157 View Code Duplication
if (!function_exists('ends_with_insensitive')) {
1 ignored issue
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...
158
    /**
159
     * Determine if a given string ends with a given substring (case insensitive).
160
     *
161
     * @param  string $haystack
162
     * @param  string|array $needles
163
     * @return bool
164
     */
165
    function ends_with_insensitive($haystack, $needles)
166
    {
167
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
168
            return false;
169
        }
170
171
        $haystack = strtolower($haystack);
172
        $needles = strtolower($needles);
173
174
        return ends_with($haystack, $needles);
175
    }
176
}
177
178
if (!function_exists('starts_with')) {
179
    /**
180
     * Determine if a given string starts with a given substring.
181
     *
182
     * @param  string $haystack
183
     * @param  string|array $needles
184
     * @return bool
185
     */
186
    function starts_with($haystack, $needles)
187
    {
188
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
189
            return false;
190
        }
191
192
        foreach ((array)$needles as $needle) {
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...
193
            if ($needle != '' && strpos($haystack, $needle) === 0) {
194
                return true;
195
            }
196
        }
197
        return false;
198
    }
199
}
200
201 View Code Duplication
if (!function_exists('starts_with_insensitive')) {
1 ignored issue
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...
202
    /**
203
     * Determine if a given string starts with a given substring (case insensitive).
204
     *
205
     * @param  string $haystack
206
     * @param  string|array $needles
207
     * @return bool
208
     */
209
    function starts_with_insensitive($haystack, $needles)
210
    {
211
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
212
            return false;
213
        }
214
215
        $haystack = strtolower($haystack);
216
        $needles = strtolower($needles);
217
218
        return starts_with($haystack, $needles);
219
    }
220
}
221
222
if (!function_exists('str_contains')) {
223
    /**
224
     * Determine if a given string contains a given substring.
225
     *
226
     * @param  string $haystack
227
     * @param  string|array $needles
228
     * @return bool
229
     */
230
    function str_contains(string $haystack, $needles)
231
    {
232
        if (isNullOrEmpty($haystack)) {
233
            return false;
234
        }
235
        if ((is_array($needles) && isNullOrEmptyArray($needles))
236
            || (!is_array($needles) && isNullOrEmpty($needles))
237
        ) {
238
            return false;
239
        }
240
241
        foreach ((array)$needles as $needle) {
242
            if ($needle != '' && strpos($haystack, $needle) !== false) {
243
                return true;
244
            }
245
        }
246
        return false;
247
    }
248
}
249
250 View Code Duplication
if (!function_exists('str_contains_insensitive')) {
1 ignored issue
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...
251
    /**
252
     * Determine if a given string contains a given substring (case insensitive).
253
     *
254
     * @param  string $haystack
255
     * @param  string|array $needles
256
     * @return bool
257
     */
258
    function str_contains_insensitive($haystack, $needles)
259
    {
260
        if (isNullOrEmpty($haystack) || isNullOrEmpty($needles)) {
261
            return false;
262
        }
263
264
        $haystack = strtolower($haystack);
265
        $needles = strtolower($needles);
266
267
        return str_contains($haystack, $needles);
268
    }
269
}
270
271
if (!function_exists('str_finish')) {
272
    /**
273
     * Cap a string with a single instance of a given value.
274
     *
275
     * @param  string $value
276
     * @param  string $cap
277
     * @return string
278
     */
279
    function str_finish($value, $cap)
280
    {
281
        if (isNullOrEmpty($value) || isNullOrEmpty($cap)) {
282
            return false;
283
        }
284
285
        $quoted = preg_quote($cap, '/');
286
        return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap;
287
    }
288
}
289
290 View Code Duplication
if (!function_exists('str_finish_insensitive')) {
1 ignored issue
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...
291
    /**
292
     * Cap a string with a single instance of a given value (Case Insensitive).
293
     *
294
     * @param  string $value
295
     * @param  string $cap
296
     * @return string
297
     */
298
    function str_finish_insensitive($value, $cap)
299
    {
300
        if (isNullOrEmpty($value) || isNullOrEmpty($cap)) {
301
            return false;
302
        }
303
304
        $value = strtolower($value);
305
        $cap = strtolower($cap);
306
307
        return str_finish($value, $cap);
308
    }
309
}
310
311
if (!function_exists('str_is')) {
312
    /**
313
     * Determine if a given string matches a given pattern.
314
     *
315
     * @param  string $pattern
316
     * @param  string $value
317
     * @return bool
318
     */
319
    function str_is($pattern, $value)
320
    {
321
        if ($pattern == $value) {
322
            return true;
323
        }
324
        $pattern = preg_quote($pattern, '#');
325
        // Asterisks are translated into zero-or-more regular expression wildcards
326
        // to make it convenient to check if the strings starts with the given
327
        // pattern such as "library/*", making any string check convenient.
328
        $pattern = str_replace('\*', '.*', $pattern) . '\z';
329
        return preg_match('#^' . $pattern . '#', $value) === 1;
330
    }
331
}
332
if (!function_exists('str_limit')) {
333
    /**
334
     * Limit the number of characters in a string.
335
     *
336
     * @param  string $value
337
     * @param  int $limit
338
     * @param  string $end append in
339
     * @param  bool $wordsafe if set to true, remove any truncated word in the end of string.
340
     * @return string
341
     */
342
    function str_limit(string $value, int $limit = 100, string $end = '...', bool $wordsafe = false) : string
343
    {
344
        $limit = max($limit, 0);
345
        if (mb_strlen($value) <= $limit) {
346
            return $value;
347
        }
348
349
        $string = rtrim(mb_substr($value, 0, $limit, 'UTF-8'));
350
        if ($wordsafe) {
351
            $string = preg_replace('/\s+?(\S+)?$/', '', $string);
352
        }
353
        return $string . $end;
354
    }
355
}
356
357
if (!function_exists('str_replace_array')) {
358
    /**
359
     * Replace a given value in the string sequentially with an array.
360
     *
361
     * @param  string $search
362
     * @param  array $replace
363
     * @param  string $subject
364
     * @return string
365
     */
366
    function str_replace_array($search, array $replace, $subject)
367
    {
368
        foreach ($replace as $value) {
369
            $subject = preg_replace('/' . $search . '/', $value, $subject, 1);
370
        }
371
        return $subject;
372
    }
373
}
374
375
if (!function_exists('studly_case')) {
376
    /**
377
     * Convert a value to studly caps case.
378
     *
379
     * @param  string $value
380
     * @return string
381
     */
382
    function studly_case($value)
383
    {
384
        $studlyCache = [];
385
        $key = $value;
386
        if (isset($studlyCache[$key])) {
387
            return $studlyCache[$key];
388
        }
389
        $value = ucwords(str_replace(array('-', '_'), ' ', $value));
390
        return $studlyCache[$key] = str_replace(' ', '', $value);
391
    }
392
}
393
394
if (!function_exists('studly')) {
395
    /**
396
     * Convert a value to studly caps case.
397
     * Alias of studly_case
398
     *
399
     * @param  string $value
400
     * @return string
401
     */
402
    function studly($value)
403
    {
404
        return studly_case($value);
405
    }
406
}
407
408
if (!function_exists('camel_case')) {
409
    /**
410
     * Convert a value to camel case.
411
     *
412
     * @param  string $value
413
     * @return string
414
     */
415
    function camel_case($value)
416
    {
417
        $camelCache = [];
418
        if (isset($camelCache[$value])) {
419
            return $camelCache[$value];
420
        }
421
        return $camelCache[$value] = lcfirst(studly($value));
422
    }
423
}
424
425
/**
426
 * Replace underscores with dashes in the string.
427
 * @param string $word
428
 * @return string
429
 */
430
function underscore2dash(string $word) : string
431
{
432
    return str_replace('_', '-', $word);
433
}
434
435
/**
436
 * Make an underscored, lowercase form from the expression in the string.
437
 * @param string $word
438
 * @return string
439
 */
440
function dash2underscore(string $word) : string
441
{
442
    $word = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
443
    $word = preg_replace('/([a-z])([A-Z])/', '\1_\2', $word);
444
    return str_replace('-', '_', strtolower($word));
445
}
446
447
if (!function_exists('str_replace_multiple_space')) {
448
449
    /**
450
     * Replace multiple spaces with one space.
451
     * @param string $str
452
     * @return string
453
     */
454
    function str_replace_multiple_space(string $str) : string
455
    {
456
        return preg_replace('/\s+/', ' ', $str);
457
    }
458
}
459
460
if (!function_exists('str_replace_last')) {
461
    /**
462
     * Replace last occurrence ($search) of a string ($subject) with $replace string.
463
     * @param string $search
464
     * @param string $replace
465
     * @param string $subject
466
     * @return string
467
     */
468
    function str_replace_last(string $search, string $replace, string $subject) : string
469
    {
470
        if ($search == '') {
471
            return $subject;
472
        }
473
        $position = strrpos($subject, $search);
474
        if ($position === false) {
475
            return $subject;
476
        }
477
        return substr_replace($subject, $replace, $position, strlen($search));
478
    }
479
}
480
if (!function_exists('segment')) {
481
482
    /**
483
     * Get a segment from a string based on a delimiter.
484
     * Returns an empty string when the offset doesn't exist.
485
     * Use a negative index to start counting from the last element.
486
     *
487
     * @param string $delimiter
488
     * @param int $index
489
     * @param string $subject
490
     *
491
     * @return string
492
     * @see https://github.com/spatie/string/blob/master/src/Str.php
493
     */
494
    function segment($delimiter, $index, $subject)
495
    {
496
        $segments = explode($delimiter, $subject);
497
        if ($index < 0) {
498
            $segments = array_reverse($segments);
499
            $index = (int)abs($index) - 1;
500
        }
501
        $segment = isset($segments[$index]) ? $segments[$index] : '';
502
        return $segment;
503
    }
504
}
505
if (!function_exists('firstSegment')) {
506
507
    /**
508
     * Get the first segment from a string based on a delimiter.
509
     *
510
     * @param string $delimiter
511
     * @param string $subject
512
     *
513
     * @return string
514
     * @see https://github.com/spatie/string/blob/master/src/Str.php
515
     */
516
    function firstSegment($delimiter, $subject) : string
517
    {
518
        return segment($delimiter, 0, $subject);
519
    }
520
}
521
522
if (!function_exists('lastSegment')) {
523
524
    /**
525
     * Get the last segment from a string based on a delimiter.
526
     *
527
     * @param string $delimiter
528
     * @param string $subject
529
     *
530
     * @return string
531
     * @see https://github.com/spatie/string/blob/master/src/Str.php
532
     */
533
    function lastSegment($delimiter, $subject) : string
534
    {
535
        return segment($delimiter, -1, $subject);
536
    }
537
}
538
/**
539
 * Return true if $subject is null or empty string ('').
540
 * @param $subject
541
 * @param bool $withTrim if set to true (default) check if trim()!='' too.
542
 * @return bool
543
 */
544
function isNullOrEmpty($subject, bool $withTrim = true) : bool
545
{
546
    return $subject === null || $subject == '' || ($withTrim == true && trim($subject) == '');
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
547
}
548
549
/**
550
 * Return true if $subject is not null and is not empty string ('').
551
 * @param $subject
552
 * @param bool $withTrim if set to true (default) check if trim()!='' too.
553
 * @return bool
554
 */
555
function isNotNullOrEmpty($subject, bool $withTrim = true) : bool
556
{
557
    return !isNullOrEmpty($subject, $withTrim);
558
}
559
560
561
/**
562
 * Convert number to word representation.
563
 *
564
 * @param int $number number to convert to word
565
 * @param string $locale default 'IT' support only IT or EN
566
 *
567
 * @return string converted string
568
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
569
 */
570
function numberToWord(int $number, string $locale = 'IT') : string
571
{
572
    if (isNullOrEmpty($locale) || (strtoupper($locale) != 'IT' && strtoupper($locale) != 'EN')) {
573
        $locale = 'IT';
574
    } else {
575
        $locale = strtoupper($locale);
576
    }
577
578
    $hyphen = $locale == 'EN' ? '-' : '';
579
    $conjunction = $locale == 'EN' ? ' and ' : ' ';
580
    $separator = ', ';
581
    $negative = $locale == 'EN' ? 'negative ' : 'negativo ';
582
    $decimal = $locale == 'EN' ? ' point ' : ' punto ';
583
    $fraction = null;
584
    $dictionary = $locale == 'EN' ? NUMBERS_EN_ARR : NUMBERS_ITA_ARR;
585
    if (!is_numeric($number)) {
586
        return '';
587
    }
588
    if (!isInteger($number, false, true)) {
589
        trigger_error('numberToWord only accepts numbers between -' . PHP_INT_MAX . ' and ' . PHP_INT_MAX,
590
            E_USER_WARNING);
591
        return '';
592
    }
593
    if ($number < 0) {
594
        return $negative . numberToWord(abs($number), $locale);
595
    }
596
    if (strpos($number, '.') !== false) {
597
        list($number, $fraction) = explode('.', $number);
598
    }
599
    switch (true) {
600
        case $number < 21:
601
            $string = $dictionary[$number];
602
            break;
603
        case $number < 100:
604
            $tens = ((int)($number / 10)) * 10;
605
            $units = $number % 10;
606
            $string = $dictionary[$tens];
607
            if ($units) {
608
                $string .= $hyphen . $dictionary[$units];
609
            }
610
            break;
611
        case $number < 1000:
612
            $hundreds = $number / 100;
613
            $remainder = $number % 100;
614
            $string = $dictionary[$hundreds] . ' ' . $dictionary[100];
615
            if ($remainder) {
616
                $string .= $conjunction . numberToWord($remainder, $locale);
617
            }
618
            break;
619
        default:
620
            $baseUnit = pow(1000, floor(log($number, 1000)));
621
            $numBaseUnits = (int)($number / $baseUnit);
622
            $remainder = $number % $baseUnit;
623
            $string = numberToWord($numBaseUnits, $locale) . ' ' . $dictionary[$baseUnit];
624
            if ($remainder) {
625
                $string .= $remainder < 100 ? $conjunction : $separator;
626
                $string .= numberToWord($remainder, $locale);
627
            }
628
            break;
629
    }
630
    if (null !== $fraction && is_numeric($fraction)) {
631
        $string .= $decimal;
632
        $words = [];
633
        foreach (str_split((string)$fraction) as $number) {
634
            $words[] = $dictionary[$number];
635
        }
636
        $string .= implode(' ', $words);
637
    }
638
    return $string;
639
}
640
641
/**
642
 * Convert seconds to real time.
643
 *
644
 * @param int $seconds time in seconds
645
 * @param bool $returnAsWords return time in words (example one minute and 20 seconds) if value is True or (1 minute and 20 seconds) if value is false, default false
646
 * @param string $locale 'IT' default, or 'EN'
647
 *
648
 * @return string
649
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
650
 */
651
function secondsToText(int $seconds, bool $returnAsWords = false, string $locale = 'IT') : string
652
{
653
    $parts = [];
654
    $arrPeriod = ($locale == 'EN' ? PERIOD_IN_SECONDS_EN_ARR : PERIOD_IN_SECONDS_ITA_ARR);
655
    foreach ($arrPeriod as $name => $dur) {
656
        $div = floor($seconds / $dur);
657
        if ($div == 0) {
658
            continue;
659
        }
660
        if ($div == 1) {
661
            $parts[] = ($returnAsWords ? numberToWord($div, $locale) : $div) . ' ' . $name;
662
        } else {
663
            $parts[] = ($returnAsWords ? numberToWord($div,
664
                    $locale) : $div) . ' ' . ($locale == 'EN' ? $name : PERIOD_SINGULAR_PLURAL_ITA_ARR[$name]) . (strtoupper($locale) == 'EN' ? 's' : '');
665
        }
666
        $seconds %= $dur;
667
    }
668
    $last = array_pop($parts);
669
    if (isNullOrEmptyArray($parts)) {
670
        return $last;
671
    }
672
    return implode(', ', $parts) . (strtoupper($locale) == 'EN' ? ' and ' : ' e ') . $last;
673
}
674
675
676
/**
677
 * Convert minutes to real time.
678
 *
679
 * @param float $minutes time in minutes
680
 * @param bool $returnAsWords return time in words (example one hour and 20 minutes) if value is True or (1 hour and 20 minutes) if value is false, default false
681
 * @param string $locale 'IT' (default) or 'EN'
682
 *
683
 * @return string
684
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
685
 */
686
function minutesToText(float $minutes, bool $returnAsWords = false, string $locale = 'IT') : string
687
{
688
    $seconds = $minutes * 60;
689
    return secondsToText($seconds, $returnAsWords, $locale);
690
}
691
692
/**
693
 * Convert hours to real time.
694
 *
695
 * @param float $hours time in hours
696
 * @param bool $returnAsWords return time in words (example one hour) if value is True or (1 hour) if value is false, default false
697
 * @param string $locale 'IT' (default) or 'EN'
698
 *
699
 * @return string
700
 * @see https://github.com/ngfw/Recipe/blob/master/src/ngfw/Recipe.php
701
 */
702
function hoursToText(float $hours, bool $returnAsWords = false, string $locale = 'IT') : string
703
{
704
    $seconds = $hours * 3600;
705
    return secondsToText($seconds, $returnAsWords, $locale);
706
}
707
708
if (!function_exists('str_html_compress')) {
709
710
    /**
711
     * Removes whitespace from html and compact it.
712
     * @param string $value
713
     * @return string
714
     */
715
    function str_html_compress(string $value) : string
716
    {
717
        return preg_replace(array('/\>[^\S ]+/s', '/[^\S ]+\</s', '/(\s)+/s'), array('>', '<', '\\1'), $value);
718
    }
719
}
720