CakeValidationRule.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <?php
  2. /**
  3. * CakeValidationRule.
  4. *
  5. * Provides the Model validation logic.
  6. *
  7. * PHP versions 5
  8. *
  9. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  10. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. *
  12. * Licensed under The MIT License
  13. * For full copyright and license information, please see the LICENSE.txt
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  17. * @link http://cakephp.org CakePHP(tm) Project
  18. * @package Cake.Model.Validator
  19. * @since CakePHP(tm) v 2.2.0
  20. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  21. */
  22. App::uses('Validation', 'Utility');
  23. /**
  24. * CakeValidationRule object. Represents a validation method, error message and
  25. * rules for applying such method to a field.
  26. *
  27. * @package Cake.Model.Validator
  28. * @link http://book.cakephp.org/2.0/en/data-validation.html
  29. */
  30. class CakeValidationRule {
  31. /**
  32. * Whether the field passed this validation rule
  33. *
  34. * @var mixed
  35. */
  36. protected $_valid = true;
  37. /**
  38. * Holds whether the record being validated exists in datasource or not
  39. *
  40. * @var boolean
  41. */
  42. protected $_recordExists = false;
  43. /**
  44. * Validation method
  45. *
  46. * @var mixed
  47. */
  48. protected $_rule = null;
  49. /**
  50. * Validation method arguments
  51. *
  52. * @var array
  53. */
  54. protected $_ruleParams = array();
  55. /**
  56. * Holds passed in options
  57. *
  58. * @var array
  59. */
  60. protected $_passedOptions = array();
  61. /**
  62. * The 'rule' key
  63. *
  64. * @var mixed
  65. */
  66. public $rule = 'blank';
  67. /**
  68. * The 'required' key
  69. *
  70. * @var mixed
  71. */
  72. public $required = null;
  73. /**
  74. * The 'allowEmpty' key
  75. *
  76. * @var boolean
  77. */
  78. public $allowEmpty = null;
  79. /**
  80. * The 'on' key
  81. *
  82. * @var string
  83. */
  84. public $on = null;
  85. /**
  86. * The 'last' key
  87. *
  88. * @var boolean
  89. */
  90. public $last = true;
  91. /**
  92. * The 'message' key
  93. *
  94. * @var string
  95. */
  96. public $message = null;
  97. /**
  98. * Constructor
  99. *
  100. * @param array $validator [optional] The validator properties
  101. */
  102. public function __construct($validator = array()) {
  103. $this->_addValidatorProps($validator);
  104. }
  105. /**
  106. * Checks if the rule is valid
  107. *
  108. * @return boolean
  109. */
  110. public function isValid() {
  111. if (!$this->_valid || (is_string($this->_valid) && !empty($this->_valid))) {
  112. return false;
  113. }
  114. return true;
  115. }
  116. /**
  117. * Returns whether the field can be left blank according to this rule
  118. *
  119. * @return boolean
  120. */
  121. public function isEmptyAllowed() {
  122. return $this->skip() || $this->allowEmpty === true;
  123. }
  124. /**
  125. * Checks if the field is required according to the `required` property
  126. *
  127. * @return boolean
  128. */
  129. public function isRequired() {
  130. if (in_array($this->required, array('create', 'update'), true)) {
  131. if ($this->required === 'create' && !$this->isUpdate() || $this->required === 'update' && $this->isUpdate()) {
  132. return true;
  133. } else {
  134. return false;
  135. }
  136. }
  137. return $this->required;
  138. }
  139. /**
  140. * Checks whether the field failed the `field should be present` validation
  141. *
  142. * @param string $field Field name
  143. * @param array $data Data to check rule against
  144. * @return boolean
  145. */
  146. public function checkRequired($field, &$data) {
  147. return (
  148. (!array_key_exists($field, $data) && $this->isRequired() === true) ||
  149. (
  150. array_key_exists($field, $data) && (empty($data[$field]) &&
  151. !is_numeric($data[$field])) && $this->allowEmpty === false
  152. )
  153. );
  154. }
  155. /**
  156. * Checks if the allowEmpty key applies
  157. *
  158. * @param string $field Field name
  159. * @param array $data data to check rule against
  160. * @return boolean
  161. */
  162. public function checkEmpty($field, &$data) {
  163. if (empty($data[$field]) && $data[$field] != '0' && $this->allowEmpty === true) {
  164. return true;
  165. }
  166. return false;
  167. }
  168. /**
  169. * Checks if the validation rule should be skipped
  170. *
  171. * @return boolean True if the ValidationRule can be skipped
  172. */
  173. public function skip() {
  174. if (!empty($this->on)) {
  175. if ($this->on === 'create' && $this->isUpdate() || $this->on === 'update' && !$this->isUpdate()) {
  176. return true;
  177. }
  178. }
  179. return false;
  180. }
  181. /**
  182. * Returns whether this rule should break validation process for associated field
  183. * after it fails
  184. *
  185. * @return boolean
  186. */
  187. public function isLast() {
  188. return (bool)$this->last;
  189. }
  190. /**
  191. * Gets the validation error message
  192. *
  193. * @return string
  194. */
  195. public function getValidationResult() {
  196. return $this->_valid;
  197. }
  198. /**
  199. * Gets an array with the rule properties
  200. *
  201. * @return array
  202. */
  203. protected function _getPropertiesArray() {
  204. $rule = $this->rule;
  205. if (!is_string($rule)) {
  206. unset($rule[0]);
  207. }
  208. return array(
  209. 'rule' => $rule,
  210. 'required' => $this->required,
  211. 'allowEmpty' => $this->allowEmpty,
  212. 'on' => $this->on,
  213. 'last' => $this->last,
  214. 'message' => $this->message
  215. );
  216. }
  217. /**
  218. * Sets the recordExists configuration value for this rule,
  219. * ir refers to whether the model record it is validating exists
  220. * exists in the collection or not (create or update operation)
  221. *
  222. * If called with no parameters it will return whether this rule
  223. * is configured for update operations or not.
  224. *
  225. * @param boolean $exists Boolean to indicate if records exists
  226. * @return boolean
  227. */
  228. public function isUpdate($exists = null) {
  229. if ($exists === null) {
  230. return $this->_recordExists;
  231. }
  232. return $this->_recordExists = $exists;
  233. }
  234. /**
  235. * Dispatches the validation rule to the given validator method
  236. *
  237. * @param string $field Field name
  238. * @param array $data Data array
  239. * @param array $methods Methods list
  240. * @return boolean True if the rule could be dispatched, false otherwise
  241. */
  242. public function process($field, &$data, &$methods) {
  243. $this->_valid = true;
  244. $this->_parseRule($field, $data);
  245. $validator = $this->_getPropertiesArray();
  246. $rule = strtolower($this->_rule);
  247. if (isset($methods[$rule])) {
  248. $this->_ruleParams[] = array_merge($validator, $this->_passedOptions);
  249. $this->_ruleParams[0] = array($field => $this->_ruleParams[0]);
  250. $this->_valid = call_user_func_array($methods[$rule], $this->_ruleParams);
  251. } elseif (class_exists('Validation') && method_exists('Validation', $this->_rule)) {
  252. $this->_valid = call_user_func_array(array('Validation', $this->_rule), $this->_ruleParams);
  253. } elseif (is_string($validator['rule'])) {
  254. $this->_valid = preg_match($this->_rule, $data[$field]);
  255. } else {
  256. trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $this->_rule, $field), E_USER_WARNING);
  257. return false;
  258. }
  259. return true;
  260. }
  261. /**
  262. * Resets internal state for this rule, by default it will become valid
  263. * and it will set isUpdate() to false
  264. *
  265. * @return void
  266. */
  267. public function reset() {
  268. $this->_valid = true;
  269. $this->_recordExists = false;
  270. }
  271. /**
  272. * Returns passed options for this rule
  273. *
  274. * @param string|integer $key Array index
  275. * @return array
  276. */
  277. public function getOptions($key) {
  278. if (!isset($this->_passedOptions[$key])) {
  279. return null;
  280. }
  281. return $this->_passedOptions[$key];
  282. }
  283. /**
  284. * Sets the rule properties from the rule entry in validate
  285. *
  286. * @param array $validator [optional]
  287. * @return void
  288. */
  289. protected function _addValidatorProps($validator = array()) {
  290. if (!is_array($validator)) {
  291. $validator = array('rule' => $validator);
  292. }
  293. foreach ($validator as $key => $value) {
  294. if (isset($value) || !empty($value)) {
  295. if (in_array($key, array('rule', 'required', 'allowEmpty', 'on', 'message', 'last'))) {
  296. $this->{$key} = $validator[$key];
  297. } else {
  298. $this->_passedOptions[$key] = $value;
  299. }
  300. }
  301. }
  302. }
  303. /**
  304. * Parses the rule and sets the rule and ruleParams
  305. *
  306. * @param string $field Field name
  307. * @param array $data Data array
  308. * @return void
  309. */
  310. protected function _parseRule($field, &$data) {
  311. if (is_array($this->rule)) {
  312. $this->_rule = $this->rule[0];
  313. $this->_ruleParams = array_merge(array($data[$field]), array_values(array_slice($this->rule, 1)));
  314. } else {
  315. $this->_rule = $this->rule;
  316. $this->_ruleParams = array($data[$field]);
  317. }
  318. }
  319. }