Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure custom relations work out with new alias strictness. #1015

Merged
merged 10 commits into from
Nov 28, 2024
49 changes: 48 additions & 1 deletion src/Command/ModelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@
$associations = $this->findHasMany($table, $associations);
$associations = $this->findBelongsToMany($table, $associations);

$associations = $this->ensureAliasUniqueness($associations);

return $associations;
}

Expand All @@ -275,6 +277,7 @@
if (get_class($model) !== Table::class) {
return;
}

foreach ($associations as $type => $assocs) {
foreach ($assocs as $assoc) {
$alias = $assoc['alias'];
Expand Down Expand Up @@ -349,6 +352,7 @@
continue;
}

$className = null;
if ($fieldName === 'parent_id') {
$className = $this->plugin ? $this->plugin . '.' . $model->getAlias() : $model->getAlias();
$assoc = [
Expand All @@ -375,7 +379,7 @@
$allowAliasRelations = $args && $args->getOption('skip-relation-check');
$found = $this->findTableReferencedBy($schema, $fieldName);
if ($found) {
$tmpModelName = Inflector::camelize($found);
$className = ($this->plugin ? $this->plugin . '.' : '') . Inflector::camelize($found);
} elseif (!$allowAliasRelations) {
continue;
}
Expand All @@ -384,6 +388,9 @@
'alias' => $tmpModelName,
'foreignKey' => $fieldName,
];
if ($className && $className !== $tmpModelName) {
$assoc['className'] = $className;
}
if ($schema->getColumn($fieldName)['null'] === false) {
$assoc['joinType'] = 'INNER';
}
Expand All @@ -392,6 +399,7 @@
if ($this->plugin && empty($assoc['className'])) {
$assoc['className'] = $this->plugin . '.' . $assoc['alias'];
}

$associations['belongsTo'][] = $assoc;
}

Expand Down Expand Up @@ -1546,4 +1554,43 @@
$enumCommand->execute($args, $io);
}
}

/**
* @param array<string, array<string, mixed>> $associations
* @return array<string, array<string, mixed>>
*/
protected function ensureAliasUniqueness(array $associations): array
dereuromark marked this conversation as resolved.
Show resolved Hide resolved
{
$existing = [];
foreach ($associations as $type => $associationsPerType) {
foreach ($associationsPerType as $k => $association) {
$alias = $association['alias'];
if (in_array($alias, $existing, true)) {
$alias = $this->createAssociationAlias($association);

Check warning on line 1569 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1569

Added line #L1569 was not covered by tests
}
$existing[] = $alias;
if (empty($association['className'])) {
$className = $this->plugin ? $this->plugin . '.' . $association['alias'] : $association['alias'];
if ($className !== $alias) {
$association['className'] = $className;

Check warning on line 1575 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1575

Added line #L1575 was not covered by tests
}
}
$association['alias'] = $alias;
$associations[$type][$k] = $association;
}
}

return $associations;
}

/**
* @param array<string, mixed> $association
* @return string
*/
protected function createAssociationAlias(array $association): string

Check warning on line 1590 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1590

Added line #L1590 was not covered by tests
{
$foreignKey = $association['foreignKey'];

Check warning on line 1592 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1592

Added line #L1592 was not covered by tests

return $this->_modelNameFromKey($foreignKey);

Check warning on line 1594 in src/Command/ModelCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/ModelCommand.php#L1594

Added line #L1594 was not covered by tests
}
}
36 changes: 36 additions & 0 deletions tests/Fixture/RelationsFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 0.1.0
* @license https://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Bake\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

/**
* InvitationsFixture
*/
class RelationsFixture extends TestFixture
{
/**
* records property
*
* @var array
*/
public array $records = [
[
'user_id' => 1,
'other_id' => 1,
'body' => 'Try it out!',
],
];
}
41 changes: 37 additions & 4 deletions tests/TestCase/Command/ModelCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -597,14 +597,16 @@ public function testGetAssociationsConstraints()

$expected = [
[
'alias' => 'Users',
'alias' => 'Senders',
'foreignKey' => 'sender_id',
'joinType' => 'INNER',
'className' => 'Users',
],
[
'alias' => 'Users',
'alias' => 'Receivers',
dereuromark marked this conversation as resolved.
Show resolved Hide resolved
'foreignKey' => 'receiver_id',
'joinType' => 'INNER',
'className' => 'Users',
],
];
$this->assertEquals($expected, $result['belongsTo']);
Expand Down Expand Up @@ -667,21 +669,52 @@ public function testBelongsToGeneration()
*/
public function testBelongsToGenerationConstraints()
{
$model = $this->getTableLocator()->get('Invitations');
$model = $this->getTableLocator()->get('Relations');
$command = new ModelCommand();
$command->connection = 'test';
$result = $command->findBelongsTo($model, []);
$expected = [
'belongsTo' => [
[
'alias' => 'Users',
'foreignKey' => 'user_id',
'joinType' => 'INNER',
],
[
'alias' => 'Others',
'foreignKey' => 'other_id',
'joinType' => 'INNER',
'className' => 'Users',
],
],
];
$this->assertEquals($expected, $result);
}

