Completed
Push — master ( fb68e6...5b081f )
by Lorenzo
02:25
created

validation.php ➔ betweenDateIso()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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