From 22a765672337e9efc1154d55165f3317bee7df0d Mon Sep 17 00:00:00 2001 From: Jeremiah VALERIE Date: Mon, 29 Jan 2018 16:55:00 +0100 Subject: [PATCH] Fix resolvers args wrapper BC --- .../ConfigProcessor/AclConfigProcessor.php | 3 +- .../WrapArgumentConfigProcessor.php | 44 +++++++++++++++++++ Definition/Type/SchemaDecorator.php | 18 ++------ Resolver/Resolver.php | 13 ++++++ .../config/definition_config_processors.yml | 6 +++ .../App/config/argumentWrapper/config.yml | 15 +++++++ .../argumentWrapper/mapping/query.types.yml | 16 +++++++ .../ArgumentWrapper/ArgumentWrapperTest.php | 25 +++++++++++ 8 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 Definition/ConfigProcessor/WrapArgumentConfigProcessor.php create mode 100644 Tests/Functional/App/config/argumentWrapper/config.yml create mode 100644 Tests/Functional/App/config/argumentWrapper/mapping/query.types.yml create mode 100644 Tests/Functional/ArgumentWrapper/ArgumentWrapperTest.php diff --git a/Definition/ConfigProcessor/AclConfigProcessor.php b/Definition/ConfigProcessor/AclConfigProcessor.php index 2e9302bcf..37e96fc44 100644 --- a/Definition/ConfigProcessor/AclConfigProcessor.php +++ b/Definition/ConfigProcessor/AclConfigProcessor.php @@ -3,7 +3,6 @@ namespace Overblog\GraphQLBundle\Definition\ConfigProcessor; use GraphQL\Type\Definition\ResolveInfo; -use Overblog\GraphQLBundle\Definition\Argument; use Overblog\GraphQLBundle\Definition\LazyConfig; use Overblog\GraphQLBundle\Error\UserWarning; use Overblog\GraphQLBundle\Resolver\AccessResolver; @@ -37,7 +36,7 @@ public static function acl(array $fields, AccessResolver $accessResolver, callab $resolverCallback = self::findFieldResolver($field, $info, $defaultResolver); $isMutation = 'mutation' === $info->operation->operation && $info->parentType === $info->schema->getMutationType(); - return $accessResolver->resolve($accessChecker, $resolverCallback, [$value, new Argument($args), $context, $info], $isMutation); + return $accessResolver->resolve($accessChecker, $resolverCallback, [$value, $args, $context, $info], $isMutation); }; } } diff --git a/Definition/ConfigProcessor/WrapArgumentConfigProcessor.php b/Definition/ConfigProcessor/WrapArgumentConfigProcessor.php new file mode 100644 index 000000000..86caafac5 --- /dev/null +++ b/Definition/ConfigProcessor/WrapArgumentConfigProcessor.php @@ -0,0 +1,44 @@ +addPostLoader(function ($config) { + if (isset($config['resolveField']) && is_callable($config['resolveField'])) { + $config['resolveField'] = Resolver::wrapArgs($config['resolveField']); + } + + if (isset($config['fields'])) { + $config['fields'] = function () use ($config) { + $fields = $config['fields']; + if (is_callable($config['fields'])) { + $fields = $config['fields'](); + } + + return self::wrapFieldsArgument($fields); + }; + } + + return $config; + }); + + return $lazyConfig; + } + + private static function wrapFieldsArgument(array $fields) + { + foreach ($fields as &$field) { + if (isset($field['resolve']) && is_callable($field['resolve'])) { + $field['resolve'] = Resolver::wrapArgs($field['resolve']); + } + } + + return $fields; + } +} diff --git a/Definition/Type/SchemaDecorator.php b/Definition/Type/SchemaDecorator.php index 66233d389..f273b6e07 100644 --- a/Definition/Type/SchemaDecorator.php +++ b/Definition/Type/SchemaDecorator.php @@ -9,7 +9,7 @@ use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Schema; -use Overblog\GraphQLBundle\Definition\Argument; +use Overblog\GraphQLBundle\Resolver\Resolver; use Overblog\GraphQLBundle\Resolver\ResolverMapInterface; class SchemaDecorator @@ -49,7 +49,7 @@ private function decorateObjectType(ObjectType $type, ResolverMapInterface $reso if (ResolverMapInterface::IS_TYPEOF === $fieldName) { $this->configTypeMapping($type, $resolverMap, ResolverMapInterface::IS_TYPEOF); } elseif (ResolverMapInterface::RESOLVE_FIELD === $fieldName) { - $resolveFieldFn = self::wrapResolver($resolverMap->resolve($type->name, ResolverMapInterface::RESOLVE_FIELD)); + $resolveFieldFn = Resolver::wrapArgs($resolverMap->resolve($type->name, ResolverMapInterface::RESOLVE_FIELD)); $type->config[substr(ResolverMapInterface::RESOLVE_FIELD, 2)] = $resolveFieldFn; $type->resolveFieldFn = $resolveFieldFn; } else { @@ -139,7 +139,7 @@ private function decorateObjectTypeFields(ObjectType $type, ResolverMapInterface $fieldName = isset($field['name']) ? $field['name'] : $key; if ($resolverMap->isResolvable($type->name, $fieldName)) { - $field['resolve'] = self::wrapResolver($resolverMap->resolve($type->name, $fieldName)); + $field['resolve'] = Resolver::wrapArgs($resolverMap->resolve($type->name, $fieldName)); } $fieldNames[] = $fieldName; @@ -164,16 +164,4 @@ private function configTypeMapping(Type $type, ResolverMapInterface $resolverMap $type->config[substr($fieldName, 2)] = $resolverMap->resolve($type->name, $fieldName); } } - - private static function wrapResolver(callable $resolver) - { - return static function () use ($resolver) { - $args = func_get_args(); - if (count($args) > 1) { - $args[1] = new Argument($args[1]); - } - - return call_user_func_array($resolver, $args); - }; - } } diff --git a/Resolver/Resolver.php b/Resolver/Resolver.php index 5a98d7885..396ebbcd0 100644 --- a/Resolver/Resolver.php +++ b/Resolver/Resolver.php @@ -3,6 +3,7 @@ namespace Overblog\GraphQLBundle\Resolver; use GraphQL\Type\Definition\ResolveInfo; +use Overblog\GraphQLBundle\Definition\Argument; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessor; @@ -44,6 +45,18 @@ public static function setObjectOrArrayValue(&$objectOrArray, $fieldName, $value } } + public static function wrapArgs(callable $resolver) + { + return static function () use ($resolver) { + $args = func_get_args(); + if (count($args) > 1) { + $args[1] = new Argument($args[1]); + } + + return $resolver(...$args); + }; + } + private static function isReadable($objectOrArray, $indexOrProperty) { return self::getAccessor()->isReadable($objectOrArray, $indexOrProperty); diff --git a/Resources/config/definition_config_processors.yml b/Resources/config/definition_config_processors.yml index db7b0abee..a1f8d7f73 100644 --- a/Resources/config/definition_config_processors.yml +++ b/Resources/config/definition_config_processors.yml @@ -11,5 +11,11 @@ services: - '@overblog_graphql.access_resolver' - "%overblog_graphql.default_resolver%" public: false + tags: + - { name: overblog_graphql.definition_config_processor, priority: 512 } + + Overblog\GraphQLBundle\Definition\ConfigProcessor\WrapArgumentConfigProcessor: + class: Overblog\GraphQLBundle\Definition\ConfigProcessor\WrapArgumentConfigProcessor + public: false tags: - { name: overblog_graphql.definition_config_processor } diff --git a/Tests/Functional/App/config/argumentWrapper/config.yml b/Tests/Functional/App/config/argumentWrapper/config.yml new file mode 100644 index 000000000..2505a63a3 --- /dev/null +++ b/Tests/Functional/App/config/argumentWrapper/config.yml @@ -0,0 +1,15 @@ +imports: + - { resource: ../config.yml } + +overblog_graphql: + errors_handler: + debug: true + definitions: + class_namespace: "Overblog\\GraphQLBundle\\ArgumentWrapper\\__DEFINITIONS__" + schema: + query: RootQuery + mappings: + types: + - + type: yaml + dir: "%kernel.root_dir%/config/argumentWrapper/mapping" diff --git a/Tests/Functional/App/config/argumentWrapper/mapping/query.types.yml b/Tests/Functional/App/config/argumentWrapper/mapping/query.types.yml new file mode 100644 index 000000000..447453250 --- /dev/null +++ b/Tests/Functional/App/config/argumentWrapper/mapping/query.types.yml @@ -0,0 +1,16 @@ +RootQuery: + type: object + config: + resolveField: '@="Arguments: " ~ args["unknown"] ~ args["name"]' + fields: + fieldWithResolverAndArgument: + type: String! + args: + name: {type: String!} + resolve: '@="Arguments: " ~ args["unknown"] ~ args["name"]' + fieldWithDefaultResolverAndArgument: + type: String! + args: + name: {type: String!} + field: + type: String! diff --git a/Tests/Functional/ArgumentWrapper/ArgumentWrapperTest.php b/Tests/Functional/ArgumentWrapper/ArgumentWrapperTest.php new file mode 100644 index 000000000..53e7c066d --- /dev/null +++ b/Tests/Functional/ArgumentWrapper/ArgumentWrapperTest.php @@ -0,0 +1,25 @@ + 'argumentWrapper']); + } + + public function testQuery() + { + $query = '{ fieldWithResolverAndArgument(name: "foo") fieldWithDefaultResolverAndArgument(name: "bar") field }'; + $expectedData = [ + 'fieldWithResolverAndArgument' => 'Arguments: foo', + 'fieldWithDefaultResolverAndArgument' => 'Arguments: bar', + 'field' => 'Arguments: ', + ]; + + $this->assertGraphQL($query, $expectedData); + } +}