Development

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

You must first sign up to be able to contribute.

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

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