3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
36 require_once 'HTML/QuickForm/Rule/Email.php';
39 * Class CRM_Utils_Rule
41 class CRM_Utils_Rule
{
45 * @param int $maxLength
49 static function title($str, $maxLength = 127) {
52 if (empty($str) ||
strlen($str) > $maxLength) {
56 // Make sure it include valid characters, alpha numeric and underscores
57 if (!preg_match('/^\w[\w\s\'\&\,\$\#\-\.\"\?\!]+$/i', $str)) {
69 static function longTitle($str) {
70 return self
::title($str, 255);
78 static function variable($str) {
80 if (empty($str) ||
strlen($str) > 31) {
84 // make sure it include valid characters, alpha numeric and underscores
85 if (!preg_match('/^[\w]+$/i', $str)) {
97 static function qfVariable($str) {
99 //if ( empty( $str ) || strlen( $str ) > 31 ) {
100 if (strlen(trim($str)) == 0 ||
strlen($str) > 31) {
104 // make sure it include valid characters, alpha numeric and underscores
105 // added (. and ,) option (CRM-1336)
106 if (!preg_match('/^[\w\s\.\,]+$/i', $str)) {
118 static function phone($phone) {
120 if (empty($phone) ||
strlen($phone) > 16) {
124 // make sure it include valid characters, (, \s and numeric
125 if (preg_match('/^[\d\(\)\-\.\s]+$/', $phone)) {
136 static function query($query) {
138 if (empty($query) ||
strlen($query) < 3 ||
strlen($query) > 127) {
142 // make sure it include valid characters, alpha numeric and underscores
143 if (!preg_match('/^[\w\s\%\'\&\,\$\#]+$/i', $query)) {
155 static function url($url) {
156 return (bool) filter_var($url, FILTER_VALIDATE_URL
);
164 static function wikiURL($string) {
165 $items = explode(' ', trim($string), 2);
166 return self
::url($items[0]);
174 static function domain($domain) {
175 // not perfect, but better than the previous one; see CRM-1502
176 if (!preg_match('/^[A-Za-z0-9]([A-Za-z0-9\.\-]*[A-Za-z0-9])?$/', $domain)) {
184 * @param null $default
188 static function date($value, $default = NULL) {
189 if (is_string($value) &&
190 preg_match('/^\d\d\d\d-?\d\d-?\d\d$/', $value)
199 * @param null $default
201 * @return null|string
203 static function dateTime($value, $default = NULL) {
205 if (is_string($value) &&
206 preg_match('/^\d\d\d\d-?\d\d-?\d\d(\s\d\d:\d\d(:\d\d)?|\d\d\d\d(\d\d)?)?$/', $value)
215 * check the validity of the date (in qf format)
216 * note that only a year is valid, or a mon-year is
217 * also valid in addition to day-mon-year. The date
218 * specified has to be beyond today. (i.e today or later)
221 * @param bool $monthRequired check whether month is mandatory
223 * @return bool true if valid date
227 static function currentDate($date, $monthRequired = TRUE) {
228 $config = CRM_Core_Config
::singleton();
230 $d = CRM_Utils_Array
::value('d', $date);
231 $m = CRM_Utils_Array
::value('M', $date);
232 $y = CRM_Utils_Array
::value('Y', $date);
234 if (!$d && !$m && !$y) {
238 // CRM-9017 CiviContribute/CiviMember form with expiration date format 'm Y'
239 if (!$m && !empty($date['m'])) {
240 $m = CRM_Utils_Array
::value('m', $date);
255 // if we have day we need mon, and if we have mon we need year
264 if (!empty($day) ||
!empty($mon) ||
!empty($year)) {
265 $result = checkdate($mon, $day, $year);
272 // ensure we have month if required
273 if ($monthRequired && !$m) {
277 // now make sure this date is greater that today
278 $currentDate = getdate();
279 if ($year > $currentDate['year']) {
282 elseif ($year < $currentDate['year']) {
287 if ($mon > $currentDate['mon']) {
290 elseif ($mon < $currentDate['mon']) {
296 if ($day > $currentDate['mday']) {
299 elseif ($day < $currentDate['mday']) {
308 * check the validity of a date or datetime (timestamp)
309 * value which is in YYYYMMDD or YYYYMMDDHHMMSS format
311 * Uses PHP checkdate() - params are ( int $month, int $day, int $year )
313 * @param string $date
315 * @return bool true if valid date
319 static function mysqlDate($date) {
320 // allow date to be null
325 if (checkdate(substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4))) {
337 static function integer($value) {
338 if (is_int($value)) {
343 // ensure number passed is always a string numeral
344 if (!is_numeric($value)) {
348 // note that is_int matches only integer type
349 // and not strings which are only integers
350 // hence we do this here
351 if (preg_match('/^\d+$/', $value)) {
356 $negValue = -1 * $value;
357 if (is_int($negValue)) {
370 static function positiveInteger($value) {
371 if (is_int($value)) {
372 return ($value < 0) ?
FALSE : TRUE;
376 // ensure number passed is always a string numeral
377 if (!is_numeric($value)) {
381 if (preg_match('/^\d+$/', $value)) {
393 static function numeric($value) {
394 // lets use a php gatekeeper to ensure this is numeric
395 if (!is_numeric($value)) {
399 return preg_match('/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/', $value) ?
TRUE : FALSE;
408 static function numberOfDigit($value, $noOfDigit) {
409 return preg_match('/^\d{' . $noOfDigit . '}$/', $value) ?
TRUE : FALSE;
417 static function cleanMoney($value) {
418 // first remove all white space
419 $value = str_replace(array(' ', "\t", "\n"), '', $value);
421 $config = CRM_Core_Config
::singleton();
424 $currencySymbols = CRM_Core_PseudoConstant
::get(
425 'CRM_Contribute_DAO_Contribution',
427 'keyColumn' => 'name',
428 'labelColumn' => 'symbol'
430 $value = str_replace($currencySymbols,'',$value);
432 if ($config->monetaryThousandSeparator
) {
433 $mon_thousands_sep = $config->monetaryThousandSeparator
;
436 $mon_thousands_sep = ',';
439 // ugly fix for CRM-6391: do not drop the thousand separator if
440 // it looks like it’s separating decimal part (because a given
441 // value undergoes a second cleanMoney() call, for example)
442 if ($mon_thousands_sep != '.' or substr($value, -3, 1) != '.') {
443 $value = str_replace($mon_thousands_sep, '', $value);
446 if ($config->monetaryDecimalPoint
) {
447 $mon_decimal_point = $config->monetaryDecimalPoint
;
450 $mon_decimal_point = '.';
452 $value = str_replace($mon_decimal_point, '.', $value);
462 static function money($value) {
463 $config = CRM_Core_Config
::singleton();
465 //only edge case when we have a decimal point in the input money
466 //field and not defined in the decimal Point in config settings
467 if ($config->monetaryDecimalPoint
&&
468 $config->monetaryDecimalPoint
!= '.' &&
469 /* CRM-7122 also check for Thousands Separator in config settings */
470 $config->monetaryThousandSeparator
!= '.' &&
471 substr_count($value, '.')
476 $value = self
::cleanMoney($value);
478 if (self
::integer($value)) {
482 return preg_match('/(^-?\d+\.\d?\d?$)|(^-?\.\d\d?$)/', $value) ?
TRUE : FALSE;
487 * @param int $maxLength
491 static function string($value, $maxLength = 0) {
492 if (is_string($value) &&
493 ($maxLength === 0 ||
strlen($value) <= $maxLength)
505 static function boolean($value) {
507 '/(^(1|0)$)|(^(Y(es)?|N(o)?)$)|(^(T(rue)?|F(alse)?)$)/i', $value
516 static function email($value) {
517 return (bool) filter_var($value, FILTER_VALIDATE_EMAIL
);
525 static function emailList($list) {
526 $emails = explode(',', $list);
527 foreach ($emails as $email) {
528 $email = trim($email);
529 if (!self
::email($email)) {
536 // allow between 4-6 digits as postal code since india needs 6 and US needs 5 (or
537 // if u disregard the first 0, 4 (thanx excel!)
538 // FIXME: we need to figure out how to localize such rules
544 static function postalCode($value) {
545 if (preg_match('/^\d{4,6}(-\d{4})?$/', $value)) {
552 * see how file rules are written in HTML/QuickForm/file.php
553 * Checks to make sure the uploaded file is ascii
555 * @param array Uploaded file info (from $_FILES)
558 * @return bool true if file has been uploaded, false otherwise
560 static function asciiFile($elementValue) {
561 if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
562 (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')
564 return CRM_Utils_File
::isAscii($elementValue['tmp_name']);
570 * Checks to make sure the uploaded file is in UTF-8, recodes if it's not
572 * @param array Uploaded file info (from $_FILES)
575 * @return bool whether file has been uploaded properly and is now in UTF-8
577 static function utf8File($elementValue) {
580 if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
581 (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')
584 $success = CRM_Utils_File
::isAscii($elementValue['tmp_name']);
586 // if it's a file, but not UTF-8, let's try and recode it
587 // and then make sure it's an UTF-8 file in the end
589 $success = CRM_Utils_File
::toUtf8($elementValue['tmp_name']);
591 $success = CRM_Utils_File
::isAscii($elementValue['tmp_name']);
599 * see how file rules are written in HTML/QuickForm/file.php
600 * Checks to make sure the uploaded file is html
602 * @param array Uploaded file info (from $_FILES)
605 * @return bool true if file has been uploaded, false otherwise
607 static function htmlFile($elementValue) {
608 if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
609 (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')
611 return CRM_Utils_File
::isHtmlFile($elementValue['tmp_name']);
617 * Check if there is a record with the same name in the db
619 * @param string $value the value of the field we are checking
620 * @param array $options the daoName and fieldName (optional )
622 * @return boolean true if object exists
626 static function objectExists($value, $options) {
628 if (isset($options[2])) {
632 return CRM_Core_DAO
::objectExists($value, CRM_Utils_Array
::value(0, $options), CRM_Utils_Array
::value(1, $options), CRM_Utils_Array
::value(2, $options, $name));
641 static function optionExists($value, $options) {
642 return CRM_Core_OptionValue
::optionExists($value, $options[0], $options[1], $options[2], CRM_Utils_Array
::value(3, $options, 'name'));
651 static function creditCardNumber($value, $type) {
652 require_once 'Validate/Finance/CreditCard.php';
653 return Validate_Finance_CreditCard
::number($value, $type);
662 static function cvv($value, $type) {
663 require_once 'Validate/Finance/CreditCard.php';
665 return Validate_Finance_CreditCard
::cvv($value, $type);
673 static function currencyCode($value) {
674 static $currencyCodes = NULL;
675 if (!$currencyCodes) {
676 $currencyCodes = CRM_Core_PseudoConstant
::currencyCode();
678 if (in_array($value, $currencyCodes)) {
689 static function xssString($value) {
690 if (is_string($value)) {
691 return preg_match('!<(vb)?script[^>]*>.*</(vb)?script.*>!ims',
705 static function fileExists($path) {
706 return file_exists($path);
715 static function autocomplete($value, $options) {
717 $selectOption = CRM_Core_BAO_CustomOption
::valuesByID($options['fieldID'], $options['optionGroupID']);
719 if (!in_array($value, $selectOption)) {
728 * @param null $actualElementValue
732 static function validContact($value, $actualElementValue = NULL) {
733 if ($actualElementValue) {
734 $value = $actualElementValue;
737 if ($value && !is_numeric($value)) {
744 * check the validity of the date (in qf format)
745 * note that only a year is valid, or a mon-year is
746 * also valid in addition to day-mon-year
750 * @return bool true if valid date
754 static function qfDate($date) {
755 $config = CRM_Core_Config
::singleton();
757 $d = CRM_Utils_Array
::value('d', $date);
758 $m = CRM_Utils_Array
::value('M', $date);
759 $y = CRM_Utils_Array
::value('Y', $date);
760 if (isset($date['h']) ||
763 $m = CRM_Utils_Array
::value('M', $date);
766 if (!$d && !$m && !$y) {
782 // if we have day we need mon, and if we have mon we need year
790 if (!empty($day) ||
!empty($mon) ||
!empty($year)) {
791 return checkdate($mon, $day, $year);
801 static function qfKey($key) {
802 return ($key) ? CRM_Core_Key
::valid($key) : FALSE;