Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -3589,7 +3589,8 @@ public function createRelationship(
}

if (
$attribute->getAttribute('type') === self::VAR_RELATIONSHIP
$twoWay
&& $attribute->getAttribute('type') === self::VAR_RELATIONSHIP
&& \strtolower($attribute->getAttribute('options')['twoWayKey']) === \strtolower($twoWayKey)
&& $attribute->getAttribute('options')['relatedCollection'] === $relatedCollection->getId()
) {
Expand Down
58 changes: 24 additions & 34 deletions tests/e2e/Adapter/Scopes/Relationships/OneToOneTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -1024,26 +1024,37 @@ public function testIdenticalTwoWayKeyRelationship(): void
id: 'child1'
);

$result = $database->createRelationship(
collection: 'parent',
relatedCollection: 'child',
type: Database::RELATION_ONE_TO_MANY,
id: 'children',
);
$this->assertTrue($result);

$result = $database->createRelationship(
collection: 'parent',
relatedCollection: 'child',
type: Database::RELATION_ONE_TO_MANY,
id: 'childrenById',
twoWayKey: 'parent_id'
);
$this->assertTrue($result);

try {
$database->createRelationship(
collection: 'parent',
relatedCollection: 'child',
type: Database::RELATION_ONE_TO_MANY,
id: 'children',
twoWay: true,
id: 'twoWayChildren',
twoWayKey: 'parent_id'
);
$this->fail('Failed to throw Exception');
} catch (Exception $e) {
$this->assertEquals('Related attribute already exists', $e->getMessage());
}
Comment on lines 1044 to 1056
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Exception asserted against a one-way relationship's metadata

The DuplicateException is thrown here because childrenById (a one-way relationship) happens to carry the same twoWayKey value in its stored options. Since one-way relationships do not create a real reverse attribute in the related collection, the error message 'Related attribute already exists' is misleading — the attribute does not actually exist at the schema level.

More importantly, this test does not exercise the core guard: a genuine two-way vs two-way reverse-key collision, where the reverse attribute was actually created in the related collection. A stronger coverage would first create a twoWay: true relationship, then attempt to create a second twoWay: true relationship pointing at the same relatedCollection with an identical reverse key, and assert DuplicateException is thrown. Without that scenario, a future change could accidentally weaken the guard for real two-way key conflicts and the test suite would not catch the regression.


$database->createRelationship(
collection: 'parent',
relatedCollection: 'child',
type: Database::RELATION_ONE_TO_MANY,
id: 'children',
twoWayKey: 'parent_id'
);

$collection = $database->getCollection('parent');
$attributes = $collection->getAttribute('attributes', []);
foreach ($attributes as $attribute) {
Expand All @@ -1052,35 +1063,14 @@ public function testIdenticalTwoWayKeyRelationship(): void
}

if ($attribute['key'] === 'children') {
$this->assertEquals('parent', $attribute['options']['twoWayKey']);
}

if ($attribute['key'] === 'childrenById') {
$this->assertEquals('parent_id', $attribute['options']['twoWayKey']);
}
}

$database->createDocument('parent', new Document([
'$permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
'child1' => [
'$id' => 'foo',
'$permissions' => [Permission::read(Role::any())],
],
'children' => [
[
'$id' => 'bar',
'$permissions' => [Permission::read(Role::any())],
],
],
]));

$documents = $database->find('parent', []);
$document = array_pop($documents);
$this->assertArrayHasKey('child1', $document);
$this->assertEquals('foo', $document->getAttribute('child1')->getId());
$this->assertArrayHasKey('children', $document);
$this->assertEquals('bar', $document->getAttribute('children')[0]->getId());

try {
$database->updateRelationship(
collection: 'parent',
Expand Down
Loading