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: $question[] = __d('cake_console', "Would you like to build your controller interactively?");
149: if (file_exists($this->path . $controllerName . 'Controller.php')) {
150: $question[] = __d('cake_console', "Warning: Choosing no will overwrite the %sController.", $controllerName);
151: }
152: $doItInteractive = $this->in(implode("\n", $question), array('y', 'n'), 'y');
153:
154: if (strtolower($doItInteractive) == 'y') {
155: $this->interactive = true;
156: $useDynamicScaffold = $this->in(
157: __d('cake_console', "Would you like to use dynamic scaffolding?"), array('y', 'n'), 'n'
158: );
159:
160: if (strtolower($useDynamicScaffold) == 'y') {
161: $wannaBakeCrud = 'n';
162: $actions = 'scaffold';
163: } else {
164: list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
165:
166: $helpers = $this->doHelpers();
167: $components = $this->doComponents();
168:
169: $wannaUseSession = $this->in(
170: __d('cake_console', "Would you like to use Session flash messages?"), array('y','n'), 'y'
171: );
172: }
173: } else {
174: list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
175: }
176:
177: if (strtolower($wannaBakeCrud) == 'y') {
178: $actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) == 'y');
179: }
180: if (strtolower($wannaBakeAdminCrud) == 'y') {
181: $admin = $this->Project->getPrefix();
182: $actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) == 'y');
183: }
184:
185: $baked = false;
186: if ($this->interactive === true) {
187: $this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components);
188: $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y','n'), 'y');
189:
190: if (strtolower($looksGood) == 'y') {
191: $baked = $this->bake($controllerName, $actions, $helpers, $components);
192: if ($baked && $this->_checkUnitTest()) {
193: $this->bakeTest($controllerName);
194: }
195: }
196: } else {
197: $baked = $this->bake($controllerName, $actions, $helpers, $components);
198: if ($baked && $this->_checkUnitTest()) {
199: $this->bakeTest($controllerName);
200: }
201: }
202: return $baked;
203: }
204:
205: 206: 207: 208: 209: 210: 211: 212: 213:
214: public function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) {
215: $this->out();
216: $this->hr();
217: $this->out(__d('cake_console', 'The following controller will be created:'));
218: $this->hr();
219: $this->out(__d('cake_console', "Controller Name:\n\t%s", $controllerName));
220:
221: if (strtolower($useDynamicScaffold) == 'y') {
222: $this->out("public \$scaffold;");
223: }
224:
225: $properties = array(
226: 'helpers' => __d('cake_console', 'Helpers:'),
227: 'components' => __d('cake_console', 'Components:'),
228: );
229:
230: foreach ($properties as $var => $title) {
231: if (count($$var)) {
232: $output = '';
233: $length = count($$var);
234: foreach ($$var as $i => $propElement) {
235: if ($i != $length - 1) {
236: $output .= ucfirst($propElement) . ', ';
237: } else {
238: $output .= ucfirst($propElement);
239: }
240: }
241: $this->out($title . "\n\t" . $output);
242: }
243: }
244: $this->hr();
245: }
246:
247: 248: 249: 250: 251:
252: protected function _askAboutMethods() {
253: $wannaBakeCrud = $this->in(
254: __d('cake_console', "Would you like to create some basic class methods \n(index(), add(), view(), edit())?"),
255: array('y','n'), 'n'
256: );
257: $wannaBakeAdminCrud = $this->in(
258: __d('cake_console', "Would you like to create the basic class methods for admin routing?"),
259: array('y','n'), 'n'
260: );
261: return array($wannaBakeCrud, $wannaBakeAdminCrud);
262: }
263:
264: 265: 266: 267: 268: 269: 270: 271:
272: public function bakeActions($controllerName, $admin = null, $wannaUseSession = true) {
273: $currentModelName = $modelImport = $this->_modelName($controllerName);
274: $plugin = $this->plugin;
275: if ($plugin) {
276: $plugin .= '.';
277: }
278: App::uses($modelImport, $plugin . 'Model');
279: if (!class_exists($modelImport)) {
280: $this->err(__d('cake_console', 'You must have a model for this class to build basic methods. Please try again.'));
281: $this->_stop();
282: }
283:
284: $modelObj = ClassRegistry::init($currentModelName);
285: $controllerPath = $this->_controllerPath($controllerName);
286: $pluralName = $this->_pluralName($currentModelName);
287: $singularName = Inflector::variable($currentModelName);
288: $singularHumanName = $this->_singularHumanName($controllerName);
289: $pluralHumanName = $this->_pluralName($controllerName);
290: $displayField = $modelObj->displayField;
291: $primaryKey = $modelObj->primaryKey;
292:
293: $this->Template->set(compact(
294: 'plugin', 'admin', 'controllerPath', 'pluralName', 'singularName',
295: 'singularHumanName', 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName',
296: 'displayField', 'primaryKey'
297: ));
298: $actions = $this->Template->generate('actions', 'controller_actions');
299: return $actions;
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310:
311: public function bake($controllerName, $actions = '', $helpers = null, $components = null) {
312: $this->out("\n" . __d('cake_console', 'Baking controller class for %s...', $controllerName), 1, Shell::QUIET);
313:
314: $isScaffold = ($actions === 'scaffold') ? true : false;
315:
316: $this->Template->set(array(
317: 'plugin' => $this->plugin,
318: 'pluginPath' => empty($this->plugin) ? '' : $this->plugin . '.'
319: ));
320: $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'isScaffold'));
321: $contents = $this->Template->generate('classes', 'controller');
322:
323: $path = $this->getPath();
324: $filename = $path . $controllerName . 'Controller.php';
325: if ($this->createFile($filename, $contents)) {
326: return $contents;
327: }
328: return false;
329: }
330:
331: 332: 333: 334: 335: 336:
337: public function bakeTest($className) {
338: $this->Test->plugin = $this->plugin;
339: $this->Test->connection = $this->connection;
340: $this->Test->interactive = $this->interactive;
341: return $this->Test->bake('Controller', $className);
342: }
343:
344: 345: 346: 347: 348:
349: public function doHelpers() {
350: return $this->_doPropertyChoices(
351: __d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"),
352: __d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'")
353: );
354: }
355:
356: 357: 358: 359: 360:
361: public function doComponents() {
362: return $this->_doPropertyChoices(
363: __d('cake_console', "Would you like this controller to use any components?"),
364: __d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
365: );
366: }
367:
368: 369: 370: 371: 372: 373: 374:
375: protected function _doPropertyChoices($prompt, $example) {
376: $proceed = $this->in($prompt, array('y','n'), 'n');
377: $property = array();
378: if (strtolower($proceed) == 'y') {
379: $propertyList = $this->in($example);
380: $propertyListTrimmed = str_replace(' ', '', $propertyList);
381: $property = explode(',', $propertyListTrimmed);
382: }
383: return array_filter($property);
384: }
385:
386: 387: 388: 389: 390: 391:
392: public function listAll($useDbConfig = null) {
393: if (is_null($useDbConfig)) {
394: $useDbConfig = $this->connection;
395: }
396: $this->__tables = $this->Model->getAllTables($useDbConfig);
397:
398: if ($this->interactive == true) {
399: $this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
400: $this->_controllerNames = array();
401: $count = count($this->__tables);
402: for ($i = 0; $i < $count; $i++) {
403: $this->_controllerNames[] = $this->_controllerName($this->_modelName($this->__tables[$i]));
404: $this->out($i + 1 . ". " . $this->_controllerNames[$i]);
405: }
406: return $this->_controllerNames;
407: }
408: return $this->__tables;
409: }
410:
411: 412: 413: 414: 415: 416:
417: public function getName($useDbConfig = null) {
418: $controllers = $this->listAll($useDbConfig);
419: $enteredController = '';
420:
421: while ($enteredController == '') {
422: $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');
423: if ($enteredController === 'q') {
424: $this->out(__d('cake_console', 'Exit'));
425: return $this->_stop();
426: }
427:
428: if ($enteredController == '' || intval($enteredController) > count($controllers)) {
429: $this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
430: $enteredController = '';
431: }
432: }
433:
434: if (intval($enteredController) > 0 && intval($enteredController) <= count($controllers) ) {
435: $controllerName = $controllers[intval($enteredController) - 1];
436: } else {
437: $controllerName = Inflector::camelize($enteredController);
438: }
439: return $controllerName;
440: }
441:
442: 443: 444: 445: 446:
447: public function getOptionParser() {
448: $parser = parent::getOptionParser();
449: return $parser->description(
450: __d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.')
451: )->addArgument('name', array(
452: 'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.')
453: ))->addOption('public', array(
454: 'help' => __d('cake_console', 'Bake a controller with basic crud actions (index, view, add, edit, delete).'),
455: 'boolean' => true
456: ))->addOption('admin', array(
457: 'help' => __d('cake_console', 'Bake a controller with crud actions for one of the Routing.prefixes.'),
458: 'boolean' => true
459: ))->addOption('plugin', array(
460: 'short' => 'p',
461: 'help' => __d('cake_console', 'Plugin to bake the controller into.')
462: ))->addOption('connection', array(
463: 'short' => 'c',
464: 'help' => __d('cake_console', 'The connection the controller\'s model is on.')
465: ))->addSubcommand('all', array(
466: 'help' => __d('cake_console', 'Bake all controllers with CRUD methods.')
467: ))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
468: }
469:
470: }
471: