sfCrudGenerator.class.php 13 KB

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