Development

/branches/1.4/lib/plugins/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineUnique.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/plugins/sfDoctrinePlugin/lib/validator/sfValidatorDoctrineUnique.class.php

Revision 23810, 4.7 kB (checked in by Kris.Wallsmith, 4 years ago)

[1.3] set svn:eol-style property to native and svn:keywords property to Id on all .php files

  • 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  * (c) Jonathan H. Wage <jonwage@gmail.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 /**
13  * sfValidatorDoctrineUnique validates that the uniqueness of a column.
14  *
15  * Warning: sfValidatorDoctrineUnique is susceptible to race conditions.
16  * To avoid this issue, wrap the validation process and the model saving
17  * inside a transaction.
18  *
19  * @package    symfony
20  * @subpackage doctrine
21  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
22  * @author     Jonathan H. Wage <jonwage@gmail.com>
23  * @version    SVN: $Id$
24  */
25 class sfValidatorDoctrineUnique extends sfValidatorSchema
26 {
27   /**
28    * Constructor.
29    *
30    * @param array  An array of options
31    * @param array  An array of error messages
32    *
33    * @see sfValidatorSchema
34    */
35   public function __construct($options = array(), $messages = array())
36   {
37     parent::__construct(null, $options, $messages);
38   }
39
40   /**
41    * Configures the current validator.
42    *
43    * Available options:
44    *
45    *  * model:              The model class (required)
46    *  * column:             The unique column name in Doctrine field name format (required)
47    *                        If the uniquess is for several columns, you can pass an array of field names
48    *  * primary_key:        The primary key column name in Doctrine field name format (optional, will be introspected if not provided)
49    *                        You can also pass an array if the table has several primary keys
50    *  * connection:         The Doctrine connection to use (null by default)
51    *  * 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
52    *
53    * @see sfValidatorBase
54    */
55   protected function configure($options = array(), $messages = array())
56   {
57     $this->addRequiredOption('model');
58     $this->addRequiredOption('column');
59     $this->addOption('primary_key', null);
60     $this->addOption('connection', null);
61     $this->addOption('throw_global_error', false);
62
63     $this->setMessage('invalid', 'An object with the same "%column%" already exist.');
64   }
65
66   /**
67    * @see sfValidatorBase
68    */
69   protected function doClean($values)
70   {
71     $originalValues = $values;
72     $table = Doctrine_Core::getTable($this->getOption('model'));
73     if (!is_array($this->getOption('column')))
74     {
75       $this->setOption('column', array($this->getOption('column')));
76     }
77
78     //if $values isn't an array, make it one
79     if (!is_array($values))
80     {
81       //use first column for key
82       $columns = $this->getOption('column');
83       $values = array($columns[0] => $values);
84     }
85
86     $q = Doctrine_Core::getTable($this->getOption('model'))->createQuery('a');
87     foreach ($this->getOption('column') as $column)
88     {
89       $colName = $table->getColumnName($column);
90       if (!array_key_exists($column, $values))
91       {
92         // one of the column has be removed from the form
93         return $originalValues;
94       }
95
96       $q->addWhere('a.' . $colName . ' = ?', $values[$column]);
97     }
98
99     $object = $q->fetchOne();
100
101     // if no object or if we're updating the object, it's ok
102     if (!$object || $this->isUpdate($object, $values))
103     {
104       return $originalValues;
105     }
106
107     $error = new sfValidatorError($this, 'invalid', array('column' => implode(', ', $this->getOption('column'))));
108
109     if ($this->getOption('throw_global_error'))
110     {
111       throw $error;
112     }
113
114     $columns = $this->getOption('column');
115
116     throw new sfValidatorErrorSchema($this, array($columns[0] => $error));
117   }
118
119   /**
120    * Returns whether the object is being updated.
121    *
122    * @param BaseObject  A Doctrine object
123    * @param array       An array of values
124    *
125    * @param Boolean     true if the object is being updated, false otherwise
126    */
127   protected function isUpdate(Doctrine_Record $object, $values)
128   {
129     // check each primary key column
130     foreach ($this->getPrimaryKeys() as $column)
131     {
132       if (!isset($values[$column]) || $object->$column != $values[$column])
133       {
134         return false;
135       }
136     }
137
138     return true;
139   }
140
141   /**
142    * Returns the primary keys for the model.
143    *
144    * @return array An array of primary keys
145    */
146   protected function getPrimaryKeys()
147   {
148     if (null === $this->getOption('primary_key'))
149     {
150       $primaryKeys = Doctrine_Core::getTable($this->getOption('model'))->getIdentifier();
151       $this->setOption('primary_key', $primaryKeys);
152     }
153
154     if (!is_array($this->getOption('primary_key')))
155     {
156       $this->setOption('primary_key', array($this->getOption('primary_key')));
157     }
158
159     return $this->getOption('primary_key');
160   }
161 }
Note: See TracBrowser for help on using the browser.