PageRenderTime 32ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/oiclient/data/symfony/plugins/sfPropelPlugin/lib/propel/generator/sfPropelFormGenerator.class.php

http://openirudi.googlecode.com/
PHP | 491 lines | 314 code | 53 blank | 124 comment | 40 complexity | b0944dde800b9b90addd8e8c3a7ba08c MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * Propel form generator.
  11. *
  12. * This class generates a Propel forms.
  13. *
  14. * @package symfony
  15. * @subpackage generator
  16. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  17. * @version SVN: $Id: sfPropelFormGenerator.class.php 9534 2008-06-11 08:22:45Z fabien $
  18. */
  19. class sfPropelFormGenerator extends sfGenerator
  20. {
  21. protected
  22. $dbMap = null;
  23. /**
  24. * Initializes the current sfGenerator instance.
  25. *
  26. * @param sfGeneratorManager $generatorManager A sfGeneratorManager instance
  27. */
  28. public function initialize(sfGeneratorManager $generatorManager)
  29. {
  30. parent::initialize($generatorManager);
  31. $this->setGeneratorClass('sfPropelForm');
  32. }
  33. /**
  34. * Generates classes and templates in cache.
  35. *
  36. * @param array $params The parameters
  37. *
  38. * @return string The data to put in configuration cache
  39. */
  40. public function generate($params = array())
  41. {
  42. $this->params = $params;
  43. if (!isset($this->params['connection']))
  44. {
  45. throw new sfParseException('You must specify a "connection" parameter.');
  46. }
  47. if (!isset($this->params['model_dir_name']))
  48. {
  49. $this->params['model_dir_name'] = 'model';
  50. }
  51. if (!isset($this->params['form_dir_name']))
  52. {
  53. $this->params['form_dir_name'] = 'form';
  54. }
  55. $this->loadBuilders();
  56. $this->dbMap = Propel::getDatabaseMap($this->params['connection']);
  57. // create the project base class for all forms
  58. $file = sfConfig::get('sf_lib_dir').'/form/BaseFormPropel.class.php';
  59. if (!file_exists($file))
  60. {
  61. if (!is_dir(sfConfig::get('sf_lib_dir').'/form'))
  62. {
  63. mkdir(sfConfig::get('sf_lib_dir').'/form', 0777, true);
  64. }
  65. file_put_contents($file, $this->evalTemplate('sfPropelFormBaseTemplate.php'));
  66. }
  67. // create a form class for every Propel class
  68. foreach ($this->dbMap->getTables() as $tableName => $table)
  69. {
  70. $this->table = $table;
  71. // find the package to store forms in the same directory as the model classes
  72. $packages = explode('.', constant($table->getPhpName().'Peer::CLASS_DEFAULT'));
  73. array_pop($packages);
  74. if (false === $pos = array_search($this->params['model_dir_name'], $packages))
  75. {
  76. throw new InvalidArgumentException(sprintf('Unable to find the model dir name (%s) in the package %s.', $this->params['model_dir_name'], constant($table->getPhpName().'Peer::CLASS_DEFAULT')));
  77. }
  78. $packages[$pos] = $this->params['form_dir_name'];
  79. $baseDir = sfConfig::get('sf_root_dir').'/'.implode(DIRECTORY_SEPARATOR, $packages);
  80. if (!is_dir($baseDir.'/base'))
  81. {
  82. mkdir($baseDir.'/base', 0777, true);
  83. }
  84. file_put_contents($baseDir.'/base/Base'.$table->getPhpName().'Form.class.php', $this->evalTemplate('sfPropelFormGeneratedTemplate.php'));
  85. if (!file_exists($classFile = $baseDir.'/'.$table->getPhpName().'Form.class.php'))
  86. {
  87. file_put_contents($classFile, $this->evalTemplate('sfPropelFormTemplate.php'));
  88. }
  89. }
  90. }
  91. /**
  92. * Returns an array of tables that represents a many to many relationship.
  93. *
  94. * A table is considered to be a m2m table if it has 2 foreign keys that are also primary keys.
  95. *
  96. * @return array An array of tables.
  97. */
  98. public function getManyToManyTables()
  99. {
  100. $tables = array();
  101. // go through all tables to find m2m relationships
  102. foreach ($this->dbMap->getTables() as $tableName => $table)
  103. {
  104. foreach ($table->getColumns() as $column)
  105. {
  106. if ($column->isForeignKey() && $column->isPrimaryKey() && $this->table->getPhpName() == $this->getForeignTable($column)->getPhpName())
  107. {
  108. // we have a m2m relationship
  109. // find the other primary key
  110. foreach ($table->getColumns() as $relatedColumn)
  111. {
  112. if ($relatedColumn->isForeignKey() && $relatedColumn->isPrimaryKey() && $this->table->getPhpName() != $this->getForeignTable($relatedColumn)->getPhpName())
  113. {
  114. // we have the related table
  115. $tables[] = array(
  116. 'middleTable' => $table,
  117. 'relatedTable' => $this->getForeignTable($relatedColumn),
  118. 'column' => $column,
  119. 'relatedColumn' => $relatedColumn,
  120. );
  121. break 2;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. return $tables;
  128. }
  129. /**
  130. * Returns PHP names for all foreign keys of the current table.
  131. *
  132. * This method does not returns foreign keys that are also primary keys.
  133. *
  134. * @return array An array composed of:
  135. * * The foreign table PHP name
  136. * * The foreign key PHP name
  137. * * A Boolean to indicate whether the column is required or not
  138. * * A Boolean to indicate whether the column is a many to many relationship or not
  139. */
  140. public function getForeignKeyNames()
  141. {
  142. $names = array();
  143. foreach ($this->table->getColumns() as $column)
  144. {
  145. if (!$column->isPrimaryKey() && $column->isForeignKey())
  146. {
  147. $names[] = array($this->getForeignTable($column)->getPhpName(), $column->getPhpName(), $column->isNotNull(), false);
  148. }
  149. }
  150. foreach ($this->getManyToManyTables() as $tables)
  151. {
  152. $names[] = array($tables['relatedTable']->getPhpName(), $tables['middleTable']->getPhpName(), false, true);
  153. }
  154. return $names;
  155. }
  156. /**
  157. * Returns the first primary key column of the current table.
  158. *
  159. * @return ColumnMap A ColumnMap object
  160. */
  161. public function getPrimaryKey()
  162. {
  163. foreach ($this->table->getColumns() as $column)
  164. {
  165. if ($column->isPrimaryKey())
  166. {
  167. return $column;
  168. }
  169. }
  170. }
  171. /**
  172. * Returns the foreign table associated with a column.
  173. *
  174. * @param ColumnMap $column A ColumnMap object
  175. *
  176. * @return TableMap A TableMap object
  177. */
  178. public function getForeignTable(ColumnMap $column)
  179. {
  180. return $this->dbMap->getTable($column->getRelatedTableName());
  181. }
  182. /**
  183. * Returns a sfWidgetForm class name for a given column.
  184. *
  185. * @param ColumnMap $column A ColumnMap object
  186. *
  187. * @return string The name of a subclass of sfWidgetForm
  188. */
  189. public function getWidgetClassForColumn(ColumnMap $column)
  190. {
  191. switch ($column->getCreoleType())
  192. {
  193. case CreoleTypes::BOOLEAN:
  194. $name = 'InputCheckbox';
  195. break;
  196. case CreoleTypes::LONGVARCHAR:
  197. $name = 'Textarea';
  198. break;
  199. case CreoleTypes::DATE:
  200. $name = 'Date';
  201. break;
  202. case CreoleTypes::TIME:
  203. $name = 'Time';
  204. break;
  205. case CreoleTypes::TIMESTAMP:
  206. $name = 'DateTime';
  207. break;
  208. default:
  209. $name = 'Input';
  210. }
  211. if ($column->isPrimaryKey())
  212. {
  213. $name = 'InputHidden';
  214. }
  215. else if ($column->isForeignKey())
  216. {
  217. $name = 'PropelSelect';
  218. }
  219. return sprintf('sfWidgetForm%s', $name);
  220. }
  221. /**
  222. * Returns a PHP string representing options to pass to a widget for a given column.
  223. *
  224. * @param ColumnMap $column A ColumnMap object
  225. *
  226. * @return string The options to pass to the widget as a PHP string
  227. */
  228. public function getWidgetOptionsForColumn(ColumnMap $column)
  229. {
  230. $options = array();
  231. if (!$column->isPrimaryKey() && $column->isForeignKey())
  232. {
  233. $options[] = sprintf('\'model\' => \'%s\', \'add_empty\' => %s', $this->getForeignTable($column)->getPhpName(), $column->isNotNull() ? 'false' : 'true');
  234. }
  235. return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
  236. }
  237. /**
  238. * Returns a sfValidator class name for a given column.
  239. *
  240. * @param ColumnMap $column A ColumnMap object
  241. *
  242. * @return string The name of a subclass of sfValidator
  243. */
  244. public function getValidatorClassForColumn(ColumnMap $column)
  245. {
  246. switch ($column->getCreoleType())
  247. {
  248. case CreoleTypes::BOOLEAN:
  249. $name = 'Boolean';
  250. break;
  251. case CreoleTypes::CHAR:
  252. case CreoleTypes::VARCHAR:
  253. case CreoleTypes::LONGVARCHAR:
  254. $name = 'String';
  255. break;
  256. case CreoleTypes::DOUBLE:
  257. case CreoleTypes::FLOAT:
  258. case CreoleTypes::NUMERIC:
  259. case CreoleTypes::DECIMAL:
  260. case CreoleTypes::REAL:
  261. $name = 'Number';
  262. break;
  263. case CreoleTypes::INTEGER:
  264. case CreoleTypes::SMALLINT:
  265. case CreoleTypes::TINYINT:
  266. case CreoleTypes::BIGINT:
  267. case CreoleTypes::YEAR:
  268. $name = 'Integer';
  269. break;
  270. case CreoleTypes::DATE:
  271. $name = 'Date';
  272. break;
  273. case CreoleTypes::TIME:
  274. $name = 'Time';
  275. break;
  276. case CreoleTypes::TIMESTAMP:
  277. $name = 'DateTime';
  278. break;
  279. default:
  280. $name = 'Pass';
  281. }
  282. if ($column->isPrimaryKey() || $column->isForeignKey())
  283. {
  284. $name = 'PropelChoice';
  285. }
  286. return sprintf('sfValidator%s', $name);
  287. }
  288. /**
  289. * Returns a PHP string representing options to pass to a validator for a given column.
  290. *
  291. * @param ColumnMap $column A ColumnMap object
  292. *
  293. * @return string The options to pass to the validator as a PHP string
  294. */
  295. public function getValidatorOptionsForColumn(ColumnMap $column)
  296. {
  297. $options = array();
  298. if ($column->isForeignKey())
  299. {
  300. $map = call_user_func(array($this->getForeignTable($column)->getPhpName().'Peer', 'getTableMap'));
  301. foreach ($map->getColumns() as $primaryKey)
  302. {
  303. if ($primaryKey->isPrimaryKey())
  304. {
  305. break;
  306. }
  307. }
  308. $options[] = sprintf('\'model\' => \'%s\', \'column\' => \'%s\'', $this->getForeignTable($column)->getPhpName(), strtolower($primaryKey->getColumnName()));
  309. }
  310. else if ($column->isPrimaryKey())
  311. {
  312. $options[] = sprintf('\'model\' => \'%s\', \'column\' => \'%s\'', $column->getTable()->getPhpName(), strtolower($column->getColumnName()));
  313. }
  314. else
  315. {
  316. switch ($column->getCreoleType())
  317. {
  318. case CreoleTypes::CHAR:
  319. case CreoleTypes::VARCHAR:
  320. case CreoleTypes::LONGVARCHAR:
  321. if ($column->getSize())
  322. {
  323. $options[] = sprintf('\'max_length\' => %s', $column->getSize());
  324. }
  325. break;
  326. }
  327. }
  328. if (!$column->isNotNull() || $column->isPrimaryKey())
  329. {
  330. $options[] = '\'required\' => false';
  331. }
  332. return count($options) ? sprintf('array(%s)', implode(', ', $options)) : '';
  333. }
  334. /**
  335. * Returns the maximum length for a column name.
  336. *
  337. * @return integer The length of the longer column name
  338. */
  339. public function getColumnNameMaxLength()
  340. {
  341. $max = 0;
  342. foreach ($this->table->getColumns() as $column)
  343. {
  344. if (($m = strlen($column->getColumnName())) > $max)
  345. {
  346. $max = $m;
  347. }
  348. }
  349. foreach ($this->getManyToManyTables() as $tables)
  350. {
  351. if (($m = strlen($this->underscore($tables['middleTable']->getPhpName()).'_list')) > $max)
  352. {
  353. $max = $m;
  354. }
  355. }
  356. return $max;
  357. }
  358. /**
  359. * Returns an array of primary key column names.
  360. *
  361. * @return array An array of primary key column names
  362. */
  363. public function getPrimaryKeyColumNames()
  364. {
  365. $pks = array();
  366. foreach ($this->table->getColumns() as $column)
  367. {
  368. if ($column->isPrimaryKey())
  369. {
  370. $pks[] = strtolower($column->getColumnName());
  371. }
  372. }
  373. return $pks;
  374. }
  375. /**
  376. * Returns a PHP string representation for the array of all primary key column names.
  377. *
  378. * @return string A PHP string representation for the array of all primary key column names
  379. *
  380. * @see getPrimaryKeyColumNames()
  381. */
  382. public function getPrimaryKeyColumNamesAsString()
  383. {
  384. return sprintf('array(\'%s\')', implode('\', \'', $this->getPrimaryKeyColumNames()));
  385. }
  386. /**
  387. * Returns true if the current table is internationalized.
  388. *
  389. * @return Boolean true if the current table is internationalized, false otherwise
  390. */
  391. public function isI18n()
  392. {
  393. return method_exists($this->table->getPhpName().'Peer', 'getI18nModel');
  394. }
  395. /**
  396. * Returns the i18n model name for the current table.
  397. *
  398. * @return string The model class name
  399. */
  400. public function getI18nModel()
  401. {
  402. return call_user_func(array($this->table->getPhpName().'Peer', 'getI18nModel'));
  403. }
  404. public function underscore($name)
  405. {
  406. return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), '\\1_\\2', $name));
  407. }
  408. public function getUniqueColumnNames()
  409. {
  410. $uniqueColumns = array();
  411. foreach (call_user_func(array($this->table->getPhpName().'Peer', 'getUniqueColumnNames')) as $unique)
  412. {
  413. $uniqueColumn = array();
  414. foreach ($unique as $column)
  415. {
  416. $uniqueColumn[] = strtolower($this->table->getColumn($column)->getColumnName());
  417. }
  418. $uniqueColumns[] = $uniqueColumn;
  419. }
  420. return $uniqueColumns;
  421. }
  422. /**
  423. * Loads all Propel builders.
  424. */
  425. protected function loadBuilders()
  426. {
  427. $classes = sfFinder::type('file')->name('*MapBuilder.php')->in($this->generatorManager->getConfiguration()->getModelDirs());
  428. foreach ($classes as $class)
  429. {
  430. $class = basename($class, '.php');
  431. $map = new $class();
  432. if (!$map->isBuilt())
  433. {
  434. $map->doBuild();
  435. }
  436. }
  437. }
  438. }