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