1. sfValidatorSchema.class.php
  2. /** * sfValidatorSchema represents an array of fields. * * A field is a named validator. * * @package symfony * @subpackage validator * @author Fabien Potencier * @version SVN: $Id: sfValidatorSchema.class.php 22446 2009-09-26 07:55:47Z fabien $ */
  3. class sfValidatorSchema extends sfValidatorBase implements ArrayAccess
  4. {
  5. protected
  6. $fields = array(),
  7. $preValidator = null,
  8. $postValidator = null;
  9. /**
  10. * Constructor.
  11. *
  12. * The first argument can be:
  13. *
  14. * * null
  15. * * an array of named sfValidatorBase instances
  16. *
  17. * @param mixed $fields Initial fields
  18. * @param array $options An array of options
  19. * @param array $messages An array of error messages
  20. *
  21. * @see sfValidatorBase
  22. */
  23. public function __construct($fields = null, $options = array(), $messages = array())
  24. {
  25. if (is_array($fields))
  26. {
  27. foreach ($fields as $name => $validator)
  28. {
  29. $this[$name] = $validator;
  30. }
  31. }
  32. else if (null !== $fields)
  33. {
  34. throw new InvalidArgumentException('sfValidatorSchema constructor takes an array of sfValidatorBase objects.');
  35. }
  36. parent::__construct($options, $messages);
  37. }
  38. /**
  39. * Configures the validator.
  40. *
  41. * Available options:
  42. *
  43. * * allow_extra_fields: if false, the validator adds an error if extra fields are given in the input array of values (default to false)
  44. * * filter_extra_fields: if true, the validator filters extra fields from the returned array of cleaned values (default to true)
  45. *
  46. * Available error codes:
  47. *
  48. * * extra_fields
  49. *
  50. * @param array $options An array of options
  51. * @param array $messages An array of error messages
  52. *
  53. * @see sfValidatorBase
  54. */
  55. protected function configure($options = array(), $messages = array())
  56. {
  57. $this->addOption('allow_extra_fields', false);
  58. $this->addOption('filter_extra_fields', true);
  59. $this->addMessage('extra_fields', 'Unexpected extra form field named "%field%".');
  60. $this->addMessage('post_max_size', 'The form submission cannot be processed. It probably means that you have uploaded a file that is too big.');
  61. }
  62. /**
  63. * @see sfValidatorBase
  64. */
  65. public function clean($values)
  66. {
  67. return $this->doClean($values);
  68. }
  69. /**
  70. * @see sfValidatorBase
  71. */
  72. protected function doClean($values)
  73. {
  74. if (null === $values)
  75. {
  76. $values = array();
  77. }
  78. if (!is_array($values))
  79. {
  80. throw new InvalidArgumentException('You must pass an array parameter to the clean() method');
  81. }
  82. $clean = array();
  83. $unused = array_keys($this->fields);
  84. $errorSchema = new sfValidatorErrorSchema($this);
  85. // check that post_max_size has not been reached
  86. if (isset($_SERVER['CONTENT_LENGTH']) && (int) $_SERVER['CONTENT_LENGTH'] > $this->getBytes(ini_get('post_max_size')))
  87. {
  88. $errorSchema->addError(new sfValidatorError($this, 'post_max_size'));
  89. throw $errorSchema;
  90. }
  91. // pre validator
  92. try
  93. {
  94. $this->preClean($values);
  95. }
  96. catch (sfValidatorErrorSchema $e)
  97. {
  98. $errorSchema->addErrors($e);
  99. }
  100. catch (sfValidatorError $e)
  101. {
  102. $errorSchema->addError($e);
  103. }
  104. // validate given values
  105. foreach ($values as $name => $value)
  106. {
  107. // field exists in our schema?
  108. if (!array_key_exists($name, $this->fields))
  109. {
  110. if (!$this->options['allow_extra_fields'])
  111. {
  112. $errorSchema->addError(new sfValidatorError($this, 'extra_fields', array('field' => $name)));
  113. }
  114. else if (!$this->options['filter_extra_fields'])
  115. {
  116. $clean[$name] = $value;
  117. }
  118. continue;
  119. }
  120. unset($unused[array_search($name, $unused, true)]);
  121. // validate value
  122. try
  123. {
  124. $clean[$name] = $this->fields[$name]->clean($value);
  125. }
  126. catch (sfValidatorError $e)
  127. {
  128. $clean[$name] = null;
  129. $errorSchema->addError($e, (string) $name);
  130. }
  131. }
  132. // are non given values required?
  133. foreach ($unused as $name)
  134. {
  135. // validate value
  136. try
  137. {
  138. $clean[$name] = $this->fields[$name]->clean(null);
  139. }
  140. catch (sfValidatorError $e)
  141. {
  142. $clean[$name] = null;
  143. $errorSchema->addError($e, (string) $name);
  144. }
  145. }
  146. // post validator
  147. try
  148. {
  149. $clean = $this->postClean($clean);
  150. }
  151. catch (sfValidatorErrorSchema $e)
  152. {
  153. $errorSchema->addErrors($e);
  154. }
  155. catch (sfValidatorError $e)
  156. {
  157. $errorSchema->addError($e);
  158. }
  159. if (count($errorSchema))
  160. {
  161. throw $errorSchema;
  162. }
  163. return $clean;
  164. }
  165. /**
  166. * Cleans the input values.
  167. *
  168. * This method is the first validator executed by doClean().
  169. *
  170. * It executes the validator returned by getPreValidator()
  171. * on the global array of values.
  172. *
  173. * @param array $values The input values
  174. *
  175. * @throws sfValidatorError
  176. */
  177. public function preClean($values)
  178. {
  179. if (null === $validator = $this->getPreValidator())
  180. {
  181. return;
  182. }
  183. $validator->clean($values);
  184. }
  185. /**
  186. * Cleans the input values.
  187. *
  188. * This method is the last validator executed by doClean().
  189. *
  190. * It executes the validator returned by getPostValidator()
  191. * on the global array of cleaned values.
  192. *
  193. * @param array $values The input values
  194. *
  195. * @throws sfValidatorError
  196. */
  197. public function postClean($values)
  198. {
  199. if (null === $validator = $this->getPostValidator())
  200. {
  201. return $values;
  202. }
  203. return $validator->clean($values);
  204. }
  205. /**
  206. * Sets the pre validator.
  207. *
  208. * @param sfValidatorBase $validator An sfValidatorBase instance
  209. *
  210. * @return sfValidatorBase The current validator instance
  211. */
  212. public function setPreValidator(sfValidatorBase $validator)
  213. {
  214. $this->preValidator = clone $validator;
  215. return $this;
  216. }
  217. /**
  218. * Returns the pre validator.
  219. *
  220. * @return sfValidatorBase A sfValidatorBase instance
  221. */
  222. public function getPreValidator()
  223. {
  224. return $this->preValidator;
  225. }
  226. /**
  227. * Sets the post validator.
  228. *
  229. * @param sfValidatorBase $validator An sfValidatorBase instance
  230. *
  231. * @return sfValidatorBase The current validator instance
  232. */
  233. public function setPostValidator(sfValidatorBase $validator)
  234. {
  235. $this->postValidator = clone $validator;
  236. return $this;
  237. }
  238. /**
  239. * Returns the post validator.
  240. *
  241. * @return sfValidatorBase An sfValidatorBase instance
  242. */
  243. public function getPostValidator()
  244. {
  245. return $this->postValidator;
  246. }
  247. /**
  248. * Returns true if the schema has a field with the given name (implements the ArrayAccess interface).
  249. *
  250. * @param string $name The field name
  251. *
  252. * @return bool true if the schema has a field with the given name, false otherwise
  253. */
  254. public function offsetExists($name)
  255. {
  256. return isset($this->fields[$name]);
  257. }
  258. /**
  259. * Gets the field associated with the given name (implements the ArrayAccess interface).
  260. *
  261. * @param string $name The field name
  262. *
  263. * @return sfValidatorBase The sfValidatorBase instance associated with the given name, null if it does not exist
  264. */
  265. public function offsetGet($name)
  266. {
  267. return isset($this->fields[$name]) ? $this->fields[$name] : null;
  268. }
  269. /**
  270. * Sets a field (implements the ArrayAccess interface).
  271. *
  272. * @param string $name The field name
  273. * @param sfValidatorBase $validator An sfValidatorBase instance
  274. */
  275. public function offsetSet($name, $validator)
  276. {
  277. if (!$validator instanceof sfValidatorBase)
  278. {
  279. throw new InvalidArgumentException('A field must be an instance of sfValidatorBase.');
  280. }
  281. $this->fields[$name] = clone $validator;
  282. }
  283. /**
  284. * Removes a field by name (implements the ArrayAccess interface).
  285. *
  286. * @param string $name
  287. */
  288. public function offsetUnset($name)
  289. {
  290. unset($this->fields[$name]);
  291. }
  292. /**
  293. * Returns an array of fields.
  294. *
  295. * @return sfValidatorBase An array of sfValidatorBase instances
  296. */
  297. public function getFields()
  298. {
  299. return $this->fields;
  300. }
  301. /**
  302. * @see sfValidatorBase
  303. */
  304. public function asString($indent = 0)
  305. {
  306. throw new Exception('Unable to convert a sfValidatorSchema to string.');
  307. }
  308. public function __clone()
  309. {
  310. foreach ($this->fields as $name => $field)
  311. {
  312. $this->fields[$name] = clone $field;
  313. }
  314. if (null !== $this->preValidator)
  315. {
  316. $this->preValidator = clone $this->preValidator;
  317. }
  318. if (null !== $this->postValidator)
  319. {
  320. $this->postValidator = clone $this->postValidator;
  321. }
  322. }
  323. protected function getBytes($value)
  324. {
  325. $value = trim($value);
  326. switch (strtolower($value[strlen($value) - 1]))
  327. {
  328. // The 'G' modifier is available since PHP 5.1.0
  329. case 'g':
  330. $value *= 1024;
  331. case 'm':
  332. $value *= 1024;
  333. case 'k':
  334. $value *= 1024;
  335. }
  336. return $value;
  337. }
  338. }

Debug toolbar