From f304838624d7037f6348db1f0b4deb4c2b85bb4e Mon Sep 17 00:00:00 2001 From: "Tim.Sterker" Date: Mon, 24 Oct 2022 15:17:31 +0200 Subject: [PATCH] fix: HasManyThrough and HasOneThrough not working --- src/HasParent.php | 2 +- .../ChildModelsAreAutomaticallyScopedTest.php | 56 +++++++++++++++++++ tests/Models/ChildNode.php | 24 ++++++++ tests/Models/Node.php | 13 +++++ tests/Models/NodeEdge.php | 10 ++++ tests/Models/ParentNode.php | 24 ++++++++ tests/TestCase.php | 16 ++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 tests/Models/ChildNode.php create mode 100644 tests/Models/Node.php create mode 100644 tests/Models/NodeEdge.php create mode 100644 tests/Models/ParentNode.php diff --git a/src/HasParent.php b/src/HasParent.php index d0cd1c9..9f1c49a 100644 --- a/src/HasParent.php +++ b/src/HasParent.php @@ -38,7 +38,7 @@ public static function bootHasParent(): void $instance = new static; if ($instance->parentHasHasChildrenTrait()) { - $query->where($instance->getTable().'.'.$instance->getInheritanceColumn(), $instance->classToAlias(get_class($instance))); + $query->where($query->getModel()->getTable().'.'.$instance->getInheritanceColumn(), $instance->classToAlias(get_class($instance))); } }); } diff --git a/tests/Features/ChildModelsAreAutomaticallyScopedTest.php b/tests/Features/ChildModelsAreAutomaticallyScopedTest.php index de690b2..3082dd7 100644 --- a/tests/Features/ChildModelsAreAutomaticallyScopedTest.php +++ b/tests/Features/ChildModelsAreAutomaticallyScopedTest.php @@ -4,7 +4,10 @@ use Parental\Tests\Models\Admin; use Parental\Tests\Models\Car; +use Parental\Tests\Models\ChildNode; use Parental\Tests\Models\Driver; +use Parental\Tests\Models\NodeEdge; +use Parental\Tests\Models\ParentNode; use Parental\Tests\Models\Passenger; use Parental\Tests\Models\Trip; use Parental\Tests\Models\User; @@ -71,4 +74,57 @@ function child_is_scoped_when_accessed_from_belongs_to_many() $this->assertCount(1, $trip->cars); $this->assertCount(2, $trip->vehicles); } + + /** @test */ + function child_is_scoped_when_accessed_from_has_one_through() + { + // Create root with children + $rootA = ParentNode::create(['name' => 'Root A']); + $childA = ChildNode::create(['name' => 'Child 1']); + $childB = ChildNode::create(['name' => 'Child 2']); + $childC = ChildNode::create(['name' => 'Child 3']); + NodeEdge::create(['parent_node_id' => $rootA->id, 'child_node_id' => $childA->id]); + NodeEdge::create(['parent_node_id' => $rootA->id, 'child_node_id' => $childB->id]); + + $this->assertInstanceOf(ParentNode::class, $childA->parent); + $this->assertInstanceOf(ParentNode::class, $childB->parent); + $this->assertNull($childC->parent); + + $this->assertCount(2, ChildNode::whereHas('parent')->get()); + $this->assertTrue(ChildNode::whereId($childA->id)->whereHas('parent')->exists()); + $this->assertTrue(ChildNode::whereId($childB->id)->whereHas('parent')->exists()); + $this->assertFalse(ChildNode::whereId($childC->id)->whereHas('parent')->exists()); + } + + /** @test */ + function child_is_scoped_when_accessed_from_has_many_through() + { + // Create root with children + $rootA = ParentNode::create(['name' => 'Root A']); + $childA = ChildNode::create(['name' => 'Child 1']); + $childB = ChildNode::create(['name' => 'Child 2']); + $childC = ChildNode::create(['name' => 'Child 3']); + NodeEdge::create(['parent_node_id' => $rootA->id, 'child_node_id' => $childA->id]); + NodeEdge::create(['parent_node_id' => $rootA->id, 'child_node_id' => $childB->id]); + NodeEdge::create(['parent_node_id' => $rootA->id, 'child_node_id' => $childC->id]); + + // Create different root with different children + $rootB = ParentNode::create(['name' => 'Root B']); + $childX = ChildNode::create(['name' => 'Child X']); + NodeEdge::create(['parent_node_id' => $rootB->id, 'child_node_id' => $childX->id]); + + // Create different root children any children + $rootC = ParentNode::create(['name' => 'Root C']); + + $this->assertCount(3, $rootA->children); + $this->assertContainsOnlyInstancesOf(ChildNode::class, $rootA->children); + + $this->assertCount(1, $rootB->children); + $this->assertContainsOnlyInstancesOf(ChildNode::class, $rootB->children); + + $this->assertCount(2, ParentNode::whereHas('children')->get()); + $this->assertTrue(ParentNode::whereId($rootA->id)->whereHas('children')->exists()); + $this->assertTrue(ParentNode::whereId($rootB->id)->whereHas('children')->exists()); + $this->assertFalse(ParentNode::whereId($rootC->id)->whereHas('children')->exists()); + } } diff --git a/tests/Models/ChildNode.php b/tests/Models/ChildNode.php new file mode 100644 index 0000000..a31365e --- /dev/null +++ b/tests/Models/ChildNode.php @@ -0,0 +1,24 @@ +hasOneThrough( + ParentNode::class, + NodeEdge::class, + 'child_node_id', + 'id', + 'id', + 'parent_node_id', + ); + } +} diff --git a/tests/Models/Node.php b/tests/Models/Node.php new file mode 100644 index 0000000..2280e7d --- /dev/null +++ b/tests/Models/Node.php @@ -0,0 +1,13 @@ +hasManyThrough( + ChildNode::class, + NodeEdge::class, + 'parent_node_id', + 'id', + 'id', + 'child_node_id', + ); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 1c69ff3..375fdcc 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,6 +5,8 @@ use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Schema; use Orchestra\Testbench\TestCase as BaseTestCase; +use Parental\Tests\Models\LeCredential; +use Parental\Tests\Models\OorCredential; class TestCase extends BaseTestCase { @@ -82,5 +84,19 @@ public function runMigrations() $table->morphs('partable'); $table->timestamps(); }); + + Schema::create('nodes', function ($table) { + $table->increments('id'); + $table->string('type'); + $table->string('name'); + $table->timestamps(); + }); + + Schema::create('node_edges', function ($table) { + $table->increments('id'); + $table->string('parent_node_id'); + $table->string('child_node_id'); + $table->timestamps(); + }); } }