diff --git a/src/Command/ModelCommand.php b/src/Command/ModelCommand.php index 37dc629a..07bba472 100644 --- a/src/Command/ModelCommand.php +++ b/src/Command/ModelCommand.php @@ -346,11 +346,18 @@ public function findBelongsTo(Table $model, array $associations): array ]; } else { $tmpModelName = $this->_modelNameFromKey($fieldName); - if (!in_array(Inflector::tableize($tmpModelName), $this->_tables, true)) { + $associationTable = $this->getTableLocator()->get($tmpModelName); + $tables = $this->listAll(); + // Check if association model could not be instantiated as a subclass but a generic Table instance instead + if ( + get_class($associationTable) === Table::class && + !in_array(Inflector::tableize($tmpModelName), $tables, true) + ) { $found = $this->findTableReferencedBy($schema, $fieldName); - if ($found) { - $tmpModelName = Inflector::camelize($found); + if (!$found) { + continue; } + $tmpModelName = Inflector::camelize($found); } $assoc = [ 'alias' => $tmpModelName, diff --git a/tests/TestCase/Command/ModelCommandTest.php b/tests/TestCase/Command/ModelCommandTest.php index e96fcfc8..9860ce39 100644 --- a/tests/TestCase/Command/ModelCommandTest.php +++ b/tests/TestCase/Command/ModelCommandTest.php @@ -375,6 +375,96 @@ public function testGetAssociationsPlugin() $this->assertEquals($expected, $result); } + /** + * Test that association generation ignores `anything_id` fields if + * AnythingsTable object nor `anythings` database table exist + * + * @return void + */ + public function testGetAssociationsIgnoreUnderscoreIdIfNoDbTable() + { + $items = $this->getTableLocator()->get('TodoItems'); + + $items->setSchema($items->getSchema()->addColumn('anything_id', ['type' => 'integer'])); + $command = new ModelCommand(); + $command->connection = 'test'; + + $args = new Arguments([], [], []); + $io = $this->createMock(ConsoleIo::class); + $result = $command->getAssociations($items, $args, $io); + $expected = [ + 'belongsTo' => [ + [ + 'alias' => 'Users', + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + ], + ], + 'hasMany' => [ + [ + 'alias' => 'TodoTasks', + 'foreignKey' => 'todo_item_id', + ], + ], + 'belongsToMany' => [ + [ + 'alias' => 'TodoLabels', + 'foreignKey' => 'todo_item_id', + 'joinTable' => 'todo_items_todo_labels', + 'targetForeignKey' => 'todo_label_id', + ], + ], + ]; + $this->assertEquals($expected, $result); + } + + /** + * Test that association generation adds association when `anything_id` fields and + * AnythingsTable object exist even if no db table + * + * @return void + */ + public function testGetAssociationsAddAssociationIfTableExist() + { + $items = $this->getTableLocator()->get('TodoItems'); + + $items->setSchema($items->getSchema()->addColumn('template_task_comment_id', ['type' => 'integer'])); + $command = new ModelCommand(); + $command->connection = 'test'; + + $args = new Arguments([], [], []); + $io = $this->createMock(ConsoleIo::class); + $result = $command->getAssociations($items, $args, $io); + $expected = [ + 'belongsTo' => [ + [ + 'alias' => 'Users', + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + ], + [ + 'alias' => 'TemplateTaskComments', + 'foreignKey' => 'template_task_comment_id', + ], + ], + 'hasMany' => [ + [ + 'alias' => 'TodoTasks', + 'foreignKey' => 'todo_item_id', + ], + ], + 'belongsToMany' => [ + [ + 'alias' => 'TodoLabels', + 'foreignKey' => 'todo_item_id', + 'joinTable' => 'todo_items_todo_labels', + 'targetForeignKey' => 'todo_label_id', + ], + ], + ]; + $this->assertEquals($expected, $result); + } + /** * Test that association generation ignores `_id` fields * @@ -491,6 +581,7 @@ public function testBelongsToGenerationConstraints() { $model = $this->getTableLocator()->get('Invitations'); $command = new ModelCommand(); + $command->connection = 'test'; $result = $command->findBelongsTo($model, []); $expected = [ 'belongsTo' => [ @@ -519,6 +610,7 @@ public function testBelongsToGenerationCompositeKey() { $model = $this->getTableLocator()->get('TodoItemsTodoLabels'); $command = new ModelCommand(); + $command->connection = 'test'; $result = $command->findBelongsTo($model, []); $expected = [ 'belongsTo' => [ @@ -1673,9 +1765,9 @@ public function testBakeEntityWithPlugin() $this->_loadTestPlugin('BakeTest'); $path = Plugin::path('BakeTest'); - $this->generatedFile = $path . 'src/Model/Table/UsersTable.php'; + $this->generatedFile = $path . 'src/Model/Entity/User.php'; - $this->exec('bake model --no-validation --no-test --no-fixture --no-entity -p BakeTest Users'); + $this->exec('bake model --no-validation --no-test --no-fixture --no-table BakeTest.Users'); $this->assertExitCode(CommandInterface::CODE_SUCCESS); $this->assertFileExists($this->generatedFile); diff --git a/tests/comparisons/Model/testBakeEntityWithPlugin.php b/tests/comparisons/Model/testBakeEntityWithPlugin.php index 15f39a41..c8b295a1 100644 --- a/tests/comparisons/Model/testBakeEntityWithPlugin.php +++ b/tests/comparisons/Model/testBakeEntityWithPlugin.php @@ -1,74 +1,48 @@ */ - public function initialize(array $config): void - { - parent::initialize($config); - - $this->setTable('users'); - $this->setDisplayField('id'); - $this->setPrimaryKey('id'); - - $this->addBehavior('Timestamp'); - - $this->hasMany('Comments', [ - 'foreignKey' => 'user_id', - 'className' => 'BakeTest.Comments', - ]); - $this->hasMany('TodoItems', [ - 'foreignKey' => 'user_id', - 'className' => 'BakeTest.TodoItems', - ]); - } + protected $_accessible = [ + 'username' => true, + 'password' => true, + 'created' => true, + 'updated' => true, + 'comments' => true, + 'todo_items' => true, + ]; /** - * Returns a rules checker object that will be used for validating - * application integrity. + * Fields that are excluded from JSON versions of the entity. * - * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. - * @return \Cake\ORM\RulesChecker + * @var array */ - public function buildRules(RulesChecker $rules): RulesChecker - { - $rules->add($rules->isUnique(['username']), ['errorField' => 'username']); - - return $rules; - } + protected $_hidden = [ + 'password', + ]; }