Completed
Push — master ( a654e3...7d4ece )
by Lorenzo
01:56
created

validation.php ➔ uuid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
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 greater than zero or equals to zero..
29
 * Only number >=0 and <=PHP_INT_MAX
30
 * or if $acceptIntegerFloatingPoints==true a floating point that match an positive integer).
31
 * @param $value
32
 * @param bool $acceptIntegerFloatingPoints
33
 * @return bool
34
 */
35
function isIntegerPositiveOrZero($value, $acceptIntegerFloatingPoints = false) : bool
36
{
37
    return isInteger($value, true, $acceptIntegerFloatingPoints) && $value >= 0;
38
}
39
40
/**
41
 * Check if the value (int, float or string) is a integer.
42
 * Only number <=PHP_INT_MAX (and >=PHP_INT_MIN if unsigned=true)
43
 * or if $acceptIntegerFloatingPoints==true a floating point that match an integer).
44
 * @param $value
45
 * @param bool $unsigned
46
 * @param bool $acceptIntegerFloatingPoints
47
 * @return bool
48
 */
49
function isInteger($value, $unsigned = true, $acceptIntegerFloatingPoints = false) : bool
50
{
51
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
52
        return false;
53
    }
54
55
    //accept only integer number and if $acceptIntegerFloatingPoints is true accept integer floating point too.
56
    return ((preg_match('/^' . ($unsigned ? '' : '-{0,1}') . '[0-9]{1,}$/', $value) === 1
57
            && ($value <= PHP_INT_MAX && $value >= PHP_INT_MIN && (((int)$value) == $value))
58
        )
59
        || ($acceptIntegerFloatingPoints && isIntegerFloatingPoint($value, $unsigned)));
60
}
61
62
/**
63
 * Check if string is a valid floating point that
64
 * match an integer (<=PHP_INT_MAX and >=PHP_INT_MIN if unsigned=true)
65
 * or is an integer
66
 * Ex.: 1, 1e2, 1E2, 1e+2, 1e-2, 1.4e+2, -1.2e+2, -1.231e-2 etc...
67
 * @param $value
68
 * @param bool $unsigned
69
 * @return bool
70
 */
71
function isIntegerFloatingPoint($value, $unsigned = true) : bool
72
{
73
    return isFloatingPoint($value, $unsigned)
74
    && $value <= PHP_INT_MAX && $value >= PHP_INT_MIN
75
    //big number rouned to int aproximately!
76
    //big number change into exp format
77
    && ((int)((double)$value) == $value || (int)$value == $value || strpos(strtoupper((string)$value), 'E') === false);
78
}
79
80
/**
81
 * Check if string is a valid floating point.
82
 * Ex.: [+-]1, [+-]1e2, [+-]1E2, [+-]1e+2, [+-]1e-2, [+-]1.43234e+2, -1.231e+2, -1.231e-2 etc...
83
 * @param $value
84
 * @param $unsigned
85
 * @return bool
86
 */
87
function isFloatingPoint($value, $unsigned) : bool
88
{
89
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
90
        return false;
91
    }
92
93
    return preg_match('/^' . ($unsigned ? '[+]{0,1}' : '[-+]{0,1}') . '[0-9]{1,}(\.[0-9]{1,}){0,1}([Ee][+,-]{0,1}[0-9]{1,}){0,}$/',
94
        $value) === 1;
95
}
96
97
/**
98
 * Check if the value are a double (integer or float in the form 1, 1.11...1.
99
 * @param $value
100
 * @param int $dec
101
 * @param bool $unsigned
102
 * @param bool $exactDec if set to true aspect number of dec exact to $dec,
103
 * otherwise $dec is max decimals accepted (0 decimals are also ok in this case).
104
 * if $dec is an empty string, accept 0 to infinite decimals.
105
 * @return bool
106
 */
107
function isDouble($value, $dec = 2, $unsigned = true, $exactDec = false) : bool
108
{
109
    if (isStringNumberStartsWithMoreThanOneZero($value)) {
110
        return false;
111
    }
112
    $regEx = '/^' . ($unsigned ? '' : '-{0,1}') . '[0-9]{1,}(\.{1}[0-9]{' . ($exactDec ? '' : '1,') . $dec . '})' . ($exactDec ? '{1}' : '{0,1}') . '$/';
113
    return preg_match($regEx, $value) === 1;
114
}
115
116
/**
117
 * Check if string is dd/mm/YYYY
118
 * @param $value
119
 * @return bool
120
 */
