diff --git a/src/GraphQLRuntime.php b/src/GraphQLRuntime.php index 6d566c0d..e4d5dd50 100644 --- a/src/GraphQLRuntime.php +++ b/src/GraphQLRuntime.php @@ -4,6 +4,7 @@ use Digia\GraphQL\Language\AST\Builder\ArgumentBuilder; use Digia\GraphQL\Language\AST\Builder\BooleanBuilder; +use Digia\GraphQL\Language\AST\Builder\BuilderInterface; use Digia\GraphQL\Language\AST\Builder\DirectiveBuilder; use Digia\GraphQL\Language\AST\Builder\DirectiveDefinitionBuilder; use Digia\GraphQL\Language\AST\Builder\DocumentBuilder; @@ -73,6 +74,7 @@ use Digia\GraphQL\Language\Reader\NumberReader; use Digia\GraphQL\Language\Reader\ParenthesisReader; use Digia\GraphQL\Language\Reader\PipeReader; +use Digia\GraphQL\Language\Reader\ReaderInterface; use Digia\GraphQL\Language\Reader\SpreadReader; use Digia\GraphQL\Language\Reader\StringReader; use Digia\GraphQL\Type\Definition\TypeNameEnum; @@ -89,8 +91,21 @@ class GraphQLRuntime { + /** + * @var GraphQLRuntime + */ private static $instance; + /** + * @var BuilderInterface[] + */ + private static $nodeBuilders; + + /** + * @var ReaderInterface[] + */ + private static $sourceReaders; + /** * @var Container */ @@ -103,13 +118,13 @@ public function __construct() { $this->container = new Container(); - $this->register(); + $this->registerBindings(); } /** * @return GraphQLRuntime */ - public static function getInstance() + public static function get() { if (null === self::$instance) { self::$instance = new static(); @@ -119,65 +134,12 @@ public static function getInstance() } /** - * @param string $id - * @return mixed - */ - public function get(string $id) - { - return $this->container->get($id); - } - - /** - * @param $id - * @param $concrete - */ - public function add($id, $concrete) - { - $this->container->add($id, $concrete); - } - - /** - * @return ParserInterface - */ - public function getParser(): ParserInterface - { - return $this->container->get(ParserInterface::class); - } - - /** - * @return LexerInterface - */ - public function getLexer(): LexerInterface - { - return $this->container->get(LexerInterface::class); - } - - /** - * @return PrinterInterface + * @return BuilderInterface[] */ - public function getPrinter(): PrinterInterface + public static function getNodeBuilders(): array { - return $this->container->get(PrinterInterface::class); - } - - /** - * - */ - protected function register() - { - $this->registerParser(); - $this->registerPrinter(); - $this->registerScalarTypes(); - $this->registerDirectives(); - } - - /** - * Registers the GraphQL parser with the container. - */ - protected function registerParser() - { - $this->singleton(NodeBuilderInterface::class, function () { - $builders = [ + if (null === self::$nodeBuilders) { + self::$nodeBuilders = [ // Standard new ArgumentBuilder(), new BooleanBuilder(), @@ -223,16 +185,18 @@ protected function registerParser() new InputObjectTypeExtensionBuilder(), new DirectiveDefinitionBuilder(), ]; + } - return new NodeBuilder($builders); - }); - - $this - ->singleton(ParserInterface::class, Parser::class) - ->addArgument(NodeBuilderInterface::class); + return self::$nodeBuilders; + } - $this->container->add(LexerInterface::class, function () { - $readers = [ + /** + * @return ReaderInterface[] + */ + public static function getSourceReaders(): array + { + if (null === self::$sourceReaders) { + self::$sourceReaders = [ new AmpReader(), new AtReader(), new BangReader(), @@ -250,8 +214,65 @@ protected function registerParser() new SpreadReader(), new StringReader(), ]; + } + + return self::$sourceReaders; + } + + /** + * @param string $id + * @param mixed $concrete + * @return DefinitionInterface + */ + public function bind(string $id, $concrete): DefinitionInterface + { + return $this->container->add($id, $concrete); + } + + /** + * @param string $id + * @param mixed $concrete + * @return DefinitionInterface + */ + public function singleton(string $id, $concrete): DefinitionInterface + { + return $this->container->add($id, $concrete, true); + } + + /** + * @param string $id + * @return mixed + */ + public function make(string $id) + { + return $this->container->get($id); + } + + /** + * + */ + protected function registerBindings() + { + $this->registerParser(); + $this->registerPrinter(); + $this->registerScalarTypes(); + $this->registerDirectives(); + } + + /** + * Registers the GraphQL parser with the container. + */ + protected function registerParser() + { + $this->singleton(NodeBuilderInterface::class, function () { + return new NodeBuilder(self::getNodeBuilders()); + }); + + $this->singleton(ParserInterface::class, Parser::class) + ->addArgument(NodeBuilderInterface::class); - return new Lexer($readers); + $this->bind(LexerInterface::class, function () { + return new Lexer(self::getSourceReaders()); }); } @@ -525,24 +546,4 @@ protected function registerDirectives() ]); }); } - - /** - * @param string $id - * @param mixed $concrete - * @return DefinitionInterface - */ - protected function bind(string $id, $concrete): DefinitionInterface - { - return $this->container->add($id, $concrete); - } - - /** - * @param string $id - * @param mixed $concrete - * @return DefinitionInterface - */ - protected function singleton(string $id, $concrete): DefinitionInterface - { - return $this->container->add($id, $concrete, true); - } } diff --git a/src/Type/directives.php b/src/Type/directives.php index 0a3b7c15..2326e9ba 100644 --- a/src/Type/directives.php +++ b/src/Type/directives.php @@ -1,8 +1,8 @@ get('GraphQLIncludeDirective'); + return GraphQLRuntime::get()->make('GraphQLIncludeDirective'); } /** @@ -20,7 +20,7 @@ function GraphQLIncludeDirective(): Directive */ function GraphQLSkipDirective(): Directive { - return graphql()->get('GraphQLSkipDirective'); + return GraphQLRuntime::get()->make('GraphQLSkipDirective'); } const DEFAULT_DEPRECATION_REASON = 'No longer supported'; @@ -31,7 +31,7 @@ function GraphQLSkipDirective(): Directive */ function GraphQLDeprecatedDirective(): Directive { - return graphql()->get('GraphQLDeprecatedDirective'); + return GraphQLRuntime::get()->make('GraphQLDeprecatedDirective'); } /** diff --git a/src/Type/scalars.php b/src/Type/scalars.php index 8a795e03..cce0fc31 100644 --- a/src/Type/scalars.php +++ b/src/Type/scalars.php @@ -2,9 +2,9 @@ namespace Digia\GraphQL\Type; +use Digia\GraphQL\GraphQLRuntime; use Digia\GraphQL\Type\Definition\ScalarType; use Digia\GraphQL\Type\Definition\TypeInterface; -use function Digia\GraphQL\graphql; use function Digia\GraphQL\Util\arraySome; const MAX_INT = 2147483647; @@ -15,7 +15,7 @@ */ function GraphQLBoolean(): ScalarType { - return graphql()->get('GraphQLBoolean'); + return GraphQLRuntime::get()->make('GraphQLBoolean'); } /** @@ -23,7 +23,7 @@ function GraphQLBoolean(): ScalarType */ function GraphQLFloat(): ScalarType { - return graphql()->get('GraphQLFloat'); + return GraphQLRuntime::get()->make('GraphQLFloat'); } /** @@ -31,7 +31,7 @@ function GraphQLFloat(): ScalarType */ function GraphQLInt(): ScalarType { - return graphql()->get('GraphQLInt'); + return GraphQLRuntime::get()->make('GraphQLInt'); } /** @@ -39,7 +39,7 @@ function GraphQLInt(): ScalarType */ function GraphQLID(): ScalarType { - return graphql()->get('GraphQLID'); + return GraphQLRuntime::get()->make('GraphQLID'); } /** @@ -47,7 +47,7 @@ function GraphQLID(): ScalarType */ function GraphQLString(): ScalarType { - return graphql()->get('GraphQLString'); + return GraphQLRuntime::get()->make('GraphQLString'); } /** diff --git a/src/facades.php b/src/facades.php index 2f516dee..233a408a 100644 --- a/src/facades.php +++ b/src/facades.php @@ -4,16 +4,11 @@ use Digia\GraphQL\Error\GraphQLError; use Digia\GraphQL\Language\AST\Node\NodeInterface; +use Digia\GraphQL\Language\LexerInterface; +use Digia\GraphQL\Language\ParserInterface; +use Digia\GraphQL\Language\PrinterInterface; use Digia\GraphQL\Language\Source; -/** - * @return GraphQLRuntime - */ -function graphql(): GraphQLRuntime -{ - return GraphQLRuntime::getInstance(); -} - /** * @param string|Source $source * @param array $options @@ -23,8 +18,8 @@ function graphql(): GraphQLRuntime */ function parse($source, array $options = []): NodeInterface { - return graphql()->getParser()->parse( - graphql()->getLexer() + return GraphQLRuntime::get()->make(ParserInterface::class)->parse( + GraphQLRuntime::get()->make(LexerInterface::class) ->setSource($source instanceof Source ? $source : new Source($source)) ->setOptions($options) ); @@ -39,8 +34,8 @@ function parse($source, array $options = []): NodeInterface */ function parseValue($source, array $options = []): NodeInterface { - return graphql()->getParser()->parseValue( - graphql()->getLexer() + return GraphQLRuntime::get()->make(ParserInterface::class)->parseValue( + GraphQLRuntime::get()->make(LexerInterface::class) ->setSource($source instanceof Source ? $source : new Source($source)) ->setOptions($options) ); @@ -55,8 +50,8 @@ function parseValue($source, array $options = []): NodeInterface */ function parseType($source, array $options = []): NodeInterface { - return graphql()->getParser()->parseType( - graphql()->getLexer() + return GraphQLRuntime::get()->make(ParserInterface::class)->parseType( + GraphQLRuntime::get()->make(LexerInterface::class) ->setSource($source instanceof Source ? $source : new Source($source)) ->setOptions($options) ); @@ -68,5 +63,5 @@ function parseType($source, array $options = []): NodeInterface */ function printNode(NodeInterface $node): string { - return graphql()->getPrinter()->print($node); + return GraphQLRuntime::get()->make(PrinterInterface::class)->print($node); }