PageRenderTime 62ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/Genv/helper/DooValidator.php

https://gitlab.com/winiceo/levengit
PHP | 1221 lines | 538 code | 92 blank | 591 comment | 210 complexity | 7c89ca7b5aebde18ce211f192b42c5ce MD5 | raw file
  1. <?php
  2. /**
  3. * DooValidator class file.
  4. *
  5. * @author Leng Sheng Hong <darkredz@gmail.com>
  6. * @link http://www.doophp.com/
  7. * @copyright Copyright &copy; 2009 Leng Sheng Hong
  8. * @license http://www.doophp.com/license
  9. */
  10. /**
  11. * A helper class that helps validating data.
  12. *
  13. * <p>DooValidator can be used for form and Model data validation before saving/inserting/deleting a data.</p>
  14. *
  15. * <p>To use DooValidator, you have to create an instance of it and defined the validation rules.
  16. * All the methods start with 'test' can be used as a rule for validating data. Rule names are case insensitive.</p>
  17. *
  18. * <p>You can pass in custom error message along with the rules. By default all fields in the rules are <b>required</b></p>
  19. * <code>
  20. * $rules = array(
  21. * 'creattime'=>array(
  22. * array('datetime'),
  23. * array('email'),
  24. * array('optional') //Optional field
  25. * ),
  26. * 'username'=>array(
  27. * array('username',6,16),
  28. * //Custom error message will be used
  29. * array('lowercase', 'Username must only be lowercase.')
  30. * ),
  31. *
  32. * //Only one rule
  33. * 'pwd'=>array('password'),
  34. * 'email'=>array('email'),
  35. * 'age'=>array('between',13,200),
  36. * 'today'=>array('date','mm/dd/yy'),
  37. *
  38. * //Custom rules, static method required
  39. * 'a'=>array('custom', 'MainController::isA'),
  40. *
  41. * //Custom Required field message.
  42. * 'content'=>array('required', 'Content is required!')
  43. * );
  44. * </code>
  45. *
  46. * <p>Rules are defined based on the validation method's parameters. For example:</p>
  47. * <code>
  48. * //Validation method
  49. * testBetween($value, $min, $max, $msg=null)
  50. *
  51. * $rule = array(
  52. * 'field'=>array('between', 0, 20)
  53. * 'field2'=>array('between', 0, 20, 'Custom Err Msg!')
  54. * );
  55. * </code>
  56. *
  57. * <p>You can get the list of available validation rules by calling DooValidator::getAvailableRules()</p>
  58. *
  59. * <p>To validate the data, create an instance of DooValidator and call validate() in your Controller/Model.</p>
  60. * <code>
  61. * $v = new DooValidator();
  62. *
  63. * # There are 3 different validation Mode.
  64. * //$v->checkMode = DooValidator::CHECK_SKIP;
  65. * //$v->checkMode = DooValidator::CHECK_ALL_ONE;
  66. * //$v->checkMode = DooValidator::CHECK_ALL;
  67. *
  68. * //The $_POST or data pass in need to be an assoc array
  69. * //$data = array('username'=>'doophp', 'pwd'=>'12345');
  70. * if($error = $v->validate($_POST, $rules)){
  71. * print_r($error);
  72. * }
  73. * </code>
  74. *
  75. * <p>You can pass in a string to load predefined Rules which located at SITE_PATH/protected/config/forms/</p>
  76. * <code>
  77. * <?php
  78. * //in protected/config/forms/example.php
  79. * return array(
  80. * 'username'=>array(
  81. * array('username',4,5,'username invalid'),
  82. * array('maxlength',6,'This is too long'),
  83. * array('minlength',6)
  84. * ),
  85. * 'pwd'=>array('password',3,5),
  86. * 'email'=>array('email')
  87. * );
  88. * ?>
  89. *
  90. * //in your Controller/Model
  91. * $error = $v->validate($data, 'example');
  92. * </code>
  93. *
  94. * <p>If nothing is returned from the validate() call, it means that all the data passed the validation rules.</p>
  95. *
  96. * <p>The Model validation rules are automatically generated when you used the framework's model generator feature.
  97. * If your Models are extending DooModel or DooSmartModel, you can validate the data by calling DooModel::validate()</p>
  98. * <code>
  99. * $f = new Food;
  100. * $f->name = 'My Food name for validation';
  101. * $error = $f->validate();
  102. *
  103. * //Or...
  104. * $error = Food::_validate($f);
  105. * </code>
  106. *
  107. * @author Leng Sheng Hong <darkredz@gmail.com>
  108. * @version $Id: DooValidator.php 1000 2009-08-30 11:37:22
  109. * @package doo.helper
  110. * @since 1.2
  111. */
  112. class DooValidator {
  113. /**
  114. * Checks All and returns All errors
  115. */
  116. const CHECK_ALL = 'all';
  117. /**
  118. * Checks All and returns one error for each data field
  119. */
  120. const CHECK_ALL_ONE = 'all_one';
  121. /**
  122. * Returns one error once the first is detected
  123. */
  124. const CHECK_SKIP = 'skip';
  125. /**
  126. * Use PHP empty method to test for required (or optional)
  127. */
  128. const REQ_MODE_NULL_EMPTY = 'nullempty';
  129. /**
  130. * Only ensure required fields are non null / accept not null on required
  131. */
  132. const REQ_MODE_NULL_ONLY = 'null';
  133. /**
  134. * Default require message to display field name "first_name is required."
  135. */
  136. const REQ_MSG_FIELDNAME = 'fieldname';
  137. /**
  138. * Default require message to display "This is required."
  139. */
  140. const REQ_MSG_THIS = 'this';
  141. /**
  142. * Default require message to convert field name with underscore to words. eg(field = first_name). "First name is required."
  143. */
  144. const REQ_MSG_UNDERSCORE_TO_SPACE = 'underscore';
  145. /**
  146. * Default require message to convert field name with camelcase to words. eg(field = firstName). "First name is required."
  147. */
  148. const REQ_MSG_CAMELCASE_TO_SPACE = 'camelcase';
  149. /**
  150. * Validation mode
  151. * @var string all/all_one/skip
  152. */
  153. public $checkMode = 'all';
  154. /**
  155. * How should required fields be tested (or be considered left out on optional)
  156. * @var string empty/null
  157. */
  158. public $requireMode = 'nullempty';
  159. /**
  160. * Default method to generate error message for a required field.
  161. * @var string
  162. */
  163. public $requiredMsgDefaultMethod = 'underscore';
  164. /**
  165. * Default error message suffix for a required field.
  166. * @var string
  167. */
  168. public $requiredMsgDefaultSuffix = ' field is required';
  169. /**
  170. * Trim the data fields. The data will be modified.
  171. * @param array $data assoc array to be trimmed
  172. * @param int $maxDepth Maximum number of recursive calls. Defaults to a max nesting depth of 5.
  173. */
  174. public function trimValues(&$data, $maxDepth = 5) {
  175. foreach($data as $k=>&$v) {
  176. if (is_array($v)) {
  177. if ($maxDepth > 0) {
  178. $this->trimValues($v, $maxDepth - 1);
  179. }
  180. } else {
  181. $v = trim($v);
  182. }
  183. }
  184. }
  185. /**
  186. * Get a list of available rules
  187. * @return array
  188. */
  189. public static function getAvailableRules(){
  190. return array('alpha', 'alphaNumeric', 'between', 'betweenInclusive', 'ccAmericanExpress', 'ccDinersClub', 'ccDiscover', 'ccMasterCard',
  191. 'ccVisa', 'colorHex', 'creditCard', 'custom', 'date', 'dateBetween', 'datetime', 'digit', 'email', 'equal', 'equalAs', 'float',
  192. 'greaterThan', 'greaterThanOrEqual', 'ip', 'integer', 'lessThan', 'lessThanOrEqual', 'lowercase', 'max',
  193. 'maxlength', 'min', 'minlength', 'notEmpty', 'notEqual', 'notNull', 'password', 'passwordComplex', 'price', 'regex',
  194. 'uppercase', 'url', 'username','dbExist','dbNotExist','alphaSpace','notInList','inList'
  195. );
  196. }
  197. /**
  198. * Get appropriate rules for a certain DB data type
  199. * @param string $dataType
  200. * @return string Rule name for the data type
  201. */
  202. public static function dbDataTypeToRules($type){
  203. $dataType = array(
  204. //integers
  205. 'tinyint'=>'integer',
  206. 'smallint'=>'integer',
  207. 'mediumint'=>'integer',
  208. 'int'=>'integer',
  209. 'bigint'=>'integer',
  210. //float
  211. 'float'=>'float',
  212. 'double'=>'float',
  213. 'decimal'=>'float',
  214. //datetime
  215. 'date'=>'date',
  216. 'datetime'=>'datetime',
  217. 'timestamp'=>'datetime',
  218. 'time'=>'datetime'
  219. );
  220. if(isset($dataType[$type]))
  221. return $dataType[$type];
  222. }
  223. /**
  224. * Validate the data with the defined rules.
  225. *
  226. * @param array $data Data to be validate. One dimension assoc array, eg. array('user'=>'leng', 'email'=>'abc@abc.com')
  227. * @param string|array $rules Validation rule. Pass in a string to load the predefined rules in SITE_PATH/protected/config/forms
  228. * @return array Returns an array of errors if errors exist.
  229. */
  230. public function validate($data=null, $rules=null){
  231. //$data = array('username'=>'leng s', 'pwd'=>'234231dfasd', 'email'=>'asdb12@#asd.com.my');
  232. //$rules = array('username'=>array('username'), 'pwd'=>array('password',6,32), 'email'=>array('email'));
  233. if(is_string($rules)){
  234. $rules = include(Doo::conf()->SITE_PATH . Doo::conf()->PROTECTED_FOLDER . 'config/forms/'.$rules.'.php');
  235. }
  236. $optErrorRemove = array();
  237. foreach($data as $dk=>$dv){
  238. if($this->requireMode == DooValidator::REQ_MODE_NULL_EMPTY && ($dv === null || $dv === '') ||
  239. $this->requireMode == DooValidator::REQ_MODE_NULL_ONLY && $dv === null){
  240. unset($data[$dk]);
  241. }
  242. }
  243. if($missingKey = array_diff_key($rules, $data) ){
  244. $fieldnames = array_keys($missingKey);
  245. $customRequireMsg = null;
  246. foreach($fieldnames as $fieldname){
  247. if(isset($missingKey[$fieldname])){
  248. if( in_array('required', $missingKey[$fieldname]) ){
  249. $customRequireMsg = $missingKey[$fieldname][1];
  250. }
  251. else if(is_array($missingKey[$fieldname][0])){
  252. foreach($missingKey[$fieldname] as $f)
  253. if($f[0]=='required'){
  254. if(isset($f[1]))
  255. $customRequireMsg = $f[1];
  256. break;
  257. }
  258. }
  259. }
  260. //remove optional fields from error
  261. if(is_array($missingKey[$fieldname][0])){
  262. foreach($missingKey[$fieldname] as $innerArrayRules){
  263. if($innerArrayRules[0]=='optional'){
  264. //echo $fieldname.' - 1 this is not set and optional, should be removed from error';
  265. $optErrorRemove[] = $fieldname;
  266. break;
  267. }
  268. }
  269. }
  270. if($this->checkMode==DooValidator::CHECK_ALL){
  271. if($customRequireMsg!==null)
  272. $errors[$fieldname] = $customRequireMsg;
  273. else
  274. $errors[$fieldname] = $this->getRequiredFieldDefaultMsg($fieldname);
  275. }else if($this->checkMode==DooValidator::CHECK_SKIP){
  276. if(in_array($fieldname, $optErrorRemove))
  277. continue;
  278. if($customRequireMsg!==null)
  279. return $customRequireMsg;
  280. return $this->getRequiredFieldDefaultMsg($fieldname);
  281. }else if($this->checkMode==DooValidator::CHECK_ALL_ONE){
  282. if($customRequireMsg!==null)
  283. $errors[$fieldname] = $customRequireMsg;
  284. else
  285. $errors[$fieldname] = $this->getRequiredFieldDefaultMsg($fieldname);
  286. }
  287. }
  288. }
  289. foreach($data as $k=>$v){
  290. if(!isset($rules[$k])) continue;
  291. $cRule = $rules[$k];
  292. foreach($cRule as $v2){
  293. if(is_array($v2)){
  294. //print_r(array_slice($v2, 1));
  295. $vv = array_merge(array($v),array_slice($v2, 1));
  296. $vIsEmpty = ($this->requireMode == DooValidator::REQ_MODE_NULL_EMPTY && ($v === null || $v === '') ||
  297. $this->requireMode == DooValidator::REQ_MODE_NULL_ONLY && $v === null) ? true : false;
  298. //call func
  299. if($vIsEmpty && $v2[0]=='optional'){
  300. //echo $k.' - this is not set and optional, should be removed from error';
  301. $optErrorRemove[] = $k;
  302. }
  303. if($err = call_user_func_array(array(&$this, 'test'.$v2[0]), $vv) ){
  304. if($this->checkMode==DooValidator::CHECK_ALL)
  305. $errors[$k][$v2[0]] = $err;
  306. else if($this->checkMode==DooValidator::CHECK_SKIP && !$vIsEmpty && $v2[0]!='optional'){
  307. return $err;
  308. }else if($this->checkMode==DooValidator::CHECK_ALL_ONE)
  309. $errors[$k] = $err;
  310. }
  311. }
  312. else if(is_string($cRule[0])){
  313. if(sizeof($cRule)>1){
  314. //print_r(array_slice($cRule, 1));
  315. $vv = array_merge(array($v),array_slice($cRule, 1));
  316. if($err = call_user_func_array(array(&$this, 'test'.$cRule[0]), $vv) ){
  317. if($this->checkMode==DooValidator::CHECK_ALL || $this->checkMode==DooValidator::CHECK_ALL_ONE)
  318. $errors[$k] = $err;
  319. else if($this->checkMode==DooValidator::CHECK_SKIP){
  320. return $err;
  321. }
  322. }
  323. }else{
  324. if($err = $this->{'test'.$cRule[0]}($v) ){
  325. if($this->checkMode==DooValidator::CHECK_ALL || $this->checkMode==DooValidator::CHECK_ALL_ONE)
  326. $errors[$k] = $err;
  327. else if($this->checkMode==DooValidator::CHECK_SKIP){
  328. return $err;
  329. }
  330. }
  331. }
  332. continue 2;
  333. }
  334. }
  335. }
  336. if(isset($errors)){
  337. if(sizeof($optErrorRemove)>0){
  338. foreach($errors as $ek=>$ev){
  339. if(in_array($ek, $optErrorRemove)){
  340. //echo '<h3>Removing error '.$ek.'</h3>';
  341. unset($errors[$ek]);
  342. }
  343. }
  344. }
  345. return $errors;
  346. }
  347. }
  348. /**
  349. * Set default settings to display the default error message for required fields
  350. * @param type $displayMethod Default error message display method. use: DooValidator::REQ_MSG_UNDERSCORE_TO_SPACE, DooValidator::REQ_MSG_CAMELCASE_TO_SPACE, DooValidator::REQ_MSG_THIS, DooValidator::REQ_MSG_FIELDNAME
  351. * @param type $suffix suffix for the error message. Default is ' field is required'
  352. */
  353. public function setRequiredFieldDefaults( $displayMethod = DooValidator::REQ_MSG_UNDERSCORE_TO_SPACE, $suffix = ' field is required'){
  354. $this->requiredMsgDefaultMethod = $displayMethod;
  355. $this->requiredMsgDefaultSuffix = $suffix;
  356. }
  357. /**
  358. * Get the default error message for required field
  359. * @param string $fieldname Name of the field
  360. * @return string Error message
  361. */
  362. public function getRequiredFieldDefaultMsg($fieldname){
  363. if($this->requiredMsgDefaultMethod==DooValidator::REQ_MSG_UNDERSCORE_TO_SPACE)
  364. return ucfirst(str_replace('_', ' ', $fieldname)) . $this->requiredMsgDefaultSuffix;
  365. if($this->requiredMsgDefaultMethod==DooValidator::REQ_MSG_THIS)
  366. return 'This ' . $this->requiredMsgDefaultSuffix;
  367. if($this->requiredMsgDefaultMethod==DooValidator::REQ_MSG_CAMELCASE_TO_SPACE)
  368. return ucfirst(strtolower(preg_replace('/([A-Z])/', ' $1', $fieldname))) . $this->requiredMsgDefaultSuffix;
  369. if($this->requiredMsgDefaultMethod==DooValidator::REQ_MSG_FIELDNAME)
  370. return $fieldname . $this->requiredMsgDefaultSuffix;
  371. }
  372. public function testOptional($value){}
  373. public function testRequired($value, $msg){
  374. if ($this->requireMode == DooValidator::REQ_MODE_NULL_EMPTY && ($value === null || $value === '') ||
  375. $this->requireMode == DooValidator::REQ_MODE_NULL_ONLY && $value === null) {
  376. if($msg!==null) return $msg;
  377. return 'This field is required!';
  378. }
  379. }
  380. /**
  381. * Validate data with your own custom rules.
  382. *
  383. * Usage in Controller:
  384. * <code>
  385. * public static function isA($value){
  386. * if($value!='a'){
  387. * return 'Value must be A';
  388. * }
  389. * }
  390. *
  391. * public function test(){
  392. * $rules = array(
  393. * 'email'=>array('custom', 'TestController::isA')
  394. * );
  395. *
  396. * $v = new DooValidator();
  397. * if($error = $v->validate($_POST, $rules)){
  398. * //display error
  399. * }
  400. * }
  401. * </code>
  402. *
  403. * @param string $value Value of data to be validated
  404. * @param string $function Name of the custom function
  405. * @param string $msg Custom error message
  406. * @return string
  407. */
  408. public function testCustom($value, $function, $options=null ,$msg=null){
  409. if($options==null){
  410. if($err = call_user_func($function, $value)){
  411. if($err!==true){
  412. if($msg!==null) return $msg;
  413. return $err;
  414. }
  415. }
  416. }else{
  417. //if array, additional parameters
  418. if($err = call_user_func_array($function, array_merge(array($value), $options)) ){
  419. if($err!==true){
  420. if($msg!==null) return $msg;
  421. return $err;
  422. }
  423. }
  424. }
  425. }
  426. /**
  427. * Validate against a Regex rule
  428. *
  429. * @param string $value Value of data to be validated
  430. * @param string $regex Regex rule to be tested against
  431. * @param string $msg Custom error message
  432. * @return string
  433. */
  434. public function testRegex($value, $regex, $msg=null){
  435. if(!preg_match($regex, $value) ){
  436. if($msg!==null) return $msg;
  437. return 'Error in field.';
  438. }
  439. }
  440. /**
  441. * Validate username format.
  442. *
  443. * @param string $value Value of data to be validated
  444. * @param int $minLength Minimum length
  445. * @param int $maxLength Maximum length
  446. * @param string $msg Custom error message
  447. * @return string
  448. */
  449. public function testUsername($value, $minLength=4, $maxLength=12, $msg=null){
  450. if(!preg_match('/^[a-zA-Z][a-zA-Z.0-9_-]{'. ($minLength-1) .','.$maxLength.'}$/i', $value)){
  451. if($msg!==null) return $msg;
  452. return "User name must be $minLength-$maxLength characters. Only characters, dots, digits, underscore & hyphen are allowed.";
  453. }
  454. else if(strpos($value, '..')!==False){
  455. if($msg!==null) return $msg;
  456. return "User name cannot consist of 2 continuous dots.";
  457. }
  458. else if(strpos($value, '__')!==False){
  459. if($msg!==null) return $msg;
  460. return "User name cannot consist of 2 continuous underscore.";
  461. }
  462. else if(strpos($value, '--')!==False){
  463. if($msg!==null) return $msg;
  464. return "User name cannot consist of 2 continuous dash.";
  465. }
  466. else if(strpos($value, '.-')!==False || strpos($value, '-.')!==False ||
  467. strpos($value, '._')!==False || strpos($value, '_.')!==False ||
  468. strpos($value, '_-')!==False || strpos($value, '-_')!==False){
  469. if($msg!==null) return $msg;
  470. return "User name cannot consist of 2 continuous punctuation.";
  471. }
  472. else if(ctype_punct($value[0])){
  473. if($msg!==null) return $msg;
  474. return "User name cannot start with a punctuation.";
  475. }
  476. else if(ctype_punct( substr($value, strlen($value)-1) )){
  477. if($msg!==null) return $msg;
  478. return "User name cannot end with a punctuation.";
  479. }
  480. }
  481. /**
  482. * Validate password format
  483. *
  484. * @param string $value Value of data to be validated
  485. * @param int $minLength Minimum length
  486. * @param int $maxLength Maximum length
  487. * @param string $msg Custom error message
  488. * @return string
  489. */
  490. public function testPassword($value, $minLength=6, $maxLength=32, $msg=null){
  491. if(!preg_match('/^[a-zA-Z.0-9_-]{'.$minLength.','.$maxLength.'}$/i', $value)){
  492. if($msg!==null) return $msg;
  493. return "Only characters, dots, digits, underscore & hyphen are allowed. Password must be at least $minLength characters long.";
  494. }
  495. }
  496. /**
  497. * Validate against a complex password format
  498. *
  499. * @param string $value Value of data to be validated
  500. * @param string $msg Custom error message
  501. * @return string
  502. */
  503. public function testPasswordComplex($value, $msg=null){
  504. if(!preg_match('A(?=[-_a-zA-Z0-9]*?[A-Z])(?=[-_a-zA-Z0-9]*?[a-z])(?=[-_a-zA-Z0-9]*?[0-9])[-_a-zA-Z0-9]{6,32}z', $value)){
  505. if($msg!==null) return $msg;
  506. return 'Password must contain at least one upper case letter, one lower case letter and one digit. It must consists of 6 or more letters, digits, underscores and hyphens.';
  507. }
  508. }
  509. /**
  510. * Validate email address
  511. *
  512. * @param string $value Value of data to be validated
  513. * @param string $msg Custom error message
  514. * @return string
  515. */
  516. public function testEmail($value, $msg=null){
  517. // Regex based on best solution from here: http://fightingforalostcause.net/misc/2006/compare-email-regex.php
  518. if(!preg_match('/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i', $value) ||
  519. strpos($value, '--')!==False || strpos($value, '-.')!==False
  520. ){
  521. if($msg!==null) return $msg;
  522. return 'Invalid email format!';
  523. }
  524. }
  525. /**
  526. * Validate a URL
  527. *
  528. * @param string $value Value of data to be validated
  529. * @param string $msg Custom error message
  530. * @return string
  531. */
  532. public function testUrl($value, $msg=null){
  533. if(!preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $value)){
  534. if($msg!==null) return $msg;
  535. return 'Invalid URL!';
  536. }
  537. }
  538. /**
  539. * Validate an IP address (198.168.1.101)
  540. *
  541. * @param string $value Value of data to be validated
  542. * @param string $msg Custom error message
  543. * @return string
  544. */
  545. public function testIP($value, $msg=null){
  546. //198.168.1.101
  547. if (!preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/',$value)) {
  548. if($msg!==null) return $msg;
  549. return 'Invalid IP address!';
  550. }
  551. }
  552. /**
  553. * Validate a credit card number
  554. *
  555. * @param string $value Value of data to be validated
  556. * @param string $msg Custom error message
  557. * @return string
  558. */
  559. public function testCreditCard($value, $msg=null){
  560. //568282246310632
  561. if (!preg_match('/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/', $value)) {
  562. if($msg!==null) return $msg;
  563. return 'Invalid credit card number!';
  564. }
  565. }
  566. /**
  567. * Validate an American Express credit card number
  568. *
  569. * @param string $value Value of data to be validated
  570. * @param string $msg Custom error message
  571. * @return string
  572. */
  573. public function testCcAmericanExpress($value, $msg=null){
  574. if (!preg_match('/^3[47][0-9]{13}$/', $value)) {
  575. if($msg!==null) return $msg;
  576. return 'Invalid American Express credit card number!';
  577. }
  578. }
  579. /**
  580. * Validate an Discover credit card number
  581. *
  582. * @param string $value Value of data to be validated
  583. * @param string $msg Custom error message
  584. * @return string
  585. */
  586. public function testCcDiscover($value, $msg=null){
  587. if (!preg_match('/^6011[0-9]{12}$/', $value)) {
  588. if($msg!==null) return $msg;
  589. return 'Invalid Discover credit card number!';
  590. }
  591. }
  592. /**
  593. * Validate an Diners Club credit card number
  594. *
  595. * @param string $value Value of data to be validated
  596. * @param string $msg Custom error message
  597. * @return string
  598. */
  599. public function testCcDinersClub($value, $msg=null){
  600. if (!preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', $value)) {
  601. if($msg!==null) return $msg;
  602. return 'Invalid Diners Club credit card number!';
  603. }
  604. }
  605. /**
  606. * Validate an Master Card number
  607. *
  608. * @param string $value Value of data to be validated
  609. * @param string $msg Custom error message
  610. * @return string
  611. */
  612. public function testCcMasterCard($value, $msg=null){
  613. if (!preg_match('/^5[1-5][0-9]{14}$/', $value)) {
  614. if($msg!==null) return $msg;
  615. return 'Invalid Master Card number!';
  616. }
  617. }
  618. /**
  619. * Validate an Visa Card number
  620. *
  621. * @param string $value Value of data to be validated
  622. * @param string $msg Custom error message
  623. * @return string
  624. */
  625. public function testCcVisa($value, $msg=null){
  626. if (!preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/', $value)) {
  627. if($msg!==null) return $msg;
  628. return 'Invalid Visa card number!';
  629. }
  630. }
  631. /**
  632. * Validate Color hex #ff0000
  633. *
  634. * @param string $value Value of data to be validated
  635. * @param string $msg Custom error message
  636. * @return string
  637. */
  638. public function testColorHex($value, $msg=null){
  639. //#ff0000
  640. if (!preg_match('/^#([0-9a-f]{1,2}){3}$/i', $value)) {
  641. if($msg!==null) return $msg;
  642. return 'Invalid color code!';
  643. }
  644. }
  645. //------------------- Common data validation ---------------------
  646. /**
  647. * Validate Date Time
  648. *
  649. * @param string $value Value of data to be validated
  650. * @param string $msg Custom error message
  651. * @return string
  652. */
  653. public function testDateTime($value, $msg=null){
  654. $rs = strtotime($value);
  655. if ($rs===false || $rs===-1){
  656. if($msg!==null) return $msg;
  657. return 'Invalid date time format!';
  658. }
  659. }
  660. /**
  661. * Validate Date format. Default yyyy/mm/dd.
  662. *
  663. * <p>Date format: yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd
  664. * Date valid from 1900-01-01 through 2099-12-31</p>
  665. *
  666. * @param string $value Value of data to be validated
  667. * @param string $dateFormat Date format
  668. * @param string $msg Custom error message
  669. * @return string
  670. */
  671. public function testDate($value, $format='yyyy/mm/dd', $msg=null, $forceYearLength=false){
  672. //Date yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd
  673. //1900-01-01 through 2099-12-31
  674. $yearFormat = "(19|20)?[0-9]{2}";
  675. if ($forceYearLength == true) {
  676. if (strpos($format, 'yyyy') !== false) {
  677. $yearFormat = "(19|20)[0-9]{2}";
  678. } else {
  679. $yearFormat = "[0-9]{2}";
  680. }
  681. }
  682. switch($format){
  683. case 'dd/mm/yy':
  684. $format = "/^\b(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.]{$yearFormat}\b$/";
  685. break;
  686. case 'mm/dd/yy':
  687. $format = "/^\b(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]{$yearFormat}\b$/";
  688. break;
  689. case 'mm/dd/yyyy':
  690. $format = "/^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]{$yearFormat}$/";
  691. break;
  692. case 'dd/mm/yyyy':
  693. $format = "/^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]{$yearFormat}$/";
  694. break;
  695. case 'yy/mm/dd':
  696. $format = "/^\b{$yearFormat}[- \/.](0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])\b$/";
  697. break;
  698. case 'yyyy/mm/dd':
  699. default:
  700. $format = "/^\b{$yearFormat}[- \/.](0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])\b$/";
  701. }
  702. if (!preg_match($format, $value)) {
  703. if($msg!==null) return $msg;
  704. return 'Invalid date format!';
  705. }
  706. }
  707. /**
  708. * Validate if given date is between 2 dates.
  709. *
  710. * @param string $value Value of data to be validated
  711. * @param string $dateStart Starting date
  712. * @param string $dateEnd Ending date
  713. * @param string $msg Custom error message
  714. * @return string
  715. */
  716. public function testDateBetween($value, $dateStart, $dateEnd, $msg=null){
  717. $value = strtotime($value);
  718. if(!( $value > strtotime($dateStart) && $value < strtotime($dateEnd) ) ) {
  719. if($msg!==null) return $msg;
  720. return "Date must be between $dateStart and $dateEnd";
  721. }
  722. }
  723. /**
  724. * Validate integer
  725. *
  726. * @param string $value Value of data to be validated
  727. * @param string $msg Custom error message
  728. * @return string
  729. */
  730. public function testInteger($value, $msg=null){
  731. if(intval($value)!=$value || strlen(intval($value))!=strlen($value)){
  732. if($msg!==null) return $msg;
  733. return 'Input is not an integer.';
  734. }
  735. }
  736. /**
  737. * Validate price. 2 decimal points only
  738. *
  739. * @param string $value Value of data to be validated
  740. * @param string $msg Custom error message
  741. * @return string
  742. */
  743. public function testPrice($value, $msg=null){
  744. // 2 decimal
  745. if (!preg_match('/^[0-9]*\\.?[0-9]{0,2}$/', $value)){
  746. if($msg!==null) return $msg;
  747. return 'Input is not a valid price amount.';
  748. }
  749. }
  750. /**
  751. * Validate float value.
  752. *
  753. * @param string $value Value of data to be validated
  754. * @param int $decimal Number of Decimal points
  755. * @param string $msg Custom error message
  756. * @return string
  757. */
  758. public function testFloat($value, $decimal='', $msg=null){
  759. // any amount of decimal
  760. if (!preg_match('/^[0-9]*\\.?[0-9]{0,'.$decimal.'}$/', $value)){
  761. if($msg!==null) return $msg;
  762. return 'Input is not a valid float value.';
  763. }
  764. }
  765. /**
  766. * Validate digits.
  767. *
  768. * @param string $value Value of data to be validated
  769. * @param string $msg Custom error message
  770. * @return string
  771. */
  772. public function testDigit($value, $msg=null){
  773. if(!ctype_digit($value)){
  774. if($msg!==null) return $msg;
  775. return 'Input is not a digit.';
  776. }
  777. }
  778. /**
  779. * Validate Alpha numeric values.
  780. *
  781. * Input string can only consist of only Letters or Digits.
  782. *
  783. * @param string $value Value of data to be validated
  784. * @param string $msg Custom error message
  785. * @return string
  786. */
  787. public function testAlphaNumeric($value, $msg=null){
  788. if(!ctype_alnum($value)){
  789. if($msg!==null) return $msg;
  790. return 'Input can only consist of letters or digits.';
  791. }
  792. }
  793. /**
  794. * Validate Alpha values.
  795. *
  796. * Input string can only consist of only Letters.
  797. *
  798. * @param string $value Value of data to be validated
  799. * @param string $msg Custom error message
  800. * @return string
  801. */
  802. public function testAlpha($value, $msg=null){
  803. if(!ctype_alpha($value)){
  804. if($msg!==null) return $msg;
  805. return 'Input can only consist of letters.';
  806. }
  807. }
  808. /**
  809. * Validate if string only consist of letters and spaces
  810. *
  811. * Input string can only consist of only Letters and spaces.
  812. *
  813. * @param string $value Value of data to be validated
  814. * @param string $msg Custom error message
  815. * @return string
  816. */
  817. public function testAlphaSpace($value, $msg=null){
  818. if(!ctype_alpha(str_replace(' ','',$value))){
  819. if($msg!==null) return $msg;
  820. return 'Input can only consist of letters and spaces.';
  821. }
  822. }
  823. /**
  824. * Validate lowercase string.
  825. *
  826. * Input string can only be lowercase letters.
  827. *
  828. * @param string $value Value of data to be validated
  829. * @param string $msg Custom error message
  830. * @return string
  831. */
  832. public function testLowercase($value, $msg=null){
  833. if(!ctype_lower($value)){
  834. if($msg!==null) return $msg;
  835. return 'Input can only consists of lowercase letters.';
  836. }
  837. }
  838. /**
  839. * Validate uppercase string.
  840. *
  841. * Input string can only be uppercase letters.
  842. *
  843. * @param string $value Value of data to be validated
  844. * @param string $msg Custom error message
  845. * @return string
  846. */
  847. public function testUppercase($value, $msg=null){
  848. if(!ctype_upper($value)){
  849. if($msg!==null) return $msg;
  850. return 'Input can only consists of uppercase letters.';
  851. }
  852. }
  853. /**
  854. * Validate Not Empty. Input cannot be empty.
  855. *
  856. * @param string $value Value of data to be validated
  857. * @param string $msg Custom error message
  858. * @return string
  859. */
  860. public function testNotEmpty($value, $msg=null){
  861. if(empty($value)){
  862. if($msg!==null) return $msg;
  863. return 'Value cannot be empty!';
  864. }
  865. }
  866. /**
  867. * Validate Max length of a string.
  868. *
  869. * @param string $value Value of data to be validated
  870. * @param int $length Maximum length of the string
  871. * @param string $msg Custom error message
  872. * @return string
  873. */
  874. public function testMaxLength($value, $length=0, $msg=null){
  875. if(mb_strlen($value) > $length){
  876. if($msg!==null) return $msg;
  877. return "Input cannot be longer than the $length characters.";
  878. }
  879. }
  880. /**
  881. * Validate Minimum length of a string.
  882. *
  883. * @param string $value Value of data to be validated
  884. * @param int $length Minimum length of the string
  885. * @param string $msg Custom error message
  886. * @return string
  887. */
  888. public function testMinLength($value, $length=0, $msg=null){
  889. if(strlen($value) < $length){
  890. if($msg!==null) return $msg;
  891. return "Input cannot be shorter than the $length characters.";
  892. }
  893. }
  894. /**
  895. * Validate Not Null. Value cannot be null.
  896. *
  897. * @param string $value Value of data to be validated
  898. * @param string $msg Custom error message
  899. * @return string
  900. */
  901. public function testNotNull($value, $msg=null){
  902. if(is_null($value)){
  903. if($msg!==null) return $msg;
  904. return 'Value cannot be null.';
  905. }
  906. }
  907. /**
  908. * Validate Minimum value of a number.
  909. *
  910. * @param string $value Value of data to be validated
  911. * @param int $min Minimum value
  912. * @param string $msg Custom error message
  913. * @return string
  914. */
  915. public function testMin($value, $min, $msg=null){
  916. if( $value < $min){
  917. if($msg!==null) return $msg;
  918. return "Value cannot be less than $min";
  919. }
  920. }
  921. /**
  922. * Validate Maximum value of a number.
  923. *
  924. * @param string $value Value of data to be validated
  925. * @param int $max Maximum value
  926. * @param string $msg Custom error message
  927. * @return string
  928. */
  929. public function testMax($value, $max, $msg=null){
  930. if( $value > $max){
  931. if($msg!==null) return $msg;
  932. return "Value cannot be more than $max";
  933. }
  934. }
  935. /**
  936. * Validate if a value is Between 2 values (inclusive)
  937. *
  938. * @param string $value Value of data to be validated
  939. * @param int $min Minimum value
  940. * @param int $max Maximum value
  941. * @param string $msg Custom error message
  942. * @return string
  943. */
  944. public function testBetweenInclusive($value, $min, $max, $msg=null){
  945. if( $value < $min || $value > $max ){
  946. if($msg!==null) return $msg;
  947. return "Value must be between $min and $max inclusively.";
  948. }
  949. }
  950. /**
  951. * Validate if a value is Between 2 values
  952. *
  953. * @param string $value Value of data to be validated
  954. * @param int $min Minimum value
  955. * @param int $max Maximum value
  956. * @param string $msg Custom error message
  957. * @return string
  958. */
  959. public function testBetween($value, $min, $max, $msg=null){
  960. if( $value < $min+1 || $value > $max-1 ){
  961. if($msg!==null) return $msg;
  962. return "Value must be between $min and $max.";
  963. }
  964. }
  965. /**
  966. * Validate if a value is greater than a number
  967. *
  968. * @param string $value Value of data to be validated
  969. * @param int $number Number to be compared
  970. * @param string $msg Custom error message
  971. * @return string
  972. */
  973. public function testGreaterThan($value, $number, $msg=null){
  974. if( !($value > $number)){
  975. if($msg!==null) return $msg;
  976. return "Value must be greater than $number.";
  977. }
  978. }
  979. /**
  980. * Validate if a value is greater than or equal to a number
  981. *
  982. * @param string $value Value of data to be validated
  983. * @param int $number Number to be compared
  984. * @param string $msg Custom error message
  985. * @return string
  986. */
  987. public function testGreaterThanOrEqual($value, $number, $msg=null){
  988. if( !($value >= $number)){
  989. if($msg!==null) return $msg;
  990. return "Value must be greater than or equal to $number.";
  991. }
  992. }
  993. /**
  994. * Validate if a value is less than a number
  995. *
  996. * @param string $value Value of data to be validated
  997. * @param int $number Number to be compared
  998. * @param string $msg Custom error message
  999. * @return string
  1000. */
  1001. public function testLessThan($value, $number, $msg=null){
  1002. if( !($value < $number)){
  1003. if($msg!==null) return $msg;
  1004. return "Value must be less than $number.";
  1005. }
  1006. }
  1007. /**
  1008. * Validate if a value is less than or equal to a number
  1009. *
  1010. * @param string $value Value of data to be validated
  1011. * @param int $number Number to be compared
  1012. * @param string $msg Custom error message
  1013. * @return string
  1014. */
  1015. public function testLessThanOrEqual($value, $number, $msg=null){
  1016. if( !($value <= $number)){
  1017. if($msg!==null) return $msg;
  1018. return "Value must be less than $number.";
  1019. }
  1020. }
  1021. /**
  1022. * Validate if a value is equal to a number
  1023. *
  1024. * @param string $value Value of data to be validated
  1025. * @param int $equalValue Number to be compared
  1026. * @param string $msg Custom error message
  1027. * @return string
  1028. */
  1029. public function testEqual($value, $equalValue, $msg=null){
  1030. if(!($value==$equalValue && strlen($value)==strlen($equalValue))){
  1031. if($msg!==null) return $msg;
  1032. return 'Both values must be the same.';
  1033. }
  1034. }
  1035. /**
  1036. * Validate if a value is Not equal to a number
  1037. *
  1038. * @param string $value Value of data to be validated
  1039. * @param int $equalValue Number to be compared
  1040. * @param string $msg Custom error message
  1041. * @return string
  1042. */
  1043. public function testNotEqual($value, $equalValue, $msg=null){
  1044. if( $value==$equalValue && strlen($value)==strlen($equalValue) ){
  1045. if($msg!==null) return $msg;
  1046. return 'Both values must be different.';
  1047. }
  1048. }
  1049. /**
  1050. * Validate if value Exists in database
  1051. *
  1052. * @param string $value Value of data to be validated
  1053. * @param string $table Name of the table in DB
  1054. * @param string $field Name of field you want to check
  1055. * @return string
  1056. */
  1057. public function testDbExist($value, $table, $field, $msg=null) {
  1058. $result = Doo::db()->fetchRow("SELECT COUNT($field) AS count FROM " . $table . ' WHERE '.$field.' = ? LIMIT 1', array($value));
  1059. if ((!isset($result['count'])) || ($result['count'] < 1)) {
  1060. if($msg!==null) return $msg;
  1061. return 'Value does not exist in database.';
  1062. }
  1063. }
  1064. /**
  1065. * Validate if value does Not Exist in database
  1066. *
  1067. * @param string $value Value of data to be validated
  1068. * @param string $table Name of the table in DB
  1069. * @param string $field Name of field you want to check
  1070. * @return string
  1071. */
  1072. public function testDbNotExist($value, $table, $field, $msg=null) {
  1073. $result = Doo::db()->fetchRow("SELECT COUNT($field) AS count FROM " . $table . ' WHERE '.$field.' = ? LIMIT 1', array($value));
  1074. if ((isset($result['count'])) && ($result['count'] > 0)) {
  1075. if($msg!==null) return $msg;
  1076. return 'Same value exists in database.';
  1077. }
  1078. }
  1079. /**
  1080. * Validate if a value is in a list of values
  1081. *
  1082. * @param string $value Value of data to be validated
  1083. * @param int $equalValue List of values to be checked
  1084. * @param string $msg Custom error message
  1085. * @return string
  1086. */
  1087. public function testInList($value, $valueList, $msg=null){
  1088. if(!(in_array($value, $valueList))){
  1089. if($msg!==null) return $msg;
  1090. return 'Unmatched value.';
  1091. }
  1092. }
  1093. /**
  1094. * Validate if a value is NOT in a list of values
  1095. *
  1096. * @param string $value Value of data to be validated
  1097. * @param int $equalValue List of values to be checked
  1098. * @param string $msg Custom error message
  1099. * @return string
  1100. */
  1101. public function testNotInList($value, $valueList, $msg=null){
  1102. if(in_array($value, $valueList)){
  1103. if($msg!==null) return $msg;
  1104. return 'Unmatched value.';
  1105. }
  1106. }
  1107. /**
  1108. * Validate field if it is equal with some other field from $_GET or $_POST method
  1109. * This method is used for validating form
  1110. *
  1111. * @param string $value Value of data to be validated
  1112. * @param string $method Method (get or post), default $_POST
  1113. * @param string $field Name of field that you want to check
  1114. * @return string
  1115. */
  1116. public function testEqualAs($value, $method, $field, $msg=null) {
  1117. if ($method == "get") {
  1118. $method = $_GET;
  1119. } else if ($method == "post") {
  1120. $method = $_POST;
  1121. } else {
  1122. $method = $_POST;
  1123. }
  1124. if (!isset($method[$field]) || $value != $method[$field]) {
  1125. if($msg!==null) return $msg;
  1126. return 'Value '.$value.' is not equal with "'.$field.'".';
  1127. }
  1128. }
  1129. }