1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26: 27: 28: 29: 30: 31:
32: class ControllerTask extends Shell {
33: 34: 35: 36: 37: 38:
39: var $plugin = null;
40: 41: 42: 43: 44: 45:
46: var $tasks = array('Project');
47: 48: 49: 50: 51: 52:
53: var $path = CONTROLLERS;
54: 55: 56: 57: 58:
59: function initialize() {
60: }
61: 62: 63: 64: 65:
66: function execute() {
67: if (empty($this->args)) {
68: $this->__interactive();
69: }
70:
71: if (isset($this->args[0])) {
72: $controller = Inflector::camelize($this->args[0]);
73: $actions = null;
74: if (isset($this->args[1]) && $this->args[1] == 'scaffold') {
75: $this->out('Baking scaffold for ' . $controller);
76: $actions = $this->bakeActions($controller);
77: } else {
78: $actions = 'scaffold';
79: }
80: if ((isset($this->args[1]) && $this->args[1] == 'admin') || (isset($this->args[2]) && $this->args[2] == 'admin')) {
81: if ($admin = $this->getAdmin()) {
82: $this->out('Adding ' . Configure::read('Routing.admin') .' methods');
83: if ($actions == 'scaffold') {
84: $actions = $this->bakeActions($controller, $admin);
85: } else {
86: $actions .= $this->bakeActions($controller, $admin);
87: }
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: function __interactive($controllerName = false) {
103: if (!$controllerName) {
104: $this->interactive = true;
105: $this->hr();
106: $this->out(sprintf("Bake Controller\nPath: %s", $this->path));
107: $this->hr();
108: $actions = '';
109: $uses = array();
110: $helpers = array();
111: $components = array();
112: $wannaUseSession = 'y';
113: $wannaDoAdmin = 'n';
114: $wannaUseScaffold = 'n';
115: $wannaDoScaffolding = 'y';
116: $controllerName = $this->getName();
117: }
118: $this->hr();
119: $this->out("Baking {$controllerName}Controller");
120: $this->hr();
121:
122: $controllerFile = strtolower(Inflector::underscore($controllerName));
123:
124: $question[] = __("Would you like to build your controller interactively?", true);
125: if (file_exists($this->path . $controllerFile .'_controller.php')) {
126: $question[] = sprintf(__("Warning: Choosing no will overwrite the %sController.", true), $controllerName);
127: }
128: $doItInteractive = $this->in(implode("\n", $question), array('y','n'), 'y');
129:
130: if (strtolower($doItInteractive) == 'y' || strtolower($doItInteractive) == 'yes') {
131: $this->interactive = true;
132:
133: $wannaUseScaffold = $this->in(__("Would you like to use scaffolding?", true), array('y','n'), 'n');
134:
135: if (strtolower($wannaUseScaffold) == 'n' || strtolower($wannaUseScaffold) == 'no') {
136:
137: $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'n');
138:
139: if (strtolower($wannaDoScaffolding) == 'y' || strtolower($wannaDoScaffolding) == 'yes') {
140: $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'n');
141: }
142:
143: $wannaDoHelpers = $this->in(__("Would you like this controller to use other helpers besides HtmlHelper and FormHelper?", true), array('y','n'), 'n');
144:
145: if (strtolower($wannaDoHelpers) == 'y' || strtolower($wannaDoHelpers) == 'yes') {
146: $helpersList = $this->in(__("Please provide a comma separated list of the other helper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true));
147: $helpersListTrimmed = str_replace(' ', '', $helpersList);
148: $helpers = explode(',', $helpersListTrimmed);
149: }
150: $wannaDoComponents = $this->in(__("Would you like this controller to use any components?", true), array('y','n'), 'n');
151:
152: if (strtolower($wannaDoComponents) == 'y' || strtolower($wannaDoComponents) == 'yes') {
153: $componentsList = $this->in(__("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true));
154: $componentsListTrimmed = str_replace(' ', '', $componentsList);
155: $components = explode(',', $componentsListTrimmed);
156: }
157:
158: $wannaUseSession = $this->in(__("Would you like to use Sessions?", true), array('y','n'), 'y');
159: } else {
160: $wannaDoScaffolding = 'n';
161: }
162: } else {
163: $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'y');
164:
165: if (strtolower($wannaDoScaffolding) == 'y' || strtolower($wannaDoScaffolding) == 'yes') {
166: $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'y');
167: }
168: }
169: $admin = false;
170:
171: if ((strtolower($wannaDoAdmin) == 'y' || strtolower($wannaDoAdmin) == 'yes')) {
172: $admin = $this->getAdmin();
173: }
174:
175: if (strtolower($wannaDoScaffolding) == 'y' || strtolower($wannaDoScaffolding) == 'yes') {
176: $actions = $this->bakeActions($controllerName, null, in_array(strtolower($wannaUseSession), array('y', 'yes')));
177: if ($admin) {
178: $actions .= $this->bakeActions($controllerName, $admin, in_array(strtolower($wannaUseSession), array('y', 'yes')));
179: }
180: }
181:
182: if ($this->interactive === true) {
183: $this->out('');
184: $this->hr();
185: $this->out('The following controller will be created:');
186: $this->hr();
187: $this->out("Controller Name: $controllerName");
188:
189: if (strtolower($wannaUseScaffold) == 'y' || strtolower($wannaUseScaffold) == 'yes') {
190: $this->out(" var \$scaffold;");
191: $actions = 'scaffold';
192: }
193:
194: if (count($helpers)) {
195: $this->out("Helpers: ", false);
196:
197: foreach ($helpers as $help) {
198: if ($help != $helpers[count($helpers) - 1]) {
199: $this->out(ucfirst($help) . ", ", false);
200: } else {
201: $this->out(ucfirst($help));
202: }
203: }
204: }
205:
206: if (count($components)) {
207: $this->out("Components: ", false);
208:
209: foreach ($components as $comp) {
210: if ($comp != $components[count($components) - 1]) {
211: $this->out(ucfirst($comp) . ", ", false);
212: } else {
213: $this->out(ucfirst($comp));
214: }
215: }
216: }
217: $this->hr();
218: $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y');
219:
220: if (strtolower($looksGood) == 'y' || strtolower($looksGood) == 'yes') {
221: $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses);
222: if ($baked && $this->_checkUnitTest()) {
223: $this->bakeTest($controllerName);
224: }
225: } else {
226: $this->__interactive($controllerName);
227: }
228: } else {
229: $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses);
230: if ($baked && $this->_checkUnitTest()) {
231: $this->bakeTest($controllerName);
232: }
233: }
234: }
235: 236: 237: 238: 239: 240: 241: 242: 243:
244: function bakeActions($controllerName, $admin = null, $wannaUseSession = true) {
245: $currentModelName = $modelImport = $this->_modelName($controllerName);
246: if ($this->plugin) {
247: $modelImport = $this->plugin . '.' . $modelImport;
248: }
249: if (!App::import('Model', $modelImport)) {
250: $this->err(__('You must have a model for this class to build scaffold methods. Please try again.', true));
251: exit;
252: }
253: $actions = null;
254: $modelObj =& ClassRegistry::init($currentModelName);
255: $controllerPath = $this->_controllerPath($controllerName);
256: $pluralName = $this->_pluralName($currentModelName);
257: $singularName = Inflector::variable($currentModelName);
258: $singularHumanName = Inflector::humanize($currentModelName);
259: $pluralHumanName = Inflector::humanize($controllerName);
260: $actions .= "\n";
261: $actions .= "\tfunction {$admin}index() {\n";
262: $actions .= "\t\t\$this->{$currentModelName}->recursive = 0;\n";
263: $actions .= "\t\t\$this->set('{$pluralName}', \$this->paginate());\n";
264: $actions .= "\t}\n";
265: $actions .= "\n";
266: $actions .= "\tfunction {$admin}view(\$id = null) {\n";
267: $actions .= "\t\tif (!\$id) {\n";
268: if ($wannaUseSession) {
269: $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid {$singularHumanName}', true));\n";
270: $actions .= "\t\t\t\$this->redirect(array('action' => 'index'));\n";
271: } else {
272: $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action' => 'index'));\n";
273: }
274: $actions .= "\t\t}\n";
275: $actions .= "\t\t\$this->set('" . $singularName . "', \$this->{$currentModelName}->read(null, \$id));\n";
276: $actions .= "\t}\n";
277: $actions .= "\n";
278:
279:
280: $compact = array();
281: $actions .= "\tfunction {$admin}add() {\n";
282: $actions .= "\t\tif (!empty(\$this->data)) {\n";
283: $actions .= "\t\t\t\$this->{$currentModelName}->create();\n";
284: $actions .= "\t\t\tif (\$this->{$currentModelName}->save(\$this->data)) {\n";
285: if ($wannaUseSession) {
286: $actions .= "\t\t\t\t\$this->Session->setFlash(__('The " . $singularHumanName . " has been saved', true));\n";
287: $actions .= "\t\t\t\t\$this->redirect(array('action' => 'index'));\n";
288: } else {
289: $actions .= "\t\t\t\t\$this->flash(__('{$currentModelName} saved.', true), array('action' => 'index'));\n";
290: }
291: $actions .= "\t\t\t} else {\n";
292: if ($wannaUseSession) {
293: $actions .= "\t\t\t\t\$this->Session->setFlash(__('The {$singularHumanName} could not be saved. Please, try again.', true));\n";
294: }
295: $actions .= "\t\t\t}\n";
296: $actions .= "\t\t}\n";
297: foreach ($modelObj->hasAndBelongsToMany as $associationName => $relation) {
298: if (!empty($associationName)) {
299: $habtmModelName = $this->_modelName($associationName);
300: $habtmSingularName = $this->_singularName($associationName);
301: $habtmPluralName = $this->_pluralName($associationName);
302: $actions .= "\t\t\${$habtmPluralName} = \$this->{$currentModelName}->{$habtmModelName}->find('list');\n";
303: $compact[] = "'{$habtmPluralName}'";
304: }
305: }
306: foreach ($modelObj->belongsTo as $associationName => $relation) {
307: if (!empty($associationName)) {
308: $belongsToModelName = $this->_modelName($associationName);
309: $belongsToPluralName = $this->_pluralName($associationName);
310: $actions .= "\t\t\${$belongsToPluralName} = \$this->{$currentModelName}->{$belongsToModelName}->find('list');\n";
311: $compact[] = "'{$belongsToPluralName}'";
312: }
313: }
314: if (!empty($compact)) {
315: $actions .= "\t\t\$this->set(compact(" . implode(', ', $compact) . "));\n";
316: }
317: $actions .= "\t}\n";
318: $actions .= "\n";
319:
320:
321: $compact = array();
322: $actions .= "\tfunction {$admin}edit(\$id = null) {\n";
323: $actions .= "\t\tif (!\$id && empty(\$this->data)) {\n";
324: if ($wannaUseSession) {
325: $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid {$singularHumanName}', true));\n";
326: $actions .= "\t\t\t\$this->redirect(array('action' => 'index'));\n";
327: } else {
328: $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action' => 'index'));\n";
329: }
330: $actions .= "\t\t}\n";
331: $actions .= "\t\tif (!empty(\$this->data)) {\n";
332: $actions .= "\t\t\tif (\$this->{$currentModelName}->save(\$this->data)) {\n";
333: if ($wannaUseSession) {
334: $actions .= "\t\t\t\t\$this->Session->setFlash(__('The " . $singularHumanName . " has been saved', true));\n";
335: $actions .= "\t\t\t\t\$this->redirect(array('action' => 'index'));\n";
336: } else {
337: $actions .= "\t\t\t\t\$this->flash(__('The " . $singularHumanName . " has been saved.', true), array('action' => 'index'));\n";
338: }
339: $actions .= "\t\t\t} else {\n";
340: if ($wannaUseSession) {
341: $actions .= "\t\t\t\t\$this->Session->setFlash(__('The {$singularHumanName} could not be saved. Please, try again.', true));\n";
342: }
343: $actions .= "\t\t\t}\n";
344: $actions .= "\t\t}\n";
345: $actions .= "\t\tif (empty(\$this->data)) {\n";
346: $actions .= "\t\t\t\$this->data = \$this->{$currentModelName}->read(null, \$id);\n";
347: $actions .= "\t\t}\n";
348:
349: foreach ($modelObj->hasAndBelongsToMany as $associationName => $relation) {
350: if (!empty($associationName)) {
351: $habtmModelName = $this->_modelName($associationName);
352: $habtmSingularName = $this->_singularName($associationName);
353: $habtmPluralName = $this->_pluralName($associationName);
354: $actions .= "\t\t\${$habtmPluralName} = \$this->{$currentModelName}->{$habtmModelName}->find('list');\n";
355: $compact[] = "'{$habtmPluralName}'";
356: }
357: }
358: foreach ($modelObj->belongsTo as $associationName => $relation) {
359: if (!empty($associationName)) {
360: $belongsToModelName = $this->_modelName($associationName);
361: $belongsToPluralName = $this->_pluralName($associationName);
362: $actions .= "\t\t\${$belongsToPluralName} = \$this->{$currentModelName}->{$belongsToModelName}->find('list');\n";
363: $compact[] = "'{$belongsToPluralName}'";
364: }
365: }
366: if (!empty($compact)) {
367: $actions .= "\t\t\$this->set(compact(" . implode(',', $compact) . "));\n";
368: }
369: $actions .= "\t}\n";
370: $actions .= "\n";
371: $actions .= "\tfunction {$admin}delete(\$id = null) {\n";
372: $actions .= "\t\tif (!\$id) {\n";
373: if ($wannaUseSession) {
374: $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid id for {$singularHumanName}', true));\n";
375: $actions .= "\t\t\t\$this->redirect(array('action' => 'index'));\n";
376: } else {
377: $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action' => 'index'));\n";
378: }
379: $actions .= "\t\t}\n";
380: $actions .= "\t\tif (\$this->{$currentModelName}->del(\$id)) {\n";
381: if ($wannaUseSession) {
382: $actions .= "\t\t\t\$this->Session->setFlash(__('{$singularHumanName} deleted', true));\n";
383: $actions .= "\t\t\t\$this->redirect(array('action' => 'index'));\n";
384: } else {
385: $actions .= "\t\t\t\$this->flash(__('{$singularHumanName} deleted', true), array('action' => 'index'));\n";
386: }
387: $actions .= "\t\t}\n";
388: if ($wannaUseSession) {
389: $actions .= "\t\t\$this->Session->setFlash(__('The {$singularHumanName} could not be deleted. Please, try again.', true));\n";
390: $actions .= "\t\t\$this->redirect(array('action' => 'index'));\n";
391: } else {
392: $actions .= "\t\t\$this->flash(__('The {$singularHumanName} could not be deleted. Please, try again.', true), array('action' => 'index'));\n";
393: }
394: $actions .= "\t}\n";
395: $actions .= "\n";
396: return $actions;
397: }
398:
399:
400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410:
411: function bake($controllerName, $actions = '', $helpers = null, $components = null, $uses = null) {
412: $out = "<?php\n";
413: $out .= "class $controllerName" . "Controller extends {$this->plugin}AppController {\n\n";
414: $out .= "\tvar \$name = '$controllerName';\n";
415:
416: if (strtolower($actions) == 'scaffold') {
417: $out .= "\tvar \$scaffold;\n";
418: } else {
419: if (count($uses)) {
420: $out .= "\tvar \$uses = array('" . $this->_modelName($controllerName) . "', ";
421:
422: foreach ($uses as $use) {
423: if ($use != $uses[count($uses) - 1]) {
424: $out .= "'" . $this->_modelName($use) . "', ";
425: } else {
426: $out .= "'" . $this->_modelName($use) . "'";
427: }
428: }
429: $out .= ");\n";
430: }
431:
432: $out .= "\tvar \$helpers = array('Html', 'Form'";
433: if (count($helpers)) {
434: foreach ($helpers as $help) {
435: $out .= ", '" . Inflector::camelize($help) . "'";
436: }
437: }
438: $out .= ");\n";
439:
440: if (count($components)) {
441: $out .= "\tvar \$components = array(";
442:
443: foreach ($components as $comp) {
444: if ($comp != $components[count($components) - 1]) {
445: $out .= "'" . Inflector::camelize($comp) . "', ";
446: } else {
447: $out .= "'" . Inflector::camelize($comp) . "'";
448: }
449: }
450: $out .= ");\n";
451: }
452: $out .= $actions;
453: }
454: $out .= "}\n";
455: $out .= "?>";
456: $filename = $this->path . $this->_controllerPath($controllerName) . '_controller.php';
457: return $this->createFile($filename, $out);
458: }
459: 460: 461: 462: 463: 464: 465:
466: function bakeTest($className) {
467: $import = $className;
468: if ($this->plugin) {
469: $import = $this->plugin . '.' . $className;
470: }
471: $out = "App::import('Controller', '$import');\n\n";
472: $out .= "class Test{$className} extends {$className}Controller {\n";
473: $out .= "\tvar \$autoRender = false;\n}\n\n";
474: $out .= "class {$className}ControllerTest extends CakeTestCase {\n";
475: $out .= "\tvar \${$className} = null;\n\n";
476: $out .= "\tfunction startTest() {\n\t\t\$this->{$className} = new Test{$className}();";
477: $out .= "\n\t\t\$this->{$className}->constructClasses();\n\t}\n\n";
478: $out .= "\tfunction test{$className}ControllerInstance() {\n";
479: $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}Controller'));\n\t}\n\n";
480: $out .= "\tfunction endTest() {\n\t\tunset(\$this->{$className});\n\t}\n}\n";
481:
482: $path = CONTROLLER_TESTS;
483: if (isset($this->plugin)) {
484: $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS;
485: $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'controllers' . DS;
486: }
487:
488: $filename = Inflector::underscore($className).'_controller.test.php';
489: $this->out("\nBaking unit test for $className...");
490:
491: $header = '$Id';
492: $content = "<?php \n/* SVN FILE: $header$ */\n/* " . $className . "Controller Test cases generated on: " . date('Y-m-d H:i:s') . " : ". time() . "*/\n{$out}?>";
493: return $this->createFile($path . $filename, $content);
494: }
495: 496: 497: 498: 499: 500: 501:
502: function listAll($useDbConfig = 'default') {
503: $db =& ConnectionManager::getDataSource($useDbConfig);
504: $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix'];
505: if ($usePrefix) {
506: $tables = array();
507: foreach ($db->listSources() as $table) {
508: if (!strncmp($table, $usePrefix, strlen($usePrefix))) {
509: $tables[] = substr($table, strlen($usePrefix));
510: }
511: }
512: } else {
513: $tables = $db->listSources();
514: }
515:
516: if (empty($tables)) {
517: $this->err(__('Your database does not have any tables.', true));
518: $this->_stop();
519: }
520:
521: $this->__tables = $tables;
522: $this->out('Possible Controllers based on your current database:');
523: $this->_controllerNames = array();
524: $count = count($tables);
525: for ($i = 0; $i < $count; $i++) {
526: $this->_controllerNames[] = $this->_controllerName($this->_modelName($tables[$i]));
527: $this->out($i + 1 . ". " . $this->_controllerNames[$i]);
528: }
529: return $this->_controllerNames;
530: }
531:
532: 533: 534: 535: 536: 537:
538: function getName() {
539: $useDbConfig = 'default';
540: $controllers = $this->listAll($useDbConfig, 'Controllers');
541: $enteredController = '';
542:
543: while ($enteredController == '') {
544: $enteredController = $this->in(__("Enter a number from the list above, type in the name of another controller, or 'q' to exit", true), null, 'q');
545:
546: if ($enteredController === 'q') {
547: $this->out(__("Exit", true));
548: $this->_stop();
549: }
550:
551: if ($enteredController == '' || intval($enteredController) > count($controllers)) {
552: $this->out(__('Error:', true));
553: $this->out(__("The Controller name you supplied was empty, or the number \nyou selected was not an option. Please try again.", true));
554: $enteredController = '';
555: }
556: }
557:
558: if (intval($enteredController) > 0 && intval($enteredController) <= count($controllers) ) {
559: $controllerName = $controllers[intval($enteredController) - 1];
560: } else {
561: $controllerName = Inflector::camelize($enteredController);
562: }
563:
564: return $controllerName;
565: }
566: 567: 568: 569: 570:
571: function help() {
572: $this->hr();
573: $this->out("Usage: cake bake controller <arg1> <arg2>...");
574: $this->hr();
575: $this->out('Commands:');
576: $this->out("\n\tcontroller <name>\n\t\tbakes controller with var \$scaffold");
577: $this->out("\n\tcontroller <name> scaffold\n\t\tbakes controller with scaffold actions.\n\t\t(index, view, add, edit, delete)");
578: $this->out("\n\tcontroller <name> scaffold admin\n\t\tbakes a controller with scaffold actions for both public and Configure::read('Routing.admin')");
579: $this->out("\n\tcontroller <name> admin\n\t\tbakes a controller with scaffold actions only for Configure::read('Routing.admin')");
580: $this->out("");
581: $this->_stop();
582: }
583: }
584: ?>