Passed
Push — master ( 056350...65484c )
by Satoshi
05:02
created

DependencyGraphBuilder::addDependencyMap()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
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\ExtraPhpDocTagResolver;
16
use DependencyAnalyzer\DependencyGraphBuilder\UnknownReflectionClass;
17
use DependencyAnalyzer\Exceptions\LogicException;
18
use Fhaculty\Graph\Graph;
19
use Fhaculty\Graph\Vertex;
20
use ReflectionClass;
21
22
class DependencyGraphBuilder
23
{
24
    /**
25
     * @var Graph
26
     */
27
    protected $graph;
28
29
    /**
30
     * @var ExtraPhpDocTagResolver
31
     */
32
    protected $extraPhpDocTagResolver;
33
34
    public function __construct(ExtraPhpDocTagResolver $extraPhpDocTagResolver)
35
    {
36
        $this->graph = new Graph;
37
        $this->extraPhpDocTagResolver = $extraPhpDocTagResolver;
38
    }
39
40
    protected function getVertex(ReflectionClass $class): Vertex
41
    {
42
        if ($this->graph->hasVertex($class->getName())) {
43
            return $this->graph->getVertex($class->getName());
44
        }
45
46
        $vertex = $this->graph->createVertex($class->getName());
0 ignored issues
show
Bug introduced by
$class->getName() 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

46
        $vertex = $this->graph->createVertex(/** @scrutinizer ignore-type */ $class->getName());
Loading history...
47
        $vertex->setAttribute('reflection', $class);
48
        $vertex->setAttribute(ExtraPhpDocTagResolver::ONLY_USED_BY_TAGS, $this->extraPhpDocTagResolver->resolveCanOnlyUsedByTag($class));
49
        $vertex->setAttribute(ExtraPhpDocTagResolver::DEPS_INTERNAL, $this->extraPhpDocTagResolver->resolveDepsInternalTag($class));
50
51
        return $vertex;
52
    }
53
54
    protected function getUnknownClassVertex(string $className): Vertex
55
    {
56
        if ($this->graph->hasVertex($className)) {
57
            $vertex = $this->graph->getVertex($className);
58
            if (!$vertex->getAttribute('reflection') instanceof UnknownReflectionClass) {
59
                throw new LogicException("{$className} is not UnknownClassReflection");
60
            }
61
62
            return $vertex;
63
        }
64
65
        $vertex = $this->graph->createVertex($className);
0 ignored issues
show
Bug introduced by
$className 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

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