PageRenderTime 60ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/dooframework/helper/DooValidator.php

https://bitbucket.org/cidious/vault_doo
PHP | 1236 lines | 544 code | 93 blank | 599 comment | 212 complexity | ef1e3c1010569d491e2e534a89a2d32d 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', 'hostname', '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 hostname as per RFC 952.
  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 testHostname($value, $msg=null){
  560. //198.168.1.101
  561. if (!preg_match('/^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)(([a-zA-Z0-9])([a-zA-Z0-9\-])*\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$/',$value)) {
  562. if($msg!==null) return $msg;
  563. return 'Invalid hostname!';
  564. }
  565. }
  566. /**
  567. * Validate a 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 testCreditCard($value, $msg=null){
  574. //568282246310632
  575. 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)) {
  576. if($msg!==null) return $msg;
  577. return 'Invalid credit card number!';
  578. }
  579. }
  580. /**
  581. * Validate an American Express credit card number
  582. *
  583. * @param string $value Value of data to be validated
  584. * @param string $msg Custom error message
  585. * @return string
  586. */
  587. public function testCcAmericanExpress($value, $msg=null){
  588. if (!preg_match('/^3[47][0-9]{13}$/', $value)) {
  589. if($msg!==null) return $msg;
  590. return 'Invalid American Express credit card number!';
  591. }
  592. }
  593. /**
  594. * Validate an Discover credit card number
  595. *
  596. * @param string $value Value of data to be validated
  597. * @param string $msg Custom error message
  598. * @return string
  599. */
  600. public function testCcDiscover($value, $msg=null){
  601. if (!preg_match('/^6011[0-9]{12}$/', $value)) {
  602. if($msg!==null) return $msg;
  603. return 'Invalid Discover credit card number!';
  604. }
  605. }
  606. /**
  607. * Validate an Diners Club credit card number
  608. *
  609. * @param string $value Value of data to be validated
  610. * @param string $msg Custom error message
  611. * @return string
  612. */
  613. public function testCcDinersClub($value, $msg=null){
  614. if (!preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', $value)) {
  615. if($msg!==null) return $msg;
  616. return 'Invalid Diners Club credit card number!';
  617. }
  618. }
  619. /**
  620. * Validate an Master Card number
  621. *
  622. * @param string $value Value of data to be validated
  623. * @param string $msg Custom error message
  624. * @return string
  625. */
  626. public function testCcMasterCard($value, $msg=null){
  627. if (!preg_match('/^5[1-5][0-9]{14}$/', $value)) {
  628. if($msg!==null) return $msg;
  629. return 'Invalid Master Card number!';
  630. }
  631. }
  632. /**
  633. * Validate an Visa Card number
  634. *
  635. * @param string $value Value of data to be validated
  636. * @param string $msg Custom error message
  637. * @return string
  638. */
  639. public function testCcVisa($value, $msg=null){
  640. if (!preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/', $value)) {
  641. if($msg!==null) return $msg;
  642. return 'Invalid Visa card number!';
  643. }
  644. }
  645. /**
  646. * Validate Color hex #ff0000
  647. *
  648. * @param string $value Value of data to be validated
  649. * @param string $msg Custom error message
  650. * @return string
  651. */
  652. public function testColorHex($value, $msg=null){
  653. //#ff0000
  654. if (!preg_match('/^#([0-9a-f]{1,2}){3}$/i', $value)) {
  655. if($msg!==null) return $msg;
  656. return 'Invalid color code!';
  657. }
  658. }
  659. //------------------- Common data validation ---------------------
  660. /**
  661. * Validate Date Time
  662. *
  663. * @param string $value Value of data to be validated
  664. * @param string $msg Custom error message
  665. * @return string
  666. */
  667. public function testDateTime($value, $msg=null){
  668. $rs = strtotime($value);
  669. if ($rs===false || $rs===-1){
  670. if($msg!==null) return $msg;
  671. return 'Invalid date time format!';
  672. }
  673. }
  674. /**
  675. * Validate Date format. Default yyyy/mm/dd.
  676. *
  677. * <p>Date format: yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd
  678. * Date valid from 1900-01-01 through 2099-12-31</p>
  679. *
  680. * @param string $value Value of data to be validated
  681. * @param string $dateFormat Date format
  682. * @param string $msg Custom error message
  683. * @return string
  684. */
  685. public function testDate($value, $format='yyyy/mm/dd', $msg=null, $forceYearLength=false){
  686. //Date yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd
  687. //1900-01-01 through 2099-12-31
  688. $yearFormat = "(19|20)?[0-9]{2}";
  689. if ($forceYearLength == true) {
  690. if (strpos($format, 'yyyy') !== false) {
  691. $yearFormat = "(19|20)[0-9]{2}";
  692. } else {
  693. $yearFormat = "[0-9]{2}";
  694. }
  695. }
  696. switch($format){
  697. case 'dd/mm/yy':
  698. $format = "/^\b(0?[1-9]|[12][0-9]|3[01])[- \/.](0?[1-9]|1[012])[- \/.]{$yearFormat}\b$/";
  699. break;
  700. case 'mm/dd/yy':
  701. $format = "/^\b(0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])[- \/.]{$yearFormat}\b$/";
  702. break;
  703. case 'mm/dd/yyyy':
  704. $format = "/^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]{$yearFormat}$/";
  705. break;
  706. case 'dd/mm/yyyy':
  707. $format = "/^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]{$yearFormat}$/";
  708. break;
  709. case 'yy/mm/dd':
  710. $format = "/^\b{$yearFormat}[- \/.](0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])\b$/";
  711. break;
  712. case 'yyyy/mm/dd':
  713. default:
  714. $format = "/^\b{$yearFormat}[- \/.](0?[1-9]|1[012])[- \/.](0?[1-9]|[12][0-9]|3[01])\b$/";
  715. }
  716. if (!preg_match($format, $value)) {
  717. if($msg!==null) return $msg;
  718. return 'Invalid date format!';
  719. }
  720. }
  721. /**
  722. * Validate if given date is between 2 dates.
  723. *
  724. * @param string $value Value of data to be validated
  725. * @param string $dateStart Starting date
  726. * @param string $dateEnd Ending date
  727. * @param string $msg Custom error message
  728. * @return string
  729. */
  730. public function testDateBetween($value, $dateStart, $dateEnd, $msg=null){
  731. $value = strtotime($value);
  732. if(!( $value > strtotime($dateStart) && $value < strtotime($dateEnd) ) ) {
  733. if($msg!==null) return $msg;
  734. return "Date must be between $dateStart and $dateEnd";
  735. }
  736. }
  737. /**
  738. * Validate integer
  739. *
  740. * @param string $value Value of data to be validated
  741. * @param string $msg Custom error message
  742. * @return string
  743. */
  744. public function testInteger($value, $msg=null){
  745. if(intval($value)!=$value || strlen(intval($value))!=strlen($value)){
  746. if($msg!==null) return $msg;
  747. return 'Input is not an integer.';
  748. }
  749. }
  750. /**
  751. * Validate price. 2 decimal points only
  752. *
  753. * @param string $value Value of data to be validated
  754. * @param string $msg Custom error message
  755. * @return string
  756. */
  757. public function testPrice($value, $msg=null){
  758. // 2 decimal
  759. if (!preg_match('/^[0-9]*\\.?[0-9]{0,2}$/', $value)){
  760. if($msg!==null) return $msg;
  761. return 'Input is not a valid price amount.';
  762. }
  763. }
  764. /**
  765. * Validate float value.
  766. *
  767. * @param string $value Value of data to be validated
  768. * @param int $decimal Number of Decimal points
  769. * @param string $msg Custom error message
  770. * @return string
  771. */
  772. public function testFloat($value, $decimal='', $msg=null){
  773. // any amount of decimal
  774. if (!preg_match('/^[-]?[0-9]*\\.?[0-9]{0,'.$decimal.'}$/', $value)){
  775. if($msg!==null) return $msg;
  776. return 'Input is not a valid float value.';
  777. }
  778. }
  779. /**
  780. * Validate digits.
  781. *
  782. * @param string $value Value of data to be validated
  783. * @param string $msg Custom error message
  784. * @return string
  785. */
  786. public function testDigit($value, $msg=null){
  787. if(!ctype_digit($value)){
  788. if($msg!==null) return $msg;
  789. return 'Input is not a digit.';
  790. }
  791. }
  792. /**
  793. * Validate Alpha numeric values.
  794. *
  795. * Input string can only consist of only Letters or Digits.
  796. *
  797. * @param string $value Value of data to be validated
  798. * @param string $msg Custom error message
  799. * @return string
  800. */
  801. public function testAlphaNumeric($value, $msg=null){
  802. if(!ctype_alnum($value)){
  803. if($msg!==null) return $msg;
  804. return 'Input can only consist of letters or digits.';
  805. }
  806. }
  807. /**
  808. * Validate Alpha values.
  809. *
  810. * Input string can only consist of only Letters.
  811. *
  812. * @param string $value Value of data to be validated
  813. * @param string $msg Custom error message
  814. * @return string
  815. */
  816. public function testAlpha($value, $msg=null){
  817. if(!ctype_alpha($value)){
  818. if($msg!==null) return $msg;
  819. return 'Input can only consist of letters.';
  820. }
  821. }
  822. /**
  823. * Validate if string only consist of letters and spaces
  824. *
  825. * Input string can only consist of only Letters and spaces.
  826. *
  827. * @param string $value Value of data to be validated
  828. * @param string $msg Custom error message
  829. * @return string
  830. */
  831. public function testAlphaSpace($value, $msg=null){
  832. if(!ctype_alpha(str_replace(' ','',$value))){
  833. if($msg!==null) return $msg;
  834. return 'Input can only consist of letters and spaces.';
  835. }
  836. }
  837. /**
  838. * Validate lowercase string.
  839. *
  840. * Input string can only be lowercase letters.
  841. *
  842. * @param string $value Value of data to be validated
  843. * @param string $msg Custom error message
  844. * @return string
  845. */
  846. public function testLowercase($value, $msg=null){
  847. if(!ctype_lower($value)){
  848. if($msg!==null) return $msg;
  849. return 'Input can only consists of lowercase letters.';
  850. }
  851. }
  852. /**
  853. * Validate uppercase string.
  854. *
  855. * Input string can only be uppercase letters.
  856. *
  857. * @param string $value Value of data to be validated
  858. * @param string $msg Custom error message
  859. * @return string
  860. */
  861. public function testUppercase($value, $msg=null){
  862. if(!ctype_upper($value)){
  863. if($msg!==null) return $msg;
  864. return 'Input can only consists of uppercase letters.';
  865. }
  866. }
  867. /**
  868. * Validate Not Empty. Input cannot be empty.
  869. *
  870. * @param string $value Value of data to be validated
  871. * @param string $msg Custom error message
  872. * @return string
  873. */
  874. public function testNotEmpty($value, $msg=null){
  875. if(empty($value)){
  876. if($msg!==null) return $msg;
  877. return 'Value cannot be empty!';
  878. }
  879. }
  880. /**
  881. * Validate Max length of a string.
  882. *
  883. * @param string $value Value of data to be validated
  884. * @param int $length Maximum length of the string
  885. * @param string $msg Custom error message
  886. * @return string
  887. */
  888. public function testMaxLength($value, $length=0, $msg=null){
  889. if(mb_strlen($value) > $length){
  890. if($msg!==null) return $msg;
  891. return "Input cannot be longer than $length characters.";
  892. }
  893. }
  894. /**
  895. * Validate Minimum length of a string.
  896. *
  897. * @param string $value Value of data to be validated
  898. * @param int $length Minimum length of the string
  899. * @param string $msg Custom error message
  900. * @return string
  901. */
  902. public function testMinLength($value, $length=0, $msg=null){
  903. if(strlen($value) < $length){
  904. if($msg!==null) return $msg;
  905. return "Input cannot be shorter than $length characters.";
  906. }
  907. }
  908. /**
  909. * Validate Not Null. Value cannot be null.
  910. *
  911. * @param string $value Value of data to be validated
  912. * @param string $msg Custom error message
  913. * @return string
  914. */
  915. public function testNotNull($value, $msg=null){
  916. if(is_null($value)){
  917. if($msg!==null) return $msg;
  918. return 'Value cannot be null.';
  919. }
  920. }
  921. /**
  922. * Validate Minimum value of a number.
  923. *
  924. * @param string $value Value of data to be validated
  925. * @param int $min Minimum value
  926. * @param string $msg Custom error message
  927. * @return string
  928. */
  929. public function testMin($value, $min, $msg=null){
  930. if( $value < $min){
  931. if($msg!==null) return $msg;
  932. return "Value cannot be less than $min";
  933. }
  934. }
  935. /**
  936. * Validate Maximum value of a number.
  937. *
  938. * @param string $value Value of data to be validated
  939. * @param int $max Maximum value
  940. * @param string $msg Custom error message
  941. * @return string
  942. */
  943. public function testMax($value, $max, $msg=null){
  944. if( $value > $max){
  945. if($msg!==null) return $msg;
  946. return "Value cannot be more than $max";
  947. }
  948. }
  949. /**
  950. * Validate if a value is Between 2 values (inclusive)
  951. *
  952. * @param string $value Value of data to be validated
  953. * @param int $min Minimum value
  954. * @param int $max Maximum value
  955. * @param string $msg Custom error message
  956. * @return string
  957. */
  958. public function testBetweenInclusive($value, $min, $max, $msg=null){
  959. if( $value < $min || $value > $max ){
  960. if($msg!==null) return $msg;
  961. return "Value must be between $min and $max inclusively.";
  962. }
  963. }
  964. /**
  965. * Validate if a value is Between 2 values
  966. *
  967. * @param string $value Value of data to be validated
  968. * @param int $min Minimum value
  969. * @param int $max Maximum value
  970. * @param string $msg Custom error message
  971. * @return string
  972. */
  973. public function testBetween($value, $min, $max, $msg=null){
  974. if( $value < $min+1 || $value > $max-1 ){
  975. if($msg!==null) return $msg;
  976. return "Value must be between $min and $max.";
  977. }
  978. }
  979. /**
  980. * Validate if a value is greater than 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 testGreaterThan($value, $number, $msg=null){
  988. if( !($value > $number)){
  989. if($msg!==null) return $msg;
  990. return "Value must be greater than $number.";
  991. }
  992. }
  993. /**
  994. * Validate if a value is greater than or equal to 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 testGreaterThanOrEqual($value, $number, $msg=null){
  1002. if( !($value >= $number)){
  1003. if($msg!==null) return $msg;
  1004. return "Value must be greater than or equal to $number.";
  1005. }
  1006. }
  1007. /**
  1008. * Validate if a value is less than 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 testLessThan($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 less than or equal to a number
  1023. *
  1024. * @param string $value Value of data to be validated
  1025. * @param int $number Number to be compared
  1026. * @param string $msg Custom error message
  1027. * @return string
  1028. */
  1029. public function testLessThanOrEqual($value, $number, $msg=null){
  1030. if( !($value <= $number)){
  1031. if($msg!==null) return $msg;
  1032. return "Value must be less than $number.";
  1033. }
  1034. }
  1035. /**
  1036. * Validate if a value is 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 testEqual($value, $equalValue, $msg=null){
  1044. if(!($value==$equalValue && strlen($value)==strlen($equalValue))){
  1045. if($msg!==null) return $msg;
  1046. return 'Both values must be the same.';
  1047. }
  1048. }
  1049. /**
  1050. * Validate if a value is Not equal to a number
  1051. *
  1052. * @param string $value Value of data to be validated
  1053. * @param int $equalValue Number to be compared
  1054. * @param string $msg Custom error message
  1055. * @return string
  1056. */
  1057. public function testNotEqual($value, $equalValue, $msg=null){
  1058. if( $value==$equalValue && strlen($value)==strlen($equalValue) ){
  1059. if($msg!==null) return $msg;
  1060. return 'Both values must be different.';
  1061. }
  1062. }
  1063. /**
  1064. * Validate if value Exists in database
  1065. *
  1066. * @param string $value Value of data to be validated
  1067. * @param string $table Name of the table in DB
  1068. * @param string $field Name of field you want to check
  1069. * @return string
  1070. */
  1071. public function testDbExist($value, $table, $field, $msg=null) {
  1072. $result = Doo::db()->fetchRow("SELECT COUNT($field) AS count FROM " . $table . ' WHERE '.$field.' = ? LIMIT 1', array($value));
  1073. if ((!isset($result['count'])) || ($result['count'] < 1)) {
  1074. if($msg!==null) return $msg;
  1075. return 'Value does not exist in database.';
  1076. }
  1077. }
  1078. /**
  1079. * Validate if value does Not Exist in database
  1080. *
  1081. * @param string $value Value of data to be validated
  1082. * @param string $table Name of the table in DB
  1083. * @param string $field Name of field you want to check
  1084. * @return string
  1085. */
  1086. public function testDbNotExist($value, $table, $field, $msg=null) {
  1087. $result = Doo::db()->fetchRow("SELECT COUNT($field) AS count FROM " . $table . ' WHERE '.$field.' = ? LIMIT 1', array($value));
  1088. if ((isset($result['count'])) && ($result['count'] > 0)) {
  1089. if($msg!==null) return $msg;
  1090. return 'Same value exists in database.';
  1091. }
  1092. }
  1093. /**
  1094. * Validate if a value is 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 testInList($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 if a value is NOT in a list of values
  1109. *
  1110. * @param string $value Value of data to be validated
  1111. * @param int $equalValue List of values to be checked
  1112. * @param string $msg Custom error message
  1113. * @return string
  1114. */
  1115. public function testNotInList($value, $valueList, $msg=null){
  1116. if(in_array($value, $valueList)){
  1117. if($msg!==null) return $msg;
  1118. return 'Unmatched value.';
  1119. }
  1120. }
  1121. /**
  1122. * Validate field if it is equal with some other field from $_GET or $_POST method
  1123. * This method is used for validating form
  1124. *
  1125. * @param string $value Value of data to be validated
  1126. * @param string $method Method (get or post), default $_POST
  1127. * @param string $field Name of field that you want to check
  1128. * @return string
  1129. */
  1130. public function testEqualAs($value, $method, $field, $msg=null) {
  1131. if ($method == "get") {
  1132. $method = $_GET;
  1133. } else if ($method == "post") {
  1134. $method = $_POST;
  1135. } else {
  1136. $method = $_POST;
  1137. }
  1138. if (!isset($method[$field]) || $value != $method[$field]) {
  1139. if($msg!==null) return $msg;
  1140. return 'Value '.$value.' is not equal with "'.$field.'".';
  1141. }
  1142. }
  1143. }