Development

/branches/1.4/lib/generator/sfModelGenerator.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/generator/sfModelGenerator.class.php

Revision 25459, 12.7 kB (checked in by fabien, 4 years ago)

[1.2, 1.3, 1.4] added the module name when including a partial in the admin generator

  • 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  * Model generator.
13  *
14  * @package    symfony
15  * @subpackage generator
16  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17  * @version    SVN: $Id$
18  */
19 abstract class sfModelGenerator extends sfGenerator
20 {
21   protected
22     $configuration = null,
23     $primaryKey    = array(),
24     $modelClass    = '',
25     $params        = array(),
26     $config        = array(),
27     $formObject    = null;
28
29   /**
30    * Generates classes and templates in cache.
31    *
32    * @param array $params The parameters
33    *
34    * @return string The data to put in configuration cache
35    */
36   public function generate($params = array())
37   {
38     $this->validateParameters($params);
39
40     $this->modelClass = $this->params['model_class'];
41
42     // generated module name
43     $this->setModuleName($this->params['moduleName']);
44     $this->setGeneratedModuleName('auto'.ucfirst($this->params['moduleName']));
45
46     // theme exists?
47     $theme = isset($this->params['theme']) ? $this->params['theme'] : 'default';
48     $this->setTheme($theme);
49     $themeDir = $this->generatorManager->getConfiguration()->getGeneratorTemplate($this->getGeneratorClass(), $theme, '');
50     if (!is_dir($themeDir))
51     {
52       throw new sfConfigurationException(sprintf('The theme "%s" does not exist.', $theme));
53     }
54
55     // configure the model
56     $this->configure();
57
58     $this->configuration = $this->loadConfiguration();
59
60     // generate files
61     $this->generatePhpFiles($this->generatedModuleName, sfFinder::type('file')->relative()->in($themeDir));
62
63     // move helper file
64     if (file_exists($file = $this->generatorManager->getBasePath().'/'.$this->getGeneratedModuleName().'/lib/helper.php'))
65     {
66       @rename($file, $this->generatorManager->getBasePath().'/'.$this->getGeneratedModuleName().'/lib/Base'.ucfirst($this->moduleName).'GeneratorHelper.class.php');
67     }
68
69     return "require_once(sfConfig::get('sf_module_cache_dir').'/".$this->generatedModuleName."/actions/actions.class.php');";
70   }
71
72   /**
73    * Gets the actions base class for the generated module.
74    *
75    * @return string The actions base class
76    */
77   public function getActionsBaseClass()
78   {
79     return isset($this->params['actions_base_class']) ? $this->params['actions_base_class'] : 'sfActions';
80   }
81
82   /**
83    * Gets the class name for current model.
84    *
85    * @return string
86    */
87   public function getModelClass()
88   {
89     return $this->modelClass;
90   }
91
92   /**
93    * Gets the primary key name.
94    *
95    * @param Boolean $firstOne Whether to return the first PK or not
96    *
97    * @return array An array of primary keys
98    */
99   public function getPrimaryKeys($firstOne = false)
100   {
101     return $firstOne ? $this->primaryKey[0] : $this->primaryKey;
102   }
103
104   /**
105    * Gets the singular name for current model.
106    *
107    * @return string
108    */
109   public function getSingularName()
110   {
111     return isset($this->params['singular']) ? $this->params['singular'] : sfInflector::underscore($this->getModelClass());
112   }
113
114   /**
115    * Gets the plural name for current model.
116    *
117    * @return string
118    */
119   public function getPluralName()
120   {
121     return isset($this->params['plural']) ? $this->params['plural'] : $this->getSingularName().'_list';
122   }
123
124   /**
125    * Gets the i18n catalogue to use for user strings.
126    *
127    * @return string The i18n catalogue
128    */
129   public function getI18nCatalogue()
130   {
131     return isset($this->params['i18n_catalogue']) ? $this->params['i18n_catalogue'] : 'messages';
132   }
133
134   /**
135    * Returns PHP code for primary keys parameters.
136    *
137    * @param integer $indent The indentation value
138    * @param string  $callee The function to call
139    *
140    * @return string The PHP code
141    */
142   public function getRetrieveByPkParamsForAction($indent)
143   {
144     $params = array();
145     foreach ($this->getPrimaryKeys() as $pk)
146     {
147       $params[] = sprintf("\$request->getParameter('%s')", sfInflector::underscore($pk));
148     }
149
150     return implode(",\n".str_repeat(' ', max(0, $indent - strlen($this->getSingularName().$this->modelClass))), $params);
151   }
152
153   /**
154    * Returns PHP code to add to a URL for primary keys.
155    *
156    * @param string $prefix The prefix value
157    *
158    * @return string PHP code
159    */
160   public function getPrimaryKeyUrlParams($prefix = '', $full = false)
161   {
162     $params = array();
163     foreach ($this->getPrimaryKeys() as $pk)
164     {
165       $fieldName = sfInflector::underscore($pk);
166
167       if ($full)
168       {
169         $params[] = sprintf("%s='.%s->%s()", $fieldName, $prefix, $this->getColumnGetter($fieldName, false));
170       }
171       else
172       {
173         $params[] = sprintf("%s='.%s", $fieldName, $this->getColumnGetter($fieldName, true, $prefix));
174       }
175     }
176
177     return implode(".'&", $params);
178   }
179
180   /**
181    * Configures this generator.
182    */
183   abstract protected function configure();
184
185   abstract public function getType($column);
186
187   abstract public function getAllFieldNames();
188
189   /**
190    * Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
191    *
192    * This method is ORM dependant.
193    *
194    * @param string  $column    The column name
195    * @param boolean $developed true if you want developped method names, false otherwise
196    * @param string  $prefix    The prefix value
197    *
198    * @return string PHP code
199    */
200   abstract public function getColumnGetter($column, $developed = false , $prefix = '');
201
202   abstract public function getManyToManyTables();
203
204   /**
205    * Returns HTML code for an action link.
206    *
207    * @param string  $actionName The action name
208    * @param array   $params     The parameters
209    * @param boolean $pk_link    Whether to add a primary key link or not
210    *
211    * @return string HTML code
212    */
213   public function getLinkToAction($actionName, $params, $pk_link = false)
214   {
215     $action = isset($params['action']) ? $params['action'] : 'List'.sfInflector::camelize($actionName);
216
217     $url_params = $pk_link ? '?'.$this->getPrimaryKeyUrlParams() : '\'';
218
219     return '[?php echo link_to(__(\''.$params['label'].'\', array(), \''.$this->getI18nCatalogue().'\'), \''.$this->getModuleName().'/'.$action.$url_params.', '.$this->asPhp($params['params']).') ?]';
220   }
221
222   /**
223    * Wraps content with a credential condition.
224    *
225    * @param string $content The content
226    * @param array  $params  The parameters
227    *
228    * @return string HTML code
229    */
230   public function addCredentialCondition($content, $params = array())
231   {
232     if (isset($params['credentials']))
233     {
234       $credentials = $this->asPhp($params['credentials']);
235
236       return <<<EOF
237 [?php if (\$sf_user->hasCredential($credentials)): ?]
238 $content
239 [?php endif; ?]
240
241 EOF;
242     }
243     else
244     {
245       return $content;
246     }
247   }
248
249   /**
250    * Returns HTML code for a field.
251    *
252    * @param sfModelGeneratorConfigurationField $field The field
253    *
254    * @return string HTML code
255    */
256   public function renderField($field)
257   {
258     $html = $this->getColumnGetter($field->getName(), true);
259
260     if ($renderer = $field->getRenderer())
261     {
262       $html = sprintf("$html ? call_user_func_array(%s, array_merge(array(%s), %s)) : '&nbsp;'", $this->asPhp($renderer), $html, $this->asPhp($field->getRendererArguments()));
263     }
264     else if ($field->isComponent())
265     {
266       return sprintf("get_component('%s', '%s', array('type' => 'list', '%s' => \$%s))", $this->getModuleName(), $field->getName(), $this->getSingularName(), $this->getSingularName());
267     }
268     else if ($field->isPartial())
269     {
270       return sprintf("get_partial('%s/%s', array('type' => 'list', '%s' => \$%s))", $this->getModuleName(), $field->getName(), $this->getSingularName(), $this->getSingularName());
271     }
272     else if ('Date' == $field->getType())
273     {
274       $html = sprintf("false !== strtotime($html) ? format_date(%s, \"%s\") : '&nbsp;'", $html, $field->getConfig('date_format', 'f'));
275     }
276     else if ('Boolean' == $field->getType())
277     {
278       $html = sprintf("get_partial('%s/list_field_boolean', array('value' => %s))", $this->getModuleName(), $html);
279     }
280
281     if ($field->isLink())
282     {
283       $html = sprintf("link_to(%s, '%s', \$%s)", $html, $this->getUrlForAction('edit'), $this->getSingularName());
284     }
285
286     return $html;
287   }
288
289   /**
290    * Wraps a content for I18N.
291    *
292    * @param string $key The configuration key name
293    *
294    * @return string HTML code
295    */
296   public function getI18NString($key)
297   {
298     $value = $this->configuration->getValue($key, '', true);
299
300     $parts = explode('.', $key);
301     $context = $parts[0];
302
303     // find %%xx%% strings
304     preg_match_all('/%%([^%]+)%%/', $value, $matches, PREG_PATTERN_ORDER);
305     $fields = array();
306     foreach ($matches[1] as $name)
307     {
308       $fields[] = $name;
309     }
310
311     $vars = array();
312     foreach ($this->configuration->getContextConfiguration($context, $fields) as $field)
313     {
314       $vars[] = '\'%%'.$field->getName().'%%\' => '.$this->renderField($field);
315     }
316
317     return sprintf("__('%s', array(%s), '%s')", $value, implode(', ', $vars), $this->getI18nCatalogue());
318   }
319
320   /**
321    * Gets the form object
322    *
323    * @return sfForm
324    */
325   public function getFormObject()
326   {
327     if (null === $this->formObject)
328     {
329       $class = null === $this->configuration ? $this->getModelClass().'Form' : $this->configuration->getFormClass();
330
331       $this->formObject = new $class();
332     }
333
334     return $this->formObject;
335   }
336
337   /**
338    * Gets the HTML to add to the form tag if the form is multipart.
339    *
340    * @return string
341    */
342   public function getFormMultipartHtml()
343   {
344     if (isset($this->params['non_verbose_templates']) && $this->params['non_verbose_templates'])
345     {
346       return '[?php $form->isMultipart() and print \' enctype="multipart/form-data"\' ?]';
347     }
348     else
349     {
350       return $this->getFormObject()->isMultipart() ? ' enctype="multipart/form-data"' : '';
351     }
352   }
353
354   /**
355    * Validates the basic structure of the parameters.
356    *
357    * @param array $params An array of parameters
358    */
359   protected function validateParameters($params)
360   {
361     foreach (array('model_class', 'moduleName') as $key)
362     {
363       if (!isset($params[$key]))
364       {
365         throw new sfParseException(sprintf('sfModelGenerator must have a "%s" parameter.', $key));
366       }
367     }
368
369     if (!class_exists($params['model_class']))
370     {
371       throw new sfInitializationException(sprintf('Unable to generate a module for non-existent model "%s".', $params['model_class']));
372     }
373
374     $this->config = isset($params['config']) ? $params['config'] : array();
375
376     unset($params['config']);
377     $this->params = $params;
378   }
379
380   /**
381    * Loads the configuration for this generated module.
382    */
383   protected function loadConfiguration()
384   {
385     try
386     {
387       $this->generatorManager->getConfiguration()->getGeneratorTemplate($this->getGeneratorClass(), $this->getTheme(), '../parts/configuration.php');
388     }
389     catch (sfException $e)
390     {
391       return null;
392     }
393
394     $config = $this->getGeneratorManager()->getConfiguration();
395     if (!$config instanceof sfApplicationConfiguration)
396     {
397       throw new LogicException('The sfModelGenerator can only operates with an application configuration.');
398     }
399
400     $basePath = $this->getGeneratedModuleName().'/lib/Base'.ucfirst($this->getModuleName()).'GeneratorConfiguration.class.php';
401     $this->getGeneratorManager()->save($basePath, $this->evalTemplate('../parts/configuration.php'));
402
403     require_once $this->getGeneratorManager()->getBasePath().'/'.$basePath;
404
405     $class = 'Base'.ucfirst($this->getModuleName()).'GeneratorConfiguration';
406     foreach ($config->getLibDirs($this->getModuleName()) as $dir)
407     {
408       if (!is_file($configuration = $dir.'/'.$this->getModuleName().'GeneratorConfiguration.class.php'))
409       {
410         continue;
411       }
412
413       require_once $configuration;
414       $class = $this->getModuleName().'GeneratorConfiguration';
415       break;
416     }
417
418     // validate configuration
419     foreach ($this->config as $context => $value)
420     {
421       if (!$value)
422       {
423         continue;
424       }
425
426       throw new InvalidArgumentException(sprintf('Your generator configuration contains some errors for the "%s" context. The following configuration cannot be parsed: %s.', $context, $this->asPhp($value)));
427     }
428
429     return new $class();
430   }
431
432   /**
433    * Returns the URL for a given action.
434    *
435    * @return string The URL related to a given action
436    */
437   public function getUrlForAction($action)
438   {
439     if (isset($this->params['route_prefix']))
440     {
441       return 'list' == $action ? $this->params['route_prefix'] : $this->params['route_prefix'].'_'.$action;
442     }
443     else
444     {
445       return $this->getModuleName().'/'.$action;
446     }
447   }
448
449   public function asPhp($variable)
450   {
451     return str_replace(array("\n", 'array ('), array('', 'array('), var_export($variable, true));
452   }
453
454   public function escapeString($string)
455   {
456     return str_replace("'", "\\'", $string);
457   }
458 }
459
Note: See TracBrowser for help on using the browser.