Skip to content

Commit

Permalink
feat(graphql): parameter graphql arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Mar 29, 2024
1 parent 8cfefb9 commit 769598b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 35 deletions.
28 changes: 0 additions & 28 deletions src/Doctrine/Common/Filter/UrlPatternToFilterContextTrait.php

This file was deleted.

112 changes: 107 additions & 5 deletions src/GraphQl/Type/FieldsBuilder.php
Expand Up @@ -290,9 +290,111 @@ public function resolveResourceArgs(array $args, Operation $operation): array
$args[$id]['type'] = $this->typeConverter->resolveType($arg['type']);
}

/*
* This is @experimental, read the comment on the parameterToObjectType function as additional information.
*/
foreach ($operation->getParameters() ?? [] as $parameter) {
$key = $parameter->getKey();

Check warning on line 297 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L296-L297

Added lines #L296 - L297 were not covered by tests

if (str_contains($key, ':property')) {
if (!($filterId = $parameter->getFilter()) || !$this->filterLocator->has($filterId)) {
continue;

Check warning on line 301 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L299-L301

Added lines #L299 - L301 were not covered by tests
}

$parsedKey = explode('[:property]', $key);
$flattenFields = [];
foreach ($this->filterLocator->get($filterId)->getDescription($operation->getClass()) as $key => $value) {
$values = [];
parse_str($key, $values);
if (isset($values[$parsedKey[0]])) {
$values = $values[$parsedKey[0]];

Check warning on line 310 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L304-L310

Added lines #L304 - L310 were not covered by tests
}

$name = key($values);
$flattenFields[] = ['name' => $name, 'required' => $value['required'] ?? null, 'description' => $value['description'] ?? null, 'leafs' => $values[$name], 'type' => $value['type'] ?? 'string'];

Check warning on line 314 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L313-L314

Added lines #L313 - L314 were not covered by tests
}

$args[$parsedKey[0]] = $this->parameterToObjectType($flattenFields, $parsedKey[0]);
continue;

Check warning on line 318 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L317-L318

Added lines #L317 - L318 were not covered by tests
}

$args[$key] = ['type' => GraphQLType::string()];

Check warning on line 321 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L321

Added line #L321 was not covered by tests

if ($parameter->getRequired()) {
$args[$key]['type'] = GraphQLType::nonNull($args[$key]['type']);

Check warning on line 324 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L323-L324

Added lines #L323 - L324 were not covered by tests
}
}

return $args;
}

/**
* Transform the result of a parse_str to a GraphQL object type.
* We should consider merging getFilterArgs and this, `getFilterArgs` uses `convertType` whereas we assume that parameters have only scalar types.
* Note that this method has a lower complexity then the `getFilterArgs` one.
* TODO: Is there a use case with an argument being a complex type (eg: a Resource, Enum etc.)?
*
* @param array<array{name: string, required: bool|null, description: string|null, leafs: string|array, type: string}> $flattenFields
*/
private function parameterToObjectType(array $flattenFields, string $name): InputObjectType

Check warning on line 339 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L339

Added line #L339 was not covered by tests
{
$fields = [];
foreach ($flattenFields as $field) {
$key = $field['name'];
$type = $this->getParameterType(\in_array($field['type'], Type::$builtinTypes, true) ? new Type($field['type'], !$field['required']) : new Type('object', !$field['required'], $field['type']));

Check warning on line 344 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L341-L344

Added lines #L341 - L344 were not covered by tests

if (\is_array($l = $field['leafs'])) {
if (0 === key($l)) {
$key = $key;
$type = GraphQLType::listOf($type);

Check warning on line 349 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L346-L349

Added lines #L346 - L349 were not covered by tests
} else {
$n = [];
foreach ($field['leafs'] as $l => $value) {
$n[] = ['required' => null, 'name' => $l, 'leafs' => $value, 'type' => 'string', 'description' => null];

Check warning on line 353 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L351-L353

Added lines #L351 - L353 were not covered by tests
}

$type = $this->parameterToObjectType($n, $key);
if (isset($fields[$key]) && ($t = $fields[$key]['type']) instanceof InputObjectType) {
$t = $fields[$key]['type'];
$t->config['fields'] = array_merge($t->config['fields'], $type->config['fields']);
$type = $t;

Check warning on line 360 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L356-L360

Added lines #L356 - L360 were not covered by tests
}
}
}

if ($field['required']) {
$type = GraphQLType::nonNull($type);

Check warning on line 366 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L365-L366

Added lines #L365 - L366 were not covered by tests
}

if (isset($fields[$key])) {
if ($type instanceof ListOfType) {
$key .= '_list';

Check warning on line 371 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L369-L371

Added lines #L369 - L371 were not covered by tests
}
}

$fields[$key] = ['type' => $type, 'name' => $key];

Check warning on line 375 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L375

Added line #L375 was not covered by tests
}

return new InputObjectType(['name' => $name, 'fields' => $fields]);

Check warning on line 378 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L378

Added line #L378 was not covered by tests
}

