123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- <?php
- /*
- * This file is part of the symfony package.
- * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- /**
- * Model generator.
- *
- * @package symfony
- * @subpackage generator
- * @author Fabien Potencier <fabien.potencier@symfony-project.com>
- * @version SVN: $Id: sfModelGenerator.class.php 15622 2009-02-19 10:27:58Z fabien $
- */
- abstract class sfModelGenerator extends sfGenerator
- {
- protected
- $configuration = null,
- $primaryKey = array(),
- $modelClass = '',
- $params = array(),
- $config = array(),
- $formObject = null;
- /**
- * Generates classes and templates in cache.
- *
- * @param array $params The parameters
- *
- * @return string The data to put in configuration cache
- */
- public function generate($params = array())
- {
- $this->validateParameters($params);
- $this->modelClass = $this->params['model_class'];
- // generated module name
- $this->setModuleName($this->params['moduleName']);
- $this->setGeneratedModuleName('auto'.ucfirst($this->params['moduleName']));
- // theme exists?
- $theme = isset($this->params['theme']) ? $this->params['theme'] : 'default';
- $this->setTheme($theme);
- $themeDir = $this->generatorManager->getConfiguration()->getGeneratorTemplate($this->getGeneratorClass(), $theme, '');
- if (!is_dir($themeDir))
- {
- throw new sfConfigurationException(sprintf('The theme "%s" does not exist.', $theme));
- }
- // configure the model
- $this->configure();
- $this->configuration = $this->loadConfiguration();
- // generate files
- $this->generatePhpFiles($this->generatedModuleName, sfFinder::type('file')->relative()->in($themeDir));
- // move helper file
- if (file_exists($file = $this->generatorManager->getBasePath().'/'.$this->getGeneratedModuleName().'/lib/helper.php'))
- {
- @rename($file, $this->generatorManager->getBasePath().'/'.$this->getGeneratedModuleName().'/lib/Base'.ucfirst($this->moduleName).'GeneratorHelper.class.php');
- }
- return "require_once(sfConfig::get('sf_module_cache_dir').'/".$this->generatedModuleName."/actions/actions.class.php');";
- }
- /**
- * Gets the class name for current model.
- *
- * @return string
- */
- public function getModelClass()
- {
- return $this->modelClass;
- }
- /**
- * Gets the primary key name.
- *
- * @param Boolean $firstOne Whether to return the first PK or not
- *
- * @return array An array of primary keys
- */
- public function getPrimaryKeys($firstOne = false)
- {
- return $firstOne ? $this->primaryKey[0] : $this->primaryKey;
- }
- /**
- * Gets the singular name for current model.
- *
- * @return string
- */
- public function getSingularName()
- {
- return isset($this->params['singular']) ? $this->params['singular'] : sfInflector::underscore($this->getModelClass());
- }
- /**
- * Gets the plural name for current model.
- *
- * @return string
- */
- public function getPluralName()
- {
- return isset($this->params['plural']) ? $this->params['plural'] : $this->getSingularName().'_list';
- }
- /**
- * Gets the i18n catalogue to use for user strings.
- *
- * @return string The i18n catalogue
- */
- public function getI18nCatalogue()
- {
- return isset($this->params['i18n_catalogue']) ? $this->params['i18n_catalogue'] : 'messages';
- }
- /**
- * Returns PHP code for primary keys parameters.
- *
- * @param integer $indent The indentation value
- * @param string $callee The function to call
- *
- * @return string The PHP code
- */
- public function getRetrieveByPkParamsForAction($indent)
- {
- $params = array();
- foreach ($this->getPrimaryKeys() as $pk)
- {
- $params[] = sprintf("\$request->getParameter('%s')", sfInflector::underscore($pk));
- }
- return implode(",\n".str_repeat(' ', max(0, $indent - strlen($this->getSingularName().$this->modelClass))), $params);
- }
- /**
- * Returns PHP code to add to a URL for primary keys.
- *
- * @param string $prefix The prefix value
- *
- * @return string PHP code
- */
- public function getPrimaryKeyUrlParams($prefix = '', $full = false)
- {
- $params = array();
- foreach ($this->getPrimaryKeys() as $pk)
- {
- $fieldName = sfInflector::underscore($pk);
- if ($full)
- {
- $params[] = sprintf("%s='.%s->%s()", $fieldName, $prefix, $this->getColumnGetter($fieldName, false));
- }
- else
- {
- $params[] = sprintf("%s='.%s", $fieldName, $this->getColumnGetter($fieldName, true, $prefix));
- }
- }
- return implode(".'&", $params);
- }
- /**
- * Configures this generator.
- */
- abstract protected function configure();
- abstract public function getType($column);
- abstract public function getAllFieldNames();
- /**
- * Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
- *
- * This method is ORM dependant.
- *
- * @param string $column The column name
- * @param boolean $developed true if you want developped method names, false otherwise
- * @param string $prefix The prefix value
- *
- * @return string PHP code
- */
- abstract public function getColumnGetter($column, $developed = false , $prefix = '');
- abstract public function getManyToManyTables();
- /**
- * Returns HTML code for an action link.
- *
- * @param string $actionName The action name
- * @param array $params The parameters
- * @param boolean $pk_link Whether to add a primary key link or not
- *
- * @return string HTML code
- */
- public function getLinkToAction($actionName, $params, $pk_link = false)
- {
- $action = isset($params['action']) ? $params['action'] : 'List'.sfInflector::camelize($actionName);
- $url_params = $pk_link ? '?'.$this->getPrimaryKeyUrlParams() : '\'';
- return '[?php echo link_to(__(\''.$params['label'].'\'), \''.$this->getModuleName().'/'.$action.$url_params.', '.$this->asPhp($params['params']).', \''.$this->getI18nCatalogue().'\') ?]';
- }
- /**
- * Wraps content with a credential condition.
- *
- * @param string $content The content
- * @param array $params The parameters
- *
- * @return string HTML code
- */
- public function addCredentialCondition($content, $params = array())
- {
- if (isset($params['credentials']))
- {
- $credentials = $this->asPhp($params['credentials']);
- return <<<EOF
- [?php if (\$sf_user->hasCredential($credentials)): ?]
- $content
- [?php endif; ?]
- EOF;
- }
- else
- {
- return $content;
- }
- }
- /**
- * Returns HTML code for a field.
- *
- * @param sfModelGeneratorConfigurationField $field The field
- *
- * @return string HTML code
- */
- public function renderField($field)
- {
- $html = $this->getColumnGetter($field->getName(), true);
- if ($renderer = $field->getRenderer())
- {
- $html = sprintf("$html ? call_user_func_array(%s, array_merge(array(%s), %s)) : ' '", $this->asPhp($renderer), $html, $this->asPhp($field->getRendererArguments()));
- }
- else if ($field->isComponent())
- {
- return sprintf("get_component('%s', '%s', array('type' => 'list', '%s' => \$%s))", $this->getModuleName(), $field->getName(), $this->getSingularName(), $this->getSingularName());
- }
- else if ($field->isPartial())
- {
- return sprintf("get_partial('%s', array('type' => 'list', '%s' => \$%s))", $field->getName(), $this->getSingularName(), $this->getSingularName());
- }
- else if ('Date' == $field->getType())
- {
- $html = sprintf("$html ? format_date(%s, \"%s\") : ' '", $html, $field->getConfig('date_format', 'f'));
- }
- else if ('Boolean' == $field->getType())
- {
- $html = sprintf("get_partial('%s/list_field_boolean', array('value' => %s))", $this->getModuleName(), $html);
- }
- if ($field->isLink())
- {
- $html = sprintf("link_to(%s, '%s', \$%s)", $html, $this->getUrlForAction('edit'), $this->getSingularName());
- }
- return $html;
- }
- /**
- * Wraps a content for I18N.
- *
- * @param string $key The configuration key name
- *
- * @return string HTML code
- */
- public function getI18NString($key)
- {
- $value = $this->configuration->getValue($key, '', true);
- $parts = explode('.', $key);
- $context = $parts[0];
- // find %%xx%% strings
- preg_match_all('/%%([^%]+)%%/', $value, $matches, PREG_PATTERN_ORDER);
- $fields = array();
- foreach ($matches[1] as $name)
- {
- $fields[] = $name;
- }
- $vars = array();
- foreach ($this->configuration->getContextConfiguration($context, $fields) as $field)
- {
- $vars[] = '\'%%'.$field->getName().'%%\' => '.$this->renderField($field);
- }
- return sprintf("__('%s', array(%s), '%s')", $value, implode(', ', $vars), $this->getI18nCatalogue());
- }
- /**
- * Gets the form object
- *
- * @return sfForm
- */
- public function getFormObject()
- {
- if (is_null($this->formObject))
- {
- $class = is_null($this->configuration) ? $this->getModelClass().'Form' : $this->configuration->getFormClass();
- $this->formObject = new $class();
- }
- return $this->formObject;
- }
- /**
- * Gets the HTML to add to the form tag if the form is multipart.
- *
- * @return string
- */
- public function getFormMultipartHtml()
- {
- if (isset($this->params['non_verbose_templates']) && $this->params['non_verbose_templates'])
- {
- return '[?php $form->isMultipart() and print \' enctype="multipart/form-data"\' ?]';
- }
- else
- {
- return $this->getFormObject()->isMultipart() ? ' enctype="multipart/form-data"' : '';
- }
- }
- /**
- * Validates the basic structure of the parameters.
- *
- * @param array $params An array of parameters
- */
- protected function validateParameters($params)
- {
- foreach (array('model_class', 'moduleName') as $key)
- {
- if (!isset($params[$key]))
- {
- throw new sfParseException(sprintf('sfModelGenerator must have a "%s" parameter.', $key));
- }
- }
- if (!class_exists($params['model_class']))
- {
- throw new sfInitializationException(sprintf('Unable to generate a module for non-existent model "%s".', $params['model_class']));
- }
- $this->config = isset($params['config']) ? $params['config'] : array();
- unset($params['config']);
- $this->params = $params;
- }
- /**
- * Loads the configuration for this generated module.
- */
- protected function loadConfiguration()
- {
- try
- {
- $this->generatorManager->getConfiguration()->getGeneratorTemplate($this->getGeneratorClass(), $this->getTheme(), '../parts/configuration.php');
- }
- catch (sfException $e)
- {
- return null;
- }
- $config = $this->getGeneratorManager()->getConfiguration();
- if (!$config instanceof sfApplicationConfiguration)
- {
- throw new LogicException('The sfModelGenerator can only operates with an application configuration.');
- }
- $basePath = $this->getGeneratedModuleName().'/lib/Base'.ucfirst($this->getModuleName()).'GeneratorConfiguration.class.php';
- $this->getGeneratorManager()->save($basePath, $this->evalTemplate('../parts/configuration.php'));
- require_once $this->getGeneratorManager()->getBasePath().'/'.$basePath;
- $class = 'Base'.ucfirst($this->getModuleName()).'GeneratorConfiguration';
- foreach ($config->getLibDirs($this->getModuleName()) as $dir)
- {
- if (!is_file($configuration = $dir.'/'.$this->getModuleName().'GeneratorConfiguration.class.php'))
- {
- continue;
- }
- require_once $configuration;
- $class = $this->getModuleName().'GeneratorConfiguration';
- break;
- }
- // validate configuration
- foreach ($this->config as $context => $value)
- {
- if (!$value)
- {
- continue;
- }
- 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)));
- }
- return new $class();
- }
- /**
- * Returns the URL for a given action.
- *
- * @return string The URL related to a given action
- */
- public function getUrlForAction($action)
- {
- if (isset($this->params['route_prefix']))
- {
- return 'list' == $action ? $this->params['route_prefix'] : $this->params['route_prefix'].'_'.$action;
- }
- else
- {
- return $this->getModuleName().'/'.$action;
- }
- }
- public function asPhp($variable)
- {
- return str_replace(array("\n", 'array ('), array('', 'array('), var_export($variable, true));
- }
- public function escapeString($string)
- {
- return str_replace("'", "\\'", $string);
- }
- }
|