1: <?php
2: /**
3: * This file is part of the PHPLucidFrame library.
4: * Core utility for input validation
5: *
6: * @package PHPLucidFrame\Core
7: * @since PHPLucidFrame v 1.0.0
8: * @copyright Copyright (c), PHPLucidFrame.
9: * @link http://phplucidframe.com
10: * @license http://www.opensource.org/licenses/mit-license.php MIT License
11: *
12: * This source file is subject to the MIT license that is bundled
13: * with this source code in the file LICENSE
14: */
15:
16: use LucidFrame\Core\Validation;
17:
18: /**
19: * @internal
20: * @ignore
21: *
22: * Initialize the validation messages
23: */
24: function __validation_init()
25: {
26: $validationMessages = array(
27: 'default' => "'%s' needs to be revised.",
28: 'mandatory' => "'%s' is required.",
29: 'mandatoryOne' => "'%s' must be entered/selected at least one.",
30: 'mandatoryAll' => "'%s' is required. All must be entered/selected.",
31: 'notAllowZero' => "'%s' should not be zero.",
32: 'alphaNumeric' => "'%s' should contain only letters and numbers.",
33: 'alphaNumericSpace' => "'%s' should contain only letters, numbers and spaces.",
34: 'alphaNumericDash' => "'%s' should contain only letters, numbers and dashes.",
35: 'numeric' => "'%s' should be a number.",
36: 'numericSpace' => "'%s' should contain only numbers and spaces.",
37: 'numericDash' => "'%s' should contain only numbers and dashes. It should not start or end with a dash.",
38: 'username' => "'%s' should contain only letters, numbers, periods, underscores and dashes.",
39: 'naturalNumber' => "'%s' should be a positive integer. It is not allowed zero.",
40: 'wholeNumber' => "'%s' should be a positive integer.",
41: 'integer' => "'%s' should be a positive or negative integer.",
42: 'rationalNumber' => "'%s' should be an integer or decimal.",
43: 'positiveRationalNumber' => "'%s' should be a positive integer or decimal.",
44: 'email' => "'%s' should be a valid format, e.g., username@example.com",
45: 'domain' => "'%s' should be a valid domain name with letters, numbers and dash only.",
46: 'url' => "'%s' should be a valid website address, e.g., http://www.example.com",
47: 'exactLength' => "'%s' should have exact length of %d.",
48: 'min' => "'%s' should be greater than or equal to %d.",
49: 'max' => "'%s' should be less than or equal to %d.",
50: 'minLength' => "'%s' should have at least %d letters.",
51: 'maxLength' => "'%s' should not exceed %d letters.",
52: 'between' => "'%s' should be between %d and %d.",
53: 'fileMaxSize' => "'%s' cannot exceed the maximum allowed upload size %dMB.",
54: 'fileMaxWidth' => "'%s' cannot exceed the maximum allowed width %dpx.",
55: 'fileMaxHeight' => "'%s' cannot exceed the maximum allowed height %dpx.",
56: 'fileMaxDimension' => "'%s' cannot exceed the maximum allowed dimension %dpx%dpx.",
57: 'fileExactDimension' => "'%s' should have the dimension %dx%dpx.",
58: 'fileExtension' => "'%s' must be one of the file types: %s.",
59: 'date' => "'%s' should be valid for the date format '%s'.",
60: 'time' => "'%s' should be valid for the time format '%s'.",
61: 'datetime' => "'%s' should be valid for the date/time format '%s %s'.",
62: 'unique' => "'%s' already exists. Please try another one.",
63: 'custom' => "'%s' should be a valid format."
64: );
65:
66: if (function_exists('__validation_messages')) {
67: $validationMessages = array_merge($validationMessages, __validation_messages());
68: }
69:
70: $i18nEnabled = function_exists('_t');
71:
72: foreach ($validationMessages as $key => $msg) {
73: $validationMessages[$key] = ($i18nEnabled) ? _t($msg) : $msg;
74: }
75:
76: Validation::set('messages', $validationMessages);
77: }
78:
79: /**
80: * Setter for Validation class properties
81: * @param string $key The property name
82: * @param mixed $value The value for the property
83: * @return void
84: */
85: function validation_set($key, $value = null)
86: {
87: Validation::set($key, $value);
88: }
89:
90: /**
91: * Getter for Validation class properties
92: * @param string $key The property name
93: * @return mixed
94: */
95: function validation_get($key)
96: {
97: return Validation::get($key);
98: }
99:
100: /**
101: * Check all inputs according to the validation rules provided
102: *
103: * @param array $validations The array of the validation rules
104: * @param array $data The optional data array (if no `value` in $validation, it will be looked up in $data)
105: * @param string $type The return form of the error message:
106: * "multi" to return all error messages occurred;
107: * "single" to return the first error message occurred
108: *
109: * @return bool
110: */
111: function validation_check($validations, $data = [], $type = Validation::TYPE_MULTI)
112: {
113: return Validation::check($validations, $data, $type);
114: }
115:
116: /**
117: * Add an external error message
118: *
119: * @param string $id HTML ID
120: * @param string $msg The error message to show
121: *
122: * @return void
123: */
124: function validation_addError($id, $msg)
125: {
126: Validation::addError($id, $msg);
127: }
128:
129: /**
130: * Checks that a string contains something other than whitespace
131: * @param mixed $value The value being checked
132: * @return boolean TRUE if the value contains something other than whitespace, FALSE otherwise
133: */
134: function validate_mandatory($value)
135: {
136: if (is_array($value) && count($value) == 0) {
137: return false; # other grouped inputs
138: }
139:
140: if (is_array($value) && isset($value['name']) && empty($value['name'])) {
141: return false; # file upload
142: }
143:
144: if (empty($value) && $value != '0') {
145: return false;
146: }
147:
148: return (is_array($value)) ? true : preg_match('/[^\s]+/', $value);
149: }
150: /**
151: * Check one of the fields is required
152: * @param array $value The array of values to check
153: * @return boolean TRUE if one of the fields are not empty, FALSE otherwise
154: */
155: function validate_mandatoryOne($value)
156: {
157: if (is_array($value)) {
158: $value = array_unique($value);
159: $empty = true;
160: foreach ($value as $v) {
161: if (preg_match('/[^\s]+/', $v)) {
162: # if one of the value is not empty
163: $empty = false;
164: }
165: }
166: return !$empty;
167: } else {
168: return preg_match('/[^\s]+/', $value);
169: }
170: }
171: /**
172: * Check all the fields are not empty
173: * @param array $value The array of values being checked
174: * @return boolean TRUE if all the fields are not empty, FALSE otherwise
175: */
176: function validate_mandatoryAll($value)
177: {
178: if (is_array($value)) {
179: $value = array_unique($value);
180: foreach ($value as $v) {
181: if (preg_match('/[\s]+/', $v)) {
182: # if one of the value is empty
183: return false;
184: }
185: }
186: return true;
187: } else {
188: return preg_match('/[^\s]+/', $value);
189: }
190: }
191: /**
192: * Check a string or number is zero or not
193: * @param string $value The value being checked
194: * @return boolean TRUE for non-zero, FALSE otherwise
195: */
196: function validate_notAllowZero($value)
197: {
198: $value = trim($value);
199:
200: return ($value == '0' || $value == 0) ? false : true;
201: }
202: /**
203: * Checks that a string contains only integer or letters
204: * @param mixed $value The value being checked
205: * @return boolean TRUE if the value contains only integer or letters, FALSE otherwise
206: */
207: function validate_alphaNumeric($value)
208: {
209: $value = trim($value);
210: if ($value == '') {
211: return true;
212: }
213:
214:
215: return preg_match('/^[A-Za-z0-9]+$/', $value);
216: }
217: /**
218: * Checks that a string contains only integer, letters or spaces
219: * @param mixed $value The value being checked
220: * @return boolean TRUE if the value contains only integer, letters or spaces, FALSE otherwise
221: */
222: function validate_alphaNumericSpace($value)
223: {
224: $value = trim($value);
225: if ($value == '') {
226: return true;
227: }
228:
229:
230: return preg_match('/^[A-Za-z0-9 ]+$/', $value);
231: }
232: /**
233: * Checks that a string contains only integer, letters or dashes
234: * @param mixed $value The value being checked
235: * @return boolean TRUE if the value contains only integer, letters or dashes, FALSE otherwise
236: */
237: function validate_alphaNumericDash($value)
238: {
239: $value = trim($value);
240: if ($value == '') {
241: return true;
242: }
243:
244:
245: return preg_match('/^[A-Za-z0-9\-]+$/', $value);
246: }
247: /**
248: * Checks if a value is numeric.
249: * @param mixed $value The value being checked
250: * @return boolean TRUE if var is a number or a numeric string, FALSE otherwise.
251: */
252: function validate_numeric($value)
253: {
254: $value = trim($value);
255: if ($value == '') {
256: return true;
257: }
258:
259:
260: return is_numeric($value);
261: }
262: /**
263: * Checks if the value contains numbers and dashes
264: * @param mixed $value The value being checked
265: * @return boolean TRUE if the value contains numbers and dashes only, FALSE otherwise
266: */
267: function validate_numericDash($value)
268: {
269: if (is_numeric($value) && strlen($value) == 1) {
270: return true;
271: }
272:
273: if (empty($value)) {
274: return true;
275: }
276:
277: return preg_match('/^([0-9])+([0-9\-])*([0-9])+$/', $value);
278: }
279: /**
280: * Checks if the value contains numbers and spaces
281: * @param string $value The value being checked
282: * @return boolean TRUE if the value contains numbers and spaces only, FALSE otherwise
283: */
284: function validate_numericSpace($value)
285: {
286: if (is_numeric($value) && strlen($value) == 1) {
287: return true;
288: }
289:
290: if (empty($value)) {
291: return true;
292: }
293:
294: return preg_match('/^[0-9 ]+$/', $value);
295: }
296: /**
297: * Checks if the value does not contain special characters
298: * @param mixed $value The value being checked
299: * @return boolean TRUE if the value does not contain special characters, FALSE otherwise
300: */
301: function validate_username($value)
302: {
303: $value = trim($value);
304: if ($value == '') {
305: return true;
306: }
307:
308:
309: return preg_match('/^([A-Za-z])+([A-Za-z0-9_\-\.])*([A-Za-z0-9])+$/', $value);
310: }
311: /**
312: * Checks if a value is a positive integer starting from 1, 2, 3, and so on. No decimal
313: * @param mixed $value The value being checked
314: * @return boolean TRUE if the value is natural number, FALSE otherwise
315: * @see http://en.wikipedia.org/wiki/Natural_number
316: * http://math.about.com/od/mathhelpandtutorials/a/Understanding-Classification-Of-Numbers.htm
317: */
318: function validate_naturalNumber($value)
319: {
320: $value = trim($value);
321: if ($value == '') {
322: return true;
323: }
324:
325: return preg_match('/^[1-9][0-9]*$/', $value);
326: }
327: /**
328: * Checks if a value is a positive integer starting from 0, 1, 2, 3, and so on. No decimal.
329: * @param mixed $value The value being checked
330: * @return boolean TRUE if the value is whole number, FALSE otherwise
331: * @see http://math.about.com/od/mathhelpandtutorials/a/Understanding-Classification-Of-Numbers.htm
332: */
333: function validate_wholeNumber($value)
334: {
335: $value = trim($value);
336: if ($value == '') {
337: return true;
338: }
339:
340: return preg_match('/^(?:0|[1-9][0-9]*)$/', $value);
341: }
342: /**
343: * Checks if a value is a positive or negative integer.
344: * @param mixed $value The value being checked
345: * @return boolean TRUE if the value is integer, FALSE otherwise
346: * @see http://math.about.com/od/mathhelpandtutorials/a/Understanding-Classification-Of-Numbers.htm
347: */
348: function validate_integer($value)
349: {
350: $value = trim($value);
351: if ($value == '') {
352: return true;
353: }
354:
355: return preg_match('/^[-]?(?:0|[1-9][0-9]*)$/', $value);
356: }
357: /**
358: * Checks if a value is an integer AND decimal.
359: * @param mixed $value The value being checked
360: * @return boolean TRUE if the value is rational number, FALSE otherwise
361: * @see http://math.about.com/od/mathhelpandtutorials/a/Understanding-Classification-Of-Numbers.htm
362: */
363: function validate_rationalNumber($value)
364: {
365: $value = trim($value);
366: if ($value == '') {
367: return true;
368: }
369:
370: return preg_match('/^[-]?[0-9]*[\.]?[0-9]+$/', $value);
371: }
372: /**
373: * Checks if a value is a positive integer AND decimal
374: * @param mixed $value The value being checked
375: * @return boolean TRUE if the value is positive rational number, FALSE otherwise
376: * @see http://math.about.com/od/mathhelpandtutorials/a/Understanding-Classification-Of-Numbers.htm
377: */
378: function validate_positiveRationalNumber($value)
379: {
380: $value = trim($value);
381: if ($value == '') {
382: return true;
383: }
384:
385: return preg_match('/^[0-9]*[\.]?[0-9]+$/', $value);
386: }
387: /**
388: * Validates for an email address.
389: * @param mixed $value The value being checked
390: * @return boolean TRUE if the value is a valid email address, FALSE otherwise
391: */
392: function validate_email($value)
393: {
394: $value = trim($value);
395: if ($value == '') {
396: return true;
397: }
398:
399: return preg_match('/^[A-Za-z0-9]([A-Za-z0-9]|_|\.|\-)*@([a-z0-9]|\.|\-)+\.[a-z]{2,4}$/', $value);
400: }
401: /**
402: * Checks if the value is a valid domain (alpha-numeric and dash only)
403: * @param mixed $value The value being checked
404: * @return boolean TRUE if the value has letters, numbers and dashes only, FALSE otherwise
405: */
406: function validate_domain($value)
407: {
408: if (empty($value)) {
409: return true;
410: }
411:
412: return preg_match('/^([a-z])+([a-z0-9\-])*([a-z0-9])+$/i', $value);
413: }
414: /**
415: * Validates for a valid absolute web address
416: * @param mixed $value The value being checked
417: * @return boolean TRUE if the value is a valid absolute web address, FALSE otherwise
418: */
419: function validate_url($value)
420: {
421: if (empty($value)) {
422: return true;
423: }
424:
425: $value = rtrim($value, '/');
426:
427: # Get host name from URL
428: preg_match("/^((http|https|ftp):\/\/)?([^\/]+)/i", $value, $matches);
429: $host = $matches[3];
430: $hostParts = explode('.', $host);
431:
432: if (strstr($host, '@') !== false) {
433: return false;
434: }
435:
436: if (preg_match('/^(w+)$/i', $hostParts[0], $matches) && strlen($matches[0]) != 3) {
437: return false;
438: }
439:
440: return preg_match('/^((http|https|ftp):\/\/)?([a-z0-9_\-]+\.)+([a-z]{2,13})(\/[.^\S]+)*$/', $value);
441: }
442: /**
443: * Checks that a string/array's length is equal to the specific length.
444: * @param mixed $value The value being checked
445: * @param int $length The exact length to meet
446: * @return boolean if the character length of the value meets the specified exact length, FALSE otherwise
447: */
448: function validate_exactLength($value, $length)
449: {
450: if (is_array($value)) {
451: return count($value) == $length;
452: }
453:
454: return mb_strlen($value) == $length;
455: }
456: /**
457: * Checks that a string length is greater than the specific length.
458: * @param mixed $value The value being checked
459: * @param int $min The minimum length to meet (inclusive)
460: * @return boolean if the character length of the value meets the specified minimum length, FALSE otherwise
461: */
462: function validate_minLength($value, $min)
463: {
464: return mb_strlen($value) >= $min;
465: }
466: /**
467: * Checks that a string length is less than the specific length.
468: * @param mixed $value The value being checked
469: * @param int $max The maximum length to meet (inclusive)
470: * @return boolean if the character length of the value meets the specified maximum length, FALSE otherwise
471: */
472: function validate_maxLength($value, $max)
473: {
474: $length = mb_strlen($value);
475: return ($length <= $max);
476: }
477: /**
478: * Checks that a number is greater than the specific number.
479: * @param int/float $value The value being checked
480: * @param int/float $min The minimum value to meet (inclusive)
481: * @return boolean if the value is equal to or greater than the specific minimum number, FALSE otherwise
482: */
483: function validate_min($value, $min)
484: {
485: return $value >= $min;
486: }
487: /**
488: * Checks that a number is less than the specific number.
489: * @param int/float $value The value being checked
490: * @param int/float $max The maximum value to meet (inclusive)
491: * @return boolean if the value is equal to or less than the specific maximum number, FALSE otherwise
492: */
493: function validate_max($value, $max)
494: {
495: return $value <= $max;
496: }
497: /**
498: * Checks that a number is within a specified range.
499: * @param int/float $value The value being checked
500: * @param int/float $min The minimum value in range (inclusive)
501: * @param int/float $max The maximum value in range (inclusive)
502: * @return boolean TRUE if the number is within the specified range, FALSE otherwise
503: */
504: function validate_between($value, $min, $max)
505: {
506: return $value >= $min && $value <= $max;
507: }
508: /**
509: * Used when a custom regular expression is needed.
510: * Searches the value for a match to the regular expression given in pattern.
511: * @param mixed $value The value being checked
512: * @param string $pattern The pattern to search for, as a string
513: * @return mixed `1` if the pattern matches given value, `0` if it does not, or `FALSE` if an error occurred.
514: * @see http://php.net/manual/en/function.preg-match.php
515: */
516: function validate_custom($value, $pattern)
517: {
518: if (empty($value) && $value != '0') {
519: return true;
520: }
521:
522: return preg_match($pattern, $value);
523: }
524: /**
525: * Validation of image file upload for allowed file extensions
526: * @param array $value The $_FILES array
527: * @param array $extensions The Array of file extensions such as `array('jpg', 'jpeg', 'png', 'gif')`
528: * @return boolean TRUE if the uploaded file extension is allowed according to the given extensions, FALSE otherwise
529: */
530: function validate_fileExtension($value, $extensions = array('jpg', 'jpeg', 'png', 'gif'))
531: {
532: if (!is_array($value)) {
533: return true;
534: }
535:
536: if (!file_exists($value['tmp_name'])) {
537: return true;
538: }
539:
540: if (empty($value['name'])) {
541: return true;
542: }
543:
544: $ext = explode('.', $value['name']);
545: $ext = strtolower(end($ext));
546:
547: return in_array($ext, $extensions);
548: }
549: /**
550: * Validation of maximum file upload size
551: * @param array $value The $_FILES array
552: * @param int $maxSize The maximum file size in MB
553: * @return boolean TRUE if the uploaded file does not exceed the given file size, FALSE otherwise
554: */
555: function validate_fileMaxSize($value, $maxSize = null)
556: {
557: if (!is_array($value)) {
558: return true;
559: }
560:
561: if (is_null($maxSize)) {
562: return true;
563: }
564:
565: $fileSize = $value['size'];
566: $maxSize = $maxSize * 1024 * 1024; # in bytes
567:
568: return $fileSize <= $maxSize;
569: }
570: /**
571: * Validation of image file upload for max width and max height
572: * @param array $value The $_FILES array
573: * @param int $maxWidth The maximum image width in pixels
574: * @param int $maxHeight The maximum image height in pixels
575: * @return boolean
576: * TRUE if the image uploaded dimension does not exceed the given max width and height;
577: * FALSE otherwise
578: */
579: function validate_fileMaxDimension($value, $maxWidth, $maxHeight)
580: {
581: if (!is_array($value)) {
582: return true;
583: }
584:
585: if (!file_exists($value['tmp_name'])) {
586: return true;
587: }
588:
589: list($width, $height) = getimagesize($value['tmp_name']);
590: return $width <= $maxWidth && $height <= $maxHeight;
591: }
592: /**
593: * Validation of image file upload for exact width and height
594: * @param array $value The $_FILES array
595: * @param int $width The image width in pixels
596: * @param int $height The mage height in pixels
597: * @return boolean
598: * TRUE if the image uploaded dimension same as the given max width and height;
599: * FALSE otherwise
600: */
601: function validate_fileExactDimension($value, $width, $height)
602: {
603: if (!is_array($value)) {
604: return true;
605: }
606:
607: if (!file_exists($value['tmp_name'])) {
608: return true;
609: }
610:
611: list($w, $h) = getimagesize($value['tmp_name']);
612:
613: return $w == $width && $h == $height;
614: }
615: /**
616: * Validation of image file upload for max width only
617: * @param array $value The $_FILES array
618: * @param int $maxWidth The maximum image width in pixels
619: * @return boolean
620: * TRUE if the uploaded image does not exceed the maximum width allowed;
621: * FALSE otherwise
622: */
623: function validate_fileMaxWidth($value, $maxWidth)
624: {
625: if (!is_array($value)) {
626: return true;
627: }
628:
629: if (!file_exists($value['tmp_name'])) {
630: return true;
631: }
632:
633: list($width, $height) = getimagesize($value['tmp_name']);
634:
635: return $width <= $maxWidth;
636: }
637: /**
638: * Validation of image file upload for max height only
639: * @param array $value The $_FILES array
640: * @param int $maxHeight The maximum image height in pixels
641: * @return boolean
642: * TRUE if the uploaded image does not exceed the maximum height allowed;
643: * FALSE otherwise
644: */
645: function validate_fileMaxHeight($value, $maxHeight)
646: {
647: if (!is_array($value)) {
648: return true;
649: }
650:
651: if (!file_exists($value['tmp_name'])) {
652: return true;
653: }
654:
655: list($width, $height) = getimagesize($value['tmp_name']);
656:
657: return $height <= $maxHeight;
658: }
659: /**
660: * Validation of an IP address.
661: * @param string $value The value being checked
662: * @param string $type The IP protocol version to validate against IPv4 or IPv6
663: * @return boolean TRUE on success; FALSE on failure
664: */
665: function validate_ip($value, $type = 'both')
666: {
667: $type = strtolower($value);
668: $flags = 0;
669: if ($type === 'v4' || $type === 'ipv4') {
670: $flags = FILTER_FLAG_IPV4;
671: }
672:
673: if ($type === 'v6' || $type === 'ipv6') {
674: $flags = FILTER_FLAG_IPV6;
675: }
676:
677: return (boolean)filter_var($value, FILTER_VALIDATE_IP, array('flags' => $flags));
678: }
679: /**
680: * Validation of a date which checks if the string passed is a valid date.
681: * **Allowed formats**
682: *
683: * - `d-m-y` 31-12-2014 separators can be a period, dash, forward slash, but not allow space
684: * - `m-d-y` 12-31-2014 separators can be a period, dash, forward slash, but not allow space
685: * - `y-m-d` 2014-12-31 separators can be a period, dash, forward slash, but not allow space
686: *
687: * @param string $value The date string being checked
688: * @param string $format The date format to be validated against. Default is y-m-d for 2014-12-31
689: *
690: * @return bool TRUE on success; FALSE on failure
691: */
692: function validate_date($value, $format = 'y-m-d')
693: {
694: if (empty($value)) {
695: return true;
696: }
697:
698: $value = trim($value);
699: $format = strtolower($format);
700: $separators = array('/', '-', '.');
701: $sepGroup = '([-\/.])';
702: $cleanFormat = preg_replace('/'.$sepGroup.'/', '', $format); // remove the separators from the format
703:
704: if (in_array($cleanFormat, array('dmy', 'mdy'))) {
705: $pattern = '/^([\d]{1,2})'.$sepGroup.'([\d]{1,2})'.$sepGroup.'([\d]{4})$/'; // dmy or mdy
706: } else {
707: $pattern = '/^([\d]{4})'.$sepGroup.'([\d]{1,2})'.$sepGroup.'([\d]{1,2})$/'; // ymd
708: }
709:
710: if ($pattern && preg_match_all($pattern, $value, $matches)) {
711: if ($matches[2][0] != $matches[4][0]) {
712: return false; // inconsistent separators
713: }
714:
715: if (!in_array($matches[2][0], $separators)) {
716: return false; // invalid separator
717: }
718:
719: $sep = $matches[2][0]; // the separator using
720: $dt = explode($sep, $value);
721: $format = str_split($cleanFormat);
722: $ft = array_flip($format);
723: $y = $dt[$ft['y']];
724: $m = $dt[$ft['m']];
725: $d = $dt[$ft['d']];
726:
727: return checkdate($m, $d, $y);
728: }
729:
730: return false;
731: }
732: /**
733: * Validation of a time which checks if the string passed is a valid time in 24-hour or 12-hour format or both
734: * **Allowed inputs**
735: *
736: * - 23:59 or 01:00 or 1:00
737: * - 23:59:59 or 01:00:00 or 1:00:00
738: * - 11:59am or 01:00pm or 1:00pm
739: * - 11:59 am or 01:00 pm or 1:00 PM or 1:00PM
740: * - 11:59:59am 01:00:00pm or 1:00:00pm
741: * - 11:59:59 AM 01:00:00 PM or 1:00:00PM
742: *
743: * @param string $value The time string being checked
744: * @param string $timeFormat The time format: 12, 24 or both
745: *
746: * @return bool TRUE on success; FALSE on failure
747: */
748: function validate_time($value, $timeFormat = 'both')
749: {
750: if (empty($value)) {
751: return true;
752: }
753:
754: $value = trim($value);
755: $regex = array(
756: '24' => '/^([01]?[0-9]|2[0-3]):([0-5][0-9])(:[0-5][0-9])?$/', // 24-hour format
757: '12' => '/^(0?[0-9]|1[0-2]):([0-5][0-9])(:[0-5][0-9])?\s*(am|pm)$/i' // 12-hour format
758: );
759:
760: if (!in_array($timeFormat, array('both', '12', '24'))) {
761: $timeFormat = 'both';
762: }
763:
764: if ($timeFormat === 'both') {
765: $test = $regex;
766: } else {
767: $test = array($regex[$timeFormat]);
768: }
769:
770: foreach ($test as $pattern) {
771: if (preg_match($pattern, $value)) {
772: return true;
773: }
774: }
775:
776: return false;
777: }
778: /**
779: * Validation of a date/time which checks if the string passed is a valid date and time.
780: * **Allowed date formats**
781: *
782: * - `d-m-y` 31-12-2014 separators can be a period, dash, forward slash, but not allow space
783: * - `m-d-y` 12-31-2014 separators can be a period, dash, forward slash, but not allow space
784: * - `y-m-d` 2014-12-31 separators can be a period, dash, forward slash, but not allow space
785: *
786: * @param string $value The date/time string being checked
787: * @param string $dateFormat The date format only to be validated against. Default is y-m-d for 2014-12-31.
788: * @param string $timeFormat The time format: 12, 24 or both
789: *
790: * @return bool TRUE on success; FALSE on failure
791: */
792: function validate_datetime($value, $dateFormat = 'y-m-d', $timeFormat = 'both')
793: {
794: if (empty($value)) {
795: return true;
796: }
797:
798: $value = trim($value);
799: $generalPattern = '/^([\d]{1,4}[-\/.][\d]{1,2}[-\/.][\d]{1,4})(\s+.{4,}\s*(am|pm)?)$/i';
800: if (preg_match_all($generalPattern, $value, $matches)) {
801: $date = $matches[1][0];
802: $time = $matches[2][0];
803: return validate_date($date, $dateFormat) && validate_time($time, $timeFormat);
804: } else {
805: return false;
806: }
807: }
808: /**
809: * Validation of a record uniqueness
810: *
811: * @param mixed $value The value to check for uniqueness
812: * @param string $table The table name without prefix
813: * @param string $field The field name in the table to check
814: * @param int $id The optional ID field to be excluded
815: * @return boolean TRUE if the value already exists in the table; otherwise FALSE
816: */
817: function validate_unique($value, $table, $field, $id = 0)
818: {
819: $value = strtolower($value);
820: if (empty($value)) {
821: return true;
822: }
823:
824: $qb = db_count($table)
825: ->where()
826: ->condition($field, $value);
827:
828: if ($id) {
829: $qb->condition('id !=', $id);
830: }
831:
832: return $qb->fetch() ? false : true;
833: }
834: