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('ConnectionManager', 'Model');
22: App::uses('Model', 'Model');
23: App::uses('Validation', 'Utility');
24:
25: 26: 27: 28: 29:
30: class ModelTask extends BakeTask {
31:
32: 33: 34: 35: 36:
37: public $path = null;
38:
39: 40: 41: 42: 43:
44: public $tasks = array('DbConfig', 'Fixture', 'Test', 'Template');
45:
46: 47: 48: 49: 50:
51: public $skipTables = array('i18n');
52:
53: 54: 55: 56: 57:
58: protected $_tables = array();
59:
60: 61: 62: 63: 64:
65: protected $_modelNames = array();
66:
67: 68: 69: 70: 71:
72: protected $_validations = array();
73:
74: 75: 76: 77: 78:
79: public function initialize() {
80: $this->path = current(App::path('Model'));
81: }
82:
83: 84: 85: 86: 87:
88: public function execute() {
89: parent::execute();
90:
91: if (empty($this->args)) {
92: $this->_interactive();
93: }
94:
95: if (!empty($this->args[0])) {
96: $this->interactive = false;
97: if (!isset($this->connection)) {
98: $this->connection = 'default';
99: }
100: if (strtolower($this->args[0]) == 'all') {
101: return $this->all();
102: }
103: $model = $this->_modelName($this->args[0]);
104: $this->listAll($this->connection);
105: $useTable = $this->getTable($model);
106: $object = $this->_getModelObject($model, $useTable);
107: if ($this->bake($object, false)) {
108: if ($this->_checkUnitTest()) {
109: $this->bakeFixture($model, $useTable);
110: $this->bakeTest($model);
111: }
112: }
113: }
114: }
115:
116: 117: 118: 119: 120:
121: public function all() {
122: $this->listAll($this->connection, false);
123: $unitTestExists = $this->_checkUnitTest();
124: foreach ($this->_tables as $table) {
125: if (in_array($table, $this->skipTables)) {
126: continue;
127: }
128: $modelClass = Inflector::classify($table);
129: $this->out(__d('cake_console', 'Baking %s', $modelClass));
130: $object = $this->_getModelObject($modelClass, $table);
131: if ($this->bake($object, false) && $unitTestExists) {
132: $this->bakeFixture($modelClass, $table);
133: $this->bakeTest($modelClass);
134: }
135: }
136: }
137:
138: 139: 140: 141: 142: 143: 144:
145: protected function _getModelObject($className, $table = null) {
146: if (!$table) {
147: $table = Inflector::tableize($className);
148: }
149: $object = new Model(array('name' => $className, 'table' => $table, 'ds' => $this->connection));
150: $fields = $object->schema(true);
151: foreach ($fields as $name => $field) {
152: if (isset($field['key']) && $field['key'] == 'primary') {
153: $object->primaryKey = $name;
154: break;
155: }
156: }
157: return $object;
158: }
159:
160: 161: 162: 163: 164: 165: 166: 167:
168: public function inOptions($options, $prompt = null, $default = null) {
169: $valid = false;
170: $max = count($options);
171: while (!$valid) {
172: foreach ($options as $i => $option) {
173: $this->out($i + 1 .'. ' . $option);
174: }
175: if (empty($prompt)) {
176: $prompt = __d('cake_console', 'Make a selection from the choices above');
177: }
178: $choice = $this->in($prompt, null, $default);
179: if (intval($choice) > 0 && intval($choice) <= $max) {
180: $valid = true;
181: }
182: }
183: return $choice - 1;
184: }
185:
186: 187: 188: 189: 190:
191: protected function _interactive() {
192: $this->hr();
193: $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->getPath()));
194: $this->hr();
195: $this->interactive = true;
196:
197: $primaryKey = 'id';
198: $validate = $associations = array();
199:
200: if (empty($this->connection)) {
201: $this->connection = $this->DbConfig->getConfig();
202: }
203: $currentModelName = $this->getName();
204: $useTable = $this->getTable($currentModelName);
205: $db = ConnectionManager::getDataSource($this->connection);
206: $fullTableName = $db->fullTableName($useTable);
207:
208: if (in_array($useTable, $this->_tables)) {
209: $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection));
210: $fields = $tempModel->schema(true);
211: if (!array_key_exists('id', $fields)) {
212: $primaryKey = $this->findPrimaryKey($fields);
213: }
214: } else {
215: $this->err(__d('cake_console', 'Table %s does not exist, cannot bake a model without a table.', $useTable));
216: $this->_stop();
217: return false;
218: }
219: $displayField = $tempModel->hasField(array('name', 'title'));
220: if (!$displayField) {
221: $displayField = $this->findDisplayField($tempModel->schema());
222: }
223:
224: $prompt = __d('cake_console', "Would you like to supply validation criteria \nfor the fields in your model?");
225: $wannaDoValidation = $this->in($prompt, array('y', 'n'), 'y');
226: if (array_search($useTable, $this->_tables) !== false && strtolower($wannaDoValidation) == 'y') {
227: $validate = $this->doValidation($tempModel);
228: }
229:
230: $prompt = __d('cake_console', "Would you like to define model associations\n(hasMany, hasOne, belongsTo, etc.)?");
231: $wannaDoAssoc = $this->in($prompt, array('y', 'n'), 'y');
232: if (strtolower($wannaDoAssoc) == 'y') {
233: $associations = $this->doAssociations($tempModel);
234: }
235:
236: $this->out();
237: $this->hr();
238: $this->out(__d('cake_console', 'The following Model will be created:'));
239: $this->hr();
240: $this->out(__d('cake_console', "Name: %s", $currentModelName));
241:
242: if ($this->connection !== 'default') {
243: $this->out(__d('cake_console', "DB Config: %s", $this->connection));
244: }
245: if ($fullTableName !== Inflector::tableize($currentModelName)) {
246: $this->out(__d('cake_console', 'DB Table: %s', $fullTableName));
247: }
248: if ($primaryKey != 'id') {
249: $this->out(__d('cake_console', 'Primary Key: %s', $primaryKey));
250: }
251: if (!empty($validate)) {
252: $this->out(__d('cake_console', 'Validation: %s', print_r($validate, true)));
253: }
254: if (!empty($associations)) {
255: $this->out(__d('cake_console', 'Associations:'));
256: $assocKeys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
257: foreach ($assocKeys as $assocKey) {
258: $this->_printAssociation($currentModelName, $assocKey, $associations);
259: }
260: }
261:
262: $this->hr();
263: $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
264:
265: if (strtolower($looksGood) == 'y') {
266: $vars = compact('associations', 'validate', 'primaryKey', 'useTable', 'displayField');
267: $vars['useDbConfig'] = $this->connection;
268: if ($this->bake($currentModelName, $vars)) {
269: if ($this->_checkUnitTest()) {
270: $this->bakeFixture($currentModelName, $useTable);
271: $this->bakeTest($currentModelName, $useTable, $associations);
272: }
273: }
274: } else {
275: return false;
276: }
277: }
278:
279: 280: 281: 282: 283: 284: 285: 286:
287: protected function _printAssociation($modelName, $type, $associations) {
288: if (!empty($associations[$type])) {
289: for ($i = 0; $i < count($associations[$type]); $i++) {
290: $out = "\t" . $modelName . ' ' . $type . ' ' . $associations[$type][$i]['alias'];
291: $this->out($out);
292: }
293: }
294: }
295:
296: 297: 298: 299: 300: 301:
302: public function findPrimaryKey($fields) {
303: $name = 'id';
304: foreach ($fields as $name => $field) {
305: if (isset($field['key']) && $field['key'] == 'primary') {
306: break;
307: }
308: }
309: return $this->in(__d('cake_console', 'What is the primaryKey?'), null, $name);
310: }
311:
312: 313: 314: 315: 316: 317:
318: public function findDisplayField($fields) {
319: $fieldNames = array_keys($fields);
320: $prompt = __d('cake_console', "A displayField could not be automatically detected\nwould you like to choose one?");
321: $continue = $this->in($prompt, array('y', 'n'));
322: if (strtolower($continue) == 'n') {
323: return false;
324: }
325: $prompt = __d('cake_console', 'Choose a field from the options above:');
326: $choice = $this->inOptions($fieldNames, $prompt);
327: return $fieldNames[$choice];
328: }
329:
330: 331: 332: 333: 334: 335:
336: public function doValidation($model) {
337: if (!is_object($model)) {
338: return false;
339: }
340: $fields = $model->schema();
341:
342: if (empty($fields)) {
343: return false;
344: }
345: $validate = array();
346: $this->initValidations();
347: foreach ($fields as $fieldName => $field) {
348: $validation = $this->fieldValidation($fieldName, $field, $model->primaryKey);
349: if (!empty($validation)) {
350: $validate[$fieldName] = $validation;
351: }
352: }
353: return $validate;
354: }
355:
356: 357: 358: 359: 360:
361: public function initValidations() {
362: $options = $choices = array();
363: if (class_exists('Validation')) {
364: $options = get_class_methods('Validation');
365: }
366: sort($options);
367: $default = 1;
368: foreach ($options as $key => $option) {
369: if ($option{0} != '_') {
370: $choices[$default] = strtolower($option);
371: $default++;
372: }
373: }
374: $choices[$default] = 'none';
375: $this->_validations = $choices;
376: return $choices;
377: }
378:
379: 380: 381: 382: 383: 384: 385: 386:
387: public function fieldValidation($fieldName, $metaData, $primaryKey = 'id') {
388: $defaultChoice = count($this->_validations);
389: $validate = $alreadyChosen = array();
390:
391: $anotherValidator = 'y';
392: while ($anotherValidator == 'y') {
393: if ($this->interactive) {
394: $this->out();
395: $this->out(__d('cake_console', 'Field: %s', $fieldName));
396: $this->out(__d('cake_console', 'Type: %s', $metaData['type']));
397: $this->hr();
398: $this->out(__d('cake_console', 'Please select one of the following validation options:'));
399: $this->hr();
400: }
401:
402: $prompt = '';
403: for ($i = 1; $i < $defaultChoice; $i++) {
404: $prompt .= $i . ' - ' . $this->_validations[$i] . "\n";
405: }
406: $prompt .= __d('cake_console', "%s - Do not do any validation on this field.\n", $defaultChoice);
407: $prompt .= __d('cake_console', "... or enter in a valid regex validation string.\n");
408:
409: $methods = array_flip($this->_validations);
410: $guess = $defaultChoice;
411: if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) {
412: if ($fieldName == 'email') {
413: $guess = $methods['email'];
414: } elseif ($metaData['type'] == 'string' && $metaData['length'] == 36) {
415: $guess = $methods['uuid'];
416: } elseif ($metaData['type'] == 'string') {
417: $guess = $methods['notempty'];
418: } elseif ($metaData['type'] == 'integer') {
419: $guess = $methods['numeric'];
420: } elseif ($metaData['type'] == 'boolean') {
421: $guess = $methods['boolean'];
422: } elseif ($metaData['type'] == 'date') {
423: $guess = $methods['date'];
424: } elseif ($metaData['type'] == 'time') {
425: $guess = $methods['time'];
426: } elseif ($metaData['type'] == 'inet') {
427: $guess = $methods['ip'];
428: }
429: }
430:
431: if ($this->interactive === true) {
432: $choice = $this->in($prompt, null, $guess);
433: if (in_array($choice, $alreadyChosen)) {
434: $this->out(__d('cake_console', "You have already chosen that validation rule,\nplease choose again"));
435: continue;
436: }
437: if (!isset($this->_validations[$choice]) && is_numeric($choice)) {
438: $this->out(__d('cake_console', 'Please make a valid selection.'));
439: continue;
440: }
441: $alreadyChosen[] = $choice;
442: } else {
443: $choice = $guess;
444: }
445:
446: if (isset($this->_validations[$choice])) {
447: $validatorName = $this->_validations[$choice];
448: } else {
449: $validatorName = Inflector::slug($choice);
450: }
451:
452: if ($choice != $defaultChoice) {
453: if (is_numeric($choice) && isset($this->_validations[$choice])) {
454: $validate[$validatorName] = $this->_validations[$choice];
455: } else {
456: $validate[$validatorName] = $choice;
457: }
458: }
459: if ($this->interactive == true && $choice != $defaultChoice) {
460: $anotherValidator = $this->in(__d('cake_console', 'Would you like to add another validation rule?'), array('y', 'n'), 'n');
461: } else {
462: $anotherValidator = 'n';
463: }
464: }
465: return $validate;
466: }
467:
468: 469: 470: 471: 472: 473:
474: public function doAssociations($model) {
475: if (!is_object($model)) {
476: return false;
477: }
478: if ($this->interactive === true) {
479: $this->out(__d('cake_console', 'One moment while the associations are detected.'));
480: }
481:
482: $fields = $model->schema(true);
483: if (empty($fields)) {
484: return array();
485: }
486:
487: if (empty($this->_tables)) {
488: $this->_tables = $this->getAllTables();
489: }
490:
491: $associations = array(
492: 'belongsTo' => array(), 'hasMany' => array(), 'hasOne' => array(), 'hasAndBelongsToMany' => array()
493: );
494:
495: $associations = $this->findBelongsTo($model, $associations);
496: $associations = $this->findHasOneAndMany($model, $associations);
497: $associations = $this->findHasAndBelongsToMany($model, $associations);
498:
499: if ($this->interactive !== true) {
500: unset($associations['hasOne']);
501: }
502:
503: if ($this->interactive === true) {
504: $this->hr();
505: if (empty($associations)) {
506: $this->out(__d('cake_console', 'None found.'));
507: } else {
508: $this->out(__d('cake_console', 'Please confirm the following associations:'));
509: $this->hr();
510: $associations = $this->confirmAssociations($model, $associations);
511: }
512: $associations = $this->doMoreAssociations($model, $associations);
513: }
514: return $associations;
515: }
516:
517: 518: 519: 520: 521: 522: 523:
524: public function findBelongsTo($model, $associations) {
525: $fields = $model->schema(true);
526: foreach ($fields as $fieldName => $field) {
527: $offset = strpos($fieldName, '_id');
528: if ($fieldName != $model->primaryKey && $fieldName != 'parent_id' && $offset !== false) {
529: $tmpModelName = $this->_modelNameFromKey($fieldName);
530: $associations['belongsTo'][] = array(
531: 'alias' => $tmpModelName,
532: 'className' => $tmpModelName,
533: 'foreignKey' => $fieldName,
534: );
535: } elseif ($fieldName == 'parent_id') {
536: $associations['belongsTo'][] = array(
537: 'alias' => 'Parent' . $model->name,
538: 'className' => $model->name,
539: 'foreignKey' => $fieldName,
540: );
541: }
542: }
543: return $associations;
544: }
545:
546: 547: 548: 549: 550: 551: 552:
553: public function findHasOneAndMany($model, $associations) {
554: $foreignKey = $this->_modelKey($model->name);
555: foreach ($this->_tables as $otherTable) {
556: $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable), $otherTable);
557: $modelFieldsTemp = $tempOtherModel->schema(true);
558:
559: $pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/';
560: $possibleJoinTable = preg_match($pattern , $otherTable);
561: if ($possibleJoinTable == true) {
562: continue;
563: }
564: foreach ($modelFieldsTemp as $fieldName => $field) {
565: $assoc = false;
566: if ($fieldName != $model->primaryKey && $fieldName == $foreignKey) {
567: $assoc = array(
568: 'alias' => $tempOtherModel->name,
569: 'className' => $tempOtherModel->name,
570: 'foreignKey' => $fieldName
571: );
572: } elseif ($otherTable == $model->table && $fieldName == 'parent_id') {
573: $assoc = array(
574: 'alias' => 'Child' . $model->name,
575: 'className' => $model->name,
576: 'foreignKey' => $fieldName
577: );
578: }
579: if ($assoc) {
580: $associations['hasOne'][] = $assoc;
581: $associations['hasMany'][] = $assoc;
582: }
583:
584: }
585: }
586: return $associations;
587: }
588:
589: 590: 591: 592: 593: 594: 595:
596: public function findHasAndBelongsToMany($model, $associations) {
597: $foreignKey = $this->_modelKey($model->name);
598: foreach ($this->_tables as $otherTable) {
599: $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable), $otherTable);
600: $modelFieldsTemp = $tempOtherModel->schema(true);
601:
602: $offset = strpos($otherTable, $model->table . '_');
603: $otherOffset = strpos($otherTable, '_' . $model->table);
604:
605: if ($offset !== false) {
606: $offset = strlen($model->table . '_');
607: $habtmName = $this->_modelName(substr($otherTable, $offset));
608: $associations['hasAndBelongsToMany'][] = array(
609: 'alias' => $habtmName,
610: 'className' => $habtmName,
611: 'foreignKey' => $foreignKey,
612: 'associationForeignKey' => $this->_modelKey($habtmName),
613: 'joinTable' => $otherTable
614: );
615: } elseif ($otherOffset !== false) {
616: $habtmName = $this->_modelName(substr($otherTable, 0, $otherOffset));
617: $associations['hasAndBelongsToMany'][] = array(
618: 'alias' => $habtmName,
619: 'className' => $habtmName,
620: 'foreignKey' => $foreignKey,
621: 'associationForeignKey' => $this->_modelKey($habtmName),
622: 'joinTable' => $otherTable
623: );
624: }
625: }
626: return $associations;
627: }
628:
629: 630: 631: 632: 633: 634: 635:
636: public function confirmAssociations($model, $associations) {
637: foreach ($associations as $type => $settings) {
638: if (!empty($associations[$type])) {
639: foreach ($associations[$type] as $i => $assoc) {
640: $prompt = "{$model->name} {$type} {$assoc['alias']}?";
641: $response = $this->in($prompt, array('y', 'n'), 'y');
642:
643: if ('n' == strtolower($response)) {
644: unset($associations[$type][$i]);
645: } elseif ($type == 'hasMany') {
646: unset($associations['hasOne'][$i]);
647: }
648: }
649: $associations[$type] = array_merge($associations[$type]);
650: }
651: }
652: return $associations;
653: }
654:
655: 656: 657: 658: 659: 660: 661:
662: public function doMoreAssociations($model, $associations) {
663: $prompt = __d('cake_console', 'Would you like to define some additional model associations?');
664: $wannaDoMoreAssoc = $this->in($prompt, array('y', 'n'), 'n');
665: $possibleKeys = $this->_generatePossibleKeys();
666: while (strtolower($wannaDoMoreAssoc) == 'y') {
667: $assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
668: $this->out(__d('cake_console', 'What is the association type?'));
669: $assocType = intval($this->inOptions($assocs, __d('cake_console', 'Enter a number')));
670:
671: $this->out(__d('cake_console', "For the following options be very careful to match your setup exactly.\nAny spelling mistakes will cause errors."));
672: $this->hr();
673:
674: $alias = $this->in(__d('cake_console', 'What is the alias for this association?'));
675: $className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias );
676:
677: if ($assocType == 0) {
678: $showKeys = $possibleKeys[$model->table];
679: $suggestedForeignKey = $this->_modelKey($alias);
680: } else {
681: $otherTable = Inflector::tableize($className);
682: if (in_array($otherTable, $this->_tables)) {
683: if ($assocType < 3) {
684: $showKeys = $possibleKeys[$otherTable];
685: } else {
686: $showKeys = null;
687: }
688: } else {
689: $otherTable = $this->in(__d('cake_console', 'What is the table for this model?'));
690: $showKeys = $possibleKeys[$otherTable];
691: }
692: $suggestedForeignKey = $this->_modelKey($model->name);
693: }
694: if (!empty($showKeys)) {
695: $this->out(__d('cake_console', 'A helpful List of possible keys'));
696: $foreignKey = $this->inOptions($showKeys, __d('cake_console', 'What is the foreignKey?'));
697: $foreignKey = $showKeys[intval($foreignKey)];
698: }
699: if (!isset($foreignKey)) {
700: $foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey);
701: }
702: if ($assocType == 3) {
703: $associationForeignKey = $this->in(__d('cake_console', 'What is the associationForeignKey?'), null, $this->_modelKey($model->name));
704: $joinTable = $this->in(__d('cake_console', 'What is the joinTable?'));
705: }
706: $associations[$assocs[$assocType]] = array_values((array)$associations[$assocs[$assocType]]);
707: $count = count($associations[$assocs[$assocType]]);
708: $i = ($count > 0) ? $count : 0;
709: $associations[$assocs[$assocType]][$i]['alias'] = $alias;
710: $associations[$assocs[$assocType]][$i]['className'] = $className;
711: $associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey;
712: if ($assocType == 3) {
713: $associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey;
714: $associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable;
715: }
716: $wannaDoMoreAssoc = $this->in(__d('cake_console', 'Define another association?'), array('y', 'n'), 'y');
717: }
718: return $associations;
719: }
720:
721: 722: 723: 724: 725:
726: protected function _generatePossibleKeys() {
727: $possible = array();
728: foreach ($this->_tables as $otherTable) {
729: $tempOtherModel = new Model(array('table' => $otherTable, 'ds' => $this->connection));
730: $modelFieldsTemp = $tempOtherModel->schema(true);
731: foreach ($modelFieldsTemp as $fieldName => $field) {
732: if ($field['type'] == 'integer' || $field['type'] == 'string') {
733: $possible[$otherTable][] = $fieldName;
734: }
735: }
736: }
737: return $possible;
738: }
739:
740: 741: 742: 743: 744: 745: 746:
747: public function bake($name, $data = array()) {
748: if (is_object($name)) {
749: if ($data == false) {
750: $data = array();
751: $data['associations'] = $this->doAssociations($name);
752: $data['validate'] = $this->doValidation($name);
753: }
754: $data['primaryKey'] = $name->primaryKey;
755: $data['useTable'] = $name->table;
756: $data['useDbConfig'] = $name->useDbConfig;
757: $data['name'] = $name = $name->name;
758: } else {
759: $data['name'] = $name;
760: }
761: $defaults = array('associations' => array(), 'validate' => array(), 'primaryKey' => 'id',
762: 'useTable' => null, 'useDbConfig' => 'default', 'displayField' => null);
763: $data = array_merge($defaults, $data);
764:
765: $this->Template->set($data);
766: $this->Template->set(array(
767: 'plugin' => $this->plugin,
768: 'pluginPath' => empty($this->plugin) ? '' : $this->plugin . '.'
769: ));
770: $out = $this->Template->generate('classes', 'model');
771:
772: $path = $this->getPath();
773: $filename = $path . $name . '.php';
774: $this->out("\n" . __d('cake_console', 'Baking model class for %s...', $name), 1, Shell::QUIET);
775: $this->createFile($filename, $out);
776: ClassRegistry::flush();
777: return $out;
778: }
779:
780: 781: 782: 783: 784: 785:
786: public function bakeTest($className) {
787: $this->Test->interactive = $this->interactive;
788: $this->Test->plugin = $this->plugin;
789: $this->Test->connection = $this->connection;
790: return $this->Test->bake('Model', $className);
791: }
792:
793: 794: 795: 796: 797: 798:
799: public function listAll($useDbConfig = null) {
800: $this->_tables = $this->getAllTables($useDbConfig);
801:
802: $this->_modelNames = array();
803: $count = count($this->_tables);
804: for ($i = 0; $i < $count; $i++) {
805: $this->_modelNames[] = $this->_modelName($this->_tables[$i]);
806: }
807: if ($this->interactive === true) {
808: $this->out(__d('cake_console', 'Possible Models based on your current database:'));
809: for ($i = 0; $i < $count; $i++) {
810: $this->out($i + 1 . ". " . $this->_modelNames[$i]);
811: }
812: }
813: return $this->_tables;
814: }
815:
816: 817: 818: 819: 820: 821: 822:
823: public function getTable($modelName, $useDbConfig = null) {
824: $useTable = Inflector::tableize($modelName);
825: if (in_array($modelName, $this->_modelNames)) {
826: $modelNames = array_flip($this->_modelNames);
827: $useTable = $this->_tables[$modelNames[$modelName]];
828: }
829:
830: if ($this->interactive === true) {
831: if (!isset($useDbConfig)) {
832: $useDbConfig = $this->connection;
833: }
834: $db = ConnectionManager::getDataSource($useDbConfig);
835: $fullTableName = $db->fullTableName($useTable, false);
836: $tableIsGood = false;
837: if (array_search($useTable, $this->_tables) === false) {
838: $this->out();
839: $this->out(__d('cake_console', "Given your model named '%s',\nCake would expect a database table named '%s'", $modelName, $fullTableName));
840: $tableIsGood = $this->in(__d('cake_console', 'Do you want to use this table?'), array('y', 'n'), 'y');
841: }
842: if (strtolower($tableIsGood) == 'n') {
843: $useTable = $this->in(__d('cake_console', 'What is the name of the table?'));
844: }
845: }
846: return $useTable;
847: }
848:
849: 850: 851: 852: 853: 854: 855:
856: public function getAllTables($useDbConfig = null) {
857: if (!isset($useDbConfig)) {
858: $useDbConfig = $this->connection;
859: }
860:
861: $tables = array();
862: $db = ConnectionManager::getDataSource($useDbConfig);
863: $db->cacheSources = false;
864: $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix'];
865: if ($usePrefix) {
866: foreach ($db->listSources() as $table) {
867: if (!strncmp($table, $usePrefix, strlen($usePrefix))) {
868: $tables[] = substr($table, strlen($usePrefix));
869: }
870: }
871: } else {
872: $tables = $db->listSources();
873: }
874: if (empty($tables)) {
875: $this->err(__d('cake_console', 'Your database does not have any tables.'));
876: $this->_stop();
877: }
878: return $tables;
879: }
880:
881: 882: 883: 884: 885: 886:
887: public function getName($useDbConfig = null) {
888: $this->listAll($useDbConfig);
889:
890: $enteredModel = '';
891:
892: while ($enteredModel == '') {
893: $enteredModel = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another model, or 'q' to exit"), null, 'q');
894:
895: if ($enteredModel === 'q') {
896: $this->out(__d('cake_console', 'Exit'));
897: $this->_stop();
898: }
899:
900: if ($enteredModel == '' || intval($enteredModel) > count($this->_modelNames)) {
901: $this->err(__d('cake_console', "The model name you supplied was empty,\nor the number you selected was not an option. Please try again."));
902: $enteredModel = '';
903: }
904: }
905: if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) {
906: $currentModelName = $this->_modelNames[intval($enteredModel) - 1];
907: } else {
908: $currentModelName = $enteredModel;
909: }
910: return $currentModelName;
911: }
912:
913: 914: 915: 916: 917:
918: public function getOptionParser() {
919: $parser = parent::getOptionParser();
920: return $parser->description(
921: __d('cake_console', 'Bake models.')
922: )->addArgument('name', array(
923: 'help' => __d('cake_console', 'Name of the model to bake. Can use Plugin.name to bake plugin models.')
924: ))->addSubcommand('all', array(
925: 'help' => __d('cake_console', 'Bake all model files with associations and validation.')
926: ))->addOption('plugin', array(
927: 'short' => 'p',
928: 'help' => __d('cake_console', 'Plugin to bake the model into.')
929: ))->addOption('connection', array(
930: 'short' => 'c',
931: 'help' => __d('cake_console', 'The connection the model table is on.')
932: ))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
933: }
934:
935: 936: 937: 938: 939: 940: 941: 942:
943: public function bakeFixture($className, $useTable = null) {
944: $this->Fixture->interactive = $this->interactive;
945: $this->Fixture->connection = $this->connection;
946: $this->Fixture->plugin = $this->plugin;
947: $this->Fixture->bake($className, $useTable);
948: }
949: }
950: