validation.php ➔ isCf()   F
last analyzed

Complexity

Conditions 45
Paths 116

Size

Total Lines 134

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 45
nc 116
nop 1
dl 0
loc 134
rs 3.2266
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Check if a string number starts with one ore more zero
5
 * i.e.: 00...000 or 000...0Xxxx.x  with X an int
6
 * @param $value
7
 * @return bool
8
 */
9
function isStringNumberStartsWithMoreThanOneZero($value)
10
{
11
    return preg_match('/^[0]{2,}$/', $value) === 1 || preg_match('/^0{1,}[1-9]{1,}$/', $value) === 1;
12
}
13
14
/**
15
 * Check if the value (int, float or string) is a integer and greater than zero..
16
 * Only number >0 and <=PHP_INT_MAX
17
 * or if $acceptIntegerFloatingPoints==true a floating point that match an positive integer).
18
 * @param $value
19
 * @param bool $acceptIntegerFloatingPoints
20
 * @return bool
21
 */
22
function isIntegerPositive($value, $acceptIntegerFloatingPoints = false): bool
23
{
24
    return isInteger($value, true, $acceptIntegerFloatingPoints) && $value > 0;
25
}
26
27
/**
28
 * Check if the value (int, float or string) is a integer and less than zero..
29
 * Only number <0 and >=PHP_INT_MIN
30
 * or if $acceptIntegerFloatingPoints==true a floating point that match an negative integer).
31
 * @param $value
32
 * @param bool $acceptIntegerFloatingPoints
33
 * @return bool
34
 */
35
function isIntegerNegative($value, $acceptIntegerFloatingPoints = false): bool
36
{
37
    return isInteger($value, false, $acceptIntegerFloatingPoints) && $value < 0;
38
}
39
40
/**
41
 * Check if the value (int, float or string) is a integer and greater than zero or equals to zero.
42
 * Only number >=0 and <=PHP_INT_MAX
43
 * or if $acceptIntegerFloatingPoints==true a floating point that match an positive integer).
44
 * @param $value
45
 * @param bool $acceptIntegerFloatingPoints
46
 * @return bool
47
 */
48
function isIntegerPositiveOrZero($value, $acceptIntegerFloatingPoints = false): bool
49
{
50
    return isInteger($value, true, $acceptIntegerFloatingPoints) && $value >= 0;
51
}
52
53
/**
54
 * Check if the value (int, float or string) is a integer and less than zero or equals to zero.
55
 * Only number <=0 and >=PHP_INT_MIN
56
 * or if $acceptIntegerFloatingPoints==true a floating point that match an negative integer).
57
 * @param $value
58
 * @param bool $acceptIntegerFloatingPoints
59
 * @return bool
60
 */
61
function isIntegerNegativeOrZero($value, $acceptIntegerFloatingPoints = false): bool
62
{
63
    return isInteger($value, false, $acceptIntegerFloatingPoints) && $value <= 0;
64
}
65
66
/**
67
 * Check if the value (int, float or string) is a integer and equals to zero.
68
 * If $acceptIntegerFloatingPoints==true a floating point that match an zero integer).
69
 * @param $value
70
 * @param bool $acceptIntegerFloatingPoints default false
71
 * @param bool $acceptSign default false if set to true accept -0 and +0 otherwise accept 0.
72
 * @return bool
73
 */
74
function isIntegerZero($value, $acceptIntegerFloatingPoints = false, $acceptSign = false): bool
75
{
76
    if(isNullOrEmpty($value)){
77
        return false;
78
    }
79
    if(!$acceptSign){
80
        return $value == 0 && isNumericWithoutSign($value) && !isStringNumberStartsWithMoreThanOneZero($value);
81
    }else{
82
        return abs($value) == 0 && isInteger(abs($value), !$acceptSign, $acceptIntegerFloatingPoints);
83
    }
84
}
85
86
/**
87
 * Check if the value (int, float or string) is a integer.
88
 * Only number <=PHP_INT_MAX (and >=PHP_INT_MIN if unsigned=true)
89
 * or if $acceptIntegerFloatingPoints==true a floating point that match an integer).
90
 * @param $value
91
 * @param bool $unsigned
92
 * @param bool $acceptIntegerFloatingPoints
93
 * @return bool
94
 */
95
function isInteger($value, $unsigned = true, $acceptIntegerFloatingPoints = false): bool
96
{
97
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
98
        return false;
99
    }
100
101
    //accept only integer number and if $acceptIntegerFloatingPoints is true accept integer floating point too.
102
    return ((preg_match('/^' . ($unsigned ? '' : '-{0,1}') . '[0-9]{1,}$/', $value) === 1
103
            && ($value <= PHP_INT_MAX && $value >= PHP_INT_MIN && (((int)$value) == $value))
104
        )
105
        || ($acceptIntegerFloatingPoints && isIntegerFloatingPoint($value, $unsigned)));
106
}
107
108
/**
109
 * Check if string is a valid floating point that
110
 * match an integer (<=PHP_INT_MAX and >=PHP_INT_MIN if unsigned=true)
111
 * or is an integer
112
 * Ex.: 1, 1e2, 1E2, 1e+2, 1e-2, 1.4e+2, -1.2e+2, -1.231e-2 etc...
113
 * @param $value
114
 * @param bool $unsigned
115
 * @return bool
116
 */
117
function isIntegerFloatingPoint($value, $unsigned = true): bool
118
{
119
    return isFloatingPoint($value, $unsigned)
120
        && $value <= PHP_INT_MAX && $value >= PHP_INT_MIN
121
        //big number rouned to int aproximately!
122
        //big number change into exp format
123
        && ((int)((double)$value) == $value || (int)$value == $value || strpos(strtoupper((string)$value),
124
                'E') === false);
125
}
126
127
/**
128
 * Check if string is a valid floating point.
129
 * Ex.: [+-]1, [+-]1e2, [+-]1E2, [+-]1e+2, [+-]1e-2, [+-]1.43234e+2, -1.231e+2, -1.231e-2 etc...
130
 * @param $value
131
 * @param $unsigned
132
 * @return bool
133
 */
134
function isFloatingPoint($value, $unsigned): bool
135
{
136
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
137
        return false;
138
    }
139
140
    return preg_match('/^' . ($unsigned ? '[+]{0,1}' : '[-+]{0,1}') . '[0-9]{1,}(\.[0-9]{1,}){0,1}([Ee][+,-]{0,1}[0-9]{1,}){0,}$/',
141
            $value) === 1;
142
}
143
144
/**
145
 * Check if the value is a integer/string 0 or 1.
146
 * @param $value
147
 * @return bool
148
 */
149
function isIntBool($value): bool
150
{
151
    return $value === 1 || $value === 0 || $value === '1' || $value === '0';
152
}
153
154
/**
155
 * Check if the value are a double (integer or float in the form 1, 1.11...1.
156
 * @param $value
157
 * @param int $dec
158
 * @param bool $unsigned
159
 * @param bool $exactDec if set to true aspect number of dec exact to $dec,
160
 * otherwise $dec is max decimals accepted (0 decimals are also ok in this case).
161
 * if $dec is an empty string, accept 0 to infinite decimals.
162
 * @return bool
163
 */
164
function isDouble($value, $dec = 2, $unsigned = true, $exactDec = false): bool
165
{
166
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
167
        return false;
168
    }
169
    $regEx = '/^' . ($unsigned ? '' : '-{0,1}') . '[0-9]{1,}(\.{1}[0-9]{' . ($exactDec ? '' : '1,') . $dec . '})' . ($exactDec ? '{1}' : '{0,1}') . '$/';
170
    return preg_match($regEx, $value) === 1;
171
}
172
173
/**
174
 * Check if a string is a percent 0%-100%
175
 * @param $value
176
 * @param bool $withDecimal if set to true accept decimal values.
177
 * @param bool $withPercentChar if set to true require % char, otherwise if find a % char return false.
178
 * @return bool
179
 */
180
function isPercent($value, bool $withDecimal = true, bool $withPercentChar = false): bool
181
{
182
    if (isNullOrEmpty($value)) {
183
        return false;
184
    }
185
    $contains_perc = str_contains($value, '%');
186
    if (($withPercentChar && !$contains_perc)
187
        || (!$withPercentChar && $contains_perc)
188
        || (substr_count($value, '%') > 1) //only one %
189
    ) {
190
        return false;
191
    }
192
    $value = trim(str_replace('%', '', $value));
193
194
    return $withDecimal ? isDouble($value, '', true) : isInteger($value, true);
195
}
196
197
/**
198
 * @param float $value
199
 * @param float $leftRange
200
 * @param float $rightRange
201
 * @return bool
202
 */
203
function isInRange(float $value, float $leftRange = 0.00, float $rightRange = 0.00): bool
204
{
205
    return ($value <= $rightRange && $value >= $leftRange);
206
}
207
208
/**
209
 * Check if string is dd/mm/YYYY
210
 * @param $value
211
 * @return bool
212
 */
213 View Code Duplication
function isDateIta($value): bool
0 ignored issues
show
Duplication introduced by
This function 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...
214
{
215
    if (isNullOrEmpty($value) || strlen($value) != 10 || strpos($value, '/') === false) {
216
        return false;
217
    }
218
    list($dd, $mm, $yyyy) = explode('/', $value);
219
    try {
220
        return checkdate($mm, $dd, $yyyy);
221
    } catch (Exception $e) {
222
        return false;
223
    }
224
}
225
226
/**
227
 * Check if string is 0000-00-00
228
 * @param $value
229
 * @return bool
230
 */
231
function isDateZeroIso($value): bool
232
{
233
    return $value == '0000-00-00';
234
}
235
236
/**
237
 * Check if string is 00:00:00
238
 * @param $value
239
 * @return bool
240
 */
241
function isTimeZeroIso($value): bool
242
{
243
    return $value == '00:00:00';
244
}
245
246
/**
247
 * Check if string is '0000-00-00 00:00:00'
248
 * @param $value
249
 * @return bool
250
 */
251
function isDateTimeZeroIso($value): bool
252
{
253
    return $value == '0000-00-00 00:00:00';
254
}
255
256
/**
257
 * Check if string is YYYY-mm-dd and valid date or 0000-00-00
258
 * @param $value
259
 * @return bool
260
 */
261
function isDateOrDateZeroIso($value): bool
262
{
263
    return isDateIso($value) || isDateZeroIso($value);
264
}
265
266
/**
267
 * Check if string is 'YYYY-mm-dd HH:ii:ss' and valid date or '0000-00-00 00:00:00'
268
 * @param $value
269
 * @return bool
270
 */
271
function isDateTimeOrDateTimeZeroIso($value): bool
272
{
273
    return isDateTimeIso($value) || isDateTimeZeroIso($value);
274
}
275
276
277
/**
278
 * Check if string is 00/00/0000
279
 * @param $value
280
 * @return bool
281
 */
282
function isDateZeroIta($value): bool
283
{
284
    return $value == '00/00/0000';
285
}
286
287
/**
288
 * Check if string is 00:00:00
289
 * @param $value
290
 * @return bool
291
 */
292
function isTimeZeroIta($value): bool
293
{
294
    return $value == '00:00:00';
295
}
296
297
/**
298
 * Check if string is '00/00/0000 00:00:00'
299
 * @param $value
300
 * @return bool
301
 */
302
function isDateTimeZeroIta($value): bool
303
{
304
    return $value == '00/00/0000 00:00:00';
305
}
306
307
/**
308
 * Check if string is dd/mm/YYYY and valid date or 00/00/0000
309
 * @param $value
310
 * @return bool
311
 */
312
function isDateOrDateZeroIta($value): bool
313
{
314
    return isDateIta($value) || isDateZeroIta($value);
315
}
316
317
/**
318
 * Check if string is 'dd/mm/YYYY HH:ii:ss' and valid date or '00/00/0000 00:00:00'
319
 * @param $value
320
 * @return bool
321
 */
322
function isDateTimeOrDateTimeZeroIta($value): bool
323
{
324
    return isDateTimeIta($value) || isDateTimeZeroIta($value);
325
}
326
327
/**
328
 * Check if string is YYYY-mm-dd
329
 * @param $value
330
 * @return bool
331
 */
332 View Code Duplication
function isDateIso($value): bool
0 ignored issues
show
Duplication introduced by
This function 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...
333
{
334
    if (isNullOrEmpty($value) || strlen($value) != 10 || strpos($value, '-') === false) {
335
        return false;
336
    }
337
    list($yyyy, $mm, $dd) = explode('-', $value);
338
    try {
339
        return checkdate($mm, $dd, $yyyy);
340
    } catch (Exception $e) {
341
        return false;
342
    }
343
}
344
345
/**
346
 * Check if string is YYYY-mm-dd HH:ii:ss
347
 * @param $value
348
 * @return bool
349
 */
350
function isDateTimeIso($value): bool
351
{
352
    if (!isDateIso(substr($value, 0, 10))) {
353
        return false;
354
    }
355
    return isTimeIso(substr($value, 11));
356
}
357
358
/**
359
 * Check if string is dd/mm/YYYY HH:ii:ss
360
 * @param $value
361
 * @return bool
362
 */
363
function isDateTimeIta($value): bool
364
{
365
    if (!isDateIta(substr($value, 0, 10))) {
366
        return false;
367
    }
368
    return isTimeIso(substr($value, 11));
369
}
370
371
/**
372
 * Check if string is HH:ii:ss
373
 * @param $value
374
 * @return bool
375
 */
376
function isTimeIso($value): bool
377
{
378
    $strRegExp = '/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/';
379
    if (!(preg_match($strRegExp, $value) === 1)) {
380
        return false;
381
    }
382
    list($HH, $ii, $ss) = explode(':', $value);
383
    return isInRange((int)$HH, 0, 23) && isInRange((int)$ii, 0, 59) && isInRange((int)$ss, 0, 59);
384
}
385
386
/**
387
 * An alias of isTimeIso.
388
 * @param $value
389
 * @return bool
390
 */
391
function isTimeIta($value)
392
{
393
    return isTimeIso($value);
394
}
395
396
/**
397
 * Check if year ia a leap year in jewish calendar.
398
 * @param int $year
399
 * @return bool
400
 */
401
function isJewishLeapYear(int $year): bool
402
{
403
    if ($year % 19 == 0 || $year % 19 == 3 || $year % 19 == 6 ||
404
        $year % 19 == 8 || $year % 19 == 11 || $year % 19 == 14 ||
405
        $year % 19 == 17
406
    ) {
407
        return true;
408
    } else {
409
        return false;
410
    }
411
}
412
413
/**
414
 * Check if a number is a valid month.
415
 * More params you passed (year, calendar), more accurate is the check.
416
 * If passed a not valid year return false.
417
 * @param int $value
418
 * @param int $year
419
 * @param int $calendar
420
 * @return bool
421
 */
422
function isMonth(int $value, int $year, int $calendar = CAL_GREGORIAN): bool
423
{
424
    if (!isInRange($year, 0, PHP_INT_MAX)) {
425
        return false;
426
    }
427
428
    $maxMonths = 12;
429
430
    if ($calendar == 3
431
        || ($year > 0 && $calendar == 2 && isJewishLeapYear($year))
432
    ) {
433
        $maxMonths = 13;
434
    }
435
436
    return isInRange($value, 1, $maxMonths);
437
}
438
439
/**
440
 * Check if a number is a valid day.
441
 * More params you passed (month, year, calendar), more accurate is the check.
442
 * If passed a not valid year or month return false.
443
 * @param int $value
444
 * @param int $month
445
 * @param int $year
446
 * @param int $calendar
447
 * @return bool
448
 */
449
function isDay(int $value, int $month = 0, int $year = 0, int $calendar = CAL_GREGORIAN): bool
450
{
451
    if ($month != 0 && !isMonth($month, $year, $calendar)) {
452
        return false;
453
    }
454
    if (!isInRange($year, 0, PHP_INT_MAX)) {
455
        return false;
456
    }
457
458
    $maxDays = 31;
459
460
    if ($year > 0 && $month > 0) {
461
        $maxDays = cal_days_in_month($calendar, $month, $year);
462
    } elseif (in_array($month, [11, 4, 6, 9])) {
463
        $maxDays = 30;
464
    } elseif ($month == 2) {
465
        $maxDays = 28;
466
    }
467
468
    return isInRange($value, 1, $maxDays);
469
}
470
471
/**
472
 * Determine if the provided input meets age requirement (ISO 8601).
473
 *
474
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
475
 * @param int $age
476
 *
477
 * @return bool
478
 */
479
function hasMinAge($dateOfBirthday, int $age): bool
480
{
481
    return date_diff(date('Y-m-d'), $dateOfBirthday) >= $age;
482
}
483
484
/**
485
 * Determine if the provided input meets age requirement (ISO 8601).
486
 *
487
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
488
 * @param int $age
489
 *
490
 * @return bool
491
 */
