Development

/branches/1.4/lib/validator/sfValidatorSchema.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/validator/sfValidatorSchema.class.php

Revision 22446, 9.0 kB (checked in by fabien, 5 years ago)

[1.3] added a fluent interface to the form framework (closes #6438)

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