1. sfValidatorBase.class.php
  2. /** * sfValidatorBase is the base class for all validators. * * It also implements the required option for all validators. * * @package symfony * @subpackage validator * @author Fabien Potencier * @version SVN: $Id: sfValidatorBase.class.php 23922 2009-11-14 14:58:38Z fabien $ */
  3. abstract class sfValidatorBase
  4. {
  5. protected static
  6. $charset = 'UTF-8',
  7. $globalDefaultMessages = array('invalid' => 'Invalid.', 'required' => 'Required.');
  8. protected
  9. $requiredOptions = array(),
  10. $defaultMessages = array(),
  11. $defaultOptions = array(),
  12. $messages = array(),
  13. $options = array();
  14. /**
  15. * Constructor.
  16. *
  17. * Available options:
  18. *
  19. * * required: true if the value is required, false otherwise (default to true)
  20. * * trim: true if the value must be trimmed, false otherwise (default to false)
  21. * * empty_value: empty value when value is not required
  22. *
  23. * Available error codes:
  24. *
  25. * * required
  26. * * invalid
  27. *
  28. * @param array $options An array of options
  29. * @param array $messages An array of error messages
  30. */
  31. public function __construct($options = array(), $messages = array())
  32. {
  33. $this->options = array_merge(array('required' => true, 'trim' => false, 'empty_value' => null), $this->options);
  34. $this->messages = array_merge(array('required' => self::$globalDefaultMessages['required'], 'invalid' => self::$globalDefaultMessages['invalid']), $this->messages);
  35. $this->configure($options, $messages);
  36. $this->setDefaultOptions($this->getOptions());
  37. $this->setDefaultMessages($this->getMessages());
  38. $currentOptionKeys = array_keys($this->options);
  39. $optionKeys = array_keys($options);
  40. // check option names
  41. if ($diff = array_diff($optionKeys, array_merge($currentOptionKeys, $this->requiredOptions)))
  42. {
  43. throw new InvalidArgumentException(sprintf('%s does not support the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
  44. }
  45. // check error code names
  46. if ($diff = array_diff(array_keys($messages), array_keys($this->messages)))
  47. {
  48. throw new InvalidArgumentException(sprintf('%s does not support the following error codes: \'%s\'.', get_class($this), implode('\', \'', $diff)));
  49. }
  50. // check required options
  51. if ($diff = array_diff($this->requiredOptions, array_merge($currentOptionKeys, $optionKeys)))
  52. {
  53. throw new RuntimeException(sprintf('%s requires the following options: \'%s\'.', get_class($this), implode('\', \'', $diff)));
  54. }
  55. $this->options = array_merge($this->options, $options);
  56. $this->messages = array_merge($this->messages, $messages);
  57. }
  58. /**
  59. * Configures the current validator.
  60. *
  61. * This method allows each validator to add options and error messages
  62. * during validator creation.
  63. *
  64. * If some options and messages are given in the sfValidatorBase constructor
  65. * they will take precedence over the options and messages you configure
  66. * in this method.
  67. *
  68. * @param array $options An array of options
  69. * @param array $messages An array of error messages
  70. *
  71. * @see __construct()
  72. */
  73. protected function configure($options = array(), $messages = array())
  74. {
  75. }
  76. /**
  77. * Returns an error message given an error code.
  78. *
  79. * @param string $name The error code
  80. *
  81. * @return string The error message, or the empty string if the error code does not exist
  82. */
  83. public function getMessage($name)
  84. {
  85. return isset($this->messages[$name]) ? $this->messages[$name] : '';
  86. }
  87. /**
  88. * Adds a new error code with a default error message.
  89. *
  90. * @param string $name The error code
  91. * @param string $value The error message
  92. *
  93. * @return sfValidatorBase The current validator instance
  94. */
  95. public function addMessage($name, $value)
  96. {
  97. $this->messages[$name] = isset(self::$globalDefaultMessages[$name]) ? self::$globalDefaultMessages[$name] : $value;
  98. return $this;
  99. }
  100. /**
  101. * Changes an error message given the error code.
  102. *
  103. * @param string $name The error code
  104. * @param string $value The error message
  105. *
  106. * @return sfValidatorBase The current validator instance
  107. */
  108. public function setMessage($name, $value)
  109. {
  110. if (!in_array($name, array_keys($this->messages)))
  111. {
  112. throw new InvalidArgumentException(sprintf('%s does not support the following error code: \'%s\'.', get_class($this), $name));
  113. }
  114. $this->messages[$name] = $value;
  115. return $this;
  116. }
  117. /**
  118. * Returns an array of current error messages.
  119. *
  120. * @return array An array of messages
  121. */
  122. public function getMessages()
  123. {
  124. return $this->messages;
  125. }
  126. /**
  127. * Changes all error messages.
  128. *
  129. * @param array $values An array of error messages
  130. *
  131. * @return sfValidatorBase The current validator instance
  132. */
  133. public function setMessages($values)
  134. {
  135. $this->messages = $values;
  136. return $this;
  137. }
  138. /**
  139. * Gets an option value.
  140. *
  141. * @param string $name The option name
  142. *
  143. * @return mixed The option value
  144. */
  145. public function getOption($name)
  146. {
  147. return isset($this->options[$name]) ? $this->options[$name] : null;
  148. }
  149. /**
  150. * Adds a new option value with a default value.
  151. *
  152. * @param string $name The option name
  153. * @param mixed $value The default value
  154. *
  155. * @return sfValidatorBase The current validator instance
  156. */
  157. public function addOption($name, $value = null)
  158. {
  159. $this->options[$name] = $value;
  160. return $this;
  161. }
  162. /**
  163. * Changes an option value.
  164. *
  165. * @param string $name The option name
  166. * @param mixed $value The value
  167. *
  168. * @return sfValidatorBase The current validator instance
  169. */
  170. public function setOption($name, $value)
  171. {
  172. if (!in_array($name, array_merge(array_keys($this->options), $this->requiredOptions)))
  173. {
  174. throw new InvalidArgumentException(sprintf('%s does not support the following option: \'%s\'.', get_class($this), $name));
  175. }
  176. $this->options[$name] = $value;
  177. return $this;
  178. }
  179. /**
  180. * Returns true if the option exists.
  181. *
  182. * @param string $name The option name
  183. *
  184. * @return bool true if the option exists, false otherwise
  185. */
  186. public function hasOption($name)
  187. {
  188. return isset($this->options[$name]);
  189. }
  190. /**
  191. * Returns all options.
  192. *
  193. * @return array An array of options
  194. */
  195. public function getOptions()
  196. {
  197. return $this->options;
  198. }
  199. /**
  200. * Changes all options.
  201. *
  202. * @param array $values An array of options
  203. *
  204. * @return sfValidatorBase The current validator instance
  205. */
  206. public function setOptions($values)
  207. {
  208. $this->options = $values;
  209. return $this;
  210. }
  211. /**
  212. * Adds a required option.
  213. *
  214. * @param string $name The option name
  215. *
  216. * @return sfValidatorBase The current validator instance
  217. */
  218. public function addRequiredOption($name)
  219. {
  220. $this->requiredOptions[] = $name;
  221. return $this;
  222. }
  223. /**
  224. * Returns all required option names.
  225. *
  226. * @return array An array of required option names
  227. */
  228. public function getRequiredOptions()
  229. {
  230. return $this->requiredOptions;
  231. }
  232. /**
  233. * Sets the default message for a given name.
  234. *
  235. * @param string $name The name of the message
  236. * @param string $message The default message string
  237. */
  238. static public function setDefaultMessage($name, $message)
  239. {
  240. self::$globalDefaultMessages[$name] = $message;
  241. }
  242. /**
  243. * Cleans the input value.
  244. *
  245. * This method is also responsible for trimming the input value
  246. * and checking the required option.
  247. *
  248. * @param mixed $value The input value
  249. *
  250. * @return mixed The cleaned value
  251. *
  252. * @throws sfValidatorError
  253. */
  254. public function clean($value)
  255. {
  256. $clean = $value;
  257. if ($this->options['trim'] && is_string($clean))
  258. {
  259. $clean = trim($clean);
  260. }
  261. // empty value?
  262. if ($this->isEmpty($clean))
  263. {
  264. // required?
  265. if ($this->options['required'])
  266. {
  267. throw new sfValidatorError($this, 'required');
  268. }
  269. return $this->getEmptyValue();
  270. }
  271. return $this->doClean($clean);
  272. }
  273. /**
  274. * Cleans the input value.
  275. *
  276. * Every subclass must implements this method.
  277. *
  278. * @param mixed $value The input value
  279. *
  280. * @return mixed The cleaned value
  281. *
  282. * @throws sfValidatorError
  283. */
  284. abstract protected function doClean($value);
  285. /**
  286. * Sets the charset to use when validating strings.
  287. *
  288. * @param string $charset The charset
  289. */
  290. static public function setCharset($charset)
  291. {
  292. self::$charset = $charset;
  293. }
  294. /**
  295. * Returns the charset to use when validating strings.
  296. *
  297. * @return string The charset (default to UTF-8)
  298. */
  299. static public function getCharset()
  300. {
  301. return self::$charset;
  302. }
  303. /**
  304. * Returns true if the value is empty.
  305. *
  306. * @param mixed $value The input value
  307. *
  308. * @return bool true if the value is empty, false otherwise
  309. */
  310. protected function isEmpty($value)
  311. {
  312. return in_array($value, array(null, '', array()), true);
  313. }
  314. /**
  315. * Returns an empty value for this validator.
  316. *
  317. * @return mixed The empty value for this validator
  318. */
  319. protected function getEmptyValue()
  320. {
  321. return $this->getOption('empty_value');
  322. }
  323. /**
  324. * Returns an array of all error codes for this validator.
  325. *
  326. * @return array An array of possible error codes
  327. *
  328. * @see getDefaultMessages()
  329. */
  330. final public function getErrorCodes()
  331. {
  332. return array_keys($this->getDefaultMessages());
  333. }
  334. /**
  335. * Returns default messages for all possible error codes.
  336. *
  337. * @return array An array of default error codes and messages
  338. */
  339. public function getDefaultMessages()
  340. {
  341. return $this->defaultMessages;
  342. }
  343. /**
  344. * Sets default messages for all possible error codes.
  345. *
  346. * @param array $messages An array of default error codes and messages
  347. */
  348. protected function setDefaultMessages($messages)
  349. {
  350. $this->defaultMessages = $messages;
  351. }
  352. /**
  353. * Returns default option values.
  354. *
  355. * @return array An array of default option values
  356. */
  357. public function getDefaultOptions()
  358. {
  359. return $this->defaultOptions;
  360. }
  361. /**
  362. * Sets default option values.
  363. *
  364. * @param array $options An array of default option values
  365. */
  366. protected function setDefaultOptions($options)
  367. {
  368. $this->defaultOptions = $options;
  369. }
  370. /**
  371. * Returns a string representation of this validator.
  372. *
  373. * @param int $indent Indentation (number of spaces before each line)
  374. *
  375. * @return string The string representation of the validator
  376. */
  377. public function asString($indent = 0)
  378. {
  379. $options = $this->getOptionsWithoutDefaults();
  380. $messages = $this->getMessagesWithoutDefaults();
  381. return sprintf('%s%s(%s%s)',
  382. str_repeat(' ', $indent),
  383. str_replace('sfValidator', '', get_class($this)),
  384. $options ? sfYamlInline::dump($options) : ($messages ? '{}' : ''),
  385. $messages ? ', '.sfYamlInline::dump($messages) : ''
  386. );
  387. }
  388. /**
  389. * Returns all error messages with non default values.
  390. *
  391. * @return string A string representation of the error messages
  392. */
  393. protected function getMessagesWithoutDefaults()
  394. {
  395. $messages = $this->messages;
  396. // remove default option values
  397. foreach ($this->getDefaultMessages() as $key => $value)
  398. {
  399. if (array_key_exists($key, $messages) && $messages[$key] === $value)
  400. {
  401. unset($messages[$key]);
  402. }
  403. }
  404. return $messages;
  405. }
  406. /**
  407. * Returns all options with non default values.
  408. *
  409. * @return string A string representation of the options
  410. */
  411. protected function getOptionsWithoutDefaults()
  412. {
  413. $options = $this->options;
  414. // remove default option values
  415. foreach ($this->getDefaultOptions() as $key => $value)
  416. {
  417. if (array_key_exists($key, $options) && $options[$key] === $value)
  418. {
  419. unset($options[$key]);
  420. }
  421. }
  422. return $options;
  423. }
  424. }

Debug toolbar