492
function hasMaxAge($dateOfBirthday, int $age): bool
493
{
494
    return date_diff(date('Y-m-d'), $dateOfBirthday) <= $age;
495
}
496
497
/**
498
 * Determine if the provided input meets age requirement (ISO 8601).
499
 *
500
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
501
 * @param int $ageMin
502
 * @param int $ageMax
503
 *
504
 * @return bool
505
 */
506
function hasAgeInRange($dateOfBirthday, int $ageMin, int $ageMax): bool
507
{
508
    return hasMinAge($dateOfBirthday, $ageMin) && hasMaxAge($dateOfBirthday, $ageMax);
509
}
510
511
/**
512
 * Check if a date in iso format is in range
513
 * @param string $date iso format
514
 * @param string $minDate iso format
515
 * @param string $maxDate iso format
516
 * @param bool $strict if set to false (default) check >=min and <=max otherwise check >min and <max.
517
 * @return bool
518
 */
519
function betweenDateIso(string $date, string $minDate, string $maxDate, bool $strict = false): bool
520
{
521
    if (!isDateIso($date) || !isDateIso($minDate) || !isDateIso($maxDate)) {
522
        return false;
523
    }
524
525
    if (!$strict) {
526
        return ($date >= $minDate) && ($date <= $maxDate);
527
    }
528
    return ($date > $minDate) && ($date < $maxDate);
529
}
530
531
/**
532
 * Check if a date in ita format is in range
533
 * @param string $date ita format
534
 * @param string $minDate ita format
535
 * @param string $maxDate ita format
536
 * @param bool $strict if set to false (default) check >=min and <=max otherwise check >min and <max.
537
 * @return bool
538
 */
539
function betweenDateIta(string $date, string $minDate, string $maxDate, bool $strict = false): bool
540
{
541
    if (!isDateIta($date) || !isDateIta($minDate) || !isDateIta($maxDate)) {
542
        return false;
543
    }
544
545
    $date = dateItaToIso($date);
546
    $minDate = dateItaToIso($minDate);
547
    $maxDate = dateItaToIso($maxDate);
548
549
    return betweenDateIso($date, $minDate, $maxDate, $strict);
550
}
551
552
/**
553
 * @param $value
554
 * @param $checkMx
555
 * @return bool
556
 */
557
function isMail($value, bool $checkMx = false): bool
558
{
559
    if (filter_var($value, FILTER_VALIDATE_EMAIL) === false) {
560
        return false;
561
    }
562
    if ($checkMx) {
563
        list(, $mailDomain) = explode('@', $value);
564
        if (!checkdnsrr($mailDomain, 'MX')) {
565
            return false;
566
        }
567
    }
568
    return true;
569
}
570
571
/**
572
 * isIPv4 check if a string is a valid IP v4
573
 * @param  string $IP2Check IP to check
574
 * @return bool
575
 */
576
function isIPv4($IP2Check): bool
577
{
578
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false);
579
}
580
581
/**
582
 * isIPv6 check if a string is a valid IP v6
583
 * @param  string $IP2Check IP to check
584
 * @return bool
585
 */
586
function isIPv6($IP2Check): bool
587
{
588
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false);
589
}
590
591
/**
592
 * Check if a string is a valid IP (v4 or v6).
593
 * @param  string $IP2Check IP to check
594
 * @return bool
595
 */
596
function isIP($IP2Check): bool
597
{
598
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP) === false);
599
}
600
601
/**
602
 * Check if a string is a valid IP v4 compatibility (ffff:ffff:ffff:ffff.192.168.0.15).
603
 * @param  string $IP2Check IP to check
604
 * @return bool
605
 */
606
function isIPv4Compatibility($IP2Check): bool
607
{
608
    return (strrpos($IP2Check, ":") > 0
609
        && strrpos($IP2Check, ".") > 0
610
        && isIPv4(substr($IP2Check, strpos($IP2Check, ".") + 1))
611
        && isIPv6(substr($IP2Check, 0, strpos($IP2Check, ".")) . ':0:0:0:0')
612
    );
613
}
614
615
/**
616
 * Check if a string has a URL address syntax is valid.
617
 * It require scheme to be valide (http|https|ftp|mailto|file|data)
618
 * i.e.: http://dummy.com and http://www.dummy.com is valid but www.dummy.and dummy.com return false.
619
 * @param $url
620
 * @return bool
621
 */
622
function isUrl($url): bool
623
{
624
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
625
}
626
627
/**
628
 * Check if a string is valid hostname
629
 * (dummy.com, www.dummy.com, , www.dummy.co.uk, , www.dummy-dummy.com, etc..).
630
 * @param $value
631
 * @return bool
632
 */
633
function isHostname($value): bool
634
{
635
    return preg_match('/(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)/i', $value) === 1;
636
}
637
638
/**
639
 * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
640
 *
641
 * The regex checks for the following component parts:
642
 *
643
 * - a valid, optional, scheme
644
 * - a valid ip address OR
645
 *   a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
646
 *   with an optional port number
647
 * - an optional valid path
648
 * - an optional query string (get parameters)
649
 * - an optional fragment (anchor tag)
650
 *
651
 * @param string $check Value to check
652
 * @param bool $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher)
653
 * @return bool Success
654
 * @see https://github.com/cakephp/cakephp/blob/master/src/Validation/Validation.php#L839
655
 */
656
function urlW3c($check, bool $strict = false): bool
657
{
658
    $_pattern = array();
659
    $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
660
    $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
661
    $pattern .= '|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})';
662
    $pattern .= '(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)';
663
    $pattern .= '{4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
664
    $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}';
665
    $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
666
    $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
667
    $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
668
    $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
669
    $pattern .= '{0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)';
