DependencyGraphBuilder   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Importance

Changes 4
Bugs 2 Features 0
Metric Value
eloc 81
c 4
b 2
f 0
dl 0
loc 185
rs 10
wmc 29

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getVertex() 0 16 2
A addExtends() 0 7 2
A addDependencyType() 0 18 4
A __construct() 0 4 1
A addUseTrait() 0 7 2
A addImplements() 0 7 2
A setObserver() 0 3 1
A addConstFetch() 0 7 2
A getUnknownClassVertex() 0 18 3
A addPropertyFetch() 0 7 2
A addNew() 0 7 2
A addMethodCall() 0 7 2
A addUnknownDependency() 0 6 1
A addDependency() 0 7 2
A build() 0 3 1
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer;
5
6
use DependencyAnalyzer\DependencyGraph\DependencyTypes\Base as DependencyType;
7
use DependencyAnalyzer\DependencyGraph\DependencyTypes\ConstantFetch;
8
use DependencyAnalyzer\DependencyGraph\DependencyTypes\ExtendsClass;
9
use DependencyAnalyzer\DependencyGraph\DependencyTypes\ImplementsClass;
10
use DependencyAnalyzer\DependencyGraph\DependencyTypes\MethodCall;
11
use DependencyAnalyzer\DependencyGraph\DependencyTypes\NewObject;
12
use DependencyAnalyzer\DependencyGraph\DependencyTypes\PropertyFetch;
13
use DependencyAnalyzer\DependencyGraph\DependencyTypes\SomeDependency;
14
use DependencyAnalyzer\DependencyGraph\DependencyTypes\UseTrait;
15
use DependencyAnalyzer\DependencyGraph\ExtraPhpDocTags\DepsInternal;
16
use DependencyAnalyzer\DependencyGraph\ExtraPhpDocTags\Internal;
17
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName;
18
use DependencyAnalyzer\DependencyGraphBuilder\ExtraPhpDocTagResolver;
19
use DependencyAnalyzer\DependencyGraphBuilder\ObserverInterface;
20
use DependencyAnalyzer\DependencyGraphBuilder\UnknownReflectionClass;
21
use DependencyAnalyzer\Exceptions\LogicException;
22
use Fhaculty\Graph\Graph;
23
use Fhaculty\Graph\Vertex;
24
use ReflectionClass;
25
26
class DependencyGraphBuilder
27
{
28
    /**
29
     * @var Graph
30
     */
31
    protected $graph;
32
33
    /**
34
     * @var ExtraPhpDocTagResolver
35
     */
36
    protected $extraPhpDocTagResolver;
37
38
    public function __construct(ExtraPhpDocTagResolver $extraPhpDocTagResolver)
39
    {
40
        $this->graph = new Graph;
41
        $this->extraPhpDocTagResolver = $extraPhpDocTagResolver;
42
    }
43
44
    public function setObserver(ObserverInterface $observer): void
45
    {
46
        $this->extraPhpDocTagResolver->setObserver($observer);
47
    }
48
49
    protected function getVertex(ReflectionClass $class): Vertex
50
    {
51
        $vertexId = FullyQualifiedStructuralElementName::createClass($class->getName())->toString();
52
        if ($this->graph->hasVertex($vertexId)) {
53
            return $this->graph->getVertex($vertexId);
54
        }
55
56
        $vertex = $this->graph->createVertex($vertexId);
0 ignored issues
show
Bug introduced by
$vertexId of type string is incompatible with the type integer|null expected by parameter $id of Fhaculty\Graph\Graph::createVertex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

56
        $vertex = $this->graph->createVertex(/** @scrutinizer ignore-type */ $vertexId);
Loading history...
57
        $vertex->setAttribute('reflection', $class);
58
        $vertex->setAttribute(DepsInternal::getTagName(), array_merge(
59
            $this->extraPhpDocTagResolver->resolveDepsInternalTag($class),
60
            $this->extraPhpDocTagResolver->resolveCanOnlyUsedByTag($class)
61
        ));
62
        $vertex->setAttribute(Internal::getTagName(), $this->extraPhpDocTagResolver->resolveInternalTag($class));
63
64
        return $vertex;
65
    }
66
67
    protected function getUnknownClassVertex(string $className): Vertex
68
    {
69
        $vertexId = FullyQualifiedStructuralElementName::createClass($className)->toString();
70
        if ($this->graph->hasVertex($vertexId)) {
71
            $vertex = $this->graph->getVertex($vertexId);
72
            if (!$vertex->getAttribute('reflection') instanceof UnknownReflectionClass) {
73
                throw new LogicException("{$className} is not UnknownClassReflection");
74
            }
75
76
            return $vertex;
77
        }
78
79
        $vertex = $this->graph->createVertex($vertexId);
0 ignored issues
show
Bug introduced by
$vertexId of type string is incompatible with the type integer|null expected by parameter $id of Fhaculty\Graph\Graph::createVertex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

79
        $vertex = $this->graph->createVertex(/** @scrutinizer ignore-type */ $vertexId);
Loading history...
80
        $vertex->setAttribute('reflection', new UnknownReflectionClass($className));
81
        $vertex->setAttribute(DepsInternal::getTagName(), []);
82
        $vertex->setAttribute(Internal::getTagName(), []);
83
84
        return $vertex;
85
    }
86
87
    protected function addDependencyType(Vertex $depender, Vertex $dependee, DependencyType $additional): void
88
    {
89
        if (count($edges = $depender->getEdgesTo($dependee)) === 0) {
90
            $depender->createEdgeTo($dependee);
91
        }
92
93
        $edge = $depender->getEdgesTo($dependee)->getEdgeFirst();
94
        $types = $edge->getAttribute(DependencyGraph::DEPENDENCY_TYPE_KEY) ?? [];
95
96
        foreach ($types as $type) {
97
            /** @var DependencyType $type */
98
            if ($type->isEqual($additional)) {
99
                return;
100
            }
101
        }
102
103
        $types[] = $additional;
104
        $edge->setAttribute(DependencyGraph::DEPENDENCY_TYPE_KEY, $types);
105
    }
106
107
    /**
108
     * @param ReflectionClass $dependerReflection
109
     * @param ReflectionClass $dependeeReflection
110
     */
111
    public function addDependency(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection): void
112
    {
113
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
114
            $this->addDependencyType(
115
                $this->getVertex($dependerReflection),
116
                $this->getVertex($dependeeReflection),
117
                new SomeDependency()
118
            );
119
        }
120
    }
