Skip to content

Commit

Permalink
Implement @hasManyThrough directive
Browse files Browse the repository at this point in the history
  • Loading branch information
spawnia committed Jul 4, 2022
1 parent 1740293 commit 42302a5
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/Schema/Directives/HasManyThroughDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Nuwave\Lighthouse\Schema\Directives;

use Nuwave\Lighthouse\Support\Contracts\FieldManipulator;

class HasManyThroughDirective extends RelationDirective implements FieldManipulator
{
public static function definition(): string
{
return /** @lang GraphQL */ <<<'GRAPHQL'
"""
Corresponds to [the Eloquent relationship HasManyThrough](https://laravel.com/docs/eloquent-relationships#has-many-through).
"""
directive @hasManyThrough(
"""
Specify the relationship method name in the model class,
if it is named different from the field in the schema.
"""
relation: String
"""
Apply scopes to the underlying query.
"""
scopes: [String!]
"""
Allows to resolve the relation as a paginated list.
Allowed values: `paginator`, `connection`.
"""
type: HasManyThroughType
"""
Allow clients to query paginated lists without specifying the amount of items.
Overrules the `pagination.default_count` setting from `lighthouse.php`.
"""
defaultCount: Int
"""
Limit the maximum amount of items that clients can request from paginated lists.
Overrules the `pagination.max_count` setting from `lighthouse.php`.
"""
maxCount: Int
"""
Specify a custom type that implements the Edge interface
to extend edge object.
Only applies when using Relay style "connection" pagination.
"""
edgeType: String
) on FIELD_DEFINITION
"""
Options for the `type` argument of `@hasManyThrough`.
"""
enum HasManyThroughType {
"""
Offset-based pagination, similar to the Laravel default.
"""
PAGINATOR
"""
Offset-based pagination like the Laravel "Simple Pagination", which does not count the total number of records.
"""
SIMPLE
"""
Cursor-based pagination, compatible with the Relay specification.
"""
CONNECTION
}
GRAPHQL;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Tests\Integration\Schema\Directives;

use Tests\DBTestCase;
use Tests\Utils\Models\Comment;
use Tests\Utils\Models\Post;
use Tests\Utils\Models\Task;
use Tests\Utils\Models\User;

final class HasManyThroughDirectiveTest extends DBTestCase
{
public function testQueryHasManyThroughRelationship(): void
{
$this->schema = /** @lang GraphQL */ '
type Post {
id: ID!
}
type Task {
postComments: [Post!]! @hasManyThrough
}
type Query {
task: Task! @first
}
';

$user = factory(User::class)->create();
assert($user instanceof User);

$task = factory(Task::class)->create();
assert($task instanceof Task);

$post = factory(Post::class)->make();
assert($post instanceof Post);
$post->user()->associate($user);
$post->task()->associate($task);
$post->save();

$comments = factory(Comment::class, 2)->make();
foreach ($comments as $comment) {
assert($comment instanceof Comment);
$comment->user()->associate($user);
$comment->post()->associate($post);
$comment->save();
}

$this->graphQL(/** @lang GraphQL */ '
{
task {
postComments {
id
}
}
}
')->assertJsonCount(2, 'data.task.postComments');
}
}
6 changes: 6 additions & 0 deletions tests/Utils/Models/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
Expand Down Expand Up @@ -73,6 +74,11 @@ public function post(): HasOne
return $this->hasOne(Post::class);
}

public function postComments(): HasManyThrough
{
return $this->hasManyThrough(Comment::class, Post::class);
}

public function tags(): MorphToMany
{
return $this->morphToMany(Tag::class, 'taggable');
Expand Down

0 comments on commit 42302a5

Please sign in to comment.