GlobControllerQueryProvider::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 7
1
<?php
2
3
4
namespace TheCodingMachine\GraphQL\Controllers;
5
6
use Mouf\Composer\ClassNameMapper;
7
use Psr\Container\ContainerInterface;
8
use Psr\SimpleCache\CacheInterface;
9
use TheCodingMachine\ClassExplorer\Glob\GlobClassExplorer;
10
use TheCodingMachine\GraphQL\Controllers\Mappers\RecursiveTypeMapperInterface;
11
12
/**
13
 * Scans all the classes in a given namespace of the main project (not the vendor directory).
14
 * Analyzes all classes and detects "Query" and "Mutation" annotations.
15
 *
16
 * Assumes that the container contains a class whose identifier is the same as the class name.
17
 */
18
final class GlobControllerQueryProvider implements QueryProviderInterface
19
{
20
    /**
21
     * @var string
22
     */
23
    private $namespace;
24
    /**
25
     * @var CacheInterface
26
     */
27
    private $cache;
28
    /**
29
     * @var int|null
30
     */
31
    private $cacheTtl;
32
    /**
33
     * @var array<string,string>|null
34
     */
35
    private $instancesList;
36
    /**
37
     * @var ContainerInterface
38
     */
39
    private $container;
40
    /**
41
     * @var AggregateControllerQueryProvider
42
     */
43
    private $aggregateControllerQueryProvider;
44
    /**
45
     * @var FieldsBuilderFactory
46
     */
47
    private $fieldsBuilderFactory;
48
    /**
49
     * @var RecursiveTypeMapperInterface
50
     */
51
    private $recursiveTypeMapper;
52
    /**
53
     * @var bool
54
     */
55
    private $recursive;
56
57
    /**
58
     * @param string $namespace The namespace that contains the GraphQL types (they must have a `@Type` annotation)
59
     * @param FieldsBuilderFactory $fieldsBuilderFactory
60
     * @param RecursiveTypeMapperInterface $recursiveTypeMapper
61
     * @param ContainerInterface $container The container we will fetch controllers from.
62
     * @param CacheInterface $cache
63
     * @param int|null $cacheTtl
64
     * @param bool $recursive Whether subnamespaces of $namespace must be analyzed.
65
     */
66
    public function __construct(string $namespace, FieldsBuilderFactory $fieldsBuilderFactory, RecursiveTypeMapperInterface $recursiveTypeMapper, ContainerInterface $container, CacheInterface $cache, ?int $cacheTtl = null, bool $recursive = true)
67
    {
68
        $this->namespace = $namespace;
69
        $this->container = $container;
70
        $this->cache = $cache;
71
        $this->cacheTtl = $cacheTtl;
72
        $this->fieldsBuilderFactory = $fieldsBuilderFactory;
73
        $this->recursiveTypeMapper = $recursiveTypeMapper;
74
        $this->recursive = $recursive;
75
    }
76
77
    private function getAggregateControllerQueryProvider(): AggregateControllerQueryProvider
78
    {
79
        if ($this->aggregateControllerQueryProvider === null) {
80
            $this->aggregateControllerQueryProvider = new AggregateControllerQueryProvider($this->getInstancesList(), $this->fieldsBuilderFactory, $this->recursiveTypeMapper, $this->container);
81
        }
82
        return $this->aggregateControllerQueryProvider;
83
    }
84
85
    /**
86
     * Returns an array of fully qualified class names.
87
     *
88
     * @return string[]
89
     */
90
    private function getInstancesList(): array
91
    {
92
        if ($this->instancesList === null) {
93
            $key = 'globQueryProvider_'.str_replace('\\', '_', $this->namespace);
94
            $this->instancesList = $this->cache->get($key);
95
            if ($this->instancesList === null) {
96
                $this->instancesList = $this->buildInstancesList();
97
                $this->cache->set($key, $this->instancesList, $this->cacheTtl);
98
            }
99
        }
100
        return $this->instancesList;
101
    }
102
103
    /**
104
     * @return string[]
105
     */
106
    private function buildInstancesList(): array
107
    {
108
        $explorer = new GlobClassExplorer($this->namespace, $this->cache, $this->cacheTtl, ClassNameMapper::createFromComposerFile(null, null, true), $this->recursive);
109
        $classes = $explorer->getClasses();
110
        $instances = [];
111
        foreach ($classes as $className) {
112
            if (!\class_exists($className)) {
113
                continue;
114
            }
115
            $refClass = new \ReflectionClass($className);
116
            if (!$refClass->isInstantiable()) {
117
                continue;
118
            }
119
            if ($this->container->has($className)) {
120
                $instances[] = $className;
121
            }
122
        }
123
        return $instances;
124
    }
125
126
    /**
127
     * @return QueryField[]
128
     */
129
    public function getQueries(): array
130
    {
131
        return $this->getAggregateControllerQueryProvider()->getQueries();
132
    }
133
134
    /**
135
     * @return QueryField[]
136
     */
137
    public function getMutations(): array
138
    {
139
        return $this->getAggregateControllerQueryProvider()->getMutations();
140
    }
141
}
142