diff --git a/src/Tools/Utils.php b/src/Tools/Utils.php index 027395ca..27ceb0b5 100644 --- a/src/Tools/Utils.php +++ b/src/Tools/Utils.php @@ -269,14 +269,15 @@ public static function getModelFactory(string $modelName, array $states = [], ar $relationChain = explode('.', $relation); $relationVector = array_shift($relationChain); - $relationModel = get_class((new $modelName())->{$relationVector}()->getModel()); - $relationType = get_class((new $modelName())->{$relationVector}()); + $relation = (new $modelName())->{$relationVector}(); + $relationType = get_class($relation); + $relationModel = get_class($relation->getModel()); $factoryChain = empty($relationChain) ? call_user_func_array([$relationModel, 'factory'], []) : Utils::getModelFactory($relationModel, $states, [implode('.', $relationChain)]); - if ($relationType === BelongsToMany::class) { + if ($relation instanceof BelongsToMany) { $pivot = method_exists($factory, 'pivot' . $relationVector) ? $factory->{'pivot' . $relationVector}() : []; diff --git a/tests/Fixtures/TestPost.php b/tests/Fixtures/TestPost.php index 5d75c3ed..de05a4da 100644 --- a/tests/Fixtures/TestPost.php +++ b/tests/Fixtures/TestPost.php @@ -2,12 +2,26 @@ namespace Knuckles\Scribe\Tests\Fixtures; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\MorphToMany; class TestPost extends Model { + use HasFactory; + public function getRouteKeyName() { return 'slug'; } + + protected static function newFactory() + { + return TestPostFactory::new(); + } + + public function tags(): MorphToMany + { + return $this->morphToMany(TestTag::class, 'taggable')->withPivot('priority'); + } } diff --git a/tests/Fixtures/TestPostApiResource.php b/tests/Fixtures/TestPostApiResource.php new file mode 100644 index 00000000..509a6efa --- /dev/null +++ b/tests/Fixtures/TestPostApiResource.php @@ -0,0 +1,27 @@ + $this->id, + 'title' => $this->title , + 'body' => $this->body, + 'tags' => $this->whenLoaded('tags', function () { + return TestTagApiResource::collection($this->tags); + }), + ]; + } +} diff --git a/tests/Fixtures/TestPostFactory.php b/tests/Fixtures/TestPostFactory.php new file mode 100644 index 00000000..909b351e --- /dev/null +++ b/tests/Fixtures/TestPostFactory.php @@ -0,0 +1,26 @@ + 1, + 'title' => 'Test title', + 'body' => 'random body', + ]; + } + + public function pivotTags(): array + { + return [ + 'priority' => "high" + ]; + } +} diff --git a/tests/Fixtures/TestTag.php b/tests/Fixtures/TestTag.php new file mode 100644 index 00000000..1ef89caa --- /dev/null +++ b/tests/Fixtures/TestTag.php @@ -0,0 +1,22 @@ +morphedByMany(TestPost::class, 'taggable')->withPivot('priority'); + } +} diff --git a/tests/Fixtures/TestTagApiResource.php b/tests/Fixtures/TestTagApiResource.php new file mode 100644 index 00000000..af42e218 --- /dev/null +++ b/tests/Fixtures/TestTagApiResource.php @@ -0,0 +1,26 @@ + $this->id, + 'name' => $this->name , + 'priority' => $this->whenPivotLoaded('taggables', function () { + return $this->pivot->priority; + }), + ]; + } +} diff --git a/tests/Fixtures/TestTagFactory.php b/tests/Fixtures/TestTagFactory.php new file mode 100644 index 00000000..e419e052 --- /dev/null +++ b/tests/Fixtures/TestTagFactory.php @@ -0,0 +1,18 @@ + 1, + 'name' => 'tag 1', + ]; + } +} diff --git a/tests/Strategies/Responses/UseApiResourceTagsTest.php b/tests/Strategies/Responses/UseApiResourceTagsTest.php index 3888a07a..7e8d1257 100644 --- a/tests/Strategies/Responses/UseApiResourceTagsTest.php +++ b/tests/Strategies/Responses/UseApiResourceTagsTest.php @@ -501,6 +501,62 @@ public function loads_specified_many_to_many_relations_for_generated_model_with_ ], $results); } + /** @test */ + public function loads_specified_morph_to_many_relations_for_generated_model_with_pivot() + { + Schema::create('test_posts', function (Blueprint $table) { + $table->id(); + $table->string('title'); + $table->string('body'); + $table->timestamps(); + }); + + Schema::create('test_tags', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->timestamps(); + }); + + Schema::create('taggables', function (Blueprint $table) { + $table->id(); + $table->string('test_tag_id'); + $table->string('taggable_type'); + $table->string('taggable_id'); + $table->string('priority'); + }); + + $config = new DocumentationConfig([]); + + $route = new Route(['POST'], "/somethingRandom", ['uses' => [TestController::class, 'dummy']]); + + $strategy = new UseApiResourceTags($config); + $tags = [ + new Tag('apiResource', '\Knuckles\Scribe\Tests\Fixtures\TestPostApiResource'), + new Tag('apiResourceModel', '\Knuckles\Scribe\Tests\Fixtures\TestPost with=tags'), + ]; + $results = $strategy->getApiResourceResponseFromTags($strategy->getApiResourceTag($tags), $tags, ExtractedEndpointData::fromRoute($route)); + + $this->assertArraySubset([ + [ + 'status' => 200, + 'content' => json_encode([ + 'data' => [ + 'id' => 1, + 'title' => 'Test title', + 'body' => 'random body', + 'tags' => [ + [ + 'id' => 1, + 'name' => 'tag 1', + 'priority' => "high" + ], + ], + ], + ]), + ], + ], $results); + } + /** @test */ public function can_parse_apiresourcecollection_tags() {