Development

/branches/1.4/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php

Revision 33150, 9.3 kB (checked in by fabien, 3 years ago)

[1.4] reverted 33123 (reopens #9922)

  • 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  * sfFormFilterDoctrine is the base class for filter forms based on Doctrine objects.
14  *
15  * Available options:
16  *
17  *  * query:        The query object to use
18  *  * table_method: A method on the table class that will either filter the passed query object or create a new one
19  *
20  * @package    symfony
21  * @subpackage form
22  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
23  * @author     Jonathan H. Wage <jonwage@gmail.com>
24  * @version    SVN: $Id$
25  */
26 abstract class sfFormFilterDoctrine extends sfFormFilter
27 {
28   /**
29    * Returns the current model name.
30    *
31    * @return string The model class name
32    */
33   abstract public function getModelName();
34
35   /**
36    * Returns the fields and their filter type.
37    *
38    * @return array An array of fields with their filter type
39    */
40   abstract public function getFields();
41
42   /**
43    * Get the name of the table method used to retrieve the query object for the filter
44    *
45    * @return string
46    */
47   public function getTableMethod()
48   {
49     return $this->getOption('table_method');
50   }
51
52   /**
53    * Set the name of the table method used to retrieve the query object for the filter
54    *
55    * The specified method will be passed the query object before any changes
56    * are made based on incoming parameters.
57    *
58    * @param string $tableMethod
59    */
60   public function setTableMethod($tableMethod)
61   {
62     $this->setOption('table_method', $tableMethod);
63   }
64
65   /**
66    * Sets the query object to use.
67    *
68    * @param Doctrine_Query $query
69    */
70   public function setQuery($query)
71   {
72     $this->setOption('query', $query);
73   }
74
75   /**
76    * Returns a Doctrine Query based on the current values form the form.
77    *
78    * @return Query A Doctrine Query object
79    */
80   public function getQuery()
81   {
82     if (!$this->isValid())
83     {
84       throw $this->getErrorSchema();
85     }
86
87     return $this->buildQuery($this->getValues());
88   }
89
90   /**
91    * Processes cleaned up values with user defined methods.
92    *
93    * To process a value before it is used by the buildQuery() method,
94    * you need to define an convertXXXValue() method where XXX is the PHP name
95    * of the column.
96    *
97    * The method must return the processed value or false to remove the value
98    * from the array of cleaned up values.
99    *
100    * @param  array An array of cleaned up values to process
101    *
102    * @return array An array of cleaned up values processed by the user defined methods
103    */
104   public function processValues($values)
105   {
106     // see if the user has overridden some column setter
107     $originalValues = $values;
108     foreach ($originalValues as $field => $value)
109     {
110       if (method_exists($this, $method = sprintf('convert%sValue', self::camelize($field))))
111       {
112         if (false === $ret = $this->$method($value))
113         {
114           unset($values[$field]);
115         }
116         else
117         {
118           $values[$field] = $ret;
119         }
120       }
121     }
122
123     return $values;
124   }
125
126   /**
127    * Builds a Doctrine Query based on the passed values.
128    *
129    * @param  array    An array of parameters to build the Query object
130    *
131    * @return Query A Doctrine Query object
132    */
133   public function buildQuery(array $values)
134   {
135     return $this->doBuildQuery($this->processValues($values));
136   }
137
138   /**
139    * Builds a Doctrine query with processed values.
140    *
141    * Overload this method instead of {@link buildQuery()} to avoid running
142    * {@link processValues()} multiple times.
143    *
144    * @param  array $values
145    *
146    * @return Doctrine_Query
147    */
148   protected function doBuildQuery(array $values)
149   {
150     $query = isset($this->options['query']) ? clone $this->options['query'] : $this->getTable()->createQuery('r');
151
152     if ($method = $this->getTableMethod())
153     {
154       $tmp = $this->getTable()->$method($query);
155
156       // for backward compatibility
157       if ($tmp instanceof Doctrine_Query)
158       {
159         $query = $tmp;
160       }
161     }
162
163     $fields = $this->getFields();
164
165     // add those fields that are not represented in getFields() with a null type
166     $names = array_merge($fields, array_diff(array_keys($this->validatorSchema->getFields()), array_keys($fields)));
167     $fields = array_merge($fields, array_combine($names, array_fill(0, count($names), null)));
168
169     foreach ($fields as $field => $type)
170     {
171       if (!isset($values[$field]) || null === $values[$field] || '' === $values[$field])
172       {
173         continue;
174       }
175
176       if ($this->getTable()->hasField($field))
177       {
178         $method = sprintf('add%sColumnQuery', self::camelize($this->getFieldName($field)));
179       }
180       else if (!method_exists($this, $method = sprintf('add%sColumnQuery', self::camelize($field))) && null !== $type)
181       {
182         throw new LogicException(sprintf('You must define a "%s" method to be able to filter with the "%s" field.', $method, $field));
183       }
184
185       if (method_exists($this, $method))
186       {
187         $this->$method($query, $field, $values[$field]);
188       }
189       else if (null !== $type)
190       {
191         if (!method_exists($this, $method = sprintf('add%sQuery', $type)))
192         {
193           throw new LogicException(sprintf('Unable to filter for the "%s" type.', $type));
194         }
195
196         $this->$method($query, $field, $values[$field]);
197       }
198     }
199
200     return $query;
201   }
202
203   protected function addForeignKeyQuery(Doctrine_Query $query, $field, $value)
204   {
205     $fieldName = $this->getFieldName($field);
206
207     if (is_array($value))
208     {
209       $query->andWhereIn(sprintf('%s.%s', $query->getRootAlias(), $fieldName), $value);
210     }
211     else
212     {
213       $query->addWhere(sprintf('%s.%s = ?', $query->getRootAlias(), $fieldName), $value);
214     }
215   }
216
217   protected function addEnumQuery(Doctrine_Query $query, $field, $value)
218   {
219     $fieldName = $this->getFieldName($field);
220
221     $query->addWhere(sprintf('%s.%s = ?', $query->getRootAlias(), $fieldName), $value);
222   }
223
224   protected function addTextQuery(Doctrine_Query $query, $field, $values)
225   {
226     $fieldName = $this->getFieldName($field);
227
228     if (is_array($values) && isset($values['is_empty']) && $values['is_empty'])
229     {
230       $query->addWhere(sprintf('(%s.%s IS NULL OR %1$s.%2$s = ?)', $query->getRootAlias(), $fieldName), array(''));
231     }
232     else if (is_array($values) && isset($values['text']) && '' != $values['text'])
233     {
234       $query->addWhere(sprintf('%s.%s LIKE ?', $query->getRootAlias(), $fieldName), '%'.$values['text'].'%');
235     }
236   }
237
238   protected function addNumberQuery(Doctrine_Query $query, $field, $values)
239   {
240     $fieldName = $this->getFieldName($field);
241
242     if (is_array($values) && isset($values['is_empty']) && $values['is_empty'])
243     {
244       $query->addWhere(sprintf('(%s.%s IS NULL OR %1$s.%2$s = ?)', $query->getRootAlias(), $fieldName), array(''));
245     }
246     else if (is_array($values) && isset($values['text']) && '' !== $values['text'])
247     {
248       $query->addWhere(sprintf('%s.%s = ?', $query->getRootAlias(), $fieldName), $values['text']);
249     }
250   }
251
252   protected function addBooleanQuery(Doctrine_Query $query, $field, $value)
253   {
254     $fieldName = $this->getFieldName($field);
255     $query->addWhere(sprintf('%s.%s = ?', $query->getRootAlias(), $fieldName), $value);
256   }
257
258   protected function addDateQuery(Doctrine_Query $query, $field, $values)
259   {
260     $fieldName = $this->getFieldName($field);
261
262     if (isset($values['is_empty']) && $values['is_empty'])
263     {
264       $query->addWhere(sprintf('%s.%s IS NULL', $query->getRootAlias(), $fieldName));
265     }
266     else
267     {
268       if (null !== $values['from'] && null !== $values['to'])
269       {
270         $query->andWhere(sprintf('%s.%s >= ?', $query->getRootAlias(), $fieldName), $values['from']);
271         $query->andWhere(sprintf('%s.%s <= ?', $query->getRootAlias(), $fieldName), $values['to']);
272       }
273       else if (null !== $values['from'])
274       {
275         $query->andWhere(sprintf('%s.%s >= ?', $query->getRootAlias(), $fieldName), $values['from']);
276       }
277       else if (null !== $values['to'])
278       {
279         $query->andWhere(sprintf('%s.%s <= ?', $query->getRootAlias(), $fieldName), $values['to']);
280       }
281     }
282   }
283
284   /**
285    * Used in generated forms when models use inheritance.
286    */
287   protected function setupInheritance()
288   {
289   }
290
291   /**
292    * Returns the name of the related model.
293    *
294    * @param string $alias A relation alias
295    *
296    * @return string
297    *
298    * @throws InvalidArgumentException If no relation with the supplied alias exists on the current model
299    */
300   protected function getRelatedModelName($alias)
301   {
302     $table = Doctrine_Core::getTable($this->getModelName());
303
304     if (!$table->hasRelation($alias))
305     {
306       throw new InvalidArgumentException(sprintf('The "%s" model has no "%s" relation.', $this->getModelName(), $alias));
307     }
308
309     $relation = $table->getRelation($alias);
310
311     return $relation['class'];
312   }
313
314   protected function getColName($field)
315   {
316     return $this->getTable()->getColumnName($field);
317   }
318
319   protected function getFieldName($colName)
320   {
321     return $this->getTable()->getFieldName($colName);
322   }
323
324   protected function camelize($text)
325   {
326     return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
327   }
328
329   protected function getTable()
330   {
331     return Doctrine_Core::getTable($this->getModelName());
332   }
333 }
334
Note: See TracBrowser for help on using the browser.