ControllerTask.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Console\Command\Task;
  16. use Cake\Console\Shell;
  17. use Cake\Core\App;
  18. use Cake\Core\Configure;
  19. use Cake\ORM\TableRegistry;
  20. use Cake\Utility\ClassRegistry;
  21. use Cake\Utility\Inflector;
  22. /**
  23. * Task class for creating and updating controller files.
  24. *
  25. */
  26. class ControllerTask extends BakeTask {
  27. /**
  28. * Tasks to be loaded by this Task
  29. *
  30. * @var array
  31. */
  32. public $tasks = ['Model', 'Test', 'Template', 'DbConfig', 'Project'];
  33. /**
  34. * path to Controller directory
  35. *
  36. * @var array
  37. */
  38. public $path = null;
  39. /**
  40. * Override initialize
  41. *
  42. * @return void
  43. */
  44. public function initialize() {
  45. $this->path = current(App::path('Controller'));
  46. }
  47. /**
  48. * Execution method always used for tasks
  49. *
  50. * @return void
  51. */
  52. public function execute() {
  53. parent::execute();
  54. if (!isset($this->connection)) {
  55. $this->connection = 'default';
  56. }
  57. if (empty($this->args)) {
  58. $this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
  59. foreach ($this->listAll() as $table) {
  60. $this->out('- ' . $this->_controllerName($table));
  61. }
  62. return true;
  63. }
  64. if (strtolower($this->args[0]) === 'all') {
  65. return $this->all();
  66. }
  67. $controller = $this->_controllerName($this->args[0]);
  68. $this->bake($controller);
  69. }
  70. /**
  71. * Bake All the controllers at once. Will only bake controllers for models that exist.
  72. *
  73. * @return void
  74. */
  75. public function all() {
  76. $controllersCreated = 0;
  77. foreach ($this->listAll() as $table) {
  78. $controller = $this->_controllerName($table);
  79. $this->bake($controller);
  80. $this->bakeTest($controller);
  81. $controllersCreated++;
  82. }
  83. }
  84. /**
  85. * Bake scaffold actions
  86. *
  87. * @param string $controllerName Controller name
  88. * @return string Baked actions
  89. */
  90. public function bakeActions($controllerName) {
  91. if (!empty($this->params['no-actions'])) {
  92. return '';
  93. }
  94. $currentModelName = $controllerName;
  95. $plugin = $this->plugin;
  96. if ($plugin) {
  97. $plugin .= '.';
  98. }
  99. $modelObj = TableRegistry::get($currentModelName);
  100. $controllerPath = $this->_controllerPath($controllerName);
  101. $pluralName = $this->_pluralName($currentModelName);
  102. $singularName = Inflector::variable(Inflector::singularize($currentModelName));
  103. $singularHumanName = $this->_singularHumanName($controllerName);
  104. $pluralHumanName = $this->_pluralName($controllerName);
  105. $this->Template->set(compact(
  106. 'plugin', 'admin', 'controllerPath', 'pluralName', 'singularName',
  107. 'singularHumanName', 'pluralHumanName', 'modelObj', 'currentModelName'
  108. ));
  109. $actions = $this->Template->generate('actions', 'controller_actions');
  110. return $actions;
  111. }
  112. /**
  113. * Assembles and writes a Controller file
  114. *
  115. * @param string $controllerName Controller name already pluralized and correctly cased.
  116. * @return string Baked controller
  117. */
  118. public function bake($controllerName) {
  119. $this->out("\n" . __d('cake_console', 'Baking controller class for %s...', $controllerName), 1, Shell::QUIET);
  120. $actions = $this->bakeActions($controllerName);
  121. $helpers = $this->getHelpers();
  122. $components = $this->getComponents();
  123. $prefix = '';
  124. if (isset($this->params['prefix'])) {
  125. $prefix = '\\' . $this->params['prefix'];
  126. }
  127. $namespace = Configure::read('App.namespace');
  128. if ($this->plugin) {
  129. $namespace = $this->plugin;
  130. }
  131. $data = compact(
  132. 'prefix',
  133. 'actions',
  134. 'helpers',
  135. 'components',
  136. 'prefix',
  137. 'namespace'
  138. );
  139. $data['name'] = $controllerName;
  140. $out = $this->bakeController($controllerName, $data);
  141. $this->bakeTest($controllerName);
  142. return $out;
  143. }
  144. /**
  145. * Generate the controller code
  146. *
  147. * @param string $controllerName The name of the controller.
  148. * @param array $data The data to turn into code.
  149. */
  150. public function bakeController($controllerName, $data) {
  151. $data += [
  152. 'name' => null,
  153. 'namespace' => null,
  154. 'prefix' => null,
  155. 'actions' => null,
  156. 'helpers' => null,
  157. 'components' => null,
  158. 'plugin' => null,
  159. 'pluginPath' => null,
  160. ];
  161. $this->Template->set($data);
  162. $contents = $this->Template->generate('classes', 'controller');
  163. $path = $this->getPath();
  164. $filename = $path . $controllerName . 'Controller.php';
  165. $this->createFile($filename, $contents);
  166. return $contents;
  167. }
  168. /**
  169. * Gets the path for output. Checks the plugin property
  170. * and returns the correct path.
  171. *
  172. * @return string Path to output.
  173. */
  174. public function getPath() {
  175. $path = parent::getPath();
  176. if (!empty($this->params['prefix'])) {
  177. $path .= Inflector::camelize($this->params['prefix']) . DS;
  178. }
  179. return $path;
  180. }
  181. /**
  182. * Assembles and writes a unit test file
  183. *
  184. * @param string $className Controller class name
  185. * @return string Baked test
  186. */
  187. public function bakeTest($className) {
  188. if (!empty($this->params['no-test'])) {
  189. return;
  190. }
  191. $this->Test->plugin = $this->plugin;
  192. $this->Test->connection = $this->connection;
  193. $this->Test->interactive = $this->interactive;
  194. return $this->Test->bake('Controller', $className);
  195. }
  196. /**
  197. * Get the list of components for the controller.
  198. *
  199. * @return array
  200. */
  201. public function getComponents() {
  202. $components = [];
  203. if (!empty($this->params['components'])) {
  204. $components = explode(',', $this->params['components']);
  205. $components = array_values(array_filter(array_map('trim', $components)));
  206. }
  207. return $components;
  208. }
  209. /**
  210. * Get the list of helpers for the controller.
  211. *
  212. * @return array
  213. */
  214. public function getHelpers() {
  215. $helpers = [];
  216. if (!empty($this->params['helpers'])) {
  217. $helpers = explode(',', $this->params['helpers']);
  218. $helpers = array_values(array_filter(array_map('trim', $helpers)));
  219. }
  220. return $helpers;
  221. }
  222. /**
  223. * Interact with the user and get a list of additional components
  224. *
  225. * @return array Components the user wants to use.
  226. */
  227. public function doComponents() {
  228. $components = ['Paginator'];
  229. return array_merge($components, $this->_doPropertyChoices(
  230. __d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent?"),
  231. __d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
  232. ));
  233. }
  234. /**
  235. * Common code for property choice handling.
  236. *
  237. * @param string $prompt A yes/no question to precede the list
  238. * @param string $example A question for a comma separated list, with examples.
  239. * @return array Array of values for property.
  240. */
  241. protected function _doPropertyChoices($prompt, $example) {
  242. $proceed = $this->in($prompt, ['y', 'n'], 'n');
  243. $property = [];
  244. if (strtolower($proceed) === 'y') {
  245. $propertyList = $this->in($example);
  246. $propertyListTrimmed = str_replace(' ', '', $propertyList);
  247. $property = explode(',', $propertyListTrimmed);
  248. }
  249. return array_filter($property);
  250. }
  251. /**
  252. * Outputs and gets the list of possible controllers from database
  253. *
  254. * @param string $useDbConfig Database configuration name
  255. * @return array Set of controllers
  256. */
  257. public function listAll() {
  258. $this->Model->connection = $this->connection;
  259. return $this->Model->listAll();
  260. }
  261. /**
  262. * Gets the option parser instance and configures it.
  263. *
  264. * @return ConsoleOptionParser
  265. */
  266. public function getOptionParser() {
  267. $parser = parent::getOptionParser();
  268. $parser->description(
  269. __d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.')
  270. )->addArgument('name', [
  271. 'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.')
  272. ])->addOption('plugin', [
  273. 'short' => 'p',
  274. 'help' => __d('cake_console', 'Plugin to bake the controller into.')
  275. ])->addOption('connection', [
  276. 'short' => 'c',
  277. 'help' => __d('cake_console', 'The connection the controller\'s model is on.')
  278. ])->addOption('theme', [
  279. 'short' => 't',
  280. 'help' => __d('cake_console', 'Theme to use when baking code.')
  281. ])->addOption('components', [
  282. 'help' => __d('cake_console', 'The comma separated list of components to use.')
  283. ])->addOption('helpers', [
  284. 'help' => __d('cake_console', 'The comma separated list of helpers to use.')
  285. ])->addOption('prefix', [
  286. 'help' => __d('cake_console', 'The namespace/routing prefix to use.')
  287. ])->addOption('no-test', [
  288. 'boolean' => true,
  289. 'help' => __d('cake_console', 'Do not generate a test skeleton.')
  290. ])->addOption('no-actions', [
  291. 'boolean' => true,
  292. 'help' => __d('cake_console', 'Do not generate basic CRUD action methods.')
  293. ])->addOption('force', [
  294. 'short' => 'f',
  295. 'boolean' => true,
  296. 'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
  297. ])->addSubcommand('all', [
  298. 'help' => __d('cake_console', 'Bake all controllers with CRUD methods.')
  299. ]);
  300. return $parser;
  301. }
  302. }