121 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...
122
{
123
    if (isNullOrEmpty($value) || strlen($value) != 10 || strpos($value, '/') === false) {
124
        return false;
125
    }
126
    list($dd, $mm, $yyyy) = explode('/', $value);
127
    try {
128
        return checkdate($mm, $dd, $yyyy);
129
    } catch (Exception $e) {
130
        return false;
131
    }
132
}
133
134
/**
135
 * Check if string is YYYY-mm-dd
136
 * @param $value
137
 * @return bool
138
 */
139 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...
140
{
141
    if (isNullOrEmpty($value) || strlen($value) != 10 || strpos($value, '-') === false) {
142
        return false;
143
    }
144
    list($yyyy, $mm, $dd) = explode('-', $value);
145
    try {
146
        return checkdate($mm, $dd, $yyyy);
147
    } catch (Exception $e) {
148
        return false;
149
    }
150
}
151
152
/**
153
 * Check if string is YYYY-mm-dd HH:ii:ss
154
 * @param $value
155
 * @return bool
156
 */
157
function isDateTimeIso($value) : bool
158
{
159
    if (!isDateIso(substr($value, 0, 10))) {
160
        return false;
161
    }
162
    return isTimeIso(substr($value, 11));
163
}
164
165
/**
166
 * Check if string is dd/mm/YYYY HH:ii:ss
167
 * @param $value
168
 * @return bool
169
 */
170
function isDateTimeIta($value) : bool
171
{
172
    if (!isDateIta(substr($value, 0, 10))) {
173
        return false;
174
    }
175
    return isTimeIso(substr($value, 11));
176
}
177
178
/**
179
 * Check if string is HH:ii:ss
180
 * @param $value
181
 * @return bool
182
 */
183
function isTimeIso($value) : bool
184
{
185
    $strRegExp = '/^[0-9]{2}:[0-9]{2}:[0-9]{2}$/';
186
    return preg_match($strRegExp, $value) === 1;
187
}
188
189
/**
190
 * An alias of isTimeIso.
191
 * @param $value
192
 * @return bool
193
 */
194
function isTimeIta($value)
195
{
196
    return isTimeIso($value);
197
}
198
199
/**
200
 * Determine if the provided input meets age requirement (ISO 8601).
201
 *
202
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
203
 * @param int $age
204
 *
205
 * @return bool
206
 */
207
function hasMinAge($dateOfBirthday, int $age) : bool
208
{
209
    return date_diff(date('Y-m-d'), $dateOfBirthday) >= $age;
210
}
211
212
/**
213
 * Determine if the provided input meets age requirement (ISO 8601).
214
 *
215
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
216
 * @param int $age
217
 *
218
 * @return bool
219
 */
220
function hasMaxAge($dateOfBirthday, int $age) : bool
221
{
222
    return date_diff(date('Y-m-d'), $dateOfBirthday) <= $age;
223
}
224
225
/**
226
 * Determine if the provided input meets age requirement (ISO 8601).
227
 *
228
 * @param string $dateOfBirthday date ('Y-m-d') or datetime ('Y-m-d H:i:s') Date Of Birthday
229
 * @param int $ageMin
230
 * @param int $ageMax
231
 *
232
 * @return bool
233
 */
234
function hasAgeInRange($dateOfBirthday, int $ageMin, int $ageMax) : bool
235
{
236
    return hasMinAge($dateOfBirthday, $ageMin) && hasMaxAge($dateOfBirthday, $ageMax);
237
}
238
239
/**
240
 * @param $value
241
 * @param $checkMx
242
 * @return bool
243
 */
244
function isMail($value, bool $checkMx = false) : bool
245
{
246
    if (filter_var($value, FILTER_VALIDATE_EMAIL) === false) {
247
        return false;
248
    }
249
    if ($checkMx) {
250
        list(, $mailDomain) = explode('@', $value);
251
        if (!checkdnsrr($mailDomain, 'MX')) {
252
            return false;
253
        }
254
    }
255
    return true;
256
}
257
258
/**
259
 * isIPv4 check if a string is a valid IP v4
260
 * @param  string $IP2Check IP to check
261
 * @return bool
262
 */
263
function isIPv4($IP2Check) : bool
264
{
265
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false);
266
}
267
268
/**
269
 * isIPv6 check if a string is a valid IP v6
270
 * @param  string $IP2Check IP to check
271
 * @return bool
272
 */