670
    $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
671
    $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
672
    $pattern .= '{1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?';
673
    $_pattern['IPv6'] = $pattern;
674
675
    $pattern = '(?:(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|(?:(?:1[0-9])?|[1-9]?)[0-9])';
676
    $_pattern['IPv4'] = $pattern;
677
678
    $_pattern = ['hostname' => '(?:[_\p{L}0-9][-_\p{L}0-9]*\.)*(?:[\p{L}0-9][-\p{L}0-9]{0,62})\.(?:(?:[a-z]{2}\.)?[a-z]{2,})'];
679
680
    $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~[]') . '\/0-9\p{L}\p{N}]|(%[0-9a-f]{2}))';
681
    $regex = '/^(?:(?:https?|ftps?|sftp|file|news|gopher):\/\/)' . ($strict ? '' : '?') .
682
        '(?:' . $_pattern['IPv4'] . '|\[' . $_pattern['IPv6'] . '\]|' . $_pattern['hostname'] . ')(?::[1-9][0-9]{0,4})?' .
683
        '(?:\/?|\/' . $validChars . '*)?' .
684
        '(?:\?' . $validChars . '*)?' .
685
        '(?:#' . $validChars . '*)?$/iu';
686
    return preg_match($regex, $check) === 1;
687
}
688
689
/**
690
 * Check if a valid EU vat given.
691
 * @param string $pi required eu vat number with or without country code prefix.
692
 * If you don't pass country code prefix, 'IT' will be assumed.
693
 * @param bool $validateOnVIES default false. if se to true, first check formal EU country algorithm,
694
 * then if it valid and country code isn't 'IT' try to check by API VIES service.
695
 * If VIES return false or soap exception was thrown, return false.
696
 * @return bool
697
 */
698
function isEuVatNumber(string $pi, bool $validateOnVIES = false): bool
699
{
700
    $countryCode = getCoutryCodeByVatNumber($pi, 'IT');
701
702
    $result = true;
703
    if (function_exists('is'.$countryCode.'Vat')){
704
        $funcname = 'is'.$countryCode.'Vat';
705
        $result = $funcname($pi);
706
    }
707
    if(!$result){
708
        return false;
709
    }
710
    if($countryCode=='IT' || !$validateOnVIES){
711
        return $result;
712
    }
713
714
    //check vies
715
    try {
716
        return isVATRegisteredInVies($pi);
717
    } catch (SoapFault $e) {
718
        return false;
719
    }
720
}
721
722
/**
723
 * Try to extract EU country code in Vat number
724
 * return $fallback if it fails.
725
 *
726
 * @param string $pi
727
 * @param string $fallback
728
 * @return string
729
 */
730
function getCoutryCodeByVatNumber(string $pi, string $fallback  ='IT'): string
731
{
732
    if ($pi === null || $pi === '' || strlen($pi) < 2) {
733
        return $fallback;
734
    }
735
736
    //try to find country code
737
    $countryCode = strtoupper(substr($pi, 0, 2));
738
    if (!(preg_match('/^[A-Za-z]{2}$/', $countryCode) === 1)) {
739
        $countryCode = $fallback;
740
    }
741
    return $countryCode;
742
}
743
744
/**
745
 * Check Italian Vat Number (Partita IVA).
746
 * @author Umberto Salsi <[email protected]>
747
 * @author Lorenzo Padovani modified.
748
 * @version 2012-05-12
749
 * @param string $pi Partita IVA Italiana è costituita da 11 cifre o 13 caratteri (prefisso 2 lettere IT).
750
 * Non sono ammessi caratteri di spazio, per cui i campi di input dell'utente dovrebbero
751
 * essere trimmati preventivamente.
752
 * @return bool
753
 */
754
function isITVat(string $pi): bool
755
{
756
    $countryCode = getCoutryCodeByVatNumber($pi, '');
757
    if($countryCode!='IT' && $countryCode!=''){
758
        return false;
759
    }
760
    if($countryCode!=''){
761
        $pi = substr($pi, 2);
762
    }
763
764
    if ($pi === null || $pi === '' || strlen($pi) != 11 || preg_match("/^[0-9]+\$/", $pi) != 1) {
765
        return false;
766
    }
767
    $s = 0;
768
    for ($i = 0; $i <= 9; $i += 2) {
769
        $s += ord($pi[$i]) - ord('0');
770
    }
771
    for ($i = 1; $i <= 9; $i += 2) {
772
        $c = 2 * (ord($pi[$i]) - ord('0'));
773
        if ($c > 9) {
774
            $c -= 9;
775
        }
776
        $s += $c;
777
    }
778
    if ((10 - $s % 10) % 10 != ord($pi[10]) - ord('0')) {
779
        return false;
780
    }
781
782
    return true;
783
}
784
785
/**
786
 * Validate a European VAT number using the EU commission VIES service.
787
 * To verify if VAT number is authorized to carry out intra-Community operations must use the service
788
 * If not $vatNumber starts with country code, a default $countryCodeDefault applied.
789
 * @param string $vatNumber
790
 * @param string $countryCodeDefault default 'IT'
791
 * @return bool
792
 * @throws SoapFault
793
 */