/**
* Test that belongsTo association generation uses aliased constraints on the table
*
* @return void
*/
public function testBelongsToGenerationConstraintsAliased()
{
$model = $this->getTableLocator()->get('Invitations');
$command = new ModelCommand();
$command->connection = 'test';
$result = $command->findBelongsTo($model, []);
$expected = [
'belongsTo' => [
[
'alias' => 'Senders',
'foreignKey' => 'sender_id',
'joinType' => 'INNER',
'className' => 'Users',
],
[
'alias' => 'Users',
'alias' => 'Receivers',
'foreignKey' => 'receiver_id',
'joinType' => 'INNER',
'className' => 'Users',
],
],
];
Expand Down
1 change: 1 addition & 0 deletions tests/comparisons/Model/testBakeEntityCustomHidden.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \Bake\Test\App\Model\Entity\Comment[] $comments
* @property \Bake\Test\App\Model\Entity\Relation[] $relations
* @property \Bake\Test\App\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand Down
2 changes: 2 additions & 0 deletions tests/comparisons/Model/testBakeEntityFullContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \Bake\Test\App\Model\Entity\Comment[] $comments
* @property \Bake\Test\App\Model\Entity\Relation[] $relations
* @property \Bake\Test\App\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand All @@ -34,6 +35,7 @@ class User extends Entity
'created' => true,
'updated' => true,
'comments' => true,
'relations' => true,
'todo_items' => true,
];

Expand Down
1 change: 1 addition & 0 deletions tests/comparisons/Model/testBakeEntityHidden.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \Bake\Test\App\Model\Entity\Comment[] $comments
* @property \Bake\Test\App\Model\Entity\Relation[] $relations
* @property \Bake\Test\App\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand Down
1 change: 1 addition & 0 deletions tests/comparisons/Model/testBakeEntitySimple.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \Bake\Test\App\Model\Entity\Comment[] $comments
* @property \Bake\Test\App\Model\Entity\Relation[] $relations
* @property \Bake\Test\App\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand Down
1 change: 1 addition & 0 deletions tests/comparisons/Model/testBakeEntitySimpleUnchanged.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \Bake\Test\App\Model\Entity\Comment[] $comments
* @property \Bake\Test\App\Model\Entity\Relation[] $relations
* @property \Bake\Test\App\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand Down
2 changes: 2 additions & 0 deletions tests/comparisons/Model/testBakeEntityWithPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property \Cake\I18n\DateTime|null $updated
*
* @property \BakeTest\Model\Entity\Comment[] $comments
* @property \BakeTest\Model\Entity\Relation[] $relations
* @property \BakeTest\Model\Entity\TodoItem[] $todo_items
*/
class User extends Entity
Expand All @@ -34,6 +35,7 @@ class User extends Entity
'created' => true,
'updated' => true,
'comments' => true,
'relations' => true,
'todo_items' => true,
];

Expand Down
5 changes: 5 additions & 0 deletions tests/comparisons/Model/testBakeTableWithPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Users Model
*
* @property \BakeTest\Model\Table\CommentsTable&\Cake\ORM\Association\HasMany $Comments
* @property \BakeTest\Model\Table\RelationsTable&\Cake\ORM\Association\HasMany $Relations
* @property \BakeTest\Model\Table\TodoItemsTable&\Cake\ORM\Association\HasMany $TodoItems
*
* @method \BakeTest\Model\Entity\User newEmptyEntity()
Expand Down Expand Up @@ -52,6 +53,10 @@ public function initialize(array $config): void
'foreignKey' => 'user_id',
'className' => 'BakeTest.Comments',
]);
$this->hasMany('Relations', [
'foreignKey' => 'user_id',
'className' => 'BakeTest.Relations',
]);
$this->hasMany('TodoItems', [
'foreignKey' => 'user_id',
'className' => 'BakeTest.TodoItems',
Expand Down
4 changes: 4 additions & 0 deletions tests/comparisons/Model/testBakeWithRulesUnique.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Users Model
*
* @property \Bake\Test\App\Model\Table\CommentsTable&\Cake\ORM\Association\HasMany $Comments
* @property \Bake\Test\App\Model\Table\RelationsTable&\Cake\ORM\Association\HasMany $Relations
* @property \Bake\Test\App\Model\Table\TodoItemsTable&\Cake\ORM\Association\HasMany $TodoItems
*
* @method \Bake\Test\App\Model\Entity\User newEmptyEntity()
Expand Down Expand Up @@ -51,6 +52,9 @@ public function initialize(array $config): void
$this->hasMany('Comments', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Relations', [
'foreignKey' => 'user_id',
]);
$this->hasMany('TodoItems', [
'foreignKey' => 'user_id',
]);
Expand Down
28 changes: 28 additions & 0 deletions tests/schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,34 @@
],
'constraints' => ['primary' => ['type' => 'primary', 'columns' => ['id']]],
],
[
'table' => 'relations',
'columns' => [
'id' => ['type' => 'integer'],
'user_id' => ['type' => 'integer', 'null' => false],
'other_id' => ['type' => 'integer', 'null' => false],
'body' => 'text',
'created' => 'datetime',
'updated' => 'datetime',
],
'constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id']],
'user_idx' => [
'type' => 'foreign',
'columns' => ['user_id'],
'references' => ['users', 'id'],
'update' => 'noAction',
'delete' => 'noAction',
],
'other_idx' => [
'type' => 'foreign',
'columns' => ['other_id'],
'references' => ['users', 'id'],
'update' => 'noAction',
'delete' => 'noAction',
],
],
],
[
'table' => 'invitations',
'columns' => [
Expand Down
Loading