273
function isIPv6($IP2Check) : bool
274
{
275
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false);
276
}
277
278
/**
279
 * Check if a string is a valid IP (v4 or v6).
280
 * @param  string $IP2Check IP to check
281
 * @return bool
282
 */
283
function isIP($IP2Check) : bool
284
{
285
    return !(filter_var($IP2Check, FILTER_VALIDATE_IP) === false);
286
}
287
288
/**
289
 * Check if a string has a URL address syntax is valid.
290
 * It require scheme to be valide (http|https|ftp|mailto|file|data)
291
 * i.e.: http://dummy.com and http://www.dummy.com is valid but www.dummy.and dummy.com return false.
292
 * @param $url
293
 * @return bool
294
 */
295
function isUrl($url) : bool
296
{
297
    return filter_var($url, FILTER_VALIDATE_URL) !== false;
298
}
299
300
/**
301
 * Check if a string is valid hostname
302
 * (dummy.com, www.dummy.com, , www.dummy.co.uk, , www.dummy-dummy.com, etc..).
303
 * @param $value
304
 * @return bool
305
 */
306
function isHostname($value) : bool
307
{
308
    return preg_match('/(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)/i', $value) === 1;
309
}
310
311
/**
312
 * Checks that a value is a valid URL according to http://www.w3.org/Addressing/URL/url-spec.txt
313
 *
314
 * The regex checks for the following component parts:
315
 *
316
 * - a valid, optional, scheme
317
 * - a valid ip address OR
318
 *   a valid domain name as defined by section 2.3.1 of http://www.ietf.org/rfc/rfc1035.txt
319
 *   with an optional port number
320
 * - an optional valid path
321
 * - an optional query string (get parameters)
322
 * - an optional fragment (anchor tag)
323
 *
324
 * @param string $check Value to check
325
 * @param bool $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher)
326
 * @return bool Success
327
 * @see https://github.com/cakephp/cakephp/blob/master/src/Validation/Validation.php#L839
328
 */
329
function urlW3c($check, bool $strict = false) : bool
330
{
331
    $_pattern = array();
332
    $pattern = '((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}';
333
    $pattern .= '(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})';
334
    $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})';
335
    $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}:)';
336
    $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}))';
337
    $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}';
338
    $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|';
339
    $pattern .= '((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}';
340
    $pattern .= '((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2}))';
341
    $pattern .= '{3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4})';
342
    $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})?)';
343
    $pattern .= '|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]';
344
    $pattern .= '\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4})';
345
    $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})))(%.+)?';
346
    $_pattern['IPv6'] = $pattern;
347
348
    $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])';
349
    $_pattern['IPv4'] = $pattern;
350
351
    $_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,})'];
352
353
    $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~[]') . '\/0-9\p{L}\p{N}]|(%[0-9a-f]{2}))';
354
    $regex = '/^(?:(?:https?|ftps?|sftp|file|news|gopher):\/\/)' . ($strict ? '' : '?') .
355
        '(?:' . $_pattern['IPv4'] . '|\[' . $_pattern['IPv6'] . '\]|' . $_pattern['hostname'] . ')(?::[1-9][0-9]{0,4})?' .
356
        '(?:\/?|\/' . $validChars . '*)?' .
357
        '(?:\?' . $validChars . '*)?' .
358
        '(?:#' . $validChars . '*)?$/iu';
359
    return preg_match($regex, $check) === 1;
360
}
361
362
/**
363
 * Controlla partita IVA Italiana.
364
 * @author Umberto Salsi <[email protected]>
365
 * @author Lorenzo Padovani modified.
366
 * @version 2012-05-12
367
 * @param string $pi Partita IVA Italiana è costituita da 11 cifre. Non sono ammessi
368
 * caratteri di spazio, per cui i campi di input dell'utente dovrebbero
369
 * essere trimmati preventivamente. La stringa vuota e' ammessa, cioe'
370
 * il dato viene considerato opzionale.
371
 * @param bool $validateOnVIES default false. if se to true, first check algorithm then if it valid,
372
 * try to check VIES service. If VIES return false or soap exception was thrown, return false.
373
 * @return bool
374
 */
