diff --git a/src/Command/ModelCommand.php b/src/Command/ModelCommand.php index 8c72cef3..fc9b95ec 100644 --- a/src/Command/ModelCommand.php +++ b/src/Command/ModelCommand.php @@ -233,7 +233,7 @@ public function getAssociations(Table $table, Arguments $args, ConsoleIo $io): a ]; $primary = $table->getPrimaryKey(); - $associations = $this->findBelongsTo($table, $associations); + $associations = $this->findBelongsTo($table, $associations, $args); if (is_array($primary) && count($primary) > 1) { $io->warning( @@ -329,9 +329,10 @@ public function getAssociationInfo(Table $table): array * * @param \Cake\ORM\Table $model Database\Table instance of table being generated. * @param array $associations Array of in progress associations + * @param \Cake\Console\Arguments|null $args CLI arguments * @return array Associations with belongsTo added in. */ - public function findBelongsTo(Table $model, array $associations): array + public function findBelongsTo(Table $model, array $associations, ?Arguments $args = null): array { $schema = $model->getSchema(); foreach ($schema->columns() as $fieldName) { @@ -362,11 +363,13 @@ public function findBelongsTo(Table $model, array $associations): array get_class($associationTable) === Table::class && !in_array(Inflector::tableize($tmpModelName), $tables, true) ) { + $allowAliasRelations = $args && $args->getOption('skip-relation-check'); $found = $this->findTableReferencedBy($schema, $fieldName); - if (!$found) { + if ($found) { + $tmpModelName = Inflector::camelize($found); + } elseif (!$allowAliasRelations) { continue; } - $tmpModelName = Inflector::camelize($found); } $assoc = [ 'alias' => $tmpModelName, @@ -1319,6 +1322,10 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar ])->addOption('no-fixture', [ 'boolean' => true, 'help' => 'Do not generate a test fixture skeleton.', + ])->addOption('skip-relation-check', [ + 'boolean' => true, + 'help' => 'Generate relations for all "example_id" fields' + . ' without checking the database if a table "examples" exists.', ])->setEpilog( 'Omitting all arguments and options will list the table names you can generate models for.' ); diff --git a/tests/TestCase/Command/ModelCommandTest.php b/tests/TestCase/Command/ModelCommandTest.php index e7c5c679..3080f58e 100644 --- a/tests/TestCase/Command/ModelCommandTest.php +++ b/tests/TestCase/Command/ModelCommandTest.php @@ -490,6 +490,59 @@ public function testGetAssociationsAddAssociationIfTableExist() $this->assertEquals($expected, $result); } + /** + * Test that association generation adds `Anythings` association for `anything_id` field + * when using `--skip-relation-check` option, even if no db table exists + * + * @return void + */ + public function testGetAssociationsAddAssociationIfNoTableExistButAliasIsAllowed() + { + $items = $this->getTableLocator()->get('TodoItems'); + + $items->setSchema($items->getSchema()->addColumn('anything_id', ['type' => 'integer'])); + $command = new ModelCommand(); + $command->connection = 'test'; + + $args = new Arguments([], ['skip-relation-check' => true], []); + $io = $this->createMock(ConsoleIo::class); + $result = $command->getAssociations($items, $args, $io); + $expected = [ + 'belongsTo' => [ + [ + 'alias' => 'Users', + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + ], + [ + 'alias' => 'Anythings', + 'foreignKey' => 'anything_id', + ], + ], + 'hasMany' => [ + [ + 'alias' => 'TodoTasks', + 'foreignKey' => 'todo_item_id', + ], + ], + 'belongsToMany' => [ + [ + 'alias' => 'TodoLabels', + 'foreignKey' => 'todo_item_id', + 'joinTable' => 'todo_items_todo_labels', + 'targetForeignKey' => 'todo_label_id', + ], + ], + 'hasOne' => [ + [ + 'alias' => 'TodoReminders', + 'foreignKey' => 'todo_item_id', + ], + ], + ]; + $this->assertEquals($expected, $result); + } + /** * Test that association generation ignores `_id` fields *