Development

/branches/1.2/lib/plugins/sfPropelPlugin/lib/generator/sfPropelGenerator.class.php

You must first sign up to be able to contribute.

root/branches/1.2/lib/plugins/sfPropelPlugin/lib/generator/sfPropelGenerator.class.php

Revision 16976, 9.6 kB (checked in by fabien, 5 years ago)

fixed Propel forms, filters, and admin generator when column names contain uppercase letters (closes #6151, #6187, #5030, #5610, #2855)

  • 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  * Propel generator.
13  *
14  * @package    symfony
15  * @subpackage propel
16  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17  * @version    SVN: $Id$
18  */
19 class sfPropelGenerator extends sfModelGenerator
20 {
21   protected
22     $tableMap = null,
23     $dbMap    = null;
24
25   /**
26    * Initializes the current sfGenerator instance.
27    *
28    * @param sfGeneratorManager $generatorManager A sfGeneratorManager instance
29    */
30   public function initialize(sfGeneratorManager $generatorManager)
31   {
32     parent::initialize($generatorManager);
33
34     $this->setGeneratorClass('sfPropelModule');
35   }
36
37   /**
38    * Configures this generator.
39    */
40   public function configure()
41   {
42     // get some model metadata
43     $this->loadMapBuilderClasses();
44
45     // load all primary keys
46     $this->loadPrimaryKeys();
47   }
48
49   /**
50    * Gets the table map for the current model class.
51    *
52    * @return TableMap A TableMap instance
53    */
54   public function getTableMap()
55   {
56     return $this->tableMap;
57   }
58
59   /**
60    * Returns an array of tables that represents a many to many relationship.
61    *
62    * A table is considered to be a m2m table if it has 2 foreign keys that are also primary keys.
63    *
64    * @return array An array of tables.
65    */
66   public function getManyToManyTables()
67   {
68     $tables = array();
69
70     // go through all tables to find m2m relationships
71     foreach ($this->dbMap->getTables() as $tableName => $table)
72     {
73       foreach ($table->getColumns() as $column)
74       {
75         if ($column->isForeignKey() && $column->isPrimaryKey() && $this->getTableMap()->getClassname() == $this->dbMap->getTable($column->getRelatedTableName())->getClassname())
76         {
77           // we have a m2m relationship
78           // find the other primary key
79           foreach ($table->getColumns() as $relatedColumn)
80           {
81             if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->getTableMap()->getClassname() != $this->dbMap->getTable($relatedColumn->getRelatedTableName())->getClassname())
82             {
83               // we have the related table
84               $tables[] = array(
85                 'middleTable'   => $table,
86                 'relatedTable'  => $this->dbMap->getTable($relatedColumn->getRelatedTableName()),
87                 'column'        => $column,
88                 'relatedColumn' => $relatedColumn,
89               );
90
91               break 2;
92             }
93           }
94         }
95       }
96     }
97
98     return $tables;
99   }
100
101   /**
102    * Loads primary keys.
103    *
104    * @throws sfException
105    */
106   protected function loadPrimaryKeys()
107   {
108     $this->primaryKey = array();
109     foreach ($this->tableMap->getColumns() as $column)
110     {
111       if ($column->isPrimaryKey())
112       {
113         $this->primaryKey[] = $column->getPhpName();
114       }
115     }
116
117     if (!count($this->primaryKey))
118     {
119       throw new sfException(sprintf('Cannot generate a module for a model without a primary key (%s)', $this->modelClass));
120     }
121   }
122
123   /**
124    * Loads map builder classes.
125    *
126    * @throws sfException
127    */
128   protected function loadMapBuilderClasses()
129   {
130     $this->dbMap = Propel::getDatabaseMap();
131
132     // we must load all map builder classes to be able to deal with foreign keys
133     $classes = sfFinder::type('file')->name('*MapBuilder.php')->in($this->generatorManager->getConfiguration()->getModelDirs());
134     foreach ($classes as $class)
135     {
136       $omClass = basename($class, 'MapBuilder.php');
137       if (class_exists($omClass) && is_subclass_of($omClass, 'BaseObject'))
138       {
139         $mapBuilderClass = basename($class, '.php');
140         $currentMap = new $mapBuilderClass();
141         if (!$currentMap->isBuilt())
142         {
143           $currentMap->doBuild();
144         }
145
146         if ($this->modelClass == $omClass)
147         {
148           $map = $currentMap;
149         }
150       }
151     }
152
153     if (!$map)
154     {
155       throw new sfException(sprintf('The model class "%s" does not exist.', $this->modelClass));
156     }
157
158     $this->tableMap = $map->getDatabaseMap()->getTable(constant(constant($this->modelClass.'::PEER').'::TABLE_NAME'));
159   }
160
161   /**
162    * Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
163    *
164    * @param string  $column     The column name
165    * @param boolean $developed  true if you want developped method names, false otherwise
166    * @param string  $prefix     The prefix value
167    *
168    * @return string PHP code
169    */
170   public function getColumnGetter($column, $developed = false, $prefix = '')
171   {
172     try
173     {
174       $getter = 'get'.call_user_func(array(constant($this->getModelClass().'::PEER'), 'translateFieldName'), $column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
175     }
176     catch (PropelException $e)
177     {
178       // not a real column
179       $getter = 'get'.sfInflector::camelize($column);
180     }
181
182     if (!$developed)
183     {
184       return $getter;
185     }
186
187     return sprintf('$%s%s->%s()', $prefix, $this->getSingularName(), $getter);
188   }
189
190   /**
191    * Returns the type of a column.
192    *
193    * @param  object $column A column object
194    *
195    * @return string The column type
196    */
197   public function getType($column)
198   {
199     if ($column->isForeignKey())
200     {
201       return 'ForeignKey';
202     }
203
204     switch ($column->getType())
205     {
206       case PropelColumnTypes::BOOLEAN:
207         return 'Boolean';
208       case PropelColumnTypes::DATE:
209       case PropelColumnTypes::TIMESTAMP:
210         return 'Date';
211       case PropelColumnTypes::TIME:
212         return 'Time';
213       default:
214         return 'Text';
215     }
216   }
217
218   /**
219    * Returns the default configuration for fields.
220    *
221    * @return array An array of default configuration for all fields
222    */
223   public function getDefaultFieldsConfiguration()
224   {
225     $fields = array();
226
227     $names = array();
228     foreach ($this->getTableMap()->getColumns() as $column)
229     {
230       $name = $this->translateColumnName($column);
231       $names[] = $name;
232       $fields[$name] = array_merge(array(
233         'is_link'      => (Boolean) $column->isPrimaryKey(),
234         'is_real'      => true,
235         'is_partial'   => false,
236         'is_component' => false,
237         'type'         => $this->getType($column),
238       ), isset($this->config['fields'][$name]) ? $this->config['fields'][$name] : array());
239     }
240
241     foreach ($this->getManyToManyTables() as $tables)
242     {
243       $name = sfInflector::underscore($tables['middleTable']->getClassname()).'_list';
244       $names[] = $name;
245       $fields[$name] = array_merge(array(
246         'is_link'      => false,
247         'is_real'      => false,
248         'is_partial'   => false,
249         'is_component' => false,
250         'type'         => 'Text',
251       ), isset($this->config['fields'][$name]) ? $this->config['fields'][$name] : array());
252     }
253
254     if (isset($this->config['fields']))
255     {
256       foreach ($this->config['fields'] as $name => $params)
257       {
258         if (in_array($name, $names))
259         {
260           continue;
261         }
262
263         $fields[$name] = array_merge(array(
264           'is_link'      => false,
265           'is_real'      => false,
266           'is_partial'   => false,
267           'is_component' => false,
268           'type'         => 'Text',
269         ), is_array($params) ? $params : array());
270       }
271     }
272
273     unset($this->config['fields']);
274
275     return $fields;
276   }
277
278   /**
279    * Returns the configuration for fields in a given context.
280    *
281    * @param  string $context The Context
282    *
283    * @return array An array of configuration for all the fields in a given context
284    */
285   public function getFieldsConfiguration($context)
286   {
287     $fields = array();
288
289     $names = array();
290     foreach ($this->getTableMap()->getColumns() as $column)
291     {
292       $name = $this->translateColumnName($column);
293       $names[] = $name;
294       $fields[$name] = isset($this->config[$context]['fields'][$name]) ? $this->config[$context]['fields'][$name] : array();
295     }
296
297     foreach ($this->getManyToManyTables() as $tables)
298     {
299       $name = sfInflector::underscore($tables['middleTable']->getClassname()).'_list';
300       $names[] = $name;
301       $fields[$name] = isset($this->config[$context]['fields'][$name]) ? $this->config[$context]['fields'][$name] : array();
302     }
303
304     if (isset($this->config[$context]['fields']))
305     {
306       foreach ($this->config[$context]['fields'] as $name => $params)
307       {
308         if (in_array($name, $names))
309         {
310           continue;
311         }
312
313         $fields[$name] = is_array($params) ? $params : array();
314       }
315     }
316
317     unset($this->config[$context]['fields']);
318
319     return $fields;
320   }
321
322   /**
323    * Gets all the fields for the current model.
324    *
325    * @param  Boolean $withM2M Whether to include m2m fields or not
326    *
327    * @return array   An array of field names
328    */
329   public function getAllFieldNames($withM2M = true)
330   {
331     $names = array();
332     foreach ($this->getTableMap()->getColumns() as $column)
333     {
334       $names[] = $this->translateColumnName($column);
335     }
336
337     if ($withM2M)
338     {
339       foreach ($this->getManyToManyTables() as $tables)
340       {
341         $names[] = sfInflector::underscore($tables['middleTable']->getClassname()).'_list';
342       }
343     }
344
345     return $names;
346   }
347
348   public function translateColumnName($column, $related = false, $to = BasePeer::TYPE_FIELDNAME)
349   {
350     $peer = $related ? constant($column->getTable()->getDatabaseMap()->getTable($column->getRelatedTableName())->getPhpName().'::PEER') : constant($column->getTable()->getPhpName().'::PEER');
351     $field = $related ? $column->getRelatedName() : $column->getFullyQualifiedName();
352
353     return call_user_func(array($peer, 'translateFieldName'), $field, BasePeer::TYPE_COLNAME, $to);
354   }
355 }
356
Note: See TracBrowser for help on using the browser.