375
function isPiva(string $pi, bool $validateOnVIES = false) : bool
376
{
377
    if ($pi === null || $pi === '' || strlen($pi) != 11 || preg_match("/^[0-9]+\$/", $pi) != 1) {
378
        return false;
379
    }
380
    $s = 0;
381
    for ($i = 0; $i <= 9; $i += 2) {
382
        $s += ord($pi[$i]) - ord('0');
383
    }
384
    for ($i = 1; $i <= 9; $i += 2) {
385
        $c = 2 * (ord($pi[$i]) - ord('0'));
386
        if ($c > 9) {
387
            $c -= 9;
388
        }
389
        $s += $c;
390
    }
391
    if ((10 - $s % 10) % 10 != ord($pi[10]) - ord('0')) {
392
        return false;
393
    }
394
    if (!$validateOnVIES) {
395
        return true;
396
    }
397
    //check vies
398
    try {
399
        return isVATNumber($pi);
400
    } catch (SoapFault $e) {
401
        return false;
402
    }
403
}
404
405
/**
406
 * Validate a European VAT number using the EU commission VIES service.
407
 * If not $vatNumber starts with country code, a default $countryCodeDefault applied.
408
 * @param string $vatNumber
409
 * @param string $countryCodeDefault default 'IT'
410
 * @return bool
411
 * @throws SoapFault
412
 */
413
function isVATNumber(string $vatNumber, string $countryCodeDefault = 'IT') : bool
414
{
415
    if (!isAlphaNumericWhiteSpaces($vatNumber) || strlen(trim($vatNumber)) < 3) {
416
        return false;
417
    }
418
419
    $vatNumber = str_replace([' ', '-', '.', ','], '', strtoupper(trim($vatNumber)));
420
    $countryCode = strtoupper(substr($vatNumber, 0, 2));
421
422
    if (preg_match('/^[A-Za-z]{2}$/', $countryCode) === 1) {
423
        $vatNumber = substr($vatNumber, 2);
424
    } else {
425
        $countryCode = $countryCodeDefault != '' ? strtoupper($countryCodeDefault) : 'IT';
426
    }
427
    try {
428
        $serviceUrl = 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
429
        $client = new SoapClient($serviceUrl);
430
        $response = $client->checkVat([
431
            'countryCode' => $countryCode,
432
            'vatNumber' => $vatNumber,
433
        ]);
434
        return $response->valid;
435
    } catch (SoapFault $e) {
436
        throw $e;
437
    }
438
}
439
440
/**
441
 * Controlla codice fiscale.
442
 * @author Umberto Salsi <[email protected]>
443
 * @version 2012-05-12
444
 * @param string $cf Codice fiscale costituito da 16 caratteri. Non
445
 * sono ammessi caratteri di spazio, per cui i campi di input dell'utente
446
 * dovrebbero essere trimmati preventivamente. La stringa vuota e' ammessa,
447
 * cioe' il dato viene considerato opzionale.
448
 * @return bool
449
 */
