-
-
Notifications
You must be signed in to change notification settings - Fork 469
Expand file tree
/
Copy pathAllDirective.php
More file actions
129 lines (107 loc) · 4.61 KB
/
Copy pathAllDirective.php
File metadata and controls
129 lines (107 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
namespace Nuwave\Lighthouse\Schema\Directives;
use GraphQL\Error\Error;
use GraphQL\Language\AST\FieldDefinitionNode;
use GraphQL\Language\AST\ObjectTypeDefinitionNode;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Collection;
use Laravel\Scout\Builder as ScoutBuilder;
use Nuwave\Lighthouse\Execution\ResolveInfo;
use Nuwave\Lighthouse\Schema\AST\DocumentAST;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Select\SelectHelper;
use Nuwave\Lighthouse\Support\Contracts\FieldManipulator;
use Nuwave\Lighthouse\Support\Contracts\FieldResolver;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
class AllDirective extends BaseDirective implements FieldResolver, FieldManipulator
{
public static function definition(): string
{
return /** @lang GraphQL */ <<<'GRAPHQL'
"""
Fetch all Eloquent models and return the collection as the result.
"""
directive @all(
"""
Specify the class name of the model to use.
This is only needed when the default model detection does not work.
Mutually exclusive with `builder`.
"""
model: String
"""
Point to a function that provides a Query Builder instance.
Consists of two parts: a class name and a method name, seperated by an `@` symbol.
If you pass only a class name, the method name defaults to `__invoke`.
Mutually exclusive with `model`.
"""
builder: String
"""
Apply scopes to the underlying query.
"""
scopes: [String!]
) on FIELD_DEFINITION
GRAPHQL;
}
public function resolveField(FieldValue $fieldValue): FieldValue
{
$fieldValue->setResolver(function ($root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Collection {
if ($this->directiveHasArgument('builder')) {
$builderResolver = $this->getResolverFromArgument('builder');
$query = $builderResolver($root, $args, $context, $resolveInfo);
assert(
$query instanceof QueryBuilder || $query instanceof EloquentBuilder || $query instanceof ScoutBuilder || $query instanceof Relation,
"The method referenced by the builder argument of the @{$this->name()} directive on {$this->nodeName()} must return a Builder or Relation."
);
} else {
$query = $this->getModelClass()::query();
}
$builder = $resolveInfo
->enhanceBuilder(
$query,
$this->directiveArgValue('scopes', [])
);
if (config('lighthouse.optimized_selects')) {
if ($builder instanceof EloquentBuilder) {
$fieldSelection = array_keys($resolveInfo->getFieldSelection(1));
$model = $builder->getModel();
$selectColumns = SelectHelper::getSelectColumns(
$this->definitionNode,
$fieldSelection,
get_class($model)
);
if (empty($selectColumns)) {
throw new Error('The select column is empty.');
}
$query = $builder->getQuery();
if (null !== $query->columns) {
$bindings = $query->getRawBindings();
$expressions = array_filter($query->columns, function ($column) {
return $column instanceof Expression;
});
$builder = $builder->select(array_unique(array_merge($selectColumns, $expressions)));
$builder = $builder->addBinding($bindings['select'], 'select');
} else {
$builder = $builder->select($selectColumns);
}
/** @var string|string[] $keyName */
$keyName = $model->getKeyName();
if (is_string($keyName)) {
$keyName = [$keyName];
}
foreach ($keyName as $name) {
$query->orderBy($name);
}
}
}
return $builder->get();
});
return $fieldValue;
}
public function manipulateFieldDefinition(DocumentAST &$documentAST, FieldDefinitionNode &$fieldDefinition, ObjectTypeDefinitionNode &$parentType)
{
$this->validateMutuallyExclusiveArguments(['model', 'builder']);
}
}