Passed
Pull Request — master (#38)
by Marco
02:55
created

Comparator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\ApiCompare;
6
7
use Roave\ApiCompare\Comparator\BackwardsCompatibility\ClassBased\ClassBased;
8
use Roave\ApiCompare\Comparator\BackwardsCompatibility\ClassConstantBased\ConstantBased;
9
use Roave\ApiCompare\Comparator\BackwardsCompatibility\InterfaceBased\InterfaceBased;
10
use Roave\ApiCompare\Comparator\BackwardsCompatibility\MethodBased\MethodBased;
11
use Roave\ApiCompare\Comparator\BackwardsCompatibility\PropertyBased\PropertyBased;
12
use Roave\BetterReflection\Reflection\ReflectionClass;
13
use Roave\BetterReflection\Reflection\ReflectionClassConstant;
14
use Roave\BetterReflection\Reflection\ReflectionMethod;
15
use Roave\BetterReflection\Reflection\ReflectionProperty;
16
use Roave\BetterReflection\Reflector\ClassReflector;
17
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
18
use function sprintf;
19
20
class Comparator
21
{
22
    /** @var ClassBased */
23
    private $classBasedComparisons;
24
25
    /**
26
     * @var InterfaceBased
27
     */
28
    private $interfaceBasedComparisons;
29
30
    /**
31
     * @var MethodBased
32
     */
33
    private $methodBasedComparisons;
34
35
    /**
36
     * @var PropertyBased
37
     */
38
    private $propertyBasedComparisons;
39
40
    /**
41
     * @var ConstantBased
42
     */
43
    private $constantBasedComparisons;
44
45
    public function __construct(
46
        ClassBased $classBasedComparisons,
47
        InterfaceBased $interfaceBasedComparisons,
48
        MethodBased $methodBasedComparisons,
49
        PropertyBased $propertyBasedComparisons,
50
        ConstantBased $constantBasedComparisons
51
    ) {
52
        $this->classBasedComparisons     = $classBasedComparisons;
53
        $this->interfaceBasedComparisons = $interfaceBasedComparisons;
54
        $this->methodBasedComparisons    = $methodBasedComparisons;
55
        $this->propertyBasedComparisons  = $propertyBasedComparisons;
56
        $this->constantBasedComparisons  = $constantBasedComparisons;
57
    }
58
59
    public function compare(ClassReflector $oldApi, ClassReflector $newApi) : Changes
60
    {
61
        $changelog = Changes::new();
62
63
        foreach ($oldApi->getAllClasses() as $oldClass) {
64
            $changelog = $this->examineClass($changelog, $oldClass, $newApi);
65
        }
66
67
        return $changelog;
68
    }
69
70
    private function examineClass(Changes $changelog, ReflectionClass $oldClass, ClassReflector $newApi) : Changes
71
    {
72
        try {
73
            /** @var ReflectionClass $newClass */
74
            $newClass = $newApi->reflect($oldClass->getName());
75
76
            if ($oldClass->isInterface() && $newClass->isInterface()) {
77
                $changelog = $changelog->mergeWith($this->interfaceBasedComparisons->compare($oldClass, $newClass));
78
            }
79
80
            $changelog = $changelog->mergeWith($this->classBasedComparisons->compare($oldClass, $newClass));
81
        } catch (IdentifierNotFound $exception) {
82
            $changelog = $changelog->withAddedChange(
83
                Change::removed(sprintf('Class %s has been deleted', $oldClass->getName()), true)
84
            );
85
            return $changelog;
86
        }
87
88
        foreach ($oldClass->getMethods() as $oldMethod) {
89
            $changelog = $changelog->mergeWith($this->examineMethod($oldMethod, $newClass));
90
        }
91
92
        foreach ($oldClass->getProperties() as $oldProperty) {
93
            $changelog = $changelog->mergeWith($this->examineProperty($oldProperty, $newClass));
94
        }
95
96
        foreach ($oldClass->getReflectionConstants() as $oldConstant) {
97
            $changelog = $changelog->mergeWith($this->examineConstant($oldConstant, $newClass));
98
        }
99
100
        return $changelog;
101
    }
102
103
    private function examineMethod(ReflectionMethod $oldMethod, ReflectionClass $newClass) : Changes
104
    {
105
        $methodName = $oldMethod->getName();
106
107
        if (! $newClass->hasMethod($methodName)) {
108
            return Changes::new();
109
        }
110
111
        return $this->methodBasedComparisons->compare($oldMethod, $newClass->getMethod($methodName));
112
    }
113
114
    private function examineProperty(ReflectionProperty $oldProperty, ReflectionClass $newClass) : Changes
115
    {
116
        $newProperty = $newClass->getProperty($oldProperty->getName());
117
118
        if (! $newProperty) {
119
            return Changes::new();
120
        }
121
122
        return $this->propertyBasedComparisons->compare($oldProperty, $newProperty);
123
    }
124
125
    private function examineConstant(ReflectionClassConstant $oldConstant, ReflectionClass $newClass) : Changes
126
    {
127
        $newConstant = $newClass->getReflectionConstant($oldConstant->getName());
128
129
        if (! $newConstant) {
130
            return Changes::new();
131
        }
132
133
        return $this->constantBasedComparisons->compare($oldConstant, $newConstant);
134
    }
135
}
136