Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions benchmarks/ScalarOverrideBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function setUp(): void
$this->schemaTypeLoader = new Schema([
'query' => $queryTypeLoader,
'typeLoader' => static fn (string $name): ?Type => $typesForLoader[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$queryTypeTypes = new ObjectType([
Expand Down
1 change: 1 addition & 0 deletions docs/class-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ Usage example:
types?: Types|null,
directives?: array<Directive>|null,
typeLoader?: TypeLoader|null,
typeLoaderSupportsScalars?: bool|null,
assumeValid?: bool|null,
astNode?: SchemaDefinitionNode|null,
extensionASTNodes?: array<SchemaExtensionNode>|null,
Expand Down
1 change: 1 addition & 0 deletions examples/06-per-schema-scalar-override/example.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
$schemaViaTypeLoader = new Schema([
'query' => $queryTypeForLoader,
'typeLoader' => static fn (string $name): ?Type => $types[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$result = GraphQL::executeQuery($schemaViaTypeLoader, '{ greeting(name: "World") }');
Expand Down
14 changes: 10 additions & 4 deletions src/Type/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,14 @@ public function getTypeMap(): array
$allReferencedTypes[$name] = $override;
}

if (isset($this->config->typeLoader)) {
$typeLoader = $this->config->getTypeLoader();
if ($typeLoader && $this->config->getTypeLoaderSupportsScalars()) {
foreach (Type::BUILT_IN_SCALAR_NAMES as $scalarName) {
if (isset($scalarOverrides[$scalarName])) {
continue;
}

$type = ($this->config->typeLoader)($scalarName);
$type = $typeLoader($scalarName);
if ($type instanceof ScalarType
&& $type->name === $scalarName
&& $type !== $builtInScalars[$scalarName]
Expand Down Expand Up @@ -362,11 +363,16 @@ public function hasType(string $name): bool
*/
private function loadType(string $typeName): ?Type
{
if (! isset($this->config->typeLoader)) {
$typeLoader = $this->config->getTypeLoader();
if (! $typeLoader) {
return $this->getTypeMap()[$typeName] ?? null;
}

$type = ($this->config->typeLoader)($typeName);
if (! $this->config->getTypeLoaderSupportsScalars() && in_array($typeName, Type::BUILT_IN_SCALAR_NAMES)) {
return null;
}

$type = $typeLoader($typeName);
if ($type === null) {
return null;
}
Expand Down
21 changes: 21 additions & 0 deletions src/Type/SchemaConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* types?: Types|null,
* directives?: array<Directive>|null,
* typeLoader?: TypeLoader|null,
* typeLoaderSupportsScalars?: bool|null,
* assumeValid?: bool|null,
* astNode?: SchemaDefinitionNode|null,
* extensionASTNodes?: array<SchemaExtensionNode>|null,
Expand Down Expand Up @@ -72,6 +73,8 @@ class SchemaConfig
*/
public $typeLoader;

public bool $typeLoaderSupportsScalars = false;

public bool $assumeValid = false;

public ?SchemaDefinitionNode $astNode = null;
Expand Down Expand Up @@ -121,6 +124,10 @@ public static function create(array $options = []): self
$config->setTypeLoader($options['typeLoader']);
}

if (isset($options['typeLoaderSupportsScalars'])) {
$config->setTypeLoaderSupportsScalars($options['typeLoaderSupportsScalars']);
}

if (isset($options['assumeValid'])) {
$config->setAssumeValid($options['assumeValid']);
}
Expand Down Expand Up @@ -298,6 +305,20 @@ public function setTypeLoader(?callable $typeLoader): self
return $this;
}

/** @api */
public function getTypeLoaderSupportsScalars(): bool
{
return $this->typeLoaderSupportsScalars;
}

/** @api */
public function setTypeLoaderSupportsScalars(bool $supportsScalars): self
{
$this->typeLoaderSupportsScalars = $supportsScalars;

return $this;
}

public function getAssumeValid(): bool
{
return $this->assumeValid;
Expand Down
27 changes: 27 additions & 0 deletions tests/Type/ScalarOverridesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function testTypeLoaderOverrideWorksEndToEnd(): void
$schema = new Schema([
'query' => $queryType,
'typeLoader' => static fn (string $name): ?Type => $types[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$schema->assertValid();
Expand All @@ -65,6 +66,7 @@ public function testTypeLoaderOverrideWorksInProductionMode(): void
$schema = new Schema([
'query' => $queryType,
'typeLoader' => static fn (string $name): ?Type => $types[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$result = GraphQL::executeQuery($schema, '{ greeting }');
Expand Down Expand Up @@ -117,6 +119,7 @@ public function testIntrospectionUsesOverriddenScalar(): void
$schema = new Schema([
'query' => $queryType,
'typeLoader' => static fn (string $name): ?Type => $types[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$result = GraphQL::executeQuery($schema, '{ __type(name: "Query") { fields { name } } }');
Expand All @@ -128,6 +131,28 @@ public function testIntrospectionUsesOverriddenScalar(): void
self::assertContains('GREETING', $fieldNames);
}

public function testTypeLoaderNotInvokedForScalarsWhenOptInNotSet(): void
{
$invocations = [];
$uppercaseString = self::createUppercaseString();
$queryType = self::createQueryType();
$types = ['Query' => $queryType, 'String' => $uppercaseString];

$schema = new Schema([
'query' => $queryType,
'typeLoader' => static function (string $name) use ($types, &$invocations): ?Type {
$invocations[] = $name;

return $types[$name] ?? null;
},
]);

$result = GraphQL::executeQuery($schema, '{ greeting }');

self::assertSame(['data' => ['greeting' => 'hello world']], $result->toArray());
self::assertNotContains('String', $invocations);
}

public function testTwoSchemasWithDifferentOverridesAreIndependent(): void
{
$uppercaseString = new CustomScalarType([
Expand All @@ -151,6 +176,7 @@ public function testTwoSchemasWithDifferentOverridesAreIndependent(): void
$schemaB = new Schema([
'query' => $queryTypeB,
'typeLoader' => static fn (string $name): ?Type => $typesB[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$resultA = GraphQL::executeQuery($schemaA, '{ greeting }');
Expand Down Expand Up @@ -194,6 +220,7 @@ public function testNonOverriddenScalarsAreUnaffected(): void
$schema = new Schema([
'query' => $queryType,
'typeLoader' => static fn (string $name): ?Type => $types[$name] ?? null,
'typeLoaderSupportsScalars' => true,
]);

$result = GraphQL::executeQuery($schema, '{ greeting count ratio active identifier }');
Expand Down