diff --git a/Definition/Builder/SchemaBuilder.php b/Definition/Builder/SchemaBuilder.php index cbf4c7234..6ef069268 100644 --- a/Definition/Builder/SchemaBuilder.php +++ b/Definition/Builder/SchemaBuilder.php @@ -13,6 +13,7 @@ use GraphQL\Schema; use GraphQL\Type\Definition\Config; +use GraphQL\Type\LazyResolution; use Overblog\GraphQLBundle\Resolver\ResolverInterface; class SchemaBuilder @@ -22,12 +23,29 @@ class SchemaBuilder */ private $typeResolver; + /** + * @var array + */ + private $schemaDescriptor; + /** @var bool */ private $enableValidation; - public function __construct(ResolverInterface $typeResolver, $enableValidation = false) + /** + * SchemaBuilder constructor. + * + * @param ResolverInterface $typeResolver + * @param array $schemaDescriptor + * @param bool $enableValidation + */ + public function __construct( + ResolverInterface $typeResolver, + array $schemaDescriptor, + $enableValidation = false + ) { $this->typeResolver = $typeResolver; + $this->schemaDescriptor = $schemaDescriptor; $this->enableValidation = $enableValidation; } @@ -50,7 +68,7 @@ public function create($queryAlias = null, $mutationAlias = null, $subscriptionA 'query' => $query, 'mutation' => $mutation, 'subscription' => $subscription, - 'types' => $this->typeResolver->getSolutions(), + 'typeResolution' => new LazyResolution($this->schemaDescriptor, [$this->typeResolver, 'resolve']) ]); } } diff --git a/DependencyInjection/Compiler/TaggedServiceMappingPass.php b/DependencyInjection/Compiler/TaggedServiceMappingPass.php index f0db04fc0..c5c7dd3ef 100644 --- a/DependencyInjection/Compiler/TaggedServiceMappingPass.php +++ b/DependencyInjection/Compiler/TaggedServiceMappingPass.php @@ -40,15 +40,7 @@ public function process(ContainerBuilder $container) $resolverDefinition = $container->findDefinition($this->getResolverServiceID()); foreach ($mapping as $name => $options) { - $cleanOptions = $options; - $solutionID = $options['id']; - - $definition = $container->findDefinition($solutionID); - if (is_subclass_of($definition->getClass(), 'Symfony\Component\DependencyInjection\ContainerAwareInterface')) { - $solutionDefinition = $container->findDefinition($options['id']); - $solutionDefinition->addMethodCall('setContainer', [new Reference('service_container')]); - } - $resolverDefinition->addMethodCall('addSolution', [$name, new Reference($solutionID), $cleanOptions]); + $resolverDefinition->addMethodCall('addSolution', [$name, null, $options]); } } diff --git a/DependencyInjection/Compiler/TypesPass.php b/DependencyInjection/Compiler/TypesPass.php index c56d3eee7..81602b5a7 100644 --- a/DependencyInjection/Compiler/TypesPass.php +++ b/DependencyInjection/Compiler/TypesPass.php @@ -35,6 +35,44 @@ public function process(ContainerBuilder $container) ->addTag('overblog_graphql.type', ['alias' => $name]) ; } + + $types = [ + '__Schema' => 1, + '__Type' => 1, + '__TypeKind' => 1, + '__Field' => 1, + '__InputValue' => 1, + '__EnumValue' => 1, + '__Directive' => 1, + '__DirectiveLocation' => 1 + ]; + $possibleTypes = []; + + foreach ($config as $typeConf) { + $typeName = $typeConf['config']['name']; + $types[$typeName] = 1; + if ($typeConf['type'] == 'object') { + $ifaces = $typeConf['config']['interfaces'] ?? []; + foreach ($ifaces as $iface) { + if (!array_key_exists($iface, $possibleTypes)) { + $possibleTypes[$iface] = []; + } + $possibleTypes[$iface][$typeName] = 1; + } + } + if ($typeConf['type'] == 'union') { + $possibleTypes[$typeName] = []; + foreach ($typeConf['config']['types'] as $unionMember) { + $possibleTypes[$typeName][$unionMember] = 1; + } + } + } + + $container->getDefinition('overblog_graphql.schema_builder')->replaceArgument(1, [ + 'typeMap' => $types, + 'possibleTypeMap' => $possibleTypes, + 'version' => '1.0' + ]); } private function processConfig(array $configs) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 9309843b3..bca539d16 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -76,7 +76,7 @@ public function getConfigTreeBuilder() ->prototype('array') ->addDefaultsIfNotSet() ->children() - ->enumNode('type')->isRequired()->values(['yml', 'xml'])->end() + ->enumNode('type')->isRequired()->values(['yml', 'xml', 'graphqls'])->end() ->scalarNode('dir')->defaultNull()->end() ->end() ->end() diff --git a/DependencyInjection/OverblogGraphQLTypesExtension.php b/DependencyInjection/OverblogGraphQLTypesExtension.php index 25465aeae..0e5335951 100644 --- a/DependencyInjection/OverblogGraphQLTypesExtension.php +++ b/DependencyInjection/OverblogGraphQLTypesExtension.php @@ -11,6 +11,36 @@ namespace Overblog\GraphQLBundle\DependencyInjection; +use GraphQL\Error\SyntaxError; +use GraphQL\Language\AST\BooleanValueNode; +use GraphQL\Language\AST\DirectiveDefinitionNode; +use GraphQL\Language\AST\EnumTypeDefinitionNode; +use GraphQL\Language\AST\DocumentNode; +use GraphQL\Language\AST\EnumValueDefinitionNode; +use GraphQL\Language\AST\FieldDefinitionNode; +use GraphQL\Language\AST\EnumValueNode; +use GraphQL\Language\AST\FloatValueNode; +use GraphQL\Language\AST\InputObjectTypeDefinitionNode; +use GraphQL\Language\AST\InputValueDefinitionNode; +use GraphQL\Language\AST\InterfaceTypeDefinitionNode; +use GraphQL\Language\AST\FragmentDefinitionNode; +use GraphQL\Language\AST\IntValueNode; +use GraphQL\Language\AST\ListTypeNode; +use GraphQL\Language\AST\ListValueNode; +use GraphQL\Language\AST\NamedTypeNode; +use GraphQL\Language\AST\NodeKind; +use GraphQL\Language\AST\ObjectTypeDefinitionNode; +use GraphQL\Language\AST\NonNullTypeNode; +use GraphQL\Language\AST\ObjectValueNode; +use GraphQL\Language\AST\ScalarTypeDefinitionNode; +use GraphQL\Language\AST\OperationDefinitionNode; +use GraphQL\Language\AST\StringValueNode; +use GraphQL\Language\AST\UnionTypeDefinitionNode; +use GraphQL\Language\AST\TypeExtensionDefinitionNode; +use GraphQL\Language\Parser; +use GraphQL\Language\AST\VariableDefinitionNode; +use GraphQL\Language\Visitor; + use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -23,6 +53,8 @@ class OverblogGraphQLTypesExtension extends Extension { + const NAME_TO_KEY = '__key'; + private $yamlParser; public function load(array $configs, ContainerBuilder $container) @@ -55,7 +87,18 @@ private function prependExtensionConfigFromFiles($type, $files, ContainerBuilder { /** @var SplFileInfo $file */ foreach ($files as $file) { - $typeConfig = 'yml' === $type ? $this->typesConfigFromYml($file, $container) : $this->typesConfigFromXml($file, $container); + switch ($type) { + case 'yml': + $typeConfig = $this->typesConfigFromYml($file, $container); + break; + case 'xml': + $typeConfig = $this->typesConfigFromXml($file, $container); + break; + default: + $typeConfig = $this->typesConfigFromGraphqls($file, $container); + break; + } + $container->prependExtensionConfig($this->getAlias(), $typeConfig); } } @@ -82,6 +125,18 @@ private function typesConfigFromXml(SplFileInfo $file, ContainerBuilder $contain return $typesConfig; } + private function typesConfigFromGraphqls(SplFileInfo $file, ContainerBuilder $container) + { + try { + $typesConfig = $this->parseSchemaToOverblogGraphQLTypesConfigArray($file->getContents()); + $container->addResource(new FileResource($file->getRealPath())); + } catch (SyntaxError $e) { + throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid GraphQL schema language.', $file), 0, $e); + } + + return $typesConfig; + } + private function typesConfigFromYml(SplFileInfo $file, ContainerBuilder $container) { if (null === $this->yamlParser) { @@ -147,13 +202,14 @@ private function detectConfigFiles(ContainerBuilder $container, $configPath, $ty $container->addResource(new FileResource($resource)); $extension = $this->getMappingResourceExtension(); - $finder = new Finder(); - $types = null === $type ? ['yml', 'xml'] : [$type]; + $types = null === $type ? ['yml', 'xml', 'graphqls'] : [$type]; foreach ($types as $type) { + $finder = new Finder(); + $pattern = '*.' . ($type === 'graphqls' ? $type : $extension . '.' . $type); try { - $finder->files()->in($configPath)->name('*.'.$extension.'.'.$type); + $finder->files()->in($configPath)->name($pattern); } catch (\InvalidArgumentException $e) { continue; } @@ -192,4 +248,240 @@ public function getConfiguration(array $config, ContainerBuilder $container) { return new TypesConfiguration(); } + + private function parseSchemaToOverblogGraphQLTypesConfigArray($sourceString) { + $ast = Parser::parse($sourceString, ['noLocation' => true, 'noSource' => true]); + + // fixme: here there be dragons. + // + // - the commented bits are almost definitely not needed. + // - the uncommented bits that refer to self:: methods are likely to be needed at some point, but + // haven't been converted yet. + + $types = Visitor::visit($ast, array( + 'leave' => array( + NodeKind::NAME => function($node) {return '' . $node->value;}, + NodeKind::VARIABLE => function($node) {return '$' . $node->name;}, + + NodeKind::DOCUMENT => function(DocumentNode $node) { + return $node->definitions; + }, + + NodeKind::OPERATION_DEFINITION => function(OperationDefinitionNode $node) { + $op = $node->operation; + $name = $node->name; + $varDefs = self::wrap('(', self::join($node->variableDefinitions, ', '), ')'); + $directives = self::join($node->directives, ' '); + $selectionSet = $node->selectionSet; + // Anonymous queries with no directives or variable definitions can use + // the query short form. + return !$name && !$directives && !$varDefs && $op === 'query' + ? $selectionSet + : self::join([$op, self::join([$name, $varDefs]), $directives, $selectionSet], ' '); + }, + NodeKind::VARIABLE_DEFINITION => function(VariableDefinitionNode $node) { + return $node->variable . ': ' . $node->type . self::wrap(' = ', $node->defaultValue); + }, + // NodeKind::SELECTION_SET => function(SelectionSet $node) { + // return self::block($node->selections); + // }, + // NodeKind::FIELD => function(Field $node) { + // return self::join([ + // self::wrap('', $node->alias, ': ') . $node->name . self::wrap('(', self::join($node->arguments, ', '), ')'), + // self::join($node->directives, ' '), + // $node->selectionSet + // ], ' '); + // }, + // NodeKind::ARGUMENT => function(Argument $node) { + // return $node->name . ': ' . $node->value; + // }, + + // Fragments + // NodeKind::FRAGMENT_SPREAD => function(FragmentSpread $node) { + // return '...' . $node->name . self::wrap(' ', self::join($node->directives, ' ')); + // }, + // NodeKind::INLINE_FRAGMENT => function(InlineFragment $node) { + // return self::join([ + // "...", + // self::wrap('on ', $node->typeCondition), + // self::join($node->directives, ' '), + // $node->selectionSet + // ], ' '); + // }, + NodeKind::FRAGMENT_DEFINITION => function(FragmentDefinitionNode $node) { + return "fragment {$node->name} on {$node->typeCondition} " + . self::wrap('', self::join($node->directives, ' '), ' ') + . $node->selectionSet; + }, + + // Value + NodeKind::INT => function(IntValueNode $node) {return $node->value;}, + NodeKind::FLOAT => function(FloatValueNode $node) {return $node->value;}, + NodeKind::STRING => function(StringValueNode $node) {return $node->value;}, + NodeKind::BOOLEAN => function(BooleanValueNode $node) {return $node->value;}, + NodeKind::ENUM => function(EnumValueNode $node) {return $node->value;}, + // todo: these two probably won't work as is - they need to be tested with actual data + NodeKind::LST => function(ListValueNode $node) {return $node->values;}, + NodeKind::OBJECT => function(ObjectValueNode $node) {return $node->fields;}, + // todo: is this also a valid value for the purposes of defaultValue? + // NodeKind::OBJECT_FIELD => function(ObjectField $node) {return $node->name . ': ' . $node->value;}, + // + // // Directive + // NodeKind::DIRECTIVE => function(Directive $node) { + // return '@' . $node->name . self::wrap('(', self::join($node->arguments, ', '), ')'); + // }, + + // Type + NodeKind::NAMED_TYPE => function(NamedTypeNode $node) {return $node->name;}, + NodeKind::LIST_TYPE => function(ListTypeNode $node) {return '[' . $node->type . ']';}, + NodeKind::NON_NULL_TYPE => function(NonNullTypeNode $node) {return $node->type . '!';}, + + // Type System Definitions + // NodeKind::SCHEMA_DEFINITION => function(SchemaDefinition $def) {return 'schema ' . self::block($def->operationTypes);}, + // NodeKind::OPERATION_TYPE_DEFINITION => function(OperationTypeDefinition $def) {return $def->operation . ': ' . $def->type;}, + + NodeKind::SCALAR_TYPE_DEFINITION => function(ScalarTypeDefinitionNode $def) { + // todo: boo, it seems that graphql-php-generator does not support custom scalars. + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'scalar' + ]; + }, + NodeKind::OBJECT_TYPE_DEFINITION => function(ObjectTypeDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'object', + 'config' => [ + 'fields' => $def->fields, + 'interfaces' => $def->interfaces, + 'description' => $def->description + ] + ]; + }, + NodeKind::FIELD_DEFINITION => function(FieldDefinitionNode $def) { + $description = $def->description; + $resolver = null; + if (strpos($def->description, '@@resolver') === 0) { + $newLineStart = strpos($description, "\n"); + $resolver = '@=resolver'.substr($description, 10, $newLineStart - 10); + $description = substr($description, $newLineStart + 1); + } + + $config = [ + self::NAME_TO_KEY => $def->name, + 'type' => $def->type, + 'args' => $def->arguments, + 'description' => $description + ]; + + if ($resolver) { + $config['resolve'] = $resolver; + } + + return $config; + }, + NodeKind::INPUT_VALUE_DEFINITION => function(InputValueDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => $def->type, + 'defaultValue' => $def->defaultValue, + 'description' => $def->description + ]; + }, + NodeKind::INTERFACE_TYPE_DEFINITION => function(InterfaceTypeDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'interface', + 'config' => [ + 'fields' => $def->fields, + 'description' => $def->description, + 'resolveType' => "@=resolver('resolve_type', [value])" + ] + ]; + }, + NodeKind::UNION_TYPE_DEFINITION => function(UnionTypeDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'union', + 'config' => [ + 'types' => $def->types, + 'description' => $def->description, + 'resolveType' => "@=resolver('resolve_type', [value])" + ], + ]; + }, + NodeKind::ENUM_TYPE_DEFINITION => function(EnumTypeDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'enum', + 'config' => [ + 'values' => $def->values, + 'description' => $def->description + ] + ]; + }, + NodeKind::ENUM_VALUE_DEFINITION => function(EnumValueDefinitionNode $def) { + $description = $def->description; + $value = null; + if (strpos($def->description, '@@value(') === 0) { + $newLineStart = strpos($description, "\n"); + $value = substr($description, 8, $newLineStart - 9); + $description = substr($description, $newLineStart + 1); + } + + $config = [ + 'name' => $def->name, + 'description' => $description + ]; + + if ($value !== null) { + $config['value'] = $value; + } + + return $config; + }, + NodeKind::INPUT_OBJECT_TYPE_DEFINITION => function(InputObjectTypeDefinitionNode $def) { + return [ + self::NAME_TO_KEY => $def->name, + 'type' => 'input-object', + 'config' => [ + 'fields' => $def->fields, + 'description' => $def->description + ] + ]; + }, + NodeKind::TYPE_EXTENSION_DEFINITION => function(TypeExtensionDefinitionNode $def) {return "extend {$def->definition}";}, + NodeKind::DIRECTIVE_DEFINITION => function(DirectiveDefinitionNode $def) { + return 'directive @' . $def->name . self::wrap('(', self::join($def->arguments, ', '), ')') + . ' on ' . self::join($def->locations, ' | '); + } + ) + )); + + $types = $this->substituteKeys($types); + + return $types; + } + + // -.- + + private function substituteKeys($array) { + $newArray = []; + foreach ($array as $key => $value) { + if (is_array($value)) { + + if (isset($value[self::NAME_TO_KEY])) { + $key = $value[self::NAME_TO_KEY]; + unset($value[self::NAME_TO_KEY]); + } + + $substitutedValue = $this->substituteKeys($value); + $newArray[$key] = $substitutedValue; + + } else { + $newArray[$key] = $value; + } + } + return $newArray; + } } diff --git a/Generator/TypeGenerator.php b/Generator/TypeGenerator.php index fde1ed272..aa02e34ef 100644 --- a/Generator/TypeGenerator.php +++ b/Generator/TypeGenerator.php @@ -17,7 +17,7 @@ class TypeGenerator extends BaseTypeGenerator { - const USE_FOR_CLOSURES = '$container, $request, $user, $token'; + const USE_FOR_CLOSURES = '$container'; private $cacheDir; @@ -158,6 +158,7 @@ public function compile(array $configs, $loadClasses = true) $fs->remove($cacheDir); } + $configs = $this->substituteEnumNamesInDefaultValues($configs); $classes = $this->generateClasses($configs, $cacheDir, true); file_put_contents($this->getClassesMap(), "getCacheDir().'/__classes.map'; } + + /** + * Substitute enum value's names with enum value's values in all relevant defaultValue. + * + * Longer explanation follows. + * + * First, let's establish a terminology shorthand: + * enum value's name = e_name. + * enum value's value = e_value. + * + * So, type definitions in GraphQL schema language have no knowledge of custom e_values. They will therefore + * always use e_names for field argument default values. + * + * Problem: in cases when e_name != e_value, webonyx/graphql-php library requires e_values in defaultValue. + * + * Solution: translate e_names into e_values during class generation. + * + * Since the types in need of conversion could have been defined in a different graphqls file than the relevant + * enums, this class is the first place where both definitions are guaranteed to exist side-by-side, + * arg default values can be checked for whether they contain e_names, and if they do, converted into e_values. + * + * @param array $configs + * @throws \Exception If someone was very silly indeed and mixed e_names and e_values in defaultValue + */ + protected function substituteEnumNamesInDefaultValues($configs) + { + // generate a lookup table + $enumConfigsByName = []; + + foreach ($configs as $classConfig) { + if ($classConfig['type'] == 'enum') { + $name = $classConfig['config']['name']; + $enumConfigsByName[$name] = $classConfig; + } + } + + // check each type config for fields which have arguments of an enum type, and also have a defaultValue + + // first, check each type config for field arguments that have a defaultValue (cheaper check first) + foreach ($configs as &$classConfig) { + if (isset($classConfig['config']['fields'])) { + foreach ($classConfig['config']['fields'] as &$fieldConfig) { + if (isset($fieldConfig['args'])) { + foreach ($fieldConfig['args'] as &$argConfig) { + if (isset($argConfig['defaultValue'])) { + + // this argument has a default value, now perform the (more expensive) type check + $type = $argConfig['type']; + $type = ('[' === $type[0]) ? substr($type, 1, -1) : $type; + + if (isset($enumConfigsByName[$type])) { + // we've found an enum type argument that has a defaultValue + + // If defaultValue is an array, check only its first element, assuming for the sake + // of performance that people won't mix e_names and e_values in defaultValue + + $maybeName = is_array($argConfig['defaultValue']) + ? $argConfig['defaultValue'][0] + : $argConfig['defaultValue']; + + // Check whether defaultValue is defined by enum element names. + if (isset($enumConfigsByName[$type]['config']['values'][$maybeName])) { + + // Convert enum element names to enum element values. + if (is_array($argConfig['defaultValue'])) { + foreach ($argConfig['defaultValue'] as &$elem) { + // perform a very unlikely sanity check + if (isset($enumConfigsByName[$type]['config']['values'][$elem])) { + // swapsies! + $elem = $enumConfigsByName[$type]['config']['values'][$elem]['value']; + } else { + // someone DID mix up e_names and e_values, le sigh + // todo: choose a better exception type and add a descriptive message + throw new \Exception('Your mother was a hamster and your father smelt of elderberries'); + } + } + } else { + // easy peasy, swapsies! + $argConfig['defaultValue'] = $enumConfigsByName[$type]['config']['values'][$maybeName]['value']; + } + } + } + } + } + } + } + } + } + + return $configs; + } } diff --git a/Resolver/ResolverResolver.php b/Resolver/ResolverResolver.php index 8e21d8275..0d0b969dc 100644 --- a/Resolver/ResolverResolver.php +++ b/Resolver/ResolverResolver.php @@ -11,8 +11,39 @@ namespace Overblog\GraphQLBundle\Resolver; +use Symfony\Component\DependencyInjection\ContainerInterface; + class ResolverResolver extends AbstractProxyResolver { + /** + * @var ContainerInterface + */ + private $container; + + /** + * ResolverResolver constructor. + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + public function getSolution($name) + { + $solution = parent::getSolution($name); + + if (! $solution) { + $typeOptions = $this->getSolutionOptions($name); + if ($typeOptions and $this->container->has($typeOptions['id'])) { + $solution = $this->container->get($typeOptions['id']); + } + } + + return $solution; + } + protected function unresolvableMessage($alias) { return sprintf('Unknown resolver with alias "%s" (verified service tag)', $alias); diff --git a/Resolver/TypeResolver.php b/Resolver/TypeResolver.php index f2890251a..1b39ec120 100644 --- a/Resolver/TypeResolver.php +++ b/Resolver/TypeResolver.php @@ -12,8 +12,10 @@ namespace Overblog\GraphQLBundle\Resolver; use GraphQL\Type\Definition\Type; +use GraphQL\Type\Introspection; use Overblog\GraphQLBundle\Resolver\Cache\ArrayCache; use Overblog\GraphQLBundle\Resolver\Cache\CacheInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; class TypeResolver extends AbstractResolver { @@ -22,9 +24,23 @@ class TypeResolver extends AbstractResolver */ private $cache; - public function __construct(CacheInterface $cache = null) - { + /** + * @var ContainerInterface + */ + private $container; + + /** + * LazyTypeResolver constructor. + * + * @param CacheInterface|null $cache + * @param ContainerInterface $container + */ + public function __construct( + CacheInterface $cache = null, + ContainerInterface $container + ) { $this->cache = null !== $cache ? $cache : new ArrayCache(); + $this->container = $container; } /** @@ -34,6 +50,11 @@ public function __construct(CacheInterface $cache = null) */ public function resolve($alias) { + if (strpos($alias, '__') === 0) { + $staticName = '_'.lcfirst(substr($alias, 2)); + return Introspection::$staticName(); + } + if (null === $alias) { return; } @@ -65,6 +86,11 @@ private function baseType($alias) return $type; } + $typeOptions = $this->getSolutionOptions($alias); + if ($typeOptions and $this->container->has($typeOptions['id'])) { + return $this->container->get($typeOptions['id']); + } + throw new UnresolvableException( sprintf('Unknown type with alias "%s" (verified service tag)', $alias) ); @@ -99,9 +125,4 @@ private function hasNeedListOfWrapper($alias) return false; } - - protected function supportedSolutionClass() - { - return 'GraphQL\\Type\\Definition\\Type'; - } } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index ed11bd8f1..410aa4363 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -39,15 +39,19 @@ services: public: false arguments: - "@overblog_graphql.type_resolver" + - "%overblog_graphql.definition.lazy_types_descriptor%" - false overblog_graphql.type_resolver: class: Overblog\GraphQLBundle\Resolver\TypeResolver arguments: - + - "@service_container" overblog_graphql.resolver_resolver: class: Overblog\GraphQLBundle\Resolver\ResolverResolver + arguments: + - "@service_container" overblog_graphql.mutation_resolver: class: Overblog\GraphQLBundle\Resolver\MutationResolver @@ -79,7 +83,6 @@ services: - "%overblog_graphql.default_resolver%" calls: - ["addUseStatement", ["Symfony\\Component\\DependencyInjection\\ContainerInterface"]] - - ["addUseStatement", ["Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface"]] - ["setExpressionLanguage", ["@overblog_graphql.expression_language"]] overblog_graphql.event_listener.classloader_listener: diff --git a/Resources/skeleton/TypeSystem.php.skeleton b/Resources/skeleton/TypeSystem.php.skeleton index 6e80f9dc3..844795581 100644 --- a/Resources/skeleton/TypeSystem.php.skeleton +++ b/Resources/skeleton/TypeSystem.php.skeleton @@ -6,18 +6,6 @@ { public function __construct(ContainerInterface $container) { -$request = null; -$token = null; -$user = null; -if ($container->has('request_stack')) { -$request = $container->get('request_stack')->getCurrentRequest(); -} -if ($container->has('security.token_storage')) { -$token = $container->get('security.token_storage')->getToken(); -if ($token instanceof TokenInterface) { -$user = $token->getUser(); -} -} parent::__construct(); } diff --git a/composer.json b/composer.json index eba810a4d..dc2b27ff7 100644 --- a/composer.json +++ b/composer.json @@ -31,12 +31,12 @@ "require": { "php": "^5.4|~7.0", "doctrine/doctrine-cache-bundle": "^1.2", - "overblog/graphql-php-generator": "^0.4.1", + "overblog/graphql-php-generator": "^0.4.2", "symfony/expression-language": "^2.7|^3.1", "symfony/framework-bundle": "^2.7|^3.1", "symfony/options-resolver": "^2.7|^3.1", "symfony/property-access": "^2.7|^3.1", - "webonyx/graphql-php": "^0.9.0" + "webonyx/graphql-php": "^0.9.2" }, "suggest": { "twig/twig": "If you want to use graphiQL.",