794
function isVATRegisteredInVies(string $vatNumber, string $countryCodeDefault = 'IT'): bool
795
{
796
    if (!isAlphaNumericWhiteSpaces($vatNumber) || strlen(trim($vatNumber)) < 3) {
797
        return false;
798
    }
799
800
    $vatNumber = str_replace([' ', '-', '.', ','], '', strtoupper(trim($vatNumber)));
801
    $countryCode = strtoupper(substr($vatNumber, 0, 2));
802
803
    if (preg_match('/^[A-Za-z]{2}$/', $countryCode) === 1) {
804
        $vatNumber = substr($vatNumber, 2);
805
    } else {
806
        $countryCode = $countryCodeDefault != '' ? strtoupper($countryCodeDefault) : 'IT';
807
    }
808
    try {
809
        $serviceUrl = 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
810
        $client = new SoapClient($serviceUrl);
811
        $response = $client->checkVat([
812
            'countryCode' => $countryCode,
813
            'vatNumber' => $vatNumber,
814
        ]);
815
        return $response->valid;
816
    } catch (SoapFault $e) {
817
        throw $e;
818
    }
819
}
820
821
/**
822
 * Controlla codice fiscale.
823
 * @author Umberto Salsi <[email protected]>
824
 * @version 2012-05-12
825
 * @param string $cf Codice fiscale costituito da 16 caratteri. Non
826
 * sono ammessi caratteri di spazio, per cui i campi di input dell'utente
827
 * dovrebbero essere trimmati preventivamente. La stringa vuota e' ammessa,
828
 * cioe' il dato viene considerato opzionale.
829
 * @return bool
830
 */
831
function isCf(string $cf): bool
832
{
833
    if ($cf === null || $cf === '' || strlen($cf) != 16) {
834
        return false;
835
    }
836
    $cf = strtoupper($cf);
837
    if (preg_match("/^[A-Z0-9]+\$/", $cf) != 1) {
838
        return false;
839
    }
840
    $s = 0;
841
    for ($i = 1; $i <= 13; $i += 2) {
842
        $c = $cf[$i];
843
        if (strcmp($c, "0") >= 0 && strcmp($c, "9") <= 0) {
844
            $s += ord($c) - ord('0');
845
        } else {
846
            $s += ord($c) - ord('A');
847
        }
848
    }
849
    for ($i = 0; $i <= 14; $i += 2) {
850
        $c = $cf[$i];
851
        switch ($c) {
852
            case '0':
853
                $s += 1;
854
                break;
855
            case '1':
856
                $s += 0;
857
                break;
858
            case '2':
859
                $s += 5;
860
                break;
861
            case '3':
862
                $s += 7;
863
                break;
864
            case '4':
865
                $s += 9;
866
                break;
867
            case '5':
868
                $s += 13;
869
                break;
870
            case '6':
871
                $s += 15;
872
                break;
873
            case '7':
874
                $s += 17;
875
                break;
876
            case '8':
877
                $s += 19;
878
                break;
879
            case '9':
880
                $s += 21;
881
                break;
882
            case 'A':
883
                $s += 1;
884
                break;
885
            case 'B':
886
                $s += 0;
887
                break;
888
            case 'C':
889
                $s += 5;
890
                break;
891
            case 'D':
892
                $s += 7;
893
                break;
894
            case 'E':
895
                $s += 9;
896
                break;
897
            case 'F':
898
                $s += 13;
899
                break;
900
            case 'G':
901
                $s += 15;
902
                break;
903
            case 'H':
904
                $s += 17;
905
                break;
906
            case 'I':
907
                $s += 19;
908
                break;
909
            case 'J':
910
                $s += 21;
911
                break;
912
            case 'K':
913
                $s += 2;
914
                break;
915
            case 'L':
916
                $s += 4;
917
                break;
918
            case 'M':
919
                $s += 18;
920
                break;
921
            case 'N':
922
                $s += 20;
923
                break;
924
            case 'O':
925
                $s += 11;
926
                break;
927
            case 'P':
928
                $s += 3;
929
                break;
930
            case 'Q':
931
                $s += 6;
932
                break;
933
            case 'R':
934
                $s += 8;
935
                break;
936
            case 'S':
937
                $s += 12;
938
                break;
939
            case 'T':
940
                $s += 14;
941
                break;
942
            case 'U':
943
                $s += 16;
944
                break;
945
            case 'V':
946
                $s += 10;
947
                break;
948
            case 'W':
949
                $s += 22;
950
                break;
951
            case 'X':
952
                $s += 25;
953
                break;
954
            case 'Y':
955
                $s += 24;
956
                break;
957
            case 'Z':
958
                $s += 23;
959
                break;
960
            /*. missing_default: .*/
961
        }
962
    }
963
    return !(chr($s % 26 + ord('A')) != $cf[15]);
964
}
965
966
/**
967
 * Determine if the provided value contains only alpha characters.
968
 *
969
 * @param string $field
970
 *
971
 * @return mixed
972
 *
973
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
974
 */
975
function isAlpha(string $field): bool
976
{
977
    return isNotNullOrEmpty($field)
978
        && preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ])+$/i', $field) === 1;
979
}
980
981
/**
982
 * Determine if the provided value contains only alpha characters.
983
 *
984
 * @param string $field
985
 *
986
 * @return mixed
987
 *
988
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
989
 */
990
function isAlphaNumeric(string $field): bool
991
{
992
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ])+$/i', $field) === 1;
993
}
994
995
/**
996
 * Determine if the provided value contains only numeric characters with or without(default) sign.
997
 *
998
 * @param string $field
999
 * @param bool $acceptSign default false if true accept string that starts with +/- oterwise only [0-9] chars.
1000
 *
1001
 * @return mixed
1002
 */
1003
function isNumeric(string $field, bool $acceptSign = false): bool
1004
{
1005
    return preg_match('/^(' . ($acceptSign ? '[+-]{0,1}' : '') . '[0-9])+$/i', $field) === 1;
1006
}
1007
1008
/**
1009
 * Determine if the provided value contains only numeric characters with sign.
1010
 *
1011
 * @param string $field
1012
 *
1013
 * @return mixed
1014
 */
