Completed
Push — master ( a92d27...66efdd )
by Christoffer
10:22 queued 02:13
created

GraphQL::extendSchema()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 1
nop 4
1
<?php
2
3
namespace Digia\GraphQL;
4
5
use Digia\GraphQL\Cache\CacheProvider;
6
use Digia\GraphQL\Error\InvariantException;
7
use Digia\GraphQL\Execution\ExecutionInterface;
8
use Digia\GraphQL\Execution\ExecutionProvider;
9
use Digia\GraphQL\Execution\ExecutionResult;
10
use Digia\GraphQL\Language\LanguageProvider;
11
use Digia\GraphQL\Language\LexerInterface;
12
use Digia\GraphQL\Language\Node\DocumentNode;
13
use Digia\GraphQL\Language\Node\NodeInterface;
14
use Digia\GraphQL\Language\Node\TypeNodeInterface;
15
use Digia\GraphQL\Language\Node\ValueNodeInterface;
16
use Digia\GraphQL\Language\ParserInterface;
17
use Digia\GraphQL\Language\PrinterInterface;
18
use Digia\GraphQL\Language\Source;
19
use Digia\GraphQL\Schema\Building\SchemaBuilderInterface;
20
use Digia\GraphQL\Schema\Building\SchemaBuildingProvider;
21
use Digia\GraphQL\Schema\Extension\SchemaExtenderInterface;
22
use Digia\GraphQL\Schema\Extension\SchemaExtensionProvider;
23
use Digia\GraphQL\Schema\Resolver\ResolverRegistry;
24
use Digia\GraphQL\Schema\Resolver\ResolverRegistryInterface;
25
use Digia\GraphQL\Schema\SchemaInterface;
26
use Digia\GraphQL\Schema\Validation\SchemaValidationProvider;
27
use Digia\GraphQL\Schema\Validation\SchemaValidatorInterface;
28
use Digia\GraphQL\Type\CoercerProvider;
29
use Digia\GraphQL\Type\DirectivesProvider;
30
use Digia\GraphQL\Type\IntrospectionProvider;
31
use Digia\GraphQL\Type\ScalarTypesProvider;
32
use Digia\GraphQL\Util\UtilityProvider;
33
use Digia\GraphQL\Validation\RulesProvider;
34
use Digia\GraphQL\Validation\ValidationProvider;
35
use Digia\GraphQL\Validation\ValidatorInterface;
36
use League\Container\Container;
37
use League\Container\ContainerInterface;
38
39
class GraphQL
40
{
41
    public const BOOLEAN = 'GraphQLBoolean';
42
    public const FLOAT   = 'GraphQLFloat';
43
    public const INT     = 'GraphQLInt';
44
    public const ID      = 'GraphQLID';
45
    public const STRING  = 'GraphQLString';
46
47
    public const DEPRECATED_DIRECTIVE = 'GraphQLDeprecatedDirective';
48
    public const INCLUDE_DIRECTIVE    = 'GraphQLIncludeDirective';
49
    public const SKIP_DIRECTIVE       = 'GraphQLSkipDirective';
50
51
    public const SCHEMA_INTROSPECTION             = '__Schema';
52
    public const DIRECTIVE_INTROSPECTION          = '__Directive';
53
    public const DIRECTIVE_LOCATION_INTROSPECTION = '__DirectiveLocation';
54
    public const TYPE_INTROSPECTION               = '__Type';
55
    public const FIELD_INTROSPECTION              = '__Field';
56
    public const INPUT_VALUE_INTROSPECTION        = '__InputValue';
57
    public const ENUM_VALUE_INTROSPECTION         = '__EnumValue';
58
    public const TYPE_KIND_INTROSPECTION          = '__TypeKind';
59
60
    public const SCHEMA_META_FIELD_DEFINITION    = 'SchemaMetaFieldDefinition';
61
    public const TYPE_META_FIELD_DEFINITION      = 'TypeMetaFieldDefinition';
62
    public const TYPE_NAME_META_FIELD_DEFINITION = 'TypeNameMetaFieldDefinition';
63
64
    /**
65
     * @var array
66
     */
67
    private static $providers = [
68
        CacheProvider::class,
69
        LanguageProvider::class,
70
        SchemaBuildingProvider::class,
71
        SchemaExtensionProvider::class,
72
        SchemaValidationProvider::class,
73
        CoercerProvider::class,
74
        IntrospectionProvider::class,
75
        ScalarTypesProvider::class,
76
        DirectivesProvider::class,
77
        RulesProvider::class,
78
        ValidationProvider::class,
79
        ExecutionProvider::class,
80
        UtilityProvider::class,
81
    ];
82
83
    /**
84
     * @var GraphQL
85
     */
86
    private static $instance;
87
88
    /**
89
     * @var Container
90
     */
91
    protected $container;
92
93
    /**
94
     * GraphQL constructor.
95
     */
96
    private function __construct()
97
    {
98
        $container = new Container();
99
100
        $this->registerProviders($container);
101
102
        $this->container = $container;
103
    }
104
105
    /**
106
     * @return GraphQL
107
     */
108
    public static function getInstance(): self
109
    {
110
        if (null === static::$instance) {
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $instance to at least protected.
Loading history...
111
            static::$instance = new static();
112
        }
113
114
        return static::$instance;
115
    }
116
117
    /**
118
     * @param string $id
119
     * @param array  $args
120
     * @return mixed
121
     */
122
    public static function make(string $id, array $args = [])
123
    {
124
        return static::getInstance()
125
            ->getContainer()
126
            ->get($id, $args);
127
    }
128
129
    /**
130
     * @param string|Source                   $source
131
     * @param array|ResolverRegistryInterface $resolverRegistry
132
     * @param array                           $options
133
     * @return SchemaInterface
134
     * @throws InvariantException
135
     */
136
    public static function buildSchema($source, $resolverRegistry, array $options = []): SchemaInterface
137
    {
138
        return static::make(SchemaBuilderInterface::class)
139
            ->build(
140
                static::parse($source, $options),
141
                $resolverRegistry instanceof ResolverRegistryInterface
142
                    ? $resolverRegistry
143
                    : new ResolverRegistry($resolverRegistry),
144
                $options
145
            );
146
    }
147
148
    /**
149
     * @param SchemaInterface                 $schema
150
     * @param string|Source                   $source
151
     * @param array|ResolverRegistryInterface $resolverRegistry
152
     * @param array                           $options
153
     * @return SchemaInterface
154
     * @throws InvariantException
155
     */
156
    public static function extendSchema(
157
        SchemaInterface $schema,
158
        $source,
159
        $resolverRegistry,
160
        array $options = []
161
    ): SchemaInterface {
162
        return static::make(SchemaExtenderInterface::class)
163
            ->extend(
164
                $schema,
165
                static::parse($source, $options),
166
                $resolverRegistry instanceof ResolverRegistryInterface
167
                    ? $resolverRegistry
168
                    : new ResolverRegistry($resolverRegistry),
169
                $options
170
            );
171
    }
172
173
    /**
174
     * @param SchemaInterface $schema
175
     * @return array
176
     */
177
    public static function validateSchema(SchemaInterface $schema): array
178
    {
179
        return static::make(SchemaValidatorInterface::class)
180
            ->validate($schema);
181
    }
182
183
    /**
184
     * @param string|Source $source
185
     * @param array         $options
186
     * @return DocumentNode
187
     * @throws InvariantException
188
     */
189
    public static function parse($source, array $options = []): DocumentNode
190
    {
191
        return static::make(ParserInterface::class)
192
            ->parse(static::lex($source, $options));
193
    }
194
195
    /**
196
     * @param string|Source $source
197
     * @param array         $options
198
     * @return ValueNodeInterface
199
     * @throws InvariantException
200
     */
201
    public static function parseValue($source, array $options = []): ValueNodeInterface
202
    {
203
        return static::make(ParserInterface::class)
204
            ->parseValue(static::lex($source, $options));
205
    }
206
207
    /**
208
     * @param string|Source $source
209
     * @param array         $options
210
     * @return TypeNodeInterface
211
     * @throws InvariantException
212
     */
213
    public static function parseType($source, array $options = []): TypeNodeInterface
214
    {
215
        return static::make(ParserInterface::class)
216
            ->parseType(static::lex($source, $options));
217
    }
218
219
    /**
220
     * @param SchemaInterface $schema
221
     * @param DocumentNode    $document
222
     * @return array
223
     */
224
    public static function validate(SchemaInterface $schema, DocumentNode $document): array
225
    {
226
        return static::make(ValidatorInterface::class)
227
            ->validate($schema, $document);
228
    }
229
230
    /**
231
     * @param SchemaInterface $schema
232
     * @param DocumentNode    $document
233
     * @param null            $rootValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $operationName is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $contextValue is correct as it would always require null to be passed?
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $rootValue is correct as it would always require null to be passed?
Loading history...
234
     * @param null            $contextValue
235
     * @param array           $variableValues
236
     * @param null            $operationName
237
     * @param callable|null   $fieldResolver
238
     * @return ExecutionResult
239
     */
240
    public static function execute(
241
        SchemaInterface $schema,
242
        DocumentNode $document,
243
        $rootValue = null,
244
        $contextValue = null,
245
        array $variableValues = [],
246
        $operationName = null,
247
        callable $fieldResolver = null
248
    ): ExecutionResult {
249
        return static::make(ExecutionInterface::class)
250
            ->execute(
251
                $schema,
252
                $document,
253
                $rootValue,
254
                $contextValue,
255
                $variableValues,
256
                $operationName,
257
                $fieldResolver
258
            );
259
    }
260
261
    /**
262
     * @param NodeInterface $node
263
     * @return string
264
     */
265
    public static function print(NodeInterface $node): string
266
    {
267
        return static::make(PrinterInterface::class)->print($node);
268
    }
269
270
    /**
271
     * @param string|Source $source
272
     * @param array         $options
273
     * @return LexerInterface
274
     * @throws InvariantException
275
     */
276
    public static function lex($source, array $options = []): LexerInterface
277
    {
278
        // TODO: Introduce a LexerCreator to allow setting source and options via the constructor.
279
        return static::make(LexerInterface::class)
280
            ->setSource($source instanceof Source ? $source : new Source($source))
281
            ->setOptions($options);
282
    }
283
284
    /**
285
     * @return Container
286
     */
287
    public function getContainer(): Container
288
    {
289
        return $this->container;
290
    }
291
292
    /**
293
     * Registers the service provides with the container.
294
     */
295
    protected function registerProviders(ContainerInterface $container): void
296
    {
297
        foreach (static::$providers as $className) {
0 ignored issues
show
Bug introduced by
Since $providers is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $providers to at least protected.
Loading history...
298
            $container->addServiceProvider($className);
299
        }
300
    }
301
}
302