Browse Source

Merge pull request #3123 from markstory/3.0-view-bake

3.0 view bake
José Lorenzo Rodríguez 12 years ago
parent
commit
b01727d952

+ 1 - 1
src/Console/Command/Task/ControllerTask.php

@@ -32,7 +32,7 @@ class ControllerTask extends BakeTask {
  *
  * @var array
  */
-	public $tasks = ['Model', 'Test', 'Template', 'DbConfig', 'Project'];
+	public $tasks = ['Model', 'Test', 'Template'];
 
 /**
  * path to Controller directory

+ 5 - 0
src/Console/Command/Task/ModelTask.php

@@ -359,6 +359,11 @@ class ModelTask extends BakeTask {
 		$columns = $schema->columns();
 		$primary = $this->getPrimaryKey($model);
 		$exclude = array_merge($primary, ['created', 'modified', 'updated']);
+
+		$associations = $model->associations();
+		foreach ($associations->keys() as $assocName) {
+			$columns[] = $associations->get($assocName)->property();
+		}
 		return array_values(array_diff($columns, $exclude));
 	}
 

+ 173 - 167
src/Console/Command/Task/ViewTask.php

@@ -1,7 +1,5 @@
 <?php
 /**
- * The View Tasks handles creating and updating view files.
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -19,6 +17,8 @@ namespace Cake\Console\Command\Task;
 use Cake\Console\Shell;
 use Cake\Core\App;
 use Cake\Core\Configure;
+use Cake\ORM\Table;
+use Cake\ORM\TableRegistry;
 use Cake\Utility\Inflector;
 
 /**
@@ -32,7 +32,7 @@ class ViewTask extends BakeTask {
  *
  * @var array
  */
-	public $tasks = ['Project', 'Controller', 'DbConfig', 'Template'];
+	public $tasks = ['Model', 'Template'];
 
 /**
  * path to View directory
@@ -49,6 +49,20 @@ class ViewTask extends BakeTask {
 	public $controllerName = null;
 
 /**
+ * Classname of the controller being used
+ *
+ * @var string
+ */
+	public $controllerClass = null;
+
+/**
+ * Name of the table views are being baked against.
+ *
+ * @var string
+ */
+	public $tableName = null;
+
+/**
  * The template file to use
  *
  * @var string
@@ -71,12 +85,19 @@ class ViewTask extends BakeTask {
 	public $noTemplateActions = ['delete'];
 
 /**
+ * Override the name so the base class can do the right thing.
+ *
+ * @var string
+ */
+	public $name = 'Template';
+
+/**
  * Override initialize
  *
  * @return void
  */
 	public function initialize() {
-		$this->path = current(App::path('View'));
+		$this->path = current(App::path('Template'));
 	}
 
 /**
@@ -86,23 +107,31 @@ class ViewTask extends BakeTask {
  */
 	public function execute() {
 		parent::execute();
-		if (empty($this->args)) {
-			$this->_interactive();
-		}
-		if (empty($this->args[0])) {
-			return;
-		}
+
 		if (!isset($this->connection)) {
 			$this->connection = 'default';
 		}
-		$action = null;
-		$this->controllerName = $this->_controllerName($this->args[0]);
 
-		$this->Project->interactive = false;
+		if (empty($this->args)) {
+			$this->out(__d('cake_console', 'Possible tables to bake views for based on your current database:'));
+			$this->Model->connection = $this->connection;
+			foreach ($this->Model->listAll() as $table) {
+				$this->out('- ' . $this->_controllerName($table));
+			}
+			return true;
+		}
+
+		$action = null;
 		if (strtolower($this->args[0]) === 'all') {
 			return $this->all();
 		}
 
+		$controller = null;
+		if (!empty($this->params['controller'])) {
+			$controller = $this->params['controller'];
+		}
+		$this->controller($this->args[0], $controller);
+
 		if (isset($this->args[1])) {
 			$this->template = $this->args[1];
 		}
@@ -128,31 +157,63 @@ class ViewTask extends BakeTask {
 	}
 
 /**
+ * Set the controller related properties.
+ *
+ * @param string $table The table/model that is being baked.
+ * @param string $controller The controller name if specified.
+ * @return void
+ */
+	public function controller($table, $controller = null) {
+		$this->tableName = $this->_controllerName($table);
+		if (empty($controller)) {
+			$controller = $this->tableName;
+		}
+		$this->controllerName = $controller;
+
+		$plugin = $prefix = null;
+		if (!empty($this->params['plugin'])) {
+			$plugin = $this->params['plugin'] . '.';
+		}
+		if (!empty($this->params['prefix'])) {
+			$prefix = $this->params['prefix'] . '/';
+		}
+		$this->controllerClass = App::className($plugin . $prefix . $controller, 'Controller', 'Controller');
+	}
+
+/**
+ * Get the path base for views.
+ *
+ * @return string
+ */
+	public function getPath() {
+		$path = parent::getPath();
+		if (!empty($this->params['prefix'])) {
+			$path .= Inflector::camelize($this->params['prefix']) . DS;
+		}
+		$path .= $this->controllerName . DS;
+		return $path;
+	}
+
+/**
  * Get a list of actions that can / should have views baked for them.
  *
  * @return array Array of action names that should be baked
  */
 	protected function _methodsToBake() {
-		$methods = array_diff(
-			array_map('strtolower', get_class_methods($this->controllerName . 'Controller')),
-			array_map('strtolower', get_class_methods('AppController'))
-		);
-		$scaffoldActions = false;
+		$base = Configure::read('App.namespace');
+
+		$methods = [];
+		if (class_exists($this->controllerClass)) {
+			$methods = array_diff(
+				array_map('strtolower', get_class_methods($this->controllerClass)),
+				array_map('strtolower', get_class_methods($base . '\Controller\AppController'))
+			);
+		}
 		if (empty($methods)) {
-			$scaffoldActions = true;
 			$methods = $this->scaffoldActions;
 		}
-		$adminRoute = $this->Project->getPrefix();
 		foreach ($methods as $i => $method) {
-			if ($adminRoute && !empty($this->params['admin'])) {
-				if ($scaffoldActions) {
-					$methods[$i] = $adminRoute . $method;
-					continue;
-				} elseif (strpos($method, $adminRoute) === false) {
-					unset($methods[$i]);
-				}
-			}
-			if ($method[0] === '_' || $method == strtolower($this->controllerName . 'Controller')) {
+			if ($method[0] === '_') {
 				unset($methods[$i]);
 			}
 		}
@@ -165,134 +226,67 @@ class ViewTask extends BakeTask {
  * @return void
  */
 	public function all() {
-		$this->Controller->interactive = false;
-		$tables = $this->Controller->listAll($this->connection, false);
+		$this->Model->connection = $this->connection;
+		$tables = $this->Model->listAll();
 
-		$actions = null;
-		if (isset($this->args[1])) {
-			$actions = [$this->args[1]];
-		}
-		$this->interactive = false;
 		foreach ($tables as $table) {
-			$model = $this->_modelName($table);
-			$this->controllerName = $this->_controllerName($model);
-			if (class_exists($model)) {
-				$vars = $this->_loadController();
-				if (!$actions) {
-					$actions = $this->_methodsToBake();
-				}
-				$this->bakeActions($actions, $vars);
-				$actions = null;
-			}
-		}
-	}
-
-/**
- * Handles interactive baking
- *
- * @return void
- */
-	protected function _interactive() {
-		$this->hr();
-		$this->out(sprintf("Bake View\nPath: %s", $this->getPath()));
-		$this->hr();
-
-		$this->DbConfig->interactive = $this->Controller->interactive = $this->interactive = true;
-
-		if (empty($this->connection)) {
-			$this->connection = $this->DbConfig->getConfig();
-		}
-
-		$this->Controller->connection = $this->connection;
-		$this->controllerName = $this->Controller->getName();
-
-		$prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if it exist.", $this->controllerName);
-		$interactive = $this->in($prompt, ['y', 'n'], 'n');
-
-		if (strtolower($interactive) === 'n') {
-			$this->interactive = false;
-		}
-
-		$prompt = __d('cake_console', "Would you like to create some CRUD views\n(index, add, view, edit) for this controller?\nNOTE: Before doing so, you'll need to create your controller\nand model classes (including associated models).");
-		$wannaDoScaffold = $this->in($prompt, ['y', 'n'], 'y');
-
-		$wannaDoAdmin = $this->in(__d('cake_console', "Would you like to create the views for admin routing?"), ['y', 'n'], 'n');
-
-		if (strtolower($wannaDoScaffold) === 'y' || strtolower($wannaDoAdmin) === 'y') {
-			$vars = $this->_loadController();
-			if (strtolower($wannaDoScaffold) === 'y') {
-				$actions = $this->scaffoldActions;
-				$this->bakeActions($actions, $vars);
-			}
-			if (strtolower($wannaDoAdmin) === 'y') {
-				$admin = $this->Project->getPrefix();
-				$regularActions = $this->scaffoldActions;
-				$adminActions = [];
-				foreach ($regularActions as $action) {
-					$adminActions[] = $admin . $action;
-				}
-				$this->bakeActions($adminActions, $vars);
-			}
-			$this->hr();
-			$this->out();
-			$this->out(__d('cake_console', "View Scaffolding Complete.\n"));
-		} else {
-			$this->customAction();
+			$this->args[0] = $table;
+			$this->execute();
 		}
 	}
 
 /**
  * Loads Controller and sets variables for the template
- * Available template variables
- *	'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
- *	'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys',
- *	'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
+ * Available template variables:
+ *
+ * - 'modelClass'
+ * - 'primaryKey'
+ * - 'displayField'
+ * - 'singularVar'
+ * - 'pluralVar'
+ * - 'singularHumanName'
+ * - 'pluralHumanName'
+ * - 'fields'
+ * - 'keyFields'
+ * - 'schema'
  *
  * @return array Returns an variables to be made available to a view template
  */
 	protected function _loadController() {
-		if (!$this->controllerName) {
-			$this->err(__d('cake_console', 'Controller not found'));
-		}
-
 		$plugin = null;
 		if ($this->plugin) {
 			$plugin = $this->plugin . '.';
 		}
 
-		$controllerClassName = $this->controllerName . 'Controller';
-		$controllerClassName = App::className($plugin . $controllerClassName, 'Controller');
+		$modelObj = TableRegistry::get($this->tableName);
 
-		if (!class_exists($controllerClassName)) {
-			$file = $controllerClassName . '.php';
-			$this->err(__d('cake_console', "The file '%s' could not be found.\nIn order to bake a view, you'll need to first create the controller.", $file));
-			return $this->_stop();
-		}
-		$controllerObj = new $controllerClassName();
-		$controllerObj->plugin = $this->plugin;
-		$controllerObj->constructClasses();
-		$modelClass = $controllerObj->modelClass;
-		$modelObj = $controllerObj->{$controllerObj->modelClass};
-
-		if ($modelObj) {
-			$primaryKey = $modelObj->primaryKey;
-			$displayField = $modelObj->displayField;
-			$singularVar = Inflector::variable($modelClass);
-			$singularHumanName = $this->_singularHumanName($this->controllerName);
-			$schema = $modelObj->schema(true);
-			$fields = array_keys($schema);
-			$associations = $this->_associations($modelObj);
-		} else {
-			$primaryKey = $displayField = null;
-			$singularVar = Inflector::variable(Inflector::singularize($this->controllerName));
-			$singularHumanName = $this->_singularHumanName($this->controllerName);
-			$fields = $schema = $associations = [];
+		$singularVar = Inflector::variable(Inflector::singularize($this->controllerName));
+		$singularHumanName = $this->_singularHumanName($this->controllerName);
+
+		$primaryKey = (array)$modelObj->primaryKey();
+		$displayField = $modelObj->displayField();
+		$singularVar = $this->_singularName($this->controllerName);
+		$singularHumanName = $this->_singularHumanName($this->controllerName);
+		$schema = $modelObj->schema();
+		$fields = $schema->columns();
+		$associations = $this->_associations($modelObj);
+		$keyFields = [];
+		if (!empty($associations['BelongsTo'])) {
+			foreach ($associations['BelongsTo'] as $assoc) {
+				$keyFields[$assoc['foreignKey']] = $assoc['variable'];
+			}
 		}
+
 		$pluralVar = Inflector::variable($this->controllerName);
 		$pluralHumanName = $this->_pluralHumanName($this->controllerName);
 
-		return compact('modelClass', 'schema', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
-				'singularHumanName', 'pluralHumanName', 'fields', 'associations');
+		return compact(
+			'modelClass', 'schema',
+			'primaryKey', 'displayField',
+			'singularVar', 'pluralVar',
+			'singularHumanName', 'pluralHumanName',
+			'fields', 'associations', 'keyFields'
+		);
 	}
 
 /**
@@ -341,9 +335,9 @@ class ViewTask extends BakeTask {
 /**
  * Assembles and writes bakes the view file.
  *
- * @param string $action Action to bake
- * @param string $content Content to write
- * @return boolean Success
+ * @param string $action Action to bake.
+ * @param string $content Content to write.
+ * @return string Generated file content.
  */
 	public function bake($action, $content = '') {
 		if ($content === true) {
@@ -354,8 +348,9 @@ class ViewTask extends BakeTask {
 		}
 		$this->out("\n" . __d('cake_console', 'Baking `%s` view file...', $action), 1, Shell::QUIET);
 		$path = $this->getPath();
-		$filename = $path . $this->controllerName . DS . Inflector::underscore($action) . '.ctp';
-		return $this->createFile($filename, $content);
+		$filename = $path . Inflector::underscore($action) . '.ctp';
+		$this->createFile($filename, $content);
+		return $content;
 	}
 
 /**
@@ -394,22 +389,24 @@ class ViewTask extends BakeTask {
 			return $this->template;
 		}
 		$themePath = $this->Template->getThemePath();
+
+		if (!empty($this->params['prefix'])) {
+			$prefixed = Inflector::underscore($this->params['prefix']) . '_' . $action;
+			if (file_exists($themePath . 'views/' . $prefixed . '.ctp')) {
+				return $prefixed;
+			}
+			$generic = preg_replace('/(.*)(_add|_edit)$/', '\1_form', $prefixed);
+			if (file_exists($themePath . 'views/' . $generic . '.ctp')) {
+				return $generic;
+			}
+		}
 		if (file_exists($themePath . 'views/' . $action . '.ctp')) {
 			return $action;
 		}
-		$template = $action;
-		$prefixes = Configure::read('Routing.prefixes');
-		foreach ((array)$prefixes as $prefix) {
-			if (strpos($template, $prefix) !== false) {
-				$template = str_replace($prefix . '_', '', $template);
-			}
-		}
-		if (in_array($template, ['add', 'edit'])) {
-			$template = 'form';
-		} elseif (preg_match('@(_add|_edit)$@', $template)) {
-			$template = str_replace(['_add', '_edit'], '_form', $template);
+		if (in_array($action, ['add', 'edit'])) {
+			return 'form';
 		}
-		return $template;
+		return $action;
 	}
 
 /**
@@ -421,7 +418,7 @@ class ViewTask extends BakeTask {
 		$parser = parent::getOptionParser();
 
 		$parser->description(
-			__d('cake_console', 'Bake views for a controller, using built-in or custom templates.')
+			__d('cake_console', 'Bake views for a controller, using built-in or custom templates. ')
 		)->addArgument('controller', [
 			'help' => __d('cake_console', 'Name of the controller views to bake. Can be Plugin.name as a shortcut for plugin baking.')
 		])->addArgument('action', [
@@ -431,9 +428,6 @@ class ViewTask extends BakeTask {
 		])->addOption('plugin', [
 			'short' => 'p',
 			'help' => __d('cake_console', 'Plugin to bake the view into.')
-		])->addOption('admin', [
-			'help' => __d('cake_console', 'Set to only bake views for a prefix in Routing.prefixes'),
-			'boolean' => true
 		])->addOption('theme', [
 			'short' => 't',
 			'help' => __d('cake_console', 'Theme to use when baking code.')
@@ -441,8 +435,13 @@ class ViewTask extends BakeTask {
 			'short' => 'c',
 			'help' => __d('cake_console', 'The connection the connected model is on.')
 		])->addOption('force', [
+			'boolean' => true,
 			'short' => 'f',
 			'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
+		])->addOption('controller', [
+			'help' => __d('cake_console', 'The controller name if you have a controller that does not follow conventions.')
+		])->addOption('prefix', [
+			'help' => __d('cake_console', 'The routing prefix to generate views for.'),
 		])->addSubcommand('all', [
 			'help' => __d('cake_console', 'Bake all CRUD action views for all controllers. Requires models and controllers to exist.')
 		])->epilog(
@@ -455,21 +454,28 @@ class ViewTask extends BakeTask {
 /**
  * Returns associations for controllers models.
  *
- * @param Model $model
+ * @param Table $model
  * @return array $associations
  */
-	protected function _associations(Model $model) {
-		$keys = ['belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'];
+	protected function _associations(Table $model) {
+		$keys = ['BelongsTo', 'HasOne', 'HasMany', 'BelongsToMany'];
 		$associations = [];
 
 		foreach ($keys as $type) {
-			foreach ($model->{$type} as $assocKey => $assocData) {
-				list(, $modelClass) = pluginSplit($assocData['className']);
-				$associations[$type][$assocKey]['primaryKey'] = $model->{$assocKey}->primaryKey;
-				$associations[$type][$assocKey]['displayField'] = $model->{$assocKey}->displayField;
-				$associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];
-				$associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($modelClass));
-				$associations[$type][$assocKey]['fields'] = array_keys($model->{$assocKey}->schema(true));
+			foreach ($model->associations()->type($type) as $assoc) {
+				$target = $assoc->target();
+				$assocName = $assoc->name();
+				$alias = $target->alias();
+
+				$associations[$type][$assocName] = [
+					'property' => $assoc->property(),
+					'variable' => Inflector::variable($assocName),
+					'primaryKey' => (array)$target->primaryKey(),
+					'displayField' => $target->displayField(),
+					'foreignKey' => $assoc->foreignKey(),
+					'controller' => Inflector::underscore($alias),
+					'fields' => $target->schema()->columns(),
+				];
 			}
 		}
 		return $associations;

+ 35 - 21
src/Console/Templates/default/actions/controller_actions.ctp

@@ -1,7 +1,5 @@
 <?php
 /**
- * Bake Template for Controller action generation.
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -14,10 +12,26 @@
  * @since         1.3.0
  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
  */
-$associations = [];
-foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
-	$associations[] = "'" . $assoc->target()->alias() . "'";
-}
+$extractor = function ($val) {
+	return $val->target()->alias();
+};
+$stringifyList = function ($list) {
+	$wrapped = array_map(function ($v) {
+		return "'$v'";
+	}, $list);
+	return implode(', ', $wrapped);
+};
+
+$belongsTo = array_map($extractor, $modelObj->associations()->type('BelongsTo'));
+$belongsToMany = array_map($extractor, $modelObj->associations()->type('BelongsToMany'));
+
+$editAssociations = array_merge($belongsTo, $belongsToMany);
+
+$allAssociations = array_merge(
+	$editAssociations,
+	array_map($extractor, $modelObj->associations()->type('HasOne')),
+	array_map($extractor, $modelObj->associations()->type('HasMany'))
+);
 ?>
 
 /**
@@ -26,9 +40,9 @@ foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
  * @return void
  */
 	public function index() {
-<?php if ($associations): ?>
+<?php if ($belongsTo): ?>
 		$this->paginate = [
-			'contain' => [<?= implode(', ', $associations) ?>]
+			'contain' => [<?= $stringifyList($belongsTo) ?>]
 		];
 <?php endif; ?>
 		$this->set('<?= $pluralName ?>', $this->paginate($this-><?= $currentModelName ?>));
@@ -43,7 +57,7 @@ foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
  */
 	public function view($id = null) {
 		$<?= $singularName?> = $this-><?= $currentModelName ?>->get($id, [
-			'contain' => [<?= implode(', ', $associations) ?>]
+			'contain' => [<?= $stringifyList($allAssociations) ?>]
 		]);
 		$this->set('<?= $singularName; ?>', $<?= $singularName; ?>);
 	}
@@ -65,15 +79,14 @@ foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
 			}
 		}
 <?php
-	foreach (['BelongsTo', 'BelongsToMany'] as $assoc):
-		foreach ($modelObj->associations()->type($assoc) as $association):
+		foreach ($editAssociations as $assoc):
+			$association = $modelObj->association($assoc);
 			$otherName = $association->target()->alias();
 			$otherPlural = $this->_pluralName($otherName);
 			echo "\t\t\${$otherPlural} = \$this->{$currentModelName}->{$otherName}->find('list');\n";
 			$compact[] = "'{$otherPlural}'";
 		endforeach;
-	endforeach;
-	echo "\t\t\$this->set(compact(" . join(', ', $compact) . "));\n";
+		echo "\t\t\$this->set(compact(" . join(', ', $compact) . "));\n";
 ?>
 	}
 
@@ -86,7 +99,9 @@ foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
  * @return void
  */
 	public function edit($id = null) {
-		$<?= $singularName ?> = $this-><?= $currentModelName ?>->get($id);
+		$<?= $singularName ?> = $this-><?= $currentModelName ?>->get($id, [
+			'contain' => [<?= $stringifyList($belongsToMany) ?>]
+		]);
 		if ($this->request->is(['post', 'put'])) {
 			$<?= $singularName ?> = $this-><?= $currentModelName ?>->patchEntity($<?= $singularName ?>, $this->request->data);
 			if ($this-><?= $currentModelName; ?>->save($<?= $singularName ?>)) {
@@ -97,13 +112,12 @@ foreach ($modelObj->associations()->type('BelongsTo') as $assoc) {
 			}
 		}
 <?php
-		foreach (['BelongsTo', 'BelongsToMany'] as $assoc):
-			foreach ($modelObj->associations()->type($assoc) as $association):
-				$otherName = $association->target()->alias();
-				$otherPlural = $this->_pluralName($otherName);
-				echo "\t\t\${$otherPlural} = \$this->{$currentModelName}->{$otherName}->find('list');\n";
-				$compact[] = "'{$otherPlural}'";
-			endforeach;
+		foreach ($editAssociations as $assoc):
+			$association = $modelObj->association($assoc);
+			$otherName = $association->target()->alias();
+			$otherPlural = $this->_pluralName($otherName);
+			echo "\t\t\${$otherPlural} = \$this->{$currentModelName}->{$otherName}->find('list');\n";
+			$compact[] = "'{$otherPlural}'";
 		endforeach;
 		echo "\t\t\$this->set(compact(" . join(', ', $compact) . "));\n";
 	?>

+ 1 - 1
src/Console/Templates/default/classes/entity.ctp

@@ -31,7 +31,7 @@ class <?= $name ?> extends Entity {
  */
 	protected $_accessible = [
 <?php foreach ($fields as $field): ?>
-		'<?= $field ?>' => false,
+		'<?= $field ?>' => true,
 <?php endforeach; ?>
 	];
 

+ 14 - 10
src/Console/Templates/default/views/form.ctp

@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -17,28 +15,34 @@
 use Cake\Utility\Inflector;
 ?>
 <div class="<?= $pluralVar; ?> form">
-<?= "<?= \$this->Form->create('{$modelClass}'); ?>\n"; ?>
+<?= "<?= \$this->Form->create(\${$singularVar}); ?>\n"; ?>
 	<fieldset>
 		<legend><?php printf("<?= __('%s %s'); ?>", Inflector::humanize($action), $singularHumanName); ?></legend>
 <?php
 		echo "\t<?php\n";
 		foreach ($fields as $field) {
-			if (strpos($action, 'add') !== false && $field == $primaryKey) {
+			if (strpos($action, 'add') !== false && in_array($field, $primaryKey)) {
 				continue;
-			} elseif (!in_array($field, ['created', 'modified', 'updated'])) {
+			}
+			if (isset($keyFields[$field])) {
+				echo "\t\techo \$this->Form->input('{$field}', ['options' => \${$keyFields[$field]}]);\n";
+				continue;
+			}
+			if (!in_array($field, ['created', 'modified', 'updated'])) {
 				echo "\t\techo \$this->Form->input('{$field}');\n";
 			}
 		}
-		if (!empty($associations['hasAndBelongsToMany'])) {
-			foreach ($associations['hasAndBelongsToMany'] as $assocName => $assocData) {
-				echo "\t\techo \$this->Form->input('{$assocName}');\n";
+		if (!empty($associations['BelongsToMany'])) {
+			foreach ($associations['BelongsToMany'] as $assocName => $assocData) {
+				echo "\t\techo \$this->Form->input('{$assocData['property']}._ids', ['options' => \${$assocData['variable']}]);\n";
 			}
 		}
 		echo "\t?>\n";
 ?>
 	</fieldset>
 <?php
-	echo "<?= \$this->Form->end(__('Submit')); ?>\n";
+	echo "<?= \$this->Form->button(__('Submit')); ?>\n";
+	echo "<?= \$this->Form->end(); ?>\n";
 ?>
 </div>
 <div class="actions">
@@ -46,7 +50,7 @@ use Cake\Utility\Inflector;
 	<ul>
 
 <?php if (strpos($action, 'add') === false): ?>
-		<li><?= "<?= \$this->Form->postLink(__('Delete'), ['action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')], null, __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}'))); ?>"; ?></li>
+		<li><?= "<?= \$this->Form->postLink(__('Delete'), ['action' => 'delete', \${$singularVar}->{$primaryKey[0]}], [], __('Are you sure you want to delete # %s?', \${$singularVar}->{$primaryKey[0]})); ?>"; ?></li>
 <?php endif; ?>
 		<li><?= "<?= \$this->Html->link(__('List " . $pluralHumanName . "'), ['action' => 'index']); ?>"; ?></li>
 <?php

+ 14 - 17
src/Console/Templates/default/views/index.ctp

@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -30,24 +28,26 @@ use Cake\Utility\Inflector;
 	echo "\t<tr>\n";
 		foreach ($fields as $field) {
 			$isKey = false;
-			if (!empty($associations['belongsTo'])) {
-				foreach ($associations['belongsTo'] as $alias => $details) {
+			if (!empty($associations['BelongsTo'])) {
+				foreach ($associations['BelongsTo'] as $alias => $details) {
 					if ($field === $details['foreignKey']) {
 						$isKey = true;
-						echo "\t\t<td>\n\t\t\t<?= \$this->Html->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}']]); ?>\n\t\t</td>\n";
+						echo "\t\t<td>\n\t\t\t<?= \$this->Html->link(\${$singularVar}->{$details['property']}->{$details['displayField']}, ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}->{$details['primaryKey'][0]}]); ?>\n\t\t</td>\n";
 						break;
 					}
 				}
 			}
 			if ($isKey !== true) {
-				echo "\t\t<td><?= h(\${$singularVar}['{$modelClass}']['{$field}']); ?>&nbsp;</td>\n";
+				echo "\t\t<td><?= h(\${$singularVar}->{$field}); ?>&nbsp;</td>\n";
 			}
 		}
 
+		$pk = "\${$singularVar}->{$primaryKey[0]}";
+
 		echo "\t\t<td class=\"actions\">\n";
-		echo "\t\t\t<?= \$this->Html->link(__('View'), ['action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}']]); ?>\n";
-		echo "\t\t\t<?= \$this->Html->link(__('Edit'), ['action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}']]); ?>\n";
-		echo "\t\t\t<?= \$this->Form->postLink(__('Delete'), ['action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']], null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
+		echo "\t\t\t<?= \$this->Html->link(__('View'), ['action' => 'view', {$pk}]); ?>\n";
+		echo "\t\t\t<?= \$this->Html->link(__('Edit'), ['action' => 'edit', {$pk}]); ?>\n";
+		echo "\t\t\t<?= \$this->Form->postLink(__('Delete'), ['action' => 'delete', {$pk}], [], __('Are you sure you want to delete # %s?', {$pk})); ?>\n";
 		echo "\t\t</td>\n";
 	echo "\t</tr>\n";
 
@@ -56,17 +56,14 @@ use Cake\Utility\Inflector;
 	</table>
 	<p>
 	<?= "<?php
-	echo \$this->Paginator->counter([
-	'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
-	]);
-	?>"; ?>
-	</p>
+	echo \$this->Paginator->counter();
+	?>"; ?></p>
 	<div class="paging">
 	<?php
 		echo "<?php\n";
-		echo "\t\techo \$this->Paginator->prev('< ' . __('previous'), [], null, ['class' => 'prev disabled']);\n";
-		echo "\t\techo \$this->Paginator->numbers(['separator' => '']);\n";
-		echo "\t\techo \$this->Paginator->next(__('next') . ' >', [], null, ['class' => 'next disabled']);\n";
+		echo "\t\techo \$this->Paginator->prev('< ' . __('previous'));\n";
+		echo "\t\techo \$this->Paginator->numbers();\n";
+		echo "\t\techo \$this->Paginator->next(__('next') . ' >');\n";
 		echo "\t?>\n";
 	?>
 	</div>

+ 29 - 25
src/Console/Templates/default/views/view.ctp

@@ -1,7 +1,5 @@
 <?php
 /**
- *
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -22,19 +20,19 @@ use Cake\Utility\Inflector;
 <?php
 foreach ($fields as $field) {
 	$isKey = false;
-	if (!empty($associations['belongsTo'])) {
-		foreach ($associations['belongsTo'] as $alias => $details) {
+	if (!empty($associations['BelongsTo'])) {
+		foreach ($associations['BelongsTo'] as $alias => $details) {
 			if ($field === $details['foreignKey']) {
 				$isKey = true;
-				echo "\t\t<dt><?= __('" . Inflector::humanize(Inflector::underscore($alias)) . "'); ?></dt>\n";
-				echo "\t\t<dd>\n\t\t\t<?= \$this->Html->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}']]); ?>\n\t\t\t&nbsp;\n\t\t</dd>\n";
+				echo "\t\t<dt><?= __('" . Inflector::humanize(Inflector::underscore($details['property'])) . "'); ?></dt>\n";
+				echo "\t\t<dd>\n\t\t\t<?= \$this->Html->link(\${$singularVar}->{$details['property']}->{$details['displayField']}, ['controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}->{$details['property']}->{$details['primaryKey'][0]}]); ?>\n\t\t\t&nbsp;\n\t\t</dd>\n";
 				break;
 			}
 		}
 	}
 	if ($isKey !== true) {
 		echo "\t\t<dt><?= __('" . Inflector::humanize($field) . "'); ?></dt>\n";
-		echo "\t\t<dd>\n\t\t\t<?= h(\${$singularVar}['{$modelClass}']['{$field}']); ?>\n\t\t\t&nbsp;\n\t\t</dd>\n";
+		echo "\t\t<dd>\n\t\t\t<?= h(\${$singularVar}->{$field}); ?>\n\t\t\t&nbsp;\n\t\t</dd>\n";
 	}
 }
 ?>
@@ -44,8 +42,10 @@ foreach ($fields as $field) {
 	<h3><?= "<?= __('Actions'); ?>"; ?></h3>
 	<ul>
 <?php
-	echo "\t\t<li><?= \$this->Html->link(__('Edit " . $singularHumanName ."'), ['action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}']]); ?> </li>\n";
-	echo "\t\t<li><?= \$this->Form->postLink(__('Delete " . $singularHumanName . "'), ['action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']], null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> </li>\n";
+	$pk = "\${$singularVar}->{$primaryKey[0]}";
+
+	echo "\t\t<li><?= \$this->Html->link(__('Edit " . $singularHumanName ."'), ['action' => 'edit', {$pk}]); ?> </li>\n";
+	echo "\t\t<li><?= \$this->Form->postLink(__('Delete " . $singularHumanName . "'), ['action' => 'delete', {$pk}], [], __('Are you sure you want to delete # %s?', {$pk})); ?> </li>\n";
 	echo "\t\t<li><?= \$this->Html->link(__('List " . $pluralHumanName . "'), ['action' => 'index']); ?> </li>\n";
 	echo "\t\t<li><?= \$this->Html->link(__('New " . $singularHumanName . "'), ['action' => 'add']); ?> </li>\n";
 
@@ -63,8 +63,8 @@ foreach ($fields as $field) {
 	</ul>
 </div>
 <?php
-if (!empty($associations['hasOne'])) :
-	foreach ($associations['hasOne'] as $alias => $details): ?>
+if (!empty($associations['HasOne'])) :
+	foreach ($associations['HasOne'] as $alias => $details): ?>
 	<div class="related">
 		<h3><?= "<?= __('Related " . Inflector::humanize($details['controller']) . "'); ?>"; ?></h3>
 	<?= "<?php if (!empty(\${$singularVar}['{$alias}'])): ?>\n"; ?>
@@ -72,35 +72,37 @@ if (!empty($associations['hasOne'])) :
 	<?php
 			foreach ($details['fields'] as $field) {
 				echo "\t\t<dt><?= __('" . Inflector::humanize($field) . "'); ?></dt>\n";
-				echo "\t\t<dd>\n\t<?= \${$singularVar}['{$alias}']['{$field}']; ?>\n&nbsp;</dd>\n";
+				echo "\t\t<dd>\n\t<?= h(\${$singularVar}->{$details['property']}->{$field}) ?>\n&nbsp;</dd>\n";
 			}
 	?>
 		</dl>
 	<?= "<?php endif; ?>\n"; ?>
 		<div class="actions">
 			<ul>
-				<li><?= "<?= \$this->Html->link(__('Edit " . Inflector::humanize(Inflector::underscore($alias)) . "'), ['controller' => '{$details['controller']}', 'action' => 'edit', \${$singularVar}['{$alias}']['{$details['primaryKey']}']]); ?></li>\n"; ?>
+				<li><?= "<?= \$this->Html->link(__('Edit " . Inflector::humanize(Inflector::underscore($alias)) . "'), ['controller' => '{$details['controller']}', 'action' => 'edit', \${$singularVar}->{$details['property']}->{$details['primaryKey'][0]}]); ?></li>\n"; ?>
 			</ul>
 		</div>
 	</div>
 	<?php
 	endforeach;
 endif;
-if (empty($associations['hasMany'])) {
-	$associations['hasMany'] = [];
+
+if (empty($associations['HasMany'])) {
+	$associations['HasMany'] = [];
 }
-if (empty($associations['hasAndBelongsToMany'])) {
-	$associations['hasAndBelongsToMany'] = [];
+if (empty($associations['BelongsToMany'])) {
+	$associations['BelongsToMany'] = [];
 }
-$relations = array_merge($associations['hasMany'], $associations['hasAndBelongsToMany']);
+
+$relations = array_merge($associations['HasMany'], $associations['BelongsToMany']);
 foreach ($relations as $alias => $details):
 	$otherSingularVar = Inflector::variable($alias);
 	$otherPluralHumanName = Inflector::humanize($details['controller']);
 	?>
 <div class="related">
 	<h3><?= "<?= __('Related " . $otherPluralHumanName . "'); ?>"; ?></h3>
-	<?= "<?php if (!empty(\${$singularVar}['{$alias}'])): ?>\n"; ?>
-	<table cellpadding = "0" cellspacing = "0">
+	<?= "<?php if (!empty(\${$singularVar}->{$details['property']})): ?>\n"; ?>
+	<table cellpadding="0" cellspacing="0">
 	<tr>
 <?php
 			foreach ($details['fields'] as $field) {
@@ -110,16 +112,18 @@ foreach ($relations as $alias => $details):
 		<th class="actions"><?= "<?= __('Actions'); ?>"; ?></th>
 	</tr>
 <?php
-echo "\t<?php foreach (\${$singularVar}['{$alias}'] as \${$otherSingularVar}): ?>\n";
+echo "\t<?php foreach (\${$singularVar}->{$details['property']} as \${$otherSingularVar}): ?>\n";
 		echo "\t\t<tr>\n";
 			foreach ($details['fields'] as $field) {
-				echo "\t\t\t<td><?= \${$otherSingularVar}['{$field}']; ?></td>\n";
+				echo "\t\t\t<td><?= h(\${$otherSingularVar}->{$field}) ?></td>\n";
 			}
 
+			$otherPk = "\${$otherSingularVar}->{$details['primaryKey'][0]}";
+
 			echo "\t\t\t<td class=\"actions\">\n";
-			echo "\t\t\t\t<?= \$this->Html->link(__('View'), ['controller' => '{$details['controller']}', 'action' => 'view', \${$otherSingularVar}['{$details['primaryKey']}']]); ?>\n";
-			echo "\t\t\t\t<?= \$this->Html->link(__('Edit'), ['controller' => '{$details['controller']}', 'action' => 'edit', \${$otherSingularVar}['{$details['primaryKey']}']]); ?>\n";
-			echo "\t\t\t\t<?= \$this->Form->postLink(__('Delete'), ['controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']], null, __('Are you sure you want to delete # %s?', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n";
+			echo "\t\t\t\t<?= \$this->Html->link(__('View'), ['controller' => '{$details['controller']}', 'action' => 'view', {$otherPk}]); ?>\n";
+			echo "\t\t\t\t<?= \$this->Html->link(__('Edit'), ['controller' => '{$details['controller']}', 'action' => 'edit', {$otherPk}]); ?>\n";
+			echo "\t\t\t\t<?= \$this->Form->postLink(__('Delete'), ['controller' => '{$details['controller']}', 'action' => 'delete', {$otherPk}], [], __('Are you sure you want to delete # %s?', {$otherPk})); ?>\n";
 			echo "\t\t\t</td>\n";
 		echo "\t\t</tr>\n";
 

+ 0 - 4
tests/TestCase/Console/Command/Task/ControllerTaskTest.php

@@ -75,10 +75,6 @@ class ControllerTaskTest extends TestCase {
 			array('in', 'out', 'err', 'createFile', '_stop'),
 			array($out, $out, $in)
 		);
-		$this->Task->Project = $this->getMock('Cake\Console\Command\Task\ProjectTask',
-			array('in', 'out', 'err', 'createFile', '_stop', 'getPrefix'),
-			array($out, $out, $in)
-		);
 		$this->Task->Test = $this->getMock('Cake\Console\Command\Task\TestTask', array(), array($out, $out, $in));
 
 		TableRegistry::get('BakeArticles', [

+ 20 - 3
tests/TestCase/Console/Command/Task/ModelTaskTest.php

@@ -296,6 +296,23 @@ class ModelTaskTest extends TestCase {
 	}
 
 /**
+ * Test getting accessible fields includes associations.
+ *
+ * @return void
+ */
+	public function testGetFieldsAssociations() {
+		$model = TableRegistry::get('BakeArticles');
+		$model->belongsToMany('BakeTags');
+		$model->belongsTo('BakeAuthors');
+		$model->hasMany('BakeComments');
+
+		$result = $this->Task->getFields($model);
+		$this->assertContains('bake_tags', $result);
+		$this->assertContains('bake_comments', $result);
+		$this->assertContains('bake_author', $result);
+	}
+
+/**
  * Test getting field with the no- option
  *
  * @return void
@@ -629,9 +646,9 @@ class ModelTaskTest extends TestCase {
 		$result = $this->Task->bakeEntity($model, $config);
 
 		$this->assertContains("protected \$_accessible = [", $result);
-		$this->assertContains("'title' => false,", $result);
-		$this->assertContains("'body' => false,", $result);
-		$this->assertContains("'published' => false", $result);
+		$this->assertContains("'title' => true,", $result);
+		$this->assertContains("'body' => true,", $result);
+		$this->assertContains("'published' => true", $result);
 		$this->assertNotContains("protected \$_hidden", $result);
 	}
 

+ 265 - 327
tests/TestCase/Console/Command/Task/ViewTaskTest.php

@@ -1,9 +1,5 @@
 <?php
 /**
- * ViewTask Test file
- *
- * Test Case for view generation shell task
- *
  * CakePHP : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -24,6 +20,7 @@ use Cake\Controller\Controller;
 use Cake\Core\Configure;
 use Cake\Core\Plugin;
 use Cake\ORM\Table;
+use Cake\ORM\TableRegistry;
 use Cake\TestSuite\TestCase;
 
 /**
@@ -32,24 +29,13 @@ use Cake\TestSuite\TestCase;
  */
 class ViewTaskCommentsTable extends Table {
 
-/**
- * Table name
- *
- * @var string
- */
-	protected $_table = 'comments';
-
-/**
- * Belongs To Associations
- *
- * @var array
- */
-	public $belongsTo = array(
-		'Article' => array(
-			'className' => 'TestTest.ViewTaskArticle',
+	public function initialize(array $config) {
+		$this->table('comments');
+		$this->belongsTo('Articles', [
 			'foreignKey' => 'article_id'
-		)
-	);
+		]);
+	}
+
 }
 
 /**
@@ -58,12 +44,10 @@ class ViewTaskCommentsTable extends Table {
  */
 class ViewTaskArticlesTable extends Table {
 
-/**
- * Table name
- *
- * @var string
- */
-	protected $_table = 'articles';
+	public function intialize(array $config) {
+		$this->table('articles');
+	}
+
 }
 
 /**
@@ -72,7 +56,7 @@ class ViewTaskArticlesTable extends Table {
  */
 class ViewTaskCommentsController extends Controller {
 
-	public $modelClass = 'Cake\Model\Repository\ViewTaskCommentsTable';
+	public $modelClass = 'Cake\Test\TestCase\Console\Command\Task\ViewTaskCommentsTable';
 
 /**
  * Testing public controller action
@@ -94,126 +78,187 @@ class ViewTaskCommentsController extends Controller {
 
 
 /**
- * Test View Task Articles Controller
- *
+ * ViewTaskTest class
  */
-class ViewTaskArticlesController extends Controller {
-
-	public $modelClass = 'Cake\Model\ViewTaskArticle';
+class ViewTaskTest extends TestCase {
 
 /**
- * Test public controller action
+ * Fixtures
  *
- * @return void
+ * @var array
  */
-	public function index() {
-	}
+	public $fixtures = array('core.article', 'core.post', 'core.comment', 'core.articles_tag', 'core.tag');
 
 /**
- * Test public controller action
+ * setUp method
+ *
+ * Ensure that the default theme is used
  *
  * @return void
  */
-	public function add() {
+	public function setUp() {
+		parent::setUp();
+
+		Configure::write('App.namespace', 'TestApp');
+		$this->_setupTask(['in', 'err', 'createFile', '_stop']);
+
+		TableRegistry::get('ViewTaskComments', [
+			'className' => __NAMESPACE__ . '\ViewTaskCommentsTable',
+		]);
 	}
 
 /**
- * Test admin prefixed controller action
+ * Generate the mock objects used in tests.
  *
  * @return void
  */
-	public function admin_index() {
+	protected function _setupTask($methods) {
+		$out = $this->getMock('Cake\Console\ConsoleOutput', [], [], '', false);
+		$in = $this->getMock('Cake\Console\ConsoleInput', [], [], '', false);
+
+		$this->Task = $this->getMock('Cake\Console\Command\Task\ViewTask',
+			$methods,
+			[$out, $out, $in]
+		);
+		$this->Task->Template = new TemplateTask($out, $out, $in);
+		$this->Task->Model = $this->getMock('Cake\Console\Command\Task\ModelTask', [], [$out, $out, $in]);
+
+		$this->Task->path = TMP;
+		$this->Task->Template->params['theme'] = 'default';
+		$this->Task->Template->templatePaths = ['default' => CAKE . 'Console/Templates/default/'];
 	}
 
 /**
- * Test admin prefixed controller action
+ * tearDown method
  *
  * @return void
  */
-	public function admin_add() {
+	public function tearDown() {
+		parent::tearDown();
+		TableRegistry::clear();
+		unset($this->Task);
 	}
 
 /**
- * Test admin prefixed controller action
+ * Test the controller() method.
  *
  * @return void
  */
-	public function admin_view() {
+	public function testController() {
+		$this->Task->controller('Comments');
+		$this->assertEquals('Comments', $this->Task->controllerName);
+		$this->assertEquals(
+			'TestApp\Controller\CommentsController',
+			$this->Task->controllerClass
+		);
 	}
 
 /**
- * Test admin prefixed controller action
+ * Test the controller() method.
  *
+ * @dataProvider nameVariations
  * @return void
  */
-	public function admin_edit() {
+	public function testControllerVariations($name) {
+		$this->Task->controller($name);
+		$this->assertEquals('ViewTaskComments', $this->Task->controllerName);
+		$this->assertEquals('ViewTaskComments', $this->Task->tableName);
 	}
 
 /**
- * Test admin prefixed controller action
+ * Test controller method with plugins.
  *
  * @return void
  */
-	public function admin_delete() {
+	public function testControllerPlugin() {
+		$this->Task->params['plugin'] = 'TestPlugin';
+		$this->Task->controller('Tests');
+		$this->assertEquals('Tests', $this->Task->controllerName);
+		$this->assertEquals('Tests', $this->Task->tableName);
+		$this->assertEquals(
+			'TestPlugin\Controller\TestsController',
+			$this->Task->controllerClass
+		);
 	}
 
-}
-
-// Alias classes
-class_alias(__NAMESPACE__ . '\ViewTaskArticlesController', 'Cake\Controller\ViewTaskArticlesController');
-class_alias(__NAMESPACE__ . '\ViewTaskCommentsController', 'Cake\Controller\ViewTaskCommentsController');
-class_alias(__NAMESPACE__ . '\ViewTaskCommentsTable', 'Cake\Model\Repository\ViewTaskCommentsTable');
-class_alias(__NAMESPACE__ . '\ViewTaskArticlesTable', 'Cake\Model\Repostiory\ViewTaskArticlesTable');
-
 /**
- * ViewTaskTest class
+ * Test controller method with prefixes.
  *
+ * @return void
  */
-class ViewTaskTest extends TestCase {
+	public function testControllerPrefix() {
+		$this->Task->params['prefix'] = 'Admin';
+		$this->Task->controller('Posts');
+		$this->assertEquals('Posts', $this->Task->controllerName);
+		$this->assertEquals('Posts', $this->Task->tableName);
+		$this->assertEquals(
+			'TestApp\Controller\Admin\PostsController',
+			$this->Task->controllerClass
+		);
+
+		$this->Task->params['plugin'] = 'TestPlugin';
+		$this->Task->controller('Comments');
+		$this->assertEquals('Comments', $this->Task->controllerName);
+		$this->assertEquals('Comments', $this->Task->tableName);
+		$this->assertEquals(
+			'TestPlugin\Controller\Admin\CommentsController',
+			$this->Task->controllerClass
+		);
+	}
 
 /**
- * Fixtures
+ * test controller with a non-conventional controller name
  *
- * @var array
+ * @return void
  */
-	public $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag');
+	public function testControllerWithOverride() {
+		$this->Task->controller('Comments', 'Posts');
+		$this->assertEquals('Posts', $this->Task->controllerName);
+		$this->assertEquals('Comments', $this->Task->tableName);
+		$this->assertEquals(
+			'TestApp\Controller\PostsController',
+			$this->Task->controllerClass
+		);
+	}
 
 /**
- * setUp method
- *
- * Ensure that the default theme is used
+ * Test getPath()
  *
  * @return void
  */
-	public function setUp() {
-		parent::setUp();
-		$this->markTestIncomplete('Model baking will not work as models do not work.');
+	public function testGetPath() {
+		$this->Task->controllerName = 'Posts';
+		$this->Task->path = '/path/Template/';
 
-		$out = $this->getMock('Cake\Console\ConsoleOutput', array(), array(), '', false);
-		$in = $this->getMock('Cake\Console\ConsoleInput', array(), array(), '', false);
+		$result = $this->Task->getPath();
+		$this->assertEquals('/path/Template/Posts/', $result);
 
-		$this->Task = $this->getMock('Cake\Console\Command\Task\ViewTask',
-			array('in', 'err', 'createFile', '_stop'),
-			array($out, $out, $in)
-		);
-		$this->Task->Template = new TemplateTask($out, $out, $in);
-		$this->Task->Controller = $this->getMock('Cake\Console\Command\Task\ControllerTask', array(), array($out, $out, $in));
-		$this->Task->Project = $this->getMock('Cake\Console\Command\Task\ProjectTask', array(), array($out, $out, $in));
-		$this->Task->DbConfig = $this->getMock('Cake\Console\Command\Task\DbConfigTask', array(), array($out, $out, $in));
-
-		$this->Task->path = TMP;
-		$this->Task->Template->params['theme'] = 'default';
-		$this->Task->Template->templatePaths = array('default' => CAKE . 'Console/Templates/default/');
+		$this->Task->params['prefix'] = 'admin';
+		$result = $this->Task->getPath();
+		$this->assertEquals('/path/Template/Admin/Posts/', $result);
 	}
 
 /**
- * tearDown method
+ * Test getPath with plugins.
  *
  * @return void
  */
-	public function tearDown() {
-		parent::tearDown();
-		unset($this->Task, $this->Dispatch);
+	public function testGetPathPlugin() {
+		$this->Task->controllerName = 'Posts';
+		$this->Task->path = '/path/Template/';
+
+		$pluginPath = APP . 'Plugin/TestPlugin/';
+		Plugin::load('TestPlugin', array('path' => $pluginPath));
+
+		$this->Task->params['plugin'] = $this->Task->plugin = 'TestPlugin';
+		$result = $this->Task->getPath();
+		$this->assertEquals($pluginPath . 'Template/Posts/', $result);
+
+		$this->Task->params['prefix'] = 'admin';
+		$result = $this->Task->getPath();
+		$this->assertEquals($pluginPath . 'Template/Admin/Posts/', $result);
+
+		Plugin::unload('TestPlugin');
 	}
 
 /**
@@ -224,65 +269,64 @@ class ViewTaskTest extends TestCase {
 	public function testGetContent() {
 		$vars = array(
 			'modelClass' => 'TestViewModel',
-			'schema' => array(),
-			'primaryKey' => 'id',
+			'schema' => [],
+			'primaryKey' => ['id'],
 			'displayField' => 'name',
 			'singularVar' => 'testViewModel',
 			'pluralVar' => 'testViewModels',
 			'singularHumanName' => 'Test View Model',
 			'pluralHumanName' => 'Test View Models',
-			'fields' => array('id', 'name', 'body'),
-			'associations' => array()
+			'fields' => ['id', 'name', 'body'],
+			'associations' => [],
+			'keyFields' => [],
 		);
 		$result = $this->Task->getContent('view', $vars);
 
-		$this->assertRegExp('/Delete Test View Model/', $result);
-		$this->assertRegExp('/Edit Test View Model/', $result);
-		$this->assertRegExp('/List Test View Models/', $result);
-		$this->assertRegExp('/New Test View Model/', $result);
+		$this->assertContains('Delete Test View Model', $result);
+		$this->assertContains('Edit Test View Model', $result);
+		$this->assertContains('List Test View Models', $result);
+		$this->assertContains('New Test View Model', $result);
 
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'id\'\]/', $result);
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'name\'\]/', $result);
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'body\'\]/', $result);
+		$this->assertContains('$testViewModel->id', $result);
+		$this->assertContains('$testViewModel->name', $result);
+		$this->assertContains('$testViewModel->body', $result);
 	}
 
 /**
- * test getContent() using an admin_prefixed action.
+ * test getContent() using a routing prefix action.
  *
  * @return void
  */
-	public function testGetContentWithAdminAction() {
-		$_back = Configure::read('Routing');
-		Configure::write('Routing.prefixes', array('admin'));
+	public function testGetContentWithRoutingPrefix() {
 		$vars = array(
 			'modelClass' => 'TestViewModel',
-			'schema' => array(),
-			'primaryKey' => 'id',
+			'schema' => [],
+			'primaryKey' => ['id'],
 			'displayField' => 'name',
 			'singularVar' => 'testViewModel',
 			'pluralVar' => 'testViewModels',
 			'singularHumanName' => 'Test View Model',
 			'pluralHumanName' => 'Test View Models',
-			'fields' => array('id', 'name', 'body'),
-			'associations' => array()
+			'fields' => ['id', 'name', 'body'],
+			'keyFields' => [],
+			'associations' => []
 		);
-		$result = $this->Task->getContent('admin_view', $vars);
-
-		$this->assertRegExp('/Delete Test View Model/', $result);
-		$this->assertRegExp('/Edit Test View Model/', $result);
-		$this->assertRegExp('/List Test View Models/', $result);
-		$this->assertRegExp('/New Test View Model/', $result);
+		$this->Task->params['prefix'] = 'Admin';
+		$result = $this->Task->getContent('view', $vars);
 
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'id\'\]/', $result);
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'name\'\]/', $result);
-		$this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'body\'\]/', $result);
+		$this->assertContains('Delete Test View Model', $result);
+		$this->assertContains('Edit Test View Model', $result);
+		$this->assertContains('List Test View Models', $result);
+		$this->assertContains('New Test View Model', $result);
 
-		$result = $this->Task->getContent('admin_add', $vars);
-		$this->assertRegExp("/input\('name'\)/", $result);
-		$this->assertRegExp("/input\('body'\)/", $result);
-		$this->assertRegExp('/List Test View Models/', $result);
+		$this->assertContains('$testViewModel->id', $result);
+		$this->assertContains('$testViewModel->name', $result);
+		$this->assertContains('$testViewModel->body', $result);
 
-		Configure::write('Routing', $_back);
+		$result = $this->Task->getContent('add', $vars);
+		$this->assertContains("input('name')", $result);
+		$this->assertContains("input('body')", $result);
+		$this->assertContains('List Test View Models', $result);
 	}
 
 /**
@@ -292,11 +336,14 @@ class ViewTaskTest extends TestCase {
  */
 	public function testBakeView() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
-		$this->Task->expects($this->at(0))->method('createFile')
+		$this->Task->expects($this->at(0))
+			->method('createFile')
 			->with(
 				TMP . 'ViewTaskComments/view.ctp',
-				$this->stringContains('View Task Articles')
+				$this->stringContains('View Task Comments')
 			);
 
 		$this->Task->bake('view', true);
@@ -309,13 +356,18 @@ class ViewTaskTest extends TestCase {
  */
 	public function testBakeEdit() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
 		$this->Task->expects($this->at(0))->method('createFile')
 			->with(
 				TMP . 'ViewTaskComments/edit.ctp',
 				$this->anything()
 			);
-		$this->Task->bake('edit', true);
+		$result = $this->Task->bake('edit', true);
+
+		$this->assertContains("Form->input('id')", $result);
+		$this->assertContains("Form->input('article_id', ['options' => \$articles])", $result);
 	}
 
 /**
@@ -325,11 +377,13 @@ class ViewTaskTest extends TestCase {
  */
 	public function testBakeIndex() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
 		$this->Task->expects($this->at(0))->method('createFile')
 			->with(
 				TMP . 'ViewTaskComments/index.ctp',
-				$this->stringContains("\$viewTaskComment['Article']['title']")
+				$this->stringContains("\$viewTaskComment->article->title")
 			);
 		$this->Task->bake('index', true);
 	}
@@ -341,47 +395,25 @@ class ViewTaskTest extends TestCase {
  */
 	public function testBakeWithNoTemplate() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
 		$this->Task->expects($this->never())->method('createFile');
 		$this->Task->bake('delete', true);
 	}
 
 /**
- * test bake() with a -plugin param
- *
- * @return void
- */
-	public function testBakeWithPlugin() {
-		$this->markTestIncomplete('Still fails because of issues with modelClass');
-
-		$this->Task->controllerName = 'ViewTaskComments';
-		$this->Task->plugin = 'TestTest';
-		$this->Task->name = 'View';
-
-		//fake plugin path
-		Plugin::load('TestTest', array('path' => APP . 'Plugin/TestTest/'));
-		$path = APP . 'Plugin/TestTest/View/ViewTaskComments/view.ctp';
-
-		$result = $this->Task->getContent('index');
-		$this->assertNotContains('List Test Test.view Task Articles', $result);
-
-		$this->Task->expects($this->once())
-			->method('createFile')
-			->with($path, $this->anything());
-
-		$this->Task->bake('view', true);
-		Plugin::unload();
-	}
-
-/**
  * test bake actions baking multiple actions.
  *
  * @return void
  */
 	public function testBakeActions() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
-		$this->Task->expects($this->at(0))->method('createFile')
+		$this->Task->expects($this->at(0))
+			->method('createFile')
 			->with(
 				TMP . 'ViewTaskComments/view.ctp',
 				$this->stringContains('View Task Comments')
@@ -407,6 +439,8 @@ class ViewTaskTest extends TestCase {
  */
 	public function testCustomAction() {
 		$this->Task->controllerName = 'ViewTaskComments';
+		$this->Task->tableName = 'ViewTaskComments';
+		$this->Task->controllerClass = __NAMESPACE__ . '\ViewTaskCommentsController';
 
 		$this->Task->expects($this->any())->method('in')
 			->will($this->onConsecutiveCalls('', 'my_action', 'y'));
@@ -426,42 +460,11 @@ class ViewTaskTest extends TestCase {
  * @return void
  */
 	public function testExecuteIntoAll() {
+		$this->_setupTask(['in', 'err', 'createFile', 'all', '_stop']);
 		$this->Task->args[0] = 'all';
 
-		$this->Task->Controller->expects($this->once())->method('listAll')
-			->will($this->returnValue(array('view_task_comments')));
-
-		$this->Task->expects($this->at(0))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/index.ctp',
-				$this->anything()
-			);
-		$this->Task->expects($this->at(1))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/add.ctp',
-				$this->anything()
-			);
-		$this->Task->expects($this->exactly(2))->method('createFile');
-
-		$this->Task->execute();
-	}
-
-/**
- * Test all() with action parameter
- *
- * @return void
- */
-	public function testExecuteIntoAllWithActionName() {
-		$this->Task->args = array('all', 'index');
-
-		$this->Task->Controller->expects($this->once())->method('listAll')
-			->will($this->returnValue(array('view_task_comments')));
-
-		$this->Task->expects($this->once())->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/index.ctp',
-				$this->anything()
-			);
+		$this->Task->expects($this->once())
+			->method('all');
 
 		$this->Task->execute();
 	}
@@ -472,14 +475,14 @@ class ViewTaskTest extends TestCase {
  * @return void
  */
 	public function testExecuteWithActionParam() {
+		$this->_setupTask(['in', 'err', 'createFile', 'bake', '_stop']);
 		$this->Task->args[0] = 'ViewTaskComments';
 		$this->Task->args[1] = 'view';
 
-		$this->Task->expects($this->once())->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/view.ctp',
-				$this->anything()
-			);
+		$this->Task->expects($this->once())
+			->method('bake')
+			->with('view', true);
+
 		$this->Task->execute();
 	}
 
@@ -490,19 +493,27 @@ class ViewTaskTest extends TestCase {
  * @return void
  */
 	public function testExecuteWithController() {
+		$this->_setupTask(['in', 'err', 'createFile', 'bake', '_stop']);
 		$this->Task->args[0] = 'ViewTaskComments';
 
-		$this->Task->expects($this->at(0))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/index.ctp',
-				$this->anything()
-			);
-		$this->Task->expects($this->at(1))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/add.ctp',
-				$this->anything()
-			);
-		$this->Task->expects($this->exactly(2))->method('createFile');
+		$this->Task->expects($this->exactly(4))
+			->method('bake');
+
+		$this->Task->expects($this->at(0))
+			->method('bake')
+			->with('index', $this->anything());
+
+		$this->Task->expects($this->at(1))
+			->method('bake')
+			->with('view', $this->anything());
+
+		$this->Task->expects($this->at(2))
+			->method('bake')
+			->with('add', $this->anything());
+
+		$this->Task->expects($this->at(3))
+			->method('bake')
+			->with('edit', $this->anything());
 
 		$this->Task->execute();
 	}
@@ -513,100 +524,52 @@ class ViewTaskTest extends TestCase {
  * @return void
  */
 	public static function nameVariations() {
-		return array(array('ViewTaskComments'), array('ViewTaskComment'), array('view_task_comment'));
+		return [['ViewTaskComments'], ['ViewTaskComment'], ['view_task_comment']];
 	}
 
 /**
- * test that both plural and singular forms can be used for baking views.
- *
- * @dataProvider nameVariations
- * @return void
- */
-	public function testExecuteWithControllerVariations($name) {
-		$this->Task->args = array($name);
-
-		$this->Task->expects($this->at(0))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/index.ctp',
-				$this->anything()
-			);
-		$this->Task->expects($this->at(1))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/add.ctp',
-				$this->anything()
-			);
-		$this->Task->execute();
-	}
-
-/**
- * test `cake bake view $controller --admin`
- * Which only bakes admin methods, not non-admin methods.
+ * test `cake bake view $table --controller Blog`
  *
  * @return void
  */
-	public function testExecuteWithControllerAndAdminFlag() {
-		$_back = Configure::read('Routing');
-		Configure::write('Routing.prefixes', array('admin'));
-		$this->Task->args[0] = 'ViewTaskArticles';
-		$this->Task->params['admin'] = 1;
+	public function testExecuteWithControllerFlag() {
+		$this->Task->args[0] = 'Posts';
+		$this->Task->params['controller'] = 'Blog';
 
-		$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
+		$this->Task->expects($this->exactly(4))
+			->method('createFile');
 
-		$this->Task->expects($this->exactly(4))->method('createFile');
-
-		$views = array('admin_index.ctp', 'admin_add.ctp', 'admin_view.ctp', 'admin_edit.ctp');
+		$views = array('index.ctp', 'view.ctp', 'add.ctp', 'edit.ctp');
 		foreach ($views as $i => $view) {
 			$this->Task->expects($this->at($i))->method('createFile')
 				->with(
-					TMP . 'ViewTaskArticles/' . $view,
+					TMP . 'Blog/' . $view,
 					$this->anything()
 				);
 		}
 		$this->Task->execute();
-		Configure::write('Routing', $_back);
 	}
 
 /**
- * test execute into interactive.
+ * test `cake bake view $controller --prefix Admin`
  *
  * @return void
  */
-	public function testExecuteInteractive() {
-		$this->Task->connection = 'test';
-		$this->Task->args = array();
-		$this->Task->params = array();
-
-		$this->Task->Controller->expects($this->once())->method('getName')
-			->will($this->returnValue('ViewTaskComments'));
-
-		$this->Task->expects($this->any())->method('in')
-			->will($this->onConsecutiveCalls('y', 'y', 'n'));
-
-		$this->Task->expects($this->at(3))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/index.ctp',
-				$this->stringContains('ViewTaskComment')
-			);
-
-		$this->Task->expects($this->at(4))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/view.ctp',
-				$this->stringContains('ViewTaskComment')
-			);
+	public function testExecuteWithControllerAndAdminFlag() {
+		$this->Task->args[0] = 'Posts';
+		$this->Task->params['prefix'] = 'Admin';
 
-		$this->Task->expects($this->at(5))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/add.ctp',
-				$this->stringContains('Add View Task Comment')
-			);
+		$this->Task->expects($this->exactly(2))
+			->method('createFile');
 
-		$this->Task->expects($this->at(6))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/edit.ctp',
-				$this->stringContains('Edit View Task Comment')
-			);
-
-		$this->Task->expects($this->exactly(4))->method('createFile');
+		$views = array('index.ctp', 'add.ctp');
+		foreach ($views as $i => $view) {
+			$this->Task->expects($this->at($i))->method('createFile')
+				->with(
+					TMP . 'Admin/Posts/' . $view,
+					$this->anything()
+				);
+		}
 		$this->Task->execute();
 	}
 
@@ -616,89 +579,64 @@ class ViewTaskTest extends TestCase {
  * @return void
  */
 	public function testExecuteWithAlternateTemplates() {
+		$this->_setupTask(['in', 'err', 'createFile', 'bake', '_stop']);
+
 		$this->Task->connection = 'test';
-		$this->Task->args = array('ViewTaskComments', 'index', 'list');
-		$this->Task->params = array();
+		$this->Task->args = ['ViewTaskComments', 'index', 'list'];
+		$this->Task->params = [];
 
-		$this->Task->expects($this->once())->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/list.ctp',
-				$this->stringContains('ViewTaskComment')
-			);
+		$this->Task->expects($this->once())
+			->method('bake')
+			->with('list', true);
 		$this->Task->execute();
 	}
 
 /**
- * test execute into interactive() with admin methods.
+ * test getting templates, make sure noTemplateActions works and prefixed template is used before generic one.
  *
  * @return void
  */
-	public function testExecuteInteractiveWithAdmin() {
-		Configure::write('Routing.prefixes', array('admin'));
-		$this->Task->connection = 'test';
-		$this->Task->args = array();
-
-		$this->Task->Controller->expects($this->once())->method('getName')
-			->will($this->returnValue('ViewTaskComments'));
-
-		$this->Task->Project->expects($this->once())->method('getPrefix')
-			->will($this->returnValue('admin_'));
-
-		$this->Task->expects($this->any())->method('in')
-			->will($this->onConsecutiveCalls('y', 'n', 'y'));
+	public function testGetTemplate() {
+		$result = $this->Task->getTemplate('delete');
+		$this->assertFalse($result);
 
-		$this->Task->expects($this->at(3))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/admin_index.ctp',
-				$this->stringContains('ViewTaskComment')
-			);
+		$result = $this->Task->getTemplate('add');
+		$this->assertEquals('form', $result);
 
-		$this->Task->expects($this->at(4))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/admin_view.ctp',
-				$this->stringContains('ViewTaskComment')
-			);
+		$result = $this->Task->getTemplate('edit');
+		$this->assertEquals('form', $result);
 
-		$this->Task->expects($this->at(5))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/admin_add.ctp',
-				$this->stringContains('Add View Task Comment')
-			);
+		$result = $this->Task->getTemplate('view');
+		$this->assertEquals('view', $result);
 
-		$this->Task->expects($this->at(6))->method('createFile')
-			->with(
-				TMP . 'ViewTaskComments/admin_edit.ctp',
-				$this->stringContains('Edit View Task Comment')
-			);
-
-		$this->Task->expects($this->exactly(4))->method('createFile');
-		$this->Task->execute();
+		$result = $this->Task->getTemplate('index');
+		$this->assertEquals('index', $result);
 	}
 
 /**
- * test getting templates, make sure noTemplateActions works and prefixed template is used before generic one.
+ * Test getting prefixed views.
  *
  * @return void
  */
-	public function testGetTemplate() {
-		$result = $this->Task->getTemplate('delete');
-		$this->assertFalse($result);
+	public function testGetTemplatePrefixed() {
+		$this->Task->params['prefix'] = 'Admin';
 
 		$result = $this->Task->getTemplate('add');
 		$this->assertEquals('form', $result);
 
-		Configure::write('Routing.prefixes', array('admin'));
-
-		$result = $this->Task->getTemplate('admin_add');
-		$this->assertEquals('form', $result);
-
 		$this->Task->Template->templatePaths = array(
-			'test' => CAKE . 'Test/' . 'TestApp/Console/Templates/test/'
+			'test' => CORE_TESTS . '/test_app/TestApp/Console/Templates/test/'
 		);
 		$this->Task->Template->params['theme'] = 'test';
 
-		$result = $this->Task->getTemplate('admin_edit');
+		$result = $this->Task->getTemplate('edit');
 		$this->assertEquals('admin_edit', $result);
+
+		$result = $this->Task->getTemplate('add');
+		$this->assertEquals('admin_form', $result);
+
+		$result = $this->Task->getTemplate('view');
+		$this->assertEquals('view', $result);
 	}
 
 }

+ 4 - 2
tests/bake_compare/Controller/Actions.ctp

@@ -20,7 +20,7 @@
  */
 	public function view($id = null) {
 		$bakeArticle = $this->BakeArticles->get($id, [
-			'contain' => ['BakeUsers']
+			'contain' => ['BakeUsers', 'BakeTags', 'BakeComments']
 		]);
 		$this->set('bakeArticle', $bakeArticle);
 	}
@@ -53,7 +53,9 @@
  * @return void
  */
 	public function edit($id = null) {
-		$bakeArticle = $this->BakeArticles->get($id);
+		$bakeArticle = $this->BakeArticles->get($id, [
+			'contain' => ['BakeTags']
+		]);
 		if ($this->request->is(['post', 'put'])) {
 			$bakeArticle = $this->BakeArticles->patchEntity($bakeArticle, $this->request->data);
 			if ($this->BakeArticles->save($bakeArticle)) {

+ 0 - 0
tests/test_app/TestApp/Console/Templates/test/views/admin_form.ctp


+ 5 - 4
tests/test_app/TestApp/Controller/Admin/PostsController.php

@@ -30,17 +30,18 @@ class PostsController extends Controller {
 	public $components = array();
 
 /**
- * components
+ * index action
  *
- * @var array
+ * @return void
  */
-	public $uses = array();
+	public function index() {
+	}
 
 /**
  * index action
  *
  * @return void
  */
-	public function index() {
+	public function add() {
 	}
 }