450
function isCf(string $cf) : bool
451
{
452
    if ($cf === null || $cf === '' || strlen($cf) != 16) {
453
        return false;
454
    }
455
    $cf = strtoupper($cf);
456
    if (preg_match("/^[A-Z0-9]+\$/", $cf) != 1) {
457
        return false;
458
    }
459
    $s = 0;
460
    for ($i = 1; $i <= 13; $i += 2) {
461
        $c = $cf[$i];
462
        if (strcmp($c, "0") >= 0 && strcmp($c, "9") <= 0) {
463
            $s += ord($c) - ord('0');
464
        } else {
465
            $s += ord($c) - ord('A');
466
        }
467
    }
468
    for ($i = 0; $i <= 14; $i += 2) {
469
        $c = $cf[$i];
470
        switch ($c) {
471
            case '0':
472
                $s += 1;
473
                break;
474
            case '1':
475
                $s += 0;
476
                break;
477
            case '2':
478
                $s += 5;
479
                break;
480
            case '3':
481
                $s += 7;
482
                break;
483
            case '4':
484
                $s += 9;
485
                break;
486
            case '5':
487
                $s += 13;
488
                break;
489
            case '6':
490
                $s += 15;
491
                break;
492
            case '7':
493
                $s += 17;
494
                break;
495
            case '8':
496
                $s += 19;
497
                break;
498
            case '9':
499
                $s += 21;
500
                break;
501
            case 'A':
502
                $s += 1;
503
                break;
504
            case 'B':
505
                $s += 0;
506
                break;
507
            case 'C':
508
                $s += 5;
509
                break;
510
            case 'D':
511
                $s += 7;
512
                break;
513
            case 'E':
514
                $s += 9;
515
                break;
516
            case 'F':
517
                $s += 13;
518
                break;
519
            case 'G':
520
                $s += 15;
521
                break;
522
            case 'H':
523
                $s += 17;
524
                break;
525
            case 'I':
526
                $s += 19;
527
                break;
528
            case 'J':
529
                $s += 21;
530
                break;
531
            case 'K':
532
                $s += 2;
533
                break;
534
            case 'L':
535
                $s += 4;
536
                break;
537
            case 'M':
538
                $s += 18;
539
                break;
540
            case 'N':
541
                $s += 20;
542
                break;
543
            case 'O':
544
                $s += 11;
545
                break;
546
            case 'P':
547
                $s += 3;
548
                break;
549
            case 'Q':
550
                $s += 6;
551
                break;
552
            case 'R':
553
                $s += 8;
554
                break;
555
            case 'S':
556
                $s += 12;
557
                break;
558
            case 'T':
559
                $s += 14;
560
                break;
561
            case 'U':
562
                $s += 16;
563
                break;
564
            case 'V':
565
                $s += 10;
566
                break;
567
            case 'W':
568
                $s += 22;
569
                break;
570
            case 'X':
571
                $s += 25;
572
                break;
573
            case 'Y':
574
                $s += 24;
575
                break;
576
            case 'Z':
577
                $s += 23;
578
                break;
579
            /*. missing_default: .*/
580
        }
581
    }
582
    return !(chr($s % 26 + ord('A')) != $cf[15]);
583
}
584
585
/**
586
 * Determine if the provided value contains only alpha characters.
587
 *
588
 * @param string $field
589
 *
590
 * @return mixed
591
 *
592
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
593
 */
594
function isAlpha(string $field) : bool
595
{
596
    return isNotNullOrEmpty($field)
597
    && preg_match('/^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ])+$/i', $field) === 1;
598
}
599
600
/**
601
 * Determine if the provided value contains only alpha characters.
602
 *
603
 * @param string $field
604
 *
605
 * @return mixed
606
 *
607
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
608
 */
609
function isAlphaNumeric(string $field) : bool
610
{
611
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ])+$/i', $field) === 1;
612
}
613
614
/**
615
 * Determine if the provided value contains only alpha characters with dashed and underscores.
616
 *
617
 * @param string $field
618
 *
619
 * @return mixed
620
 */
621
function isAlphaNumericDash($field) : bool
622
{
623
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ\-_])+$/i', $field) === 1;
624
}
625
626
/**
627
 * Determine if the provided value contains only alpha numeric characters with spaces.
628
 *
629
 * @param string $field
630
 *
631
 * @return mixed
632
 */
633
function isAlphaNumericWhiteSpaces($field) : bool
634
{
635
    return preg_match('/^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖßÙÚÛÜÝàáâãäåçèéêëìíîïñðòóôõöùúûüýÿ\-_\s])+$/i', $field) === 1;
636
}
637
638
/**
639
 * Determine if the provided value is a boolean.
640
 *
641
 * @param string $field
642
 *
643
 * @return mixed
644
 */
645
function isBool($field) : bool
646
{
647
    return $field === true || $field === false;
648
}
649
650
/**
651
 * Determine if the provided value is a boolean or 1,0,'1','0'.
652
 *
653
 * @param string $field
654
 *
655
 * @return bool
656
 */
657
function isBoolOrIntBool($field) : bool
658
{
659
    return in_array($field, [0, 1, '0', '1', true, false], true);
660
}
661
662
/**
663
 * Determine if the input is a valid credit card number.
664
 *
665
 * See: http://stackoverflow.com/questions/174730/what-is-the-best-way-to-validate-a-credit-card-in-php
666
 *
667
 * @param string $field
668
 *
669
 * @return mixed
670
 */