/**
* A simplified version of convert type that does not support resources.
*/
private function getParameterType(Type $type): GraphQLType

Check warning on line 384 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L384

Added line #L384 was not covered by tests
{
return match ($type->getBuiltinType()) {
Type::BUILTIN_TYPE_BOOL => GraphQLType::boolean(),
Type::BUILTIN_TYPE_INT => GraphQLType::int(),
Type::BUILTIN_TYPE_FLOAT => GraphQLType::float(),
Type::BUILTIN_TYPE_STRING => GraphQLType::string(),
Type::BUILTIN_TYPE_ARRAY => GraphQLType::listOf($this->getParameterType($type->getCollectionValueTypes()[0])),
Type::BUILTIN_TYPE_ITERABLE => GraphQLType::listOf($this->getParameterType($type->getCollectionValueTypes()[0])),
Type::BUILTIN_TYPE_OBJECT => GraphQLType::string(),
default => GraphQLType::string(),
};

Check warning on line 395 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L386-L395

Added lines #L386 - L395 were not covered by tests
}

/**
* Get the field configuration of a resource.
*
Expand Down Expand Up @@ -450,9 +552,9 @@ private function getFilterArgs(array $args, ?string $resourceClass, string $root
}
}

foreach ($this->filterLocator->get($filterId)->getDescription($entityClass) as $key => $value) {
$nullable = isset($value['required']) ? !$value['required'] : true;
$filterType = \in_array($value['type'], Type::$builtinTypes, true) ? new Type($value['type'], $nullable) : new Type('object', $nullable, $value['type']);
foreach ($this->filterLocator->get($filterId)->getDescription($entityClass) as $key => $description) {
$nullable = isset($description['required']) ? !$description['required'] : true;
$filterType = \in_array($description['type'], Type::$builtinTypes, true) ? new Type($description['type'], $nullable) : new Type('object', $nullable, $description['type']);

Check warning on line 557 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L555-L557

Added lines #L555 - L557 were not covered by tests
$graphqlFilterType = $this->convertType($filterType, false, $resourceOperation, $rootOperation, $resourceClass, $rootResource, $property, $depth);

if (str_ends_with($key, '[]')) {
Expand All @@ -467,8 +569,8 @@ private function getFilterArgs(array $args, ?string $resourceClass, string $root
if (\array_key_exists($key, $parsed) && \is_array($parsed[$key])) {
$parsed = [$key => ''];
}
array_walk_recursive($parsed, static function (&$value) use ($graphqlFilterType): void {
$value = $graphqlFilterType;
array_walk_recursive($parsed, static function (&$v) use ($graphqlFilterType): void {
$v = $graphqlFilterType;

Check warning on line 573 in src/GraphQl/Type/FieldsBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/GraphQl/Type/FieldsBuilder.php#L572-L573

Added lines #L572 - L573 were not covered by tests
});
$args = $this->mergeFilterArgs($args, $parsed, $resourceOperation, $key);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Fixtures/TestBundle/Document/DummyDtoNoOutput.php
Expand Up @@ -22,7 +22,7 @@
*
* @author Vincent Chalamon <vincentchalamon@gmail.com>
*/
#[ApiResource(input: InputDto::class)]
#[ApiResource(input: InputDto::class, output: false)]
#[ODM\Document]
class DummyDtoNoOutput
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Fixtures/TestBundle/Entity/DummyDtoNoOutput.php
Expand Up @@ -22,7 +22,7 @@
*
* @author Vincent Chalamon <vincentchalamon@gmail.com>
*/
#[ApiResource(input: InputDto::class)]
#[ApiResource(input: InputDto::class, output: false)]
#[ORM\Entity]
class DummyDtoNoOutput
{
Expand Down

0 comments on commit 769598b

Please sign in to comment.