1015
function isNumericWithSign(string $field): bool
1016
{
1017
    return isNumeric($field, true);
1018
}
1019
1020
/**
1021
 * Determine if the provided value contains only numeric characters without sign.
1022
 *
1023
 * @param string $field
1024
 *
1025
 * @return mixed
1026
 */
1027
function isNumericWithoutSign(string $field): bool
1028
{
1029
    return isNumeric($field, false);
1030
}
1031
1032
/**
1033
 * Determine if the provided value contains only alpha characters with dashed and underscores.
1034
 *
1035
 * @param string $field
1036
 *
1037
 * @return mixed
1038
 */
1039
function isAlphaNumericDash($field): bool
1040
{
1041
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ\-_])+$/i', $field) === 1;
1042
}
1043
1044
/**
1045
 * Determine if the provided value contains only alpha numeric characters with spaces.
1046
 *
1047
 * @param string $field
1048
 *
1049
 * @return mixed
1050
 */
1051
function isAlphaNumericWhiteSpaces($field): bool
1052
{
1053
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ\-_\s])+$/i', $field) === 1;
1054
}
1055
1056
/**
1057
 * Determine if the provided value is a boolean.
1058
 *
1059
 * @param string $field
1060
 *
1061
 * @return mixed
1062
 */
1063
function isBool($field): bool
1064
{
1065
    return $field === true || $field === false;
1066
}
1067
1068
/**
1069
 * Determine if the provided value is a boolean or 1,0,'1','0'.
1070
 *
1071
 * @param string $field
1072
 *
1073
 * @return bool
1074
 */
1075
function isBoolOrIntBool($field): bool
1076
{
1077
    return in_array($field, [0, 1, '0', '1', true, false], true);
1078
}
1079
1080
/**
1081
 * Determine if the input is a valid credit card number.
1082
 *
1083
 * See: http://stackoverflow.com/questions/174730/what-is-the-best-way-to-validate-a-credit-card-in-php
1084
 *
1085
 * @param string $field
1086
 *
1087
 * @return mixed
1088
 */
1089
function isCrediCard(string $field): bool
1090
{
1091
    if (isNullOrEmpty($field)) {
1092
        return false;
1093
    }
1094
    $number = preg_replace('/\D/', '', $field);
1095
    if (function_exists('mb_strlen')) {
1096
        $number_length = mb_strlen($number);
1097
    } else {
1098
        $number_length = strlen($number);
1099
    }
1100
    $parity = $number_length % 2;
1101
    $total = 0;
1102
    for ($i = 0; $i < $number_length; ++$i) {
1103
        $digit = $number[$i];
1104
        if ($i % 2 == $parity) {
1105
            $digit *= 2;
1106
            if ($digit > 9) {
1107
                $digit -= 9;
1108
            }
1109
        }
1110
        $total += $digit;
1111
    }
1112
    return ($total % 10 == 0);
1113
}
1114
1115
/**
1116
 * Determine if the input is a valid human name.
1117
 *
1118
 * @param string $field
1119
 *
1120
 * @return mixed
1121
 *
1122
 * @See: https://github.com/Wixel/GUMP/issues/5
1123
 */
1124
function isValidHumanName(string $field): bool
1125
{
1126
    if (isNullOrEmpty($field)) {
1127
        return false;
1128
    }
1129
    return isAlpha($field) && preg_match("/^([ '-])+$/", $field) === 1;
1130
}
1131
1132
/**
1133
 * Determine if the provided value is a valid IBAN.
1134
 *
1135
 * @param string $field
1136
 *
1137
 * @return bool
1138
 *
1139
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
1140
 */
1141
function isIban($field): bool
1142
{
1143
    if (isNullOrEmpty($field)) {
1144
        return false;
1145
    }
1146
    static $character = array(
1147
        'A' => 10,
1148
        'C' => 12,
1149
        'D' => 13,
1150
        'E' => 14,
1151
        'F' => 15,
1152
        'G' => 16,
1153
        'H' => 17,
1154
        'I' => 18,
1155
        'J' => 19,
1156
        'K' => 20,
1157
        'L' => 21,
1158
        'M' => 22,
1159
        'N' => 23,
1160
        'O' => 24,
1161
        'P' => 25,
1162
        'Q' => 26,
1163
        'R' => 27,
1164
        'S' => 28,
1165
        'T' => 29,
1166
        'U' => 30,
1167
        'V' => 31,
1168
        'W' => 32,
1169
        'X' => 33,
1170
        'Y' => 34,
1171
        'Z' => 35,
1172
        'B' => 11
1173
    );
1174
    if (preg_match('/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/', $field) != 1) {
1175
        return false;
1176
    }
1177
    $iban = str_replace(' ', '', $field);
1178
    $iban = substr($iban, 4) . substr($iban, 0, 4);
1179
    $iban = strtr($iban, $character);
1180
    return (bcmod($iban, 97) != 1);
1181
}
1182
1183
/**
1184
 * check the file extension
1185
 * for now checks onlt the ext should add mime type check.
1186
 *
1187
 * @param string $filePath
1188
 * @param array $allowed_extensions array of extension to match
1189
 *
1190
 * @return bool
1191
 * @see https://github.com/cakephp/cakephp/blob/master/src/Validation/Validation.php
1192
 */
1193
function hasFileExtension($filePath, array $allowed_extensions): bool
1194
{
1195
    $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
1196
    $allowed_extensions = (array)array_map('mb_strtolower', $allowed_extensions);
1197
    return in_array($extension, $allowed_extensions);
1198
}
1199
1200
/**
1201
 * Determine if the provided value is a valid phone number.
1202
 *
1203
 * @param string $field
1204
 *
1205
 * @return bool
1206
 *
1207
 * Examples:
1208
 *
1209
 *    555-555-5555: valid
1210
 *    5555425555: valid
1211
 *    555 555 5555: valid
1212
 *    1(519) 555-4444: valid
1213
 *    1 (519) 555-4422: valid
1214
 *    1-555-555-5555: valid
1215
 *    1-(555)-555-5555: valid
1216
 *    +1(519) 555-4444: valid
1217
 *    +1 (519) 555-4422: valid
1218
 *    +1-555-555-5555: valid
1219
 *    +1-(555)-555-5555: valid
1220
 *
1221
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
1222
 */