671
function isCrediCard(string $field) : bool
672
{
673
    if (isNullOrEmpty($field)) {
674
        return false;
675
    }
676
    $number = preg_replace('/\D/', '', $field);
677
    if (function_exists('mb_strlen')) {
678
        $number_length = mb_strlen($number);
679
    } else {
680
        $number_length = strlen($number);
681
    }
682
    $parity = $number_length % 2;
683
    $total = 0;
684
    for ($i = 0; $i < $number_length; ++$i) {
685
        $digit = $number[$i];
686
        if ($i % 2 == $parity) {
687
            $digit *= 2;
688
            if ($digit > 9) {
689
                $digit -= 9;
690
            }
691
        }
692
        $total += $digit;
693
    }
694
    return ($total % 10 == 0);
695
}
696
697
/**
698
 * Determine if the input is a valid human name.
699
 *
700
 * @param string $field
701
 *
702
 * @return mixed
703
 *
704
 * @See: https://github.com/Wixel/GUMP/issues/5
705
 */
706
function isValidHumanName(string $field) : bool
707
{
708
    if (isNullOrEmpty($field)) {
709
        return false;
710
    }
711
    return isAlpha($field) && preg_match("/^([ '-])+$/", $field) === 1;
712
}
713
714
/**
715
 * Determine if the provided value is a valid IBAN.
716
 *
717
 * @param string $field
718
 *
719
 * @return bool
720
 *
721
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
722
 */
723
function isIban($field) : bool
724
{
725
    if (isNullOrEmpty($field)) {
726
        return false;
727
    }
728
    static $character = array(
729
        'A' => 10,
730
        'C' => 12,
731
        'D' => 13,
732
        'E' => 14,
733
        'F' => 15,
734
        'G' => 16,
735
        'H' => 17,
736
        'I' => 18,
737
        'J' => 19,
738
        'K' => 20,
739
        'L' => 21,
740
        'M' => 22,
741
        'N' => 23,
742
        'O' => 24,
743
        'P' => 25,
744
        'Q' => 26,
745
        'R' => 27,
746
        'S' => 28,
747
        'T' => 29,
748
        'U' => 30,
749
        'V' => 31,
750
        'W' => 32,
751
        'X' => 33,
752
        'Y' => 34,
753
        'Z' => 35,
754
        'B' => 11
755
    );
756
    if (preg_match('/\A[A-Z]{2}\d{2} ?[A-Z\d]{4}( ?\d{4}){1,} ?\d{1,4}\z/', $field) != 1) {
757
        return false;
758
    }
759
    $iban = str_replace(' ', '', $field);
760
    $iban = substr($iban, 4) . substr($iban, 0, 4);
761
    $iban = strtr($iban, $character);
762
    return (bcmod($iban, 97) != 1);
763
}
764
765
/**
766
 * check the file extension
767
 * for now checks onlt the ext should add mime type check.
768
 *
769
 * @param string $filePath
770
 * @param array $allowed_extensions array of extension to match
771
 *
772
 * @return bool
773
 * @see https://github.com/cakephp/cakephp/blob/master/src/Validation/Validation.php
774
 */
775
function hasFileExtension($filePath, array $allowed_extensions) : bool
776
{
777
    $extension = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
778
    $allowed_extensions = (array)array_map('mb_strtolower', $allowed_extensions);
779
    return in_array($extension, $allowed_extensions);
780
}
781
782
/**
783
 * Determine if the provided value is a valid phone number.
784
 *
785
 * @param string $field
786
 *
787
 * @return bool
788
 *
789
 * Examples:
790
 *
791
 *  555-555-5555: valid
792
 *    5555425555: valid
793
 *    555 555 5555: valid
794
 *    1(519) 555-4444: valid
795
 *    1 (519) 555-4422: valid
796
 *    1-555-555-5555: valid
797
 *    1-(555)-555-5555: valid
798
 *    +1(519) 555-4444: valid
799
 *    +1 (519) 555-4422: valid
800
 *    +1-555-555-5555: valid
801
 *    +1-(555)-555-5555: valid
802
 *
803
 * @see https://github.com/Wixel/GUMP/blob/master/gump.class.php
804
 */
805
function isphoneNumber($field) : bool
806
{
807
    if (isNullOrEmpty($field) || strlen(trim($field)) < 2) {
808
        return false;
809
    }
810
    $field = trim($field);
811
    if (starts_with($field, '+')) {
812
        $field = trim(substr($field, 1));
813
    }
814
    $regex = '/^(\d[\s-]?)?[\(\[\s-]{0,2}?\d{3}[\)\]\s-]{0,2}?\d{3}[\s-]?\d{4}$/i';
815
    return preg_match($regex, $field) === 1;
816
}
817
818
/**
819
 * check is string is a Json string.
820
 *
821
 * @param string $field
822
 *
823
 * @return bool
824
 */
825
function isJsonString($field) : bool
826
{
827
    if (isNullOrEmpty($field)) {
828
        return false;
829
    }
830
    return is_string($field) && is_object(json_decode($field));
831
}
832
833
834
/**
835
 * Checks that a value is a valid UUID - http://tools.ietf.org/html/rfc4122
836
 *
837
 * @param string $check Value to check
838
 * @return bool Success
839
 */
840
function isUuid($check)
841
{
842
    $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}$/';
843
    return preg_match($regex, $check) === 1;
844
}
845
846
847
/**
848
 * Validates a geographic coordinate.
849
 *
850
 * Supported formats:
851
 *
852
 * - `<latitude>, <longitude>` Example: `-25.274398, 133.775136`
853
 *
854
 * ### Options
855
 *
856
 * - `type` - A string of the coordinate format, right now only `latLong`.
857
 * - `format` - By default `both`, can be `long` and `lat` as well to validate
858
 *   only a part of the coordinate.
859
 *
860
 * @param string $value Geographic location as string
861
 * @param array $options Options for the validation logic.
862
 * @return bool|Exception
863
 */
864
function isGeoCoordinate($value, array $options = [])
865
{
866
    $_pattern = [
867
        'latitude' => '[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)',
868
        'longitude' => '[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)',
869
    ];
870
871
    $options += [
872
        'format' => 'both',
873
        'type' => 'latLong'
874
    ];
875
    if ($options['type'] !== 'latLong') {
876
        throw new RuntimeException(sprintf(
877
            'Unsupported coordinate type "%s". Use "latLong" instead.',
878
            $options['type']
879
        ));
880
    }
881
    $pattern = '/^' . $_pattern['latitude'] . ',\s*' . $_pattern['longitude'] . '$/';
882
    if ($options['format'] === 'long') {
883
        $pattern = '/^' . $_pattern['longitude'] . '$/';
884
    }
885
    if ($options['format'] === 'lat') {
886
        $pattern = '/^' . $_pattern['latitude'] . '$/';
887
    }
888
    return (bool)preg_match($pattern, $value);
889
}
890
891
/**
892
 * Convenience method for latitude validation.
893
 *
894
 * @param string $value Latitude as string
895
 * @param array $options Options for the validation logic.
896
 * @return bool
897
 * @link https://en.wikipedia.org/wiki/Latitude
898
 * @see \Cake\Validation\Validation::geoCoordinate()
899
 */
900
function isLatitude($value, array $options = [])
901
{
902
    $options['format'] = 'lat';
903
    return isGeoCoordinate($value, $options);
904
}
905
906
/**
907
 * Convenience method for longitude validation.
908
 *
909
 * @param string $value Latitude as string
910
 * @param array $options Options for the validation logic.
911
 * @return bool
912
 * @link https://en.wikipedia.org/wiki/Longitude
913
 * @see \Cake\Validation\Validation::geoCoordinate()
914
 */
915
function isLongitude($value, array $options = []) : bool
916
{
917
    $options['format'] = 'long';
918
    return isGeoCoordinate($value, $options);
919
}
920
921
/**
922
 * Check that the input value is within the ascii byte range.
923
 *
924
 * This method will reject all non-string values.
925
 *
926
 * @param string $value The value to check
927
 * @return bool
928
 */
929
function isAscii($value)
930
{
931
    if (!is_string($value)) {
932
        return false;
933
    }
934
    return strlen($value) <= mb_strlen($value, 'utf-8');
935
}
936
937
/**
938
 * Check that the input value is a utf8 string.
939
 *
940
 * This method will reject all non-string values.
941
 *
942
 * # Options
943
 *
944
 * - `extended` - Disallow bytes higher within the basic multilingual plane.
945
 *   MySQL's older utf8 encoding type does not allow characters above
946
 *   the basic multilingual plane. Defaults to false.
947
 *
948
 * @param string $value The value to check
949
 * @param array $options An array of options. See above for the supported options.
950
 * @return bool
951
 */
952
function isUtf8($value, array $options = []) : bool
953
{
954
    if (!is_string($value)) {
955
        return false;
956
    }
957
    $options += ['extended' => false];
958
    if ($options['extended']) {
959
        return true;
960
    }
961
    return preg_match('/[\x{10000}-\x{10FFFF}]/u', $value) === 0;
962
}
963