CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 1.3 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.3
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Classes

  • AclBase
  • AclBehavior
  • AclComponent
  • AclNode
  • AclShell
  • Aco
  • AcoAction
  • AjaxHelper
  • ApcEngine
  • ApiShell
  • App
  • AppController
  • AppHelper
  • AppModel
  • Aro
  • AuthComponent
  • BakeShell
  • BakeTask
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeRoute
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbConfigTask
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • FileLog
  • FixtureTask
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JqueryEngineHelper
  • JsBaseEngineHelper
  • JsHelper
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • MootoolsEngineHelper
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginShortRoute
  • PluginTask
  • ProjectTask
  • PrototypeEngineHelper
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • Set
  • Shell
  • String
  • TemplateTask
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

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

Generated using CakePHP API Docs