1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18:
19: App::uses('AppShell', 'Console/Command');
20: App::uses('BakeTask', 'Console/Command/Task');
21: App::uses('AppModel', 'Model');
22:
23: 24: 25: 26: 27:
28: class ControllerTask extends BakeTask {
29:
30: 31: 32: 33: 34:
35: public $tasks = array('Model', 'Test', 'Template', 'DbConfig', 'Project');
36:
37: 38: 39: 40: 41:
42: public $path = null;
43:
44: 45: 46: 47: 48:
49: public function initialize() {
50: $this->path = current(App::path('Controller'));
51: }
52:
53: 54: 55: 56: 57:
58: public function execute() {
59: parent::execute();
60: if (empty($this->args)) {
61: return $this->_interactive();
62: }
63:
64: if (isset($this->args[0])) {
65: if (!isset($this->connection)) {
66: $this->connection = 'default';
67: }
68: if (strtolower($this->args[0]) == 'all') {
69: return $this->all();
70: }
71:
72: $controller = $this->_controllerName($this->args[0]);
73: $actions = '';
74:
75: if (!empty($this->params['public'])) {
76: $this->out(__d('cake_console', 'Baking basic crud methods for ') . $controller);
77: $actions .= $this->bakeActions($controller);
78: }
79: if (!empty($this->params['admin'])) {
80: $admin = $this->Project->getPrefix();
81: if ($admin) {
82: $this->out(__d('cake_console', 'Adding %s methods', $admin));
83: $actions .= "\n" . $this->bakeActions($controller, $admin);
84: }
85: }
86: if (empty($actions)) {
87: $actions = 'scaffold';
88: }
89:
90: if ($this->bake($controller, $actions)) {
91: if ($this->_checkUnitTest()) {
92: $this->bakeTest($controller);
93: }
94: }
95: }
96: }
97:
98: 99: 100: 101: 102:
103: public function all() {
104: $this->interactive = false;
105: $this->listAll($this->connection, false);
106: ClassRegistry::config('Model', array('ds' => $this->connection));
107: $unitTestExists = $this->_checkUnitTest();
108: foreach ($this->__tables as $table) {
109: $model = $this->_modelName($table);
110: $controller = $this->_controllerName($model);
111: App::uses($model, 'Model');
112: if (class_exists($model)) {
113: $actions = $this->bakeActions($controller);
114: if ($this->bake($controller, $actions) && $unitTestExists) {
115: $this->bakeTest($controller);
116: }
117: }
118: }
119: }
120:
121: 122: 123: 124: 125:
126: protected function _interactive() {
127: $this->interactive = true;
128: $this->hr();
129: $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->getPath()));
130: $this->hr();
131:
132: if (empty($this->connection)) {
133: $this->connection = $this->DbConfig->getConfig();
134: }
135:
136: $controllerName = $this->getName();
137: $this->hr();
138: $this->out(__d('cake_console', 'Baking %sController', $controllerName));
139: $this->hr();
140:
141: $helpers = $components = array();
142: $actions = '';
143: $wannaUseSession = 'y';
144: $wannaBakeAdminCrud = 'n';
145: $useDynamicScaffold = 'n';
146: $wannaBakeCrud = 'y';
147:
148:
149: $question[] = __d('cake_console', "Would you like to build your controller interactively?");
150: if (file_exists($this->path . $controllerName .'Controller.php')) {
151: $question[] = __d('cake_console', "Warning: Choosing no will overwrite the %sController.", $controllerName);
152: }
153: $doItInteractive = $this->in(implode("\n", $question), array('y','n'), 'y');
154:
155: if (strtolower($doItInteractive) == 'y') {
156: $this->interactive = true;
157: $useDynamicScaffold = $this->in(
158: __d('cake_console', "Would you like to use dynamic scaffolding?"), array('y','n'), 'n'
159: );
160:
161: if (strtolower($useDynamicScaffold) == 'y') {
162: $wannaBakeCrud = 'n';
163: $actions = 'scaffold';
164: } else {
165: list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
166:
167: $helpers = $this->doHelpers();
168: $components = $this->doComponents();
169:
170: $wannaUseSession = $this->in(
171: __d('cake_console', "Would you like to use Session flash messages?"), array('y','n'), 'y'
172: );
173: }
174: } else {
175: list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
176: }
177:
178: if (strtolower($wannaBakeCrud) == 'y') {
179: $actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) == 'y');
180: }
181: if (strtolower($wannaBakeAdminCrud) == 'y') {
182: $admin = $this->Project->getPrefix();
183: $actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) == 'y');
184: }
185:
186: $baked = false;
187: if ($this->interactive === true) {
188: $this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components);
189: $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y','n'), 'y');
190:
191: if (strtolower($looksGood) == 'y') {
192: $baked = $this->bake($controllerName, $actions, $helpers, $components);
193: if ($baked && $this->_checkUnitTest()) {
194: $this->bakeTest($controllerName);
195: }
196: }
197: } else {
198: $baked = $this->bake($controllerName, $actions, $helpers, $components);
199: if ($baked && $this->_checkUnitTest()) {
200: $this->bakeTest($controllerName);
201: }
202: }
203: return $baked;
204: }
205:
206: 207: 208: 209: 210: 211: 212: 213: 214:
215: public function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) {
216: $this->out();
217: $this->hr();
218: $this->out(__d('cake_console', 'The following controller will be created:'));
219: $this->hr();
220: $this->out(__d('cake_console', "Controller Name:\n\t%s", $controllerName));
221:
222: if (strtolower($useDynamicScaffold) == 'y') {
223: $this->out("public \$scaffold;");
224: }
225:
226: $properties = array(
227: 'helpers' => __d('cake_console', 'Helpers:'),
228: 'components' => __d('cake_console', 'Components:'),
229: );
230:
231: foreach ($properties as $var => $title) {
232: if (count($$var)) {
233: $output = '';
234: $length = count($$var);
235: foreach ($$var as $i => $propElement) {
236: if ($i != $length -1) {
237: $output .= ucfirst($propElement) . ', ';
238: } else {
239: $output .= ucfirst($propElement);
240: }
241: }
242: $this->out($title . "\n\t" . $output);
243: }
244: }
245: $this->hr();
246: }
247:
248: 249: 250: 251: 252:
253: protected function _askAboutMethods() {
254: $wannaBakeCrud = $this->in(
255: __d('cake_console', "Would you like to create some basic class methods \n(index(), add(), view(), edit())?"),
256: array('y','n'), 'n'
257: );
258: $wannaBakeAdminCrud = $this->in(
259: __d('cake_console', "Would you like to create the basic class methods for admin routing?"),
260: array('y','n'), 'n'
261: );
262: return array($wannaBakeCrud, $wannaBakeAdminCrud);
263: }
264:
265: 266: 267: 268: 269: 270: 271: 272:
273: public function bakeActions($controllerName, $admin = null, $wannaUseSession = true) {
274: $currentModelName = $modelImport = $this->_modelName($controllerName);
275: $plugin = $this->plugin;
276: if ($plugin) {
277: $plugin .= '.';
278: }
279: App::uses($modelImport, $plugin . 'Model');
280: if (!class_exists($modelImport)) {
281: $this->err(__d('cake_console', 'You must have a model for this class to build basic methods. Please try again.'));
282: $this->_stop();
283: }
284:
285: $modelObj = ClassRegistry::init($currentModelName);
286: $controllerPath = $this->_controllerPath($controllerName);
287: $pluralName = $this->_pluralName($currentModelName);
288: $singularName = Inflector::variable($currentModelName);
289: $singularHumanName = $this->_singularHumanName($controllerName);
290: $pluralHumanName = $this->_pluralName($controllerName);
291: $displayField = $modelObj->displayField;
292: $primaryKey = $modelObj->primaryKey;
293:
294: $this->Template->set(compact(
295: 'plugin', 'admin', 'controllerPath', 'pluralName', 'singularName',
296: 'singularHumanName', 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName',
297: 'displayField', 'primaryKey'
298: ));
299: $actions = $this->Template->generate('actions', 'controller_actions');
300: return $actions;
301: }
302:
303: 304: 305: 306: 307: 308: 309: 310: 311:
312: public function bake($controllerName, $actions = '', $helpers = null, $components = null) {
313: $this->out("\n" . __d('cake_console', 'Baking controller class for %s...', $controllerName), 1, Shell::QUIET);
314:
315: $isScaffold = ($actions === 'scaffold') ? true : false;
316:
317: $this->Template->set(array(
318: 'plugin' => $this->plugin,
319: 'pluginPath' => empty($this->plugin) ? '' : $this->plugin . '.'
320: ));
321: $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'isScaffold'));
322: $contents = $this->Template->generate('classes', 'controller');
323:
324: $path = $this->getPath();
325: $filename = $path . $controllerName . 'Controller.php';
326: if ($this->createFile($filename, $contents)) {
327: return $contents;
328: }
329: return false;
330: }
331:
332: 333: 334: 335: 336: 337:
338: public function bakeTest($className) {
339: $this->Test->plugin = $this->plugin;
340: $this->Test->connection = $this->connection;
341: $this->Test->interactive = $this->interactive;
342: return $this->Test->bake('Controller', $className);
343: }
344:
345: 346: 347: 348: 349:
350: public function doHelpers() {
351: return $this->_doPropertyChoices(
352: __d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"),
353: __d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'")
354: );
355: }
356:
357: 358: 359: 360: 361:
362: public function doComponents() {
363: return $this->_doPropertyChoices(
364: __d('cake_console', "Would you like this controller to use any components?"),
365: __d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
366: );
367: }
368:
369: 370: 371: 372: 373: 374: 375:
376: protected function _doPropertyChoices($prompt, $example) {
377: $proceed = $this->in($prompt, array('y','n'), 'n');
378: $property = array();
379: if (strtolower($proceed) == 'y') {
380: $propertyList = $this->in($example);
381: $propertyListTrimmed = str_replace(' ', '', $propertyList);
382: $property = explode(',', $propertyListTrimmed);
383: }
384: return array_filter($property);
385: }
386:
387: 388: 389: 390: 391: 392:
393: public function listAll($useDbConfig = null) {
394: if (is_null($useDbConfig)) {
395: $useDbConfig = $this->connection;
396: }
397: $this->__tables = $this->Model->getAllTables($useDbConfig);
398:
399: if ($this->interactive == true) {
400: $this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
401: $this->_controllerNames = array();
402: $count = count($this->__tables);
403: for ($i = 0; $i < $count; $i++) {
404: $this->_controllerNames[] = $this->_controllerName($this->_modelName($this->__tables[$i]));
405: $this->out($i + 1 . ". " . $this->_controllerNames[$i]);
406: }
407: return $this->_controllerNames;
408: }
409: return $this->__tables;
410: }
411:
412: 413: 414: 415: 416: 417:
418: public function getName($useDbConfig = null) {
419: $controllers = $this->listAll($useDbConfig);
420: $enteredController = '';
421:
422: while ($enteredController == '') {
423: $enteredController = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit"), null, 'q');
424: if ($enteredController === 'q') {
425: $this->out(__d('cake_console', 'Exit'));
426: return $this->_stop();
427: }
428:
429: if ($enteredController == '' || intval($enteredController) > count($controllers)) {
430: $this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
431: $enteredController = '';
432: }
433: }
434:
435: if (intval($enteredController) > 0 && intval($enteredController) <= count($controllers) ) {
436: $controllerName = $controllers[intval($enteredController) - 1];
437: } else {
438: $controllerName = Inflector::camelize($enteredController);
439: }
440: return $controllerName;
441: }
442:
443: 444: 445: 446: 447:
448: public function getOptionParser() {
449: $parser = parent::getOptionParser();
450: return $parser->description(
451: __d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.')
452: )->addArgument('name', array(
453: 'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.')
454: ))->addOption('public', array(
455: 'help' => __d('cake_console', 'Bake a controller with basic crud actions (index, view, add, edit, delete).'),
456: 'boolean' => true
457: ))->addOption('admin', array(
458: 'help' => __d('cake_console', 'Bake a controller with crud actions for one of the Routing.prefixes.'),
459: 'boolean' => true
460: ))->addOption('plugin', array(
461: 'short' => 'p',
462: 'help' => __d('cake_console', 'Plugin to bake the controller into.')
463: ))->addOption('connection', array(
464: 'short' => 'c',
465: 'help' => __d('cake_console', 'The connection the controller\'s model is on.')
466: ))->addSubcommand('all', array(
467: 'help' => __d('cake_console', 'Bake all controllers with CRUD methods.')
468: ))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
469: }
470:
471: 472: 473: 474: 475:
476: public function help() {
477: $this->hr();
478: $this->out("Usage: cake bake controller <arg1> <arg2>...");
479: $this->hr();
480: $this->out('Arguments:');
481: $this->out();
482: $this->out("<name>");
483: $this->out("\tName of the controller to bake. Can use Plugin.name");
484: $this->out("\tas a shortcut for plugin baking.");
485: $this->out();
486: $this->out('Params:');
487: $this->out();
488: $this->out('-connection <config>');
489: $this->out("\tset db config <config>. uses 'default' if none is specified");
490: $this->out();
491: $this->out('Commands:');
492: $this->out();
493: $this->out("controller <name>");
494: $this->out("\tbakes controller with var \$scaffold");
495: $this->out();
496: $this->out("controller <name> public");
497: $this->out("\tbakes controller with basic crud actions");
498: $this->out("\t(index, view, add, edit, delete)");
499: $this->out();
500: $this->out("controller <name> admin");
501: $this->out("\tbakes a controller with basic crud actions for one of the");
502: $this->out("\tConfigure::read('Routing.prefixes') methods.");
503: $this->out();
504: $this->out("controller <name> public admin");
505: $this->out("\tbakes a controller with basic crud actions for one");
506: $this->out("\tConfigure::read('Routing.prefixes') and non admin methods.");
507: $this->out("\t(index, view, add, edit, delete,");
508: $this->out("\tadmin_index, admin_view, admin_edit, admin_add, admin_delete)");
509: $this->out();
510: $this->out("controller all");
511: $this->out("\tbakes all controllers with CRUD methods.");
512: $this->out();
513: $this->_stop();
514: }
515: }
516: