Skip to content

Commit

Permalink
feat(graphql): Support of extend scalar/etc X to add operators.
Browse files Browse the repository at this point in the history
(cherry picked from commit a9dd684)
  • Loading branch information
LastDragon-ru committed Feb 15, 2024
1 parent 406f5d5 commit c7bd1c4
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 3 deletions.
9 changes: 9 additions & 0 deletions packages/graphql/src/SearchBy/Directives/DirectiveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,15 @@ public function getTypeDefinition(
$locator->setResolved('customComplexOperator', $directive::class);
},
],
'scalars' => [
static function (self $test): GraphQLExpected {
return (new GraphQLExpected(
$test::getTestData()->file('~scalars-expected.graphql'),
));
},
'~scalars.graphql',
null,
],
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
"""
Use Input as Search Conditions for the current Builder.
"""
directive @searchBy
on
| ARGUMENT_DEFINITION

directive @searchByOperatorAllOf
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorEqual
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorIn
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorIsNotNull
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorIsNull
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorLessThan
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorLessThanOrEqual
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorNotEqual
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

directive @searchByOperatorProperty
on
| ENUM
| INPUT_FIELD_DEFINITION
| SCALAR

"""
Extends the list of operators by the operators from the specified `type`.
"""
directive @searchByOperators(
type: String!
)
on
| ENUM
| SCALAR

enum EnumA
@searchByOperatorIn
{
A
}

enum SearchByTypeFlag {
yes
}

"""
Available conditions for `input A` (only one property allowed at a time).
"""
input SearchByConditionA {
"""
Property condition.
"""
a: SearchByScalarMixed
@searchByOperatorProperty

"""
All of the conditions must be true.
"""
allOf: [SearchByConditionA!]
@searchByOperatorAllOf

"""
Property condition.
"""
b: SearchByScalarDateOrNull
@searchByOperatorProperty

"""
Property condition.
"""
c: SearchByEnumEnumAOrNull
@searchByOperatorProperty
}

"""
Available operators for `enum EnumA` (only one operator allowed at a time).
"""
input SearchByEnumEnumAOrNull {
"""
Within a set of values.
"""
in: [EnumA!]
@searchByOperatorIn

"""
Is NOT NULL?
"""
isNotNull: SearchByTypeFlag
@searchByOperatorIsNotNull

"""
Is NULL?
"""
isNull: SearchByTypeFlag
@searchByOperatorIsNull
}

"""
Available operators for `scalar Date` (only one operator allowed at a time).
"""
input SearchByScalarDateOrNull {
"""
Equal (`=`).
"""
equal: Date
@searchByOperatorEqual

"""
Is NOT NULL?
"""
isNotNull: SearchByTypeFlag
@searchByOperatorIsNotNull

"""
Is NULL?
"""
isNull: SearchByTypeFlag
@searchByOperatorIsNull

"""
Less than (`<`).
"""
lessThan: Date
@searchByOperatorLessThan

"""
Less than or equal to (`<=`).
"""
lessThanOrEqual: Date
@searchByOperatorLessThanOrEqual

"""
Not Equal (`!=`).
"""
notEqual: Date
@searchByOperatorNotEqual
}

"""
Available operators for `scalar Mixed` (only one operator allowed at a time).
"""
input SearchByScalarMixed {
"""
Equal (`=`).
"""
equal: Mixed
@searchByOperatorEqual

"""
Not Equal (`!=`).
"""
notEqual: Mixed
@searchByOperatorNotEqual
}

scalar Date
@scalar(
class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date"
)
@searchByOperators(
type: "Boolean"
)
@searchByOperatorLessThan
@searchByOperatorLessThanOrEqual

"""
The `String` scalar type represents textual data, represented as UTF-8
character sequences. The String type is most often used by GraphQL to
represent free-form human-readable text.
"""
scalar Mixed
@scalar(
class: "GraphQL\\Type\\Definition\\StringType"
)
@searchByOperatorEqual

type Query {
test(
where: SearchByConditionA
@searchBy
): ID!
@all
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
type Query {
test(where: A @searchBy): ID! @all
}

input A {
a: Mixed!
b: Date
c: EnumA
}

scalar Date
@scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")
@searchByOperators(type: "Boolean")
@searchByOperatorLessThan
@searchByOperatorLessThanOrEqual

enum EnumA
@searchByOperatorIn
{
A
}

scalar SearchByExtra
@searchByOperatorAllOf

scalar Mixed
@scalar(class: "GraphQL\\Type\\Definition\\StringType")
@searchByOperatorEqual

extend scalar Mixed
@searchByOperatorNotEqual
28 changes: 25 additions & 3 deletions packages/graphql/src/Utils/AstManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@
use Nuwave\Lighthouse\Support\Contracts\Directive;

use function array_merge;
use function array_udiff;
use function assert;
use function is_string;
use function json_encode;
use function spl_object_id;
use function sprintf;
use function trim;

Expand Down Expand Up @@ -323,15 +325,28 @@ public function getDirectives(
$directives = [];

if ($node instanceof NamedType) {
// From Node itself (it will also include directive from extension nodes)
if ($node->astNode()) {
$directives = $this->getDirectives($node->astNode(), $class, $callback);
}

foreach ($node->extensionASTNodes() as $extensionNode) {
// Form Node's extensions but without already added
$typeExtensionNodes = $node->extensionASTNodes();
$astExtensionNodes = $this->getDocument()->typeExtensions[$node->name()] ?? [];
$extensionNodes = array_udiff(
$typeExtensionNodes,
$astExtensionNodes,
static function (object $a, object $b): int {
return spl_object_id($a) <=> spl_object_id($b);
},
);

foreach ($extensionNodes as $extensionNode) {
$directives = array_merge($directives, $this->getDirectives($extensionNode, $class, $callback));
}
} elseif ($node instanceof Node) {
$associated = $this->getDirectiveLocator()->associated($node)->all();
// From Node itself
$associated = $this->getDirectiveLocator()->associated($node);

if ($class !== null || $callback !== null) {
foreach ($associated as $directive) {
Expand All @@ -349,7 +364,14 @@ public function getDirectives(
$directives[] = $directive;
}
} else {
$directives = $associated;
$directives = $associated->all();
}

// From extensions ("extend scalar ..."/etc)
if ($node instanceof TypeDefinitionNode) {
foreach ($this->getDocument()->typeExtensions[$node->getName()->value] ?? [] as $extensionNode) {
$directives = array_merge($directives, $this->getDirectives($extensionNode, $class, $callback));
}
}
} elseif ($node instanceof InputObjectField || $node instanceof FieldDefinition || $node instanceof Argument) {
if ($node->astNode) {
Expand Down
1 change: 1 addition & 0 deletions packages/graphql/src/Utils/AstManipulatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ public function testGetDirectives(): void {
[
AstManipulatorTest_BDirective::class,
AstManipulatorTest_CDirective::class,
AstManipulatorTest_ADirective::class,
],
array_map(
$map,
Expand Down

0 comments on commit c7bd1c4

Please sign in to comment.