Development

/branches/1.1/lib/plugins/sfPropelPlugin/lib/propel/validator/sfValidatorPropelUnique.class.php

You must first sign up to be able to contribute.

root/branches/1.1/lib/plugins/sfPropelPlugin/lib/propel/validator/sfValidatorPropelUnique.class.php

Revision 9666, 5.1 kB (checked in by fabien, 7 years ago)

added a throw_global_error to sfPropelValidatorUnique (closes #3732)

  • 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  * sfValidatorPropelUnique validates that the uniqueness of a column.
13  *
14  * Warning: sfValidatorPropelUnique is susceptible to race conditions.
15  * To avoid this issue, wrap the validation process and the model saving
16  * inside a transaction.
17  *
18  * @package    symfony
19  * @subpackage validator
20  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
21  * @version    SVN: $Id$
22  */
23 class sfValidatorPropelUnique extends sfValidatorSchema
24 {
25   /**
26    * Constructor.
27    *
28    * @param array  $options   An array of options
29    * @param array  $messages  An array of error messages
30    *
31    * @see sfValidatorSchema
32    */
33   public function __construct($options = array(), $messages = array())
34   {
35     parent::__construct(null, $options, $messages);
36   }
37
38   /**
39    * Configures the current validator.
40    *
41    * Available options:
42    *
43    *  * model:              The model class (required)
44    *  * column:             The unique column name in Propel field name format (required)
45    *                        If the uniquess is for several columns, you can pass an array of field names
46    *  * primary_key:        The primary key column name in Propel field name format (optional, will be introspected if not provided)
47    *                        You can also pass an array if the table has several primary keys
48    *  * connection:         The Propel connection to use (null by default)
49    *  * throw_global_error: Whether to throw a global error (false by default) or an error tied to the first field related to the column option array
50    *
51    * @see sfValidatorBase
52    */
53   protected function configure($options = array(), $messages = array())
54   {
55     $this->addRequiredOption('model');
56     $this->addRequiredOption('column');
57     $this->addOption('primary_key', null);
58     $this->addOption('connection', null);
59     $this->addOption('throw_global_error', false);
60
61     $this->setMessage('invalid', 'An object with the same "%column%" already exist.');
62   }
63
64   /**
65    * @see sfValidatorBase
66    */
67   protected function doClean($values)
68   {
69     if (!is_array($values))
70     {
71       throw new InvalidArgumentException('You must pass an array parameter to the clean() method (this validator can only be used as a post validator).');
72     }
73
74     if (!is_array($this->getOption('column')))
75     {
76       $this->setOption('column', array($this->getOption('column')));
77     }
78
79     $criteria = new Criteria();
80     foreach ($this->getOption('column') as $column)
81     {
82       $colName = call_user_func(array($this->getOption('model').'Peer', 'translateFieldName'), $column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
83
84       $criteria->add($colName, $values[$column]);
85     }
86
87     $object = call_user_func(array($this->getOption('model').'Peer', 'doSelectOne'), $criteria, $this->getOption('connection'));
88
89     // if no object or if we're updating the object, it's ok
90     if (is_null($object) || $this->isUpdate($object, $values))
91     {
92       return $values;
93     }
94
95     $error = new sfValidatorError($this, 'invalid', array('column' => implode(', ', $this->getOption('column'))));
96
97     if ($this->getOption('throw_global_error'))
98     {
99       throw $error;
100     }
101
102     $columns = $this->getOption('column');
103
104     throw new sfValidatorErrorSchema($this, array($columns[0] => $error));
105   }
106
107   /**
108    * Returns whether the object is being updated.
109    *
110    * @param BaseObject  $object   A Propel object
111    * @param array       $values   An array of values
112    *
113    * @return Boolean     true if the object is being updated, false otherwise
114    */
115   protected function isUpdate(BaseObject $object, $values)
116   {
117     // check each primary key column
118     foreach ($this->getPrimaryKeys() as $column)
119     {
120       $columnPhpName = call_user_func(array($this->getOption('model').'Peer', 'translateFieldName'), $column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
121       $method = 'get'.$columnPhpName;
122       if (!isset($values[$column]) or $object->$method() != $values[$column])
123       {
124         return false;
125       }
126     }
127
128     return true;
129   }
130
131   /**
132    * Returns the primary keys for the model.
133    *
134    * @return array An array of primary keys
135    */
136   protected function getPrimaryKeys()
137   {
138     if (is_null($this->getOption('primary_key')))
139     {
140       $primaryKeys = array();
141       $tableMap = call_user_func(array($this->getOption('model').'Peer', 'getTableMap'));
142       foreach ($tableMap->getColumns() as $column)
143       {
144         if (!$column->isPrimaryKey())
145         {
146           continue;
147         }
148
149         $primaryKeys[] = call_user_func(array($this->getOption('model').'Peer', 'translateFieldName'), $column->getPhpName(), BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME);
150       }
151
152       $this->setOption('primary_key', $primaryKeys);
153     }
154
155     if (!is_array($this->getOption('primary_key')))
156     {
157       $this->setOption('primary_key', array($this->getOption('primary_key')));
158     }
159
160     return $this->getOption('primary_key');
161   }
162 }
163
Note: See TracBrowser for help on using the browser.