PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Cake/Model/Validator/CakeValidationRule.php

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