1223
function isphoneNumber($field): bool
1224
{
1225
    if (isNullOrEmpty($field) || strlen(trim($field)) < 2) {
1226
        return false;
1227
    }
1228
    $field = trim($field);
1229
    if (starts_with($field, '+')) {
1230
        $field = trim(substr($field, 1));
1231
    }
1232
    $regex = '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
1233
    return preg_match($regex, $field) === 1;
1234
}
1235
1236
/**
1237
 * check is string is a Json string.
1238
 *
1239
 * @param string $field
1240
 *
1241
 * @return bool
1242
 */
1243
function isJsonString($field): bool
1244
{
1245
    if (isNullOrEmpty($field)) {
1246
        return false;
1247
    }
1248
    return is_string($field) && is_object(json_decode($field));
1249
}
1250
1251
1252
/**
1253
 * Checks that a value is a valid UUID - http://tools.ietf.org/html/rfc4122
1254
 *
1255
 * @param string $check Value to check
1256
 * @return bool Success
1257
 */
1258
function isUuid($check)
1259
{
1260
    $regex = '/^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[0-5][a-fA-F0-9]{3}-[089aAbB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$/';
1261
    return preg_match($regex, $check) === 1;
1262
}
1263
1264
1265
/**
1266
 * Validates a geographic coordinate.
1267
 *
1268
 * Supported formats:
1269
 *
1270
 * - `<latitude>, <longitude>` Example: `-25.274398, 133.775136`
1271
 *
1272
 * ### Options
1273
 *
1274
 * - `type` - A string of the coordinate format, right now only `latLong`.
1275
 * - `format` - By default `both`, can be `long` and `lat` as well to validate
1276
 *   only a part of the coordinate.
1277
 *
1278
 * @param string $value Geographic location as string
1279
 * @param array $options Options for the validation logic.
1280
 * @return bool|Exception
1281
 */
1282
function isGeoCoordinate($value, array $options = [])
1283
{
1284
    $_pattern = [
1285
        'latitude' => '[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)',
1286
        'longitude' => '[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)',
1287
    ];
1288
1289
    $options += [
1290
        'format' => 'both',
1291
        'type' => 'latLong'
1292
    ];
1293
    if ($options['type'] !== 'latLong') {
1294
        throw new RuntimeException(sprintf(
1295
            'Unsupported coordinate type "%s". Use "latLong" instead.',
1296
            $options['type']
1297
        ));
1298
    }
1299
    $pattern = '/^' . $_pattern['latitude'] . ',\s*' . $_pattern['longitude'] . '$/';
1300
    if ($options['format'] === 'long') {
1301
        $pattern = '/^' . $_pattern['longitude'] . '$/';
1302
    }
1303
    if ($options['format'] === 'lat') {
1304
        $pattern = '/^' . $_pattern['latitude'] . '$/';
1305
    }
1306
    return (bool)preg_match($pattern, $value);
1307
}
1308
1309
/**
1310
 * Convenience method for latitude validation.
1311
 *
1312
 * @param string $value Latitude as string
1313
 * @param array $options Options for the validation logic.
1314
 * @return bool
1315
 * @link https://en.wikipedia.org/wiki/Latitude
1316
 * @see \Cake\Validation\Validation::geoCoordinate()
1317
 */
1318
function isLatitude($value, array $options = [])
1319
{
1320
    $options['format'] = 'lat';
1321
    return isGeoCoordinate($value, $options);
1322
}
1323
1324
/**
1325
 * Convenience method for longitude validation.
1326
 *
1327
 * @param string $value Latitude as string
1328
 * @param array $options Options for the validation logic.
1329
 * @return bool
1330
 * @link https://en.wikipedia.org/wiki/Longitude
1331
 * @see \Cake\Validation\Validation::geoCoordinate()
1332
 */
1333
function isLongitude($value, array $options = []): bool
1334
{
1335
    $options['format'] = 'long';
1336
    return isGeoCoordinate($value, $options);
1337
}
1338
1339
/**
1340
 * Check that the input value is within the ascii byte range.
1341
 *
1342
 * This method will reject all non-string values.
1343
 *
1344
 * @param string $value The value to check
1345
 * @return bool
1346
 */
1347
function isAscii($value)
1348
{
1349
    if (!is_string($value)) {
1350
        return false;
1351
    }
1352
    return strlen($value) <= mb_strlen($value, 'utf-8');
1353
}
1354
1355
/**
1356
 * Check that the input value is a utf8 string.
1357
 *
1358
 * This method will reject all non-string values.
1359
 *
1360
 * # Options
1361
 *
1362
 * - `extended` - Disallow bytes higher within the basic multilingual plane.
1363
 *   MySQL's older utf8 encoding type does not allow characters above
1364
 *   the basic multilingual plane. Defaults to false.
1365
 *
1366
 * @param string $value The value to check
1367
 * @param array $options An array of options. See above for the supported options.
1368
 * @return bool
1369
 */
1370
function isUtf8($value, array $options = []): bool
1371
{
1372
    if (!is_string($value)) {
1373
        return false;
1374
    }
1375
    $options += ['extended' => false];
1376
    if ($options['extended']) {
1377
        return true;
1378
    }
1379
    return preg_match('/[\x{10000}-\x{10FFFF}]/u', $value) === 0;
1380
}
1381