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 Shell extends Object {
33: 34: 35: 36: 37: 38:
39: var $Dispatch = null;
40: 41: 42: 43: 44: 45:
46: var $interactive = true;
47: 48: 49: 50: 51: 52: 53:
54: var $DbConfig = null;
55: 56: 57: 58: 59: 60:
61: var $params = array();
62: 63: 64: 65: 66: 67:
68: var $args = array();
69: 70: 71: 72: 73: 74:
75: var $shell = null;
76: 77: 78: 79: 80: 81:
82: var $className = null;
83: 84: 85: 86: 87: 88:
89: var $command = null;
90: 91: 92: 93: 94: 95:
96: var $name = null;
97: 98: 99: 100: 101: 102:
103: var $alias = null;
104: 105: 106: 107: 108: 109:
110: var $tasks = array();
111: 112: 113: 114: 115: 116:
117: var $taskNames = array();
118: 119: 120: 121: 122: 123:
124: var $uses = array();
125: 126: 127: 128:
129: function __construct(&$dispatch) {
130: $vars = array('params', 'args', 'shell', 'shellCommand' => 'command');
131: foreach ($vars as $key => $var) {
132: if (is_string($key)) {
133: $this->{$var} =& $dispatch->{$key};
134: } else {
135: $this->{$var} =& $dispatch->{$var};
136: }
137: }
138:
139: if ($this->name == null) {
140: $this->name = get_class($this);
141: }
142:
143: if ($this->alias == null) {
144: $this->alias = $this->name;
145: }
146:
147: ClassRegistry::addObject($this->name, $this);
148: ClassRegistry::map($this->name, $this->alias);
149:
150: if (!PHP5 && isset($this->args[0])) {
151: if (strpos($this->name, strtolower(Inflector::camelize($this->args[0]))) !== false) {
152: $dispatch->shiftArgs();
153: }
154: if (strtolower($this->command) == strtolower(Inflector::variable($this->args[0])) && method_exists($this, $this->command)) {
155: $dispatch->shiftArgs();
156: }
157: }
158:
159: $this->Dispatch =& $dispatch;
160: }
161: 162: 163: 164: 165: 166: 167:
168: function initialize() {
169: $this->_loadModels();
170: }
171: 172: 173: 174: 175: 176: 177:
178: function startup() {
179: $this->_welcome();
180: }
181: 182: 183: 184: 185:
186: function _welcome() {
187: $this->out("\nWelcome to CakePHP v" . Configure::version() . " Console");
188: $this->out("---------------------------------------------------------------");
189: $this->out('App : '. $this->params['app']);
190: $this->out('Path: '. $this->params['working']);
191: $this->hr();
192: }
193: 194: 195: 196: 197: 198: 199:
200: function _loadDbConfig() {
201: if (config('database') && class_exists('DATABASE_CONFIG')) {
202: $this->DbConfig =& new DATABASE_CONFIG();
203: return true;
204: }
205: $this->err('Database config could not be loaded');
206: $this->out('Run \'bake\' to create the database configuration');
207: return false;
208: }
209: 210: 211: 212: 213: 214: 215: 216: 217:
218: function _loadModels() {
219: if ($this->uses === null || $this->uses === false) {
220: return;
221: }
222:
223: if ($this->uses === true && App::import('Model', 'AppModel')) {
224: $this->AppModel =& new AppModel(false, false, false);
225: return true;
226: }
227:
228: if ($this->uses !== true && !empty($this->uses)) {
229: $uses = is_array($this->uses) ? $this->uses : array($this->uses);
230:
231: $modelClassName = $uses[0];
232: if (strpos($uses[0], '.') !== false) {
233: list($plugin, $modelClassName) = explode('.', $uses[0]);
234: }
235: $this->modelClass = $modelClassName;
236:
237: foreach ($uses as $modelClass) {
238: $plugin = null;
239: if (strpos($modelClass, '.') !== false) {
240: list($plugin, $modelClass) = explode('.', $modelClass);
241: $plugin = $plugin . '.';
242: }
243: if (PHP5) {
244: $this->{$modelClass} = ClassRegistry::init($plugin . $modelClass);
245: } else {
246: $this->{$modelClass} =& ClassRegistry::init($plugin . $modelClass);
247: }
248: }
249: return true;
250: }
251: return false;
252: }
253: 254: 255: 256: 257: 258:
259: function loadTasks() {
260: if ($this->tasks === null || $this->tasks === false || $this->tasks === true || empty($this->tasks)) {
261: return true;
262: }
263:
264: $tasks = $this->tasks;
265: if (!is_array($tasks)) {
266: $tasks = array($tasks);
267: }
268:
269: foreach ($tasks as $taskName) {
270: $task = Inflector::underscore($taskName);
271: $taskClass = Inflector::camelize($taskName . 'Task');
272:
273: if (!class_exists($taskClass)) {
274: foreach ($this->Dispatch->shellPaths as $path) {
275: $taskPath = $path . 'tasks' . DS . $task.'.php';
276: if (file_exists($taskPath)) {
277: require_once $taskPath;
278: break;
279: }
280: }
281: }
282: if (ClassRegistry::isKeySet($taskClass)) {
283: $this->taskNames[] = $taskName;
284: if (!PHP5) {
285: $this->{$taskName} =& ClassRegistry::getObject($taskClass);
286: } else {
287: $this->{$taskName} = ClassRegistry::getObject($taskClass);
288: }
289: } else {
290: $this->taskNames[] = $taskName;
291: if (!PHP5) {
292: $this->{$taskName} =& new $taskClass($this->Dispatch);
293: } else {
294: $this->{$taskName} = new $taskClass($this->Dispatch);
295: }
296: }
297:
298: if (!isset($this->{$taskName})) {
299: $this->err("Task '" . $taskName . "' could not be loaded");
300: $this->_stop();
301: }
302: }
303:
304: return true;
305: }
306: 307: 308: 309: 310: 311: 312: 313: 314:
315: function in($prompt, $options = null, $default = null) {
316: if (!$this->interactive) {
317: return $default;
318: }
319: $in = $this->Dispatch->getInput($prompt, $options, $default);
320:
321: if ($options && is_string($options)) {
322: if (strpos($options, ',')) {
323: $options = explode(',', $options);
324: } elseif (strpos($options, '/')) {
325: $options = explode('/', $options);
326: } else {
327: $options = array($options);
328: }
329: }
330: if (is_array($options)) {
331: while ($in == '' || ($in && (!in_array(strtolower($in), $options) && !in_array(strtoupper($in), $options)) && !in_array($in, $options))) {
332: $in = $this->Dispatch->getInput($prompt, $options, $default);
333: }
334: }
335: if ($in) {
336: return $in;
337: }
338: }
339: 340: 341: 342: 343: 344: 345:
346: function out($string, $newline = true) {
347: if (is_array($string)) {
348: $string = implode("\n", $string) . "\n";
349: }
350: return $this->Dispatch->stdout($string, $newline);
351: }
352: 353: 354: 355: 356: 357:
358: function err($string) {
359: if (is_array($string)) {
360: $str = '';
361: foreach ($string as $message) {
362: $str .= $message ."\n";
363: }
364: $string = $str;
365: }
366: return $this->Dispatch->stderr($string."\n");
367: }
368: 369: 370: 371: 372: 373:
374: function hr($newline = false) {
375: if ($newline) {
376: $this->out("\n");
377: }
378: $this->out('---------------------------------------------------------------');
379: if ($newline) {
380: $this->out("\n");
381: }
382: }
383: 384: 385: 386: 387: 388: 389:
390: function error($title, $msg) {
391: $out = "$title\n";
392: $out .= "$msg\n";
393: $out .= "\n";
394: $this->err($out);
395: $this->_stop();
396: }
397: 398: 399: 400: 401: 402: 403:
404: function _checkArgs($expectedNum, $command = null) {
405: if (!$command) {
406: $command = $this->command;
407: }
408: if (count($this->args) < $expectedNum) {
409: $this->error("Wrong number of parameters: ".count($this->args), "Expected: {$expectedNum}\nPlease type 'cake {$this->shell} help' for help on usage of the {$this->name} {$command}");
410: }
411: }
412: 413: 414: 415: 416: 417: 418: 419:
420: function createFile ($path, $contents) {
421: $path = str_replace(DS . DS, DS, $path);
422: $this->out("\n" . sprintf(__("Creating file %s", true), $path));
423: if (is_file($path) && $this->interactive === true) {
424: $key = $this->in(__("File exists, overwrite?", true). " {$path}", array('y', 'n', 'q'), 'n');
425: if (strtolower($key) == 'q') {
426: $this->out(__("Quitting.", true) ."\n");
427: exit;
428: } elseif (strtolower($key) != 'y') {
429: $this->out(__("Skip", true) ." {$path}\n");
430: return false;
431: }
432: }
433: if (!class_exists('File')) {
434: uses('file');
435: }
436:
437: if ($File = new File($path, true)) {
438: $data = $File->prepare($contents);
439: $File->write($data);
440: $this->out(__("Wrote", true) ." {$path}");
441: return true;
442: } else {
443: $this->err(__("Error! Could not write to", true)." {$path}.\n");
444: return false;
445: }
446: }
447: 448: 449: 450: 451:
452: function help() {
453: if ($this->command != null) {
454: $this->err("Unknown {$this->name} command '$this->command'.\nFor usage, try 'cake {$this->shell} help'.\n\n");
455: } else {
456: $this->Dispatch->help();
457: }
458: }
459: 460: 461: 462: 463: 464:
465: function _checkUnitTest() {
466: if (App::import('vendor', 'simpletest' . DS . 'simpletest')) {
467: return true;
468: }
469: $unitTest = $this->in('SimpleTest is not installed. Do you want to bake unit test files anyway?', array('y','n'), 'y');
470: $result = strtolower($unitTest) == 'y' || strtolower($unitTest) == 'yes';
471:
472: if ($result) {
473: $this->out("\nYou can download SimpleTest from http://simpletest.org", true);
474: }
475: return $result;
476: }
477: 478: 479: 480: 481: 482: 483:
484: function shortPath($file) {
485: $shortPath = str_replace(ROOT, null, $file);
486: $shortPath = str_replace('..' . DS, '', $shortPath);
487: return str_replace(DS . DS, DS, $shortPath);
488: }
489: 490: 491: 492: 493: 494:
495: function getAdmin() {
496: $admin = '';
497: $cakeAdmin = null;
498: $adminRoute = Configure::read('Routing.admin');
499: if (!empty($adminRoute)) {
500: $cakeAdmin = $adminRoute . '_';
501: } else {
502: $this->out('You need to enable Configure::write(\'Routing.admin\',\'admin\') in /app/config/core.php to use admin routing.');
503: $this->out('What would you like the admin route to be?');
504: $this->out('Example: www.example.com/admin/controller');
505: while ($admin == '') {
506: $admin = $this->in("What would you like the admin route to be?", null, 'admin');
507: }
508: if ($this->Project->cakeAdmin($admin) !== true) {
509: $this->out('Unable to write to /app/config/core.php.');
510: $this->out('You need to enable Configure::write(\'Routing.admin\',\'admin\') in /app/config/core.php to use admin routing.');
511: $this->_stop();
512: } else {
513: $cakeAdmin = $admin . '_';
514: }
515: }
516: return $cakeAdmin;
517: }
518: 519: 520: 521: 522: 523: 524:
525: function _controllerPath($name) {
526: return strtolower(Inflector::underscore($name));
527: }
528: 529: 530: 531: 532: 533: 534:
535: function _controllerName($name) {
536: return Inflector::pluralize(Inflector::camelize($name));
537: }
538: 539: 540: 541: 542: 543: 544:
545: function _modelName($name) {
546: return Inflector::camelize(Inflector::singularize($name));
547: }
548: 549: 550: 551: 552: 553: 554:
555: function _modelKey($name) {
556: return Inflector::underscore(Inflector::singularize($name)).'_id';
557: }
558: 559: 560: 561: 562: 563: 564:
565: function _modelNameFromKey($key) {
566: $name = str_replace('_id', '',$key);
567: return Inflector::camelize($name);
568: }
569: 570: 571: 572: 573: 574: 575:
576: function _singularName($name) {
577: return Inflector::variable(Inflector::singularize($name));
578: }
579: 580: 581: 582: 583: 584: 585:
586: function _pluralName($name) {
587: return Inflector::variable(Inflector::pluralize($name));
588: }
589: 590: 591: 592: 593: 594: 595:
596: function _singularHumanName($name) {
597: return Inflector::humanize(Inflector::underscore(Inflector::singularize($name)));
598: }
599: 600: 601: 602: 603: 604: 605:
606: function _pluralHumanName($name) {
607: return Inflector::humanize(Inflector::underscore(Inflector::pluralize($name)));
608: }
609: }
610: ?>