Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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: sfValidatorSchema.class.php 22446 2009-09-26 07:55:47Z fabien $
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
}