Completed
Push — master ( 9802ab...25d319 )
by Lorenzo
03:18
created

validation.php ➔ isphoneNumber()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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