Completed
Push — master ( cbfed7...c39fb6 )
by Rafael
05:06
created

DefinitionRegistry   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 94.12%

Importance

Changes 0
Metric Value
dl 0
loc 141
ccs 48
cts 51
cp 0.9412
rs 10
c 0
b 0
f 0
wmc 24

7 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeArguments() 0 7 3
A getManager() 0 19 4
A getTaggedServices() 0 3 1
A normalizeFields() 0 9 3
A __construct() 0 4 1
B compile() 0 19 7
B normalizeType() 0 11 5
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Definition\Registry;
12
13
use Ynlo\GraphQLBundle\Component\TaggedServices\TaggedServices;
14
use Ynlo\GraphQLBundle\Component\TaggedServices\TagSpecification;
15
use Ynlo\GraphQLBundle\Definition\ArgumentAwareInterface;
16
use Ynlo\GraphQLBundle\Definition\FieldsAwareDefinitionInterface;
17
use Ynlo\GraphQLBundle\Definition\Loader\DefinitionLoaderInterface;
18
19
/**
20
 * Contains many definition managers with all definitions
21
 * each manager represent a different endpoint in the API.
22
 */
23
class DefinitionRegistry
24
{
25
    /**
26
     * @var TaggedServices
27
     */
28
    private $taggedServices;
29
30
    /**
31
     * @var DefinitionManager[]
32
     */
33
    private static $manager = [];
34
35
    /**
36
     * @var string
37
     */
38
    private $cacheDir;
39
40
    /**
41
     * DefinitionRegistry constructor.
42
     *
43
     * @param TaggedServices $taggedServices
44
     * @param null|string    $cacheDir
45
     */
46 14
    public function __construct(TaggedServices $taggedServices, ?string $cacheDir = null)
47
    {
48 14
        $this->taggedServices = $taggedServices;
49 14
        $this->cacheDir = $cacheDir;
50 14
    }
51
52
    /**
53
     * @param string $name
54
     *
55
     * @return DefinitionManager
56
     */
57 14
    public function getManager($name = 'default'): DefinitionManager
58
    {
59 14
        if (array_key_exists($name, self::$manager)) {
60 14
            return self::$manager[$name];
61
        }
62
63 1
        $manager = self::$manager[$name] = new DefinitionManager($name);
64
65 1
        $specifications = $this->getTaggedServices('graphql.definition_loader');
66 1
        foreach ($specifications as $specification) {
67 1
            $resolver = $specification->getService();
68 1
            if ($resolver instanceof DefinitionLoaderInterface) {
69 1
                $resolver->loadDefinitions($manager);
70
            }
71
        }
72
73 1
        $this->compile($manager);
74
75 1
        return $manager;
76
    }
77
78
    /**
79
     * Verify the manager definitions and do some tasks to prepare the manager
80
     *
81
     * @param DefinitionManager $manager
82
     */
83 1
    private function compile(DefinitionManager $manager)
84
    {
85 1
        foreach ($manager->allTypes() as $type) {
86 1
            if ($type instanceof FieldsAwareDefinitionInterface) {
87 1
                $this->normalizeFields($manager, $type);
88
            }
89
        }
90
91 1
        foreach ($manager->allQueries() as $query) {
92 1
            $query->setType($this->normalizeType($manager, $query->getType()));
93 1
            if ($query instanceof ArgumentAwareInterface) {
94 1
                $this->normalizeArguments($manager, $query);
95
            }
96
        }
97
98 1
        foreach ($manager->allMutations() as $mutation) {
99 1
            $mutation->setType($this->normalizeType($manager, $mutation->getType()));
100 1
            if ($mutation instanceof ArgumentAwareInterface) {
101 1
                $this->normalizeArguments($manager, $mutation);
102
            }
103
        }
104 1
    }
105
106
    /**
107
     * @param DefinitionManager      $manager
108
     * @param ArgumentAwareInterface $argumentAware
109
     */
110 1
    private function normalizeArguments(DefinitionManager $manager, ArgumentAwareInterface $argumentAware)
111
    {
112 1
        foreach ($argumentAware->getArguments() as $argument) {
113 1
            $argument->setType($this->normalizeType($manager, $argument->getType()));
114 1
            if (!$argument->getType()) {
115
                $msg = sprintf('The argument "%s" of "%s" does not have a valid type', $argument->getName(), $argumentAware->getName());
116 1
                throw new \RuntimeException($msg);
117
            }
118
        }
119 1
    }
120
121
    /**
122
     * @param DefinitionManager              $manager
123
     * @param FieldsAwareDefinitionInterface $fieldsAwareDefinition
124
     */
125 1
    private function normalizeFields(DefinitionManager $manager, FieldsAwareDefinitionInterface $fieldsAwareDefinition)
126
    {
127 1
        foreach ($fieldsAwareDefinition->getFields() as $field) {
128 1
            $field->setType($this->normalizeType($manager, $field->getType()));
129 1
            if (!$field->getType()) {
130
                $msg = sprintf('The field "%s" of "%s" does not have a valid type', $field->getName(), $fieldsAwareDefinition->getName());
131
                throw new \RuntimeException($msg);
132
            }
133 1
            $this->normalizeArguments($manager, $field);
134
        }
135 1
    }
136
137
    /**
138
     * @param DefinitionManager $manager
139
     * @param string|null       $type
140
     *
141
     * @return null|string
142
     */
143 1
    private function normalizeType(DefinitionManager $manager, $type)
144
    {
145 1
        if ($type) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
146 1
            if (class_exists($type) || interface_exists($type)) {
147 1
                if ($manager->hasTypeForClass($type)) {
148 1
                    $type = $manager->getTypeForClass($type);
149
                }
150
            }
151
        }
152
153 1
        return $type;
154
    }
155
156
    /**
157
     * @param string $tag
158
     *
159
     * @return array|TagSpecification[]
160
     */
161 1
    private function getTaggedServices($tag): array
162
    {
163 1
        return $this->taggedServices->findTaggedServices($tag);
164
    }
165
}
166