sfCrudGenerator.class.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 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. * CRUD generator.
  11. *
  12. * This class generates a basic CRUD module.
  13. *
  14. * @package symfony
  15. * @subpackage generator
  16. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  17. * @version SVN: $Id: sfCrudGenerator.class.php 11471 2008-09-12 10:03:49Z fabien $
  18. */
  19. abstract class sfCrudGenerator extends sfGenerator
  20. {
  21. protected
  22. $singularName = '',
  23. $pluralName = '',
  24. $map = null,
  25. $tableMap = null,
  26. $primaryKey = array(),
  27. $className = '',
  28. $params = array();
  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->params = $params;
  39. $required_parameters = array('model_class', 'moduleName');
  40. foreach ($required_parameters as $entry)
  41. {
  42. if (!isset($this->params[$entry]))
  43. {
  44. throw new sfParseException(sprintf('You must specify a "%s".', $entry));
  45. }
  46. }
  47. $modelClass = $this->params['model_class'];
  48. if (!class_exists($modelClass))
  49. {
  50. throw new sfInitializationException(sprintf('Unable to scaffold nonexistent model "%s".', $modelClass));
  51. }
  52. $this->setScaffoldingClassName($modelClass);
  53. // generated module name
  54. $this->setGeneratedModuleName('auto'.ucfirst($this->params['moduleName']));
  55. $this->setModuleName($this->params['moduleName']);
  56. // get some model metadata
  57. $this->loadMapBuilderClasses();
  58. // load all primary keys
  59. $this->loadPrimaryKeys();
  60. // theme exists?
  61. $theme = isset($this->params['theme']) ? $this->params['theme'] : 'default';
  62. $themeDir = $this->generatorManager->getConfiguration()->getGeneratorTemplate($this->getGeneratorClass(), $theme, '');
  63. if (!is_dir($themeDir))
  64. {
  65. throw new sfConfigurationException(sprintf('The theme "%s" does not exist.', $theme));
  66. }
  67. $this->setTheme($theme);
  68. $files = sfFinder::type('file')->relative()->in($themeDir);
  69. $this->generatePhpFiles($this->generatedModuleName, $files);
  70. // require generated action class
  71. $data = "require_once(sfConfig::get('sf_module_cache_dir').'/".$this->generatedModuleName."/actions/actions.class.php');\n";
  72. return $data;
  73. }
  74. /**
  75. * Returns PHP code for primary keys parameters.
  76. *
  77. * @param integer $indent The indentation value
  78. * @param string $callee The function to call
  79. *
  80. * @return string The PHP code
  81. */
  82. public function getRetrieveByPkParamsForAction($indent, $callee = '$this->getRequestParameter')
  83. {
  84. $params = array();
  85. foreach ($this->getPrimaryKey() as $pk)
  86. {
  87. $params[] = "$callee('".sfInflector::underscore($pk->getPhpName())."')";
  88. }
  89. return implode(",\n".str_repeat(' ', max(0, $indent - strlen($this->singularName.$this->className))), $params);
  90. }
  91. /**
  92. * Returns PHP code for primary keys parameters.
  93. *
  94. * @param integer $indent The indentation value
  95. * @param string $prefix No effect at this time
  96. *
  97. * @return string The PHP code
  98. */
  99. public function getRetrieveByPkParamsForEdit($indent, $prefix)
  100. {
  101. $params = array();
  102. foreach ($this->getPrimaryKey() as $pk)
  103. {
  104. $params[] = sprintf("\$request->getParameter('%s')", sfInflector::underscore($pk->getPhpName()));
  105. }
  106. return implode(",\n".str_repeat(' ', max(0, $indent - strlen($this->singularName.$this->className))), $params);
  107. }
  108. /**
  109. * Returns PHP code for getOrCreate() parameters.
  110. *
  111. * @return string The PHP code
  112. */
  113. public function getMethodParamsForGetOrCreate()
  114. {
  115. $method_params = array();
  116. foreach ($this->getPrimaryKey() as $pk)
  117. {
  118. $fieldName = sfInflector::underscore($pk->getPhpName());
  119. $method_params[] = "\$$fieldName = '$fieldName'";
  120. }
  121. return implode(', ', $method_params);
  122. }
  123. /**
  124. * Returns PHP code for getOrCreate() promary keys condition.
  125. *
  126. * @param boolean $fieldNameAsArgument true if we pass the field name as an argument, false otherwise
  127. *
  128. * @return string The PHP code
  129. */
  130. public function getTestPksForGetOrCreate($fieldNameAsArgument = true)
  131. {
  132. $test_pks = array();
  133. foreach ($this->getPrimaryKey() as $pk)
  134. {
  135. $fieldName = sfInflector::underscore($pk->getPhpName());
  136. // 2 checks needed here, as '0' is a vaild PK.
  137. $test_pks[] = sprintf("\$this->getRequestParameter(%s) === ''", $fieldNameAsArgument ? "\$$fieldName" : "'".$fieldName."'");
  138. $test_pks[] = sprintf("\$this->getRequestParameter(%s) === null", $fieldNameAsArgument ? "\$$fieldName" : "'".$fieldName."'");
  139. }
  140. return implode("\n || ", $test_pks);
  141. }
  142. /**
  143. * Returns PHP code for primary keys parameters used in getOrCreate() method.
  144. *
  145. * @return string The PHP code
  146. */
  147. public function getRetrieveByPkParamsForGetOrCreate()
  148. {
  149. $retrieve_params = array();
  150. foreach ($this->getPrimaryKey() as $pk)
  151. {
  152. $fieldName = sfInflector::underscore($pk->getPhpName());
  153. $retrieve_params[] = "\$this->getRequestParameter(\$$fieldName)";
  154. }
  155. return implode(",\n".str_repeat(' ', max(0, 45 - strlen($this->singularName.$this->className))), $retrieve_params);
  156. }
  157. /**
  158. * Gets the table map for the current model class.
  159. *
  160. * @return TableMap A TableMap instance
  161. */
  162. public function getTableMap()
  163. {
  164. return $this->tableMap;
  165. }
  166. /**
  167. * Sets the class name to use for scaffolding
  168. *
  169. * @param string $className class name
  170. */
  171. protected function setScaffoldingClassName($className)
  172. {
  173. $this->singularName = isset($this->params['singular']) ? $this->params['singular'] : sfInflector::underscore($className);
  174. $this->pluralName = isset($this->params['plural']) ? $this->params['plural'] : $this->singularName.'s';
  175. $this->className = $className;
  176. }
  177. /**
  178. * Gets the singular name for current scaffolding class.
  179. *
  180. * @return string
  181. */
  182. public function getSingularName()
  183. {
  184. return $this->singularName;
  185. }
  186. /**
  187. * Gets the plural name for current scaffolding class.
  188. *
  189. * @return string
  190. */
  191. public function getPluralName()
  192. {
  193. return $this->pluralName;
  194. }
  195. /**
  196. * Gets the class name for current scaffolding class.
  197. *
  198. * @return string
  199. */
  200. public function getClassName()
  201. {
  202. return $this->className;
  203. }
  204. /**
  205. * Gets the primary key name.
  206. *
  207. * @return string
  208. */
  209. public function getPrimaryKey()
  210. {
  211. return $this->primaryKey;
  212. }
  213. /**
  214. * Gets the Map object.
  215. *
  216. * @return object
  217. */
  218. public function getMap()
  219. {
  220. return $this->map;
  221. }
  222. /**
  223. * Returns PHP code to add to a URL for primary keys.
  224. *
  225. * @param string $prefix The prefix value
  226. *
  227. * @return string PHP code
  228. */
  229. public function getPrimaryKeyUrlParams($prefix = '', $full = false)
  230. {
  231. $params = array();
  232. foreach ($this->getPrimaryKey() as $pk)
  233. {
  234. $phpName = $pk->getPhpName();
  235. $fieldName = sfInflector::underscore($phpName);
  236. if ($full)
  237. {
  238. $params[] = "$fieldName='.".$prefix.'->'.$this->getColumnGetter($pk, false).'()';
  239. }
  240. else
  241. {
  242. $params[] = "$fieldName='.".$this->getColumnGetter($pk, true, $prefix);
  243. }
  244. }
  245. return implode(".'&", $params);
  246. }
  247. /**
  248. * Gets PHP code for primary key condition.
  249. *
  250. * @param string $prefix The prefix value
  251. *
  252. * @return string PHP code
  253. */
  254. public function getPrimaryKeyIsSet($prefix = '')
  255. {
  256. $params = array();
  257. foreach ($this->getPrimaryKey() as $pk)
  258. {
  259. $params[] = $this->getColumnGetter($pk, true, $prefix);
  260. }
  261. return implode(' && ', $params);
  262. }
  263. /**
  264. * Gets object tag parameters.
  265. *
  266. * @param array $params An array of parameters
  267. * @param array $default_params An array of default parameters
  268. *
  269. * @return string PHP code
  270. */
  271. protected function getObjectTagParams($params, $default_params = array())
  272. {
  273. return var_export(array_merge($default_params, $params), true);
  274. }
  275. /**
  276. * Returns HTML code for a column in list mode.
  277. *
  278. * @param string $column The column name
  279. * @param array $params The parameters
  280. *
  281. * @return string HTML code
  282. */
  283. public function getColumnListTag($column, $params = array())
  284. {
  285. $type = $column->getType();
  286. $columnGetter = $this->getColumnGetter($column, true);
  287. if ($type == PropelColumnTypes::TIMESTAMP)
  288. {
  289. return "format_date($columnGetter, 'f')";
  290. }
  291. elseif ($type == PropelColumnTypes::DATE)
  292. {
  293. return "format_date($columnGetter, 'D')";
  294. }
  295. else
  296. {
  297. return "$columnGetter";
  298. }
  299. }
  300. /**
  301. * Returns HTML code for a column in edit mode.
  302. *
  303. * @param string $column The column name
  304. * @param array $params The parameters
  305. *
  306. * @return string HTML code
  307. */
  308. public function getCrudColumnEditTag($column, $params = array())
  309. {
  310. $type = $column->getType();
  311. if ($column->isForeignKey())
  312. {
  313. if (!$column->isNotNull() && !isset($params['include_blank']))
  314. {
  315. $params['include_blank'] = true;
  316. }
  317. return $this->getPHPObjectHelper('select_tag', $column, $params, array('related_class' => $this->getRelatedClassName($column)));
  318. }
  319. else if ($type == PropelColumnTypes::DATE)
  320. {
  321. // rich=false not yet implemented
  322. return $this->getPHPObjectHelper('input_date_tag', $column, $params, array('rich' => true));
  323. }
  324. else if ($type == PropelColumnTypes::TIMESTAMP)
  325. {
  326. // rich=false not yet implemented
  327. return $this->getPHPObjectHelper('input_date_tag', $column, $params, array('rich' => true, 'withtime' => true));
  328. }
  329. else if ($type == PropelColumnTypes::BOOLEAN)
  330. {
  331. return $this->getPHPObjectHelper('checkbox_tag', $column, $params);
  332. }
  333. else if ($type == PropelColumnTypes::CHAR || $type == PropelColumnTypes::VARCHAR)
  334. {
  335. $size = ($column->getSize() > 20 ? ($column->getSize() < 80 ? $column->getSize() : 80) : 20);
  336. return $this->getPHPObjectHelper('input_tag', $column, $params, array('size' => $size));
  337. }
  338. else if ($type == PropelColumnTypes::INTEGER || $type == PropelColumnTypes::TINYINT || $type == PropelColumnTypes::SMALLINT || $type == PropelColumnTypes::BIGINT)
  339. {
  340. return $this->getPHPObjectHelper('input_tag', $column, $params, array('size' => 7));
  341. }
  342. else if ($type == PropelColumnTypes::FLOAT || $type == PropelColumnTypes::DOUBLE || $type == PropelColumnTypes::DECIMAL || $type == PropelColumnTypes::NUMERIC || $type == PropelColumnTypes::REAL)
  343. {
  344. return $this->getPHPObjectHelper('input_tag', $column, $params, array('size' => 7));
  345. }
  346. else if ($type == PropelColumnTypes::LONGVARCHAR)
  347. {
  348. return $this->getPHPObjectHelper('textarea_tag', $column, $params, array('size' => '30x3'));
  349. }
  350. else
  351. {
  352. return $this->getPHPObjectHelper('input_tag', $column, $params, array('disabled' => true));
  353. }
  354. }
  355. /**
  356. * Loads primary keys.
  357. *
  358. * This method is ORM dependant.
  359. *
  360. * @throws sfException
  361. */
  362. abstract protected function loadPrimaryKeys();
  363. /**
  364. * Loads map builder classes.
  365. *
  366. * This method is ORM dependant.
  367. *
  368. * @throws sfException
  369. */
  370. abstract protected function loadMapBuilderClasses();
  371. /**
  372. * Generates a PHP call to an object helper.
  373. *
  374. * This method is ORM dependant.
  375. *
  376. * @param string $helperName The helper name
  377. * @param string $column The column name
  378. * @param array $params An array of parameters
  379. * @param array $localParams An array of local parameters
  380. *
  381. * @return string PHP code
  382. */
  383. abstract function getPHPObjectHelper($helperName, $column, $params, $localParams = array());
  384. /**
  385. * Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
  386. *
  387. * This method is ORM dependant.
  388. *
  389. * @param string $column The column name
  390. * @param boolean $developed true if you want developped method names, false otherwise
  391. * @param string $prefix The prefix value
  392. *
  393. * @return string PHP code
  394. */
  395. abstract function getColumnGetter($column, $developed = false , $prefix = '');
  396. /*
  397. * Gets the PHP name of the related class name.
  398. *
  399. * Used for foreign keys only; this method should be removed when we use sfAdminColumn instead.
  400. *
  401. * This method is ORM dependant.
  402. *
  403. * @param string $column The column name
  404. *
  405. * @return string The PHP name of the related class name
  406. */
  407. abstract function getRelatedClassName($column);
  408. }