1 |
<?php
|
|
2 |
|
|
3 |
namespace Nuwave\Lighthouse\OrderBy; |
|
4 |
|
|
5 |
use GraphQL\Language\AST\FieldDefinitionNode; |
|
6 |
use GraphQL\Language\AST\InputValueDefinitionNode; |
|
7 |
use GraphQL\Language\AST\ObjectTypeDefinitionNode; |
|
8 |
use GraphQL\Language\Parser; |
|
9 |
use Nuwave\Lighthouse\Schema\AST\ASTHelper; |
|
10 |
use Nuwave\Lighthouse\Schema\AST\DocumentAST; |
|
11 |
use Nuwave\Lighthouse\Schema\Directives\BaseDirective; |
|
12 |
use Nuwave\Lighthouse\Support\Contracts\ArgBuilderDirective; |
|
13 |
use Nuwave\Lighthouse\Support\Contracts\ArgDirectiveForArray; |
|
14 |
use Nuwave\Lighthouse\Support\Contracts\ArgManipulator; |
|
15 |
use Nuwave\Lighthouse\Support\Contracts\FieldBuilderDirective; |
|
16 |
use Nuwave\Lighthouse\Support\Traits\GeneratesColumnsEnum; |
|
17 |
|
|
18 |
class OrderByDirective extends BaseDirective implements ArgBuilderDirective, ArgDirectiveForArray, ArgManipulator, FieldBuilderDirective |
|
19 |
{
|
|
20 |
use GeneratesColumnsEnum; |
|
21 |
|
|
22 | 1 |
public static function definition(): string |
23 |
{
|
|
24 |
return /** @lang GraphQL */ <<<'GRAPHQL' |
|
25 | 1 |
"""
|
26 |
Sort a result list by one or more given columns.
|
|
27 |
"""
|
|
28 |
directive @orderBy(
|
|
29 |
"""
|
|
30 |
Restrict the allowed column names to a well-defined list.
|
|
31 |
This improves introspection capabilities and security.
|
|
32 |
Mutually exclusive with the `columnsEnum` argument.
|
|
33 |
Only used when the directive is added on an argument.
|
|
34 |
"""
|
|
35 |
columns: [String!]
|
|
36 |
|
|
37 |
"""
|
|
38 |
Use an existing enumeration type to restrict the allowed columns to a predefined list.
|
|
39 |
This allowes you to re-use the same enum for multiple fields.
|
|
40 |
Mutually exclusive with the `columns` argument.
|
|
41 |
Only used when the directive is added on an argument.
|
|
42 |
"""
|
|
43 |
columnsEnum: String
|
|
44 |
|
|
45 |
"""
|
|
46 |
The database column for which the order by clause will be applied on.
|
|
47 |
Only used when the directive is added on a field.
|
|
48 |
"""
|
|
49 |
column: String
|
|
50 |
|
|
51 |
"""
|
|
52 |
The direction of the order by clause.
|
|
53 |
Only used when the directive is added on a field.
|
|
54 |
"""
|
|
55 |
direction: OrderByDirection = ASC
|
|
56 |
) on ARGUMENT_DEFINITION | FIELD_DEFINITION
|
|
57 |
|
|
58 |
"""
|
|
59 |
Options for the `direction` argument on `@orderBy`.
|
|
60 |
"""
|
|
61 |
enum OrderByDirection {
|
|
62 |
"""
|
|
63 |
Sort in ascending order.
|
|
64 |
"""
|
|
65 |
ASC
|
|
66 |
|
|
67 |
"""
|
|
68 |
Sort in descending order.
|
|
69 |
"""
|
|
70 |
DESC
|
|
71 |
}
|
|
72 |
GRAPHQL; |
|
73 |
}
|
|
74 |
|
|
75 |
/**
|
|
76 |
* Apply an "ORDER BY" clause.
|
|
77 |
*
|
|
78 |
* @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder
|
|
79 |
* @param array<array<string, string>> $value
|
|
80 |
* @return \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder
|
|
81 |
*/
|
|
82 | 1 |
public function handleBuilder($builder, $value): object |
83 |
{
|
|
84 | 1 |
foreach ($value as $orderByClause) { |
85 | 1 |
$builder->orderBy( |
86 | 1 |
$orderByClause['column'], |
87 | 1 |
$orderByClause['order'] |
88 |
);
|
|
89 |
}
|
|
90 |
|
|
91 | 1 |
return $builder; |
92 |
}
|
|
93 |
|
|
94 | 1 |
public function manipulateArgDefinition( |
95 |
DocumentAST &$documentAST, |
|
96 |
InputValueDefinitionNode &$argDefinition, |
|
97 |
FieldDefinitionNode &$parentField, |
|
98 |
ObjectTypeDefinitionNode &$parentType |
|
99 |
): void { |
|
100 | 1 |
if ($this->hasAllowedColumns()) { |
101 | 1 |
$restrictedOrderByName = ASTHelper::qualifiedArgType($argDefinition, $parentField, $parentType).'OrderByClause'; |
102 | 1 |
$argDefinition->type = Parser::typeReference("[$restrictedOrderByName!]"); |
103 | 1 |
$allowedColumnsEnumName = $this->generateColumnsEnum($documentAST, $argDefinition, $parentField, $parentType); |
104 |
|
|
105 |
$documentAST
|
|
106 | 1 |
->setTypeDefinition( |
107 | 1 |
OrderByServiceProvider::createOrderByClauseInput( |
108 | 1 |
$restrictedOrderByName, |
109 | 1 |
"Order by clause for the `{$argDefinition->name->value}` argument on the query `{$parentField->name->value}`.", |
110 | 1 |
$allowedColumnsEnumName
|
111 |
)
|
|
112 |
);
|
|
113 |
} else { |
|
114 | 1 |
$argDefinition->type = Parser::typeReference('['.OrderByServiceProvider::DEFAULT_ORDER_BY_CLAUSE.'!]'); |
115 |
}
|
|
116 |
}
|
|
117 |
|
|
118 |
/**
|
|
119 |
* @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder
|
|
120 |
* @return \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder
|
|
121 |
*/
|
|
122 | 1 |
public function handleFieldBuilder(object $builder): object |
123 |
{
|
|
124 | 1 |
return $builder->orderBy( |
125 | 1 |
$this->directiveArgValue('column'), |
126 | 1 |
$this->directiveArgValue('direction', 'ASC') |
127 |
);
|
|
128 |
}
|
|
129 |
}
|
Read our documentation on viewing source code .