PageRenderTime 40ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/www/libs/nette-dev/Forms/Rules.php

https://github.com/bazo/Mokuji
PHP | 262 lines | 134 code | 55 blank | 73 comment | 20 complexity | 94a1fe37407b1c8fd847067e23422a26 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * @copyright Copyright (c) 2004, 2010 David Grudl
  6. * @license http://nettephp.com/license Nette license
  7. * @link http://nettephp.com
  8. * @category Nette
  9. * @package Nette\Forms
  10. */
  11. /**
  12. * List of validation & condition rules.
  13. *
  14. * @copyright Copyright (c) 2004, 2010 David Grudl
  15. * @package Nette\Forms
  16. */
  17. final class Rules extends Object implements IteratorAggregate
  18. {
  19. /** @ignore internal */
  20. const VALIDATE_PREFIX = 'validate';
  21. /** @var array */
  22. public static $defaultMessages = array(
  23. );
  24. /** @var array of Rule */
  25. private $rules = array();
  26. /** @var Rules */
  27. private $parent;
  28. /** @var array */
  29. private $toggles = array();
  30. /** @var IFormControl */
  31. private $control;
  32. public function __construct(IFormControl $control)
  33. {
  34. $this->control = $control;
  35. }
  36. /**
  37. * Adds a validation rule for the current control.
  38. * @param mixed rule type
  39. * @param string message to display for invalid data
  40. * @param mixed optional rule arguments
  41. * @return Rules provides a fluent interface
  42. */
  43. public function addRule($operation, $message = NULL, $arg = NULL)
  44. {
  45. $rule = new Rule;
  46. $rule->control = $this->control;
  47. $rule->operation = $operation;
  48. $this->adjustOperation($rule);
  49. $rule->arg = $arg;
  50. $rule->type = Rule::VALIDATOR;
  51. if ($message === NULL && isset(self::$defaultMessages[$rule->operation])) {
  52. $rule->message = self::$defaultMessages[$rule->operation];
  53. } else {
  54. $rule->message = $message;
  55. }
  56. if ($this->parent === NULL) {
  57. // notify only direct rules
  58. $this->control->notifyRule($rule);
  59. }
  60. $this->rules[] = $rule;
  61. return $this;
  62. }
  63. /**
  64. * Adds a validation condition a returns new branch.
  65. * @param mixed condition type
  66. * @param mixed optional condition arguments
  67. * @return Rules new branch
  68. */
  69. public function addCondition($operation, $arg = NULL)
  70. {
  71. return $this->addConditionOn($this->control, $operation, $arg);
  72. }
  73. /**
  74. * Adds a validation condition on specified control a returns new branch.
  75. * @param IFormControl form control
  76. * @param mixed condition type
  77. * @param mixed optional condition arguments
  78. * @return Rules new branch
  79. */
  80. public function addConditionOn(IFormControl $control, $operation, $arg = NULL)
  81. {
  82. $rule = new Rule;
  83. $rule->control = $control;
  84. $rule->operation = $operation;
  85. $this->adjustOperation($rule);
  86. $rule->arg = $arg;
  87. $rule->type = Rule::CONDITION;
  88. $rule->subRules = new self($this->control);
  89. $rule->subRules->parent = $this;
  90. $this->rules[] = $rule;
  91. return $rule->subRules;
  92. }
  93. /**
  94. * Adds a else statement.
  95. * @return Rules else branch
  96. */
  97. public function elseCondition()
  98. {
  99. $rule = clone end($this->parent->rules);
  100. $rule->isNegative = !$rule->isNegative;
  101. $rule->subRules = new self($this->parent->control);
  102. $rule->subRules->parent = $this->parent;
  103. $this->parent->rules[] = $rule;
  104. return $rule->subRules;
  105. }
  106. /**
  107. * Ends current validation condition.
  108. * @return Rules parent branch
  109. */
  110. public function endCondition()
  111. {
  112. return $this->parent;
  113. }
  114. /**
  115. * Toggles HTML elememnt visibility.
  116. * @param string element id
  117. * @param bool hide element?
  118. * @return Rules provides a fluent interface
  119. */
  120. public function toggle($id, $hide = TRUE)
  121. {
  122. $this->toggles[$id] = $hide;
  123. return $this;
  124. }
  125. /**
  126. * Validates against ruleset.
  127. * @param bool stop before first error?
  128. * @return bool is valid?
  129. */
  130. public function validate($onlyCheck = FALSE)
  131. {
  132. $valid = TRUE;
  133. foreach ($this->rules as $rule)
  134. {
  135. if ($rule->control->isDisabled()) continue;
  136. $success = ($rule->isNegative xor $this->getCallback($rule)->invoke($rule->control, $rule->arg));
  137. if ($rule->type === Rule::CONDITION && $success) {
  138. $success = $rule->subRules->validate($onlyCheck);
  139. $valid = $valid && $success;
  140. } elseif ($rule->type === Rule::VALIDATOR && !$success) {
  141. if ($onlyCheck) {
  142. return FALSE;
  143. }
  144. $rule->control->addError(self::formatMessage($rule, TRUE));
  145. $valid = FALSE;
  146. if ($rule->breakOnFailure) {
  147. break;
  148. }
  149. }
  150. }
  151. return $valid;
  152. }
  153. /**
  154. * Iterates over ruleset.
  155. * @return ArrayIterator
  156. */
  157. final public function getIterator()
  158. {
  159. return new ArrayIterator($this->rules);
  160. }
  161. /**
  162. * @return array
  163. */
  164. final public function getToggles()
  165. {
  166. return $this->toggles;
  167. }
  168. /**
  169. * Process 'operation' string.
  170. * @param Rule
  171. * @return void
  172. */
  173. private function adjustOperation($rule)
  174. {
  175. if (is_string($rule->operation) && ord($rule->operation[0]) > 127) {
  176. $rule->isNegative = TRUE;
  177. $rule->operation = ~$rule->operation;
  178. }
  179. if (!$this->getCallback($rule)->isCallable()) {
  180. $operation = is_scalar($rule->operation) ? " '$rule->operation'" : '';
  181. throw new InvalidArgumentException("Unknown operation$operation for control '{$rule->control->name}'.");
  182. }
  183. }
  184. private function getCallback($rule)
  185. {
  186. $op = $rule->operation;
  187. if (is_string($op) && strncmp($op, ':', 1) === 0) {
  188. return callback(get_class($rule->control), self::VALIDATE_PREFIX . ltrim($op, ':'));
  189. } else {
  190. return callback($op);
  191. }
  192. }
  193. public static function formatMessage($rule, $withValue)
  194. {
  195. $message = $rule->message;
  196. if ($translator = $rule->control->getForm()->getTranslator()) {
  197. $message = $translator->translate($message, is_int($rule->arg) ? $rule->arg : NULL);
  198. }
  199. $message = str_replace('%name', $rule->control->getName(), $message);
  200. $message = str_replace('%label', $rule->control->translate($rule->control->caption), $message);
  201. if (strpos($message, '%value') !== FALSE) {
  202. $message = str_replace('%value', $withValue ? (string) $rule->control->getValue() : '%%value', $message);
  203. }
  204. $message = vsprintf($message, (array) $rule->arg);
  205. return $message;
  206. }
  207. }