121
122
    public function addUnknownDependency(ReflectionClass $dependerReflection, string $dependeeName)
123
    {
124
        $this->addDependencyType(
125
            $this->getVertex($dependerReflection),
126
            $this->getUnknownClassVertex($dependeeName),
127
            new SomeDependency()
128
        );
129
    }
130
131
    public function addNew(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection, string $caller = null)
132
    {
133
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
134
            $this->addDependencyType(
135
                $this->getVertex($dependerReflection),
136
                $this->getVertex($dependeeReflection),
137
                new NewObject($caller)
138
            );
139
        }
140
    }
141
142
    public function addMethodCall(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection, string $callee, string $caller = null)
143
    {
144
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
145
            $this->addDependencyType(
146
                $this->getVertex($dependerReflection),
147
                $this->getVertex($dependeeReflection),
148
                new MethodCall($callee, $caller)
149
            );
150
        }
151
    }
152
153
    public function addPropertyFetch(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection, string $propertyName, string $caller = null)
154
    {
155
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
156
            $this->addDependencyType(
157
                $this->getVertex($dependerReflection),
158
                $this->getVertex($dependeeReflection),
159
                new PropertyFetch($propertyName, $caller)
160
            );
161
        }
162
    }
163
164
    public function addConstFetch(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection, string $constantName, string $caller = null)
165
    {
166
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
167
            $this->addDependencyType(
168
                $this->getVertex($dependerReflection),
169
                $this->getVertex($dependeeReflection),
170
                new ConstantFetch($constantName, $caller)
171
            );
172
        }
173
    }
174
175
    public function addExtends(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection)
176
    {
177
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
178
            $this->addDependencyType(
179
                $this->getVertex($dependerReflection),
180
                $this->getVertex($dependeeReflection),
181
                new ExtendsClass()
182
            );
183
        }
184
    }
185
186
    public function addImplements(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection)
187
    {
188
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
189
            $this->addDependencyType(
190
                $this->getVertex($dependerReflection),
191
                $this->getVertex($dependeeReflection),
192
                new ImplementsClass()
193
            );
194
        }
195
    }
196
197
    public function addUseTrait(ReflectionClass $dependerReflection, ReflectionClass $dependeeReflection)
198
    {
199
        if ($dependerReflection->getName() !== $dependeeReflection->getName()) {
200
            $this->addDependencyType(
201
                $this->getVertex($dependerReflection),
202
                $this->getVertex($dependeeReflection),
203
                new UseTrait()
204
            );
205
        }
206
    }
207
208
    public function build(): DependencyGraph
209
    {
210
        return new DependencyGraph($this->graph);
211
    }
212
}
213