Passed
Pull Request — master (#108)
by Marco
02:35
created

CompareClasses::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\BackwardCompatibility;
6
7
use Generator;
8
use Roave\BackwardCompatibility\DetectChanges\BCBreak\ClassBased\ClassBased;
9
use Roave\BackwardCompatibility\DetectChanges\BCBreak\InterfaceBased\InterfaceBased;
10
use Roave\BackwardCompatibility\DetectChanges\BCBreak\TraitBased\TraitBased;
11
use Roave\BetterReflection\Reflection\ReflectionClass;
12
use Roave\BetterReflection\Reflector\ClassReflector;
13
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
14
use function array_filter;
15
use function array_map;
16
use function sprintf;
17
18
final class CompareClasses implements CompareApi
19
{
20
    /** @var ClassBased */
21
    private $classBasedComparisons;
22
23
    /** @var InterfaceBased */
24
    private $interfaceBasedComparisons;
25
26
    /** @var TraitBased */
27
    private $traitBasedComparisons;
28
29
    public function __construct(
30
        ClassBased $classBasedComparisons,
31
        InterfaceBased $interfaceBasedComparisons,
32
        TraitBased $traitBasedComparisons
33
    ) {
34
        $this->classBasedComparisons     = $classBasedComparisons;
35
        $this->interfaceBasedComparisons = $interfaceBasedComparisons;
36
        $this->traitBasedComparisons     = $traitBasedComparisons;
37
    }
38
39
    /**
40
     * {@inheritDoc}
41
     */
42
    public function __invoke(
43
        ClassReflector $definedSymbols,
44
        ClassReflector $pastSourcesWithDependencies,
45
        ClassReflector $newSourcesWithDependencies
46
    ) : Changes {
47
        $definedApiClassNames = array_map(
48
            function (ReflectionClass $class) : string {
49
                return $class->getName();
50
            },
51
            array_filter(
52
                $definedSymbols->getAllClasses(),
53
                function (ReflectionClass $class) : bool {
54
                    return ! $class->isAnonymous();
55
                }
56
            )
57
        );
58
59
        return Changes::fromIterator($this->makeSymbolsIterator(
60
            $definedApiClassNames,
61
            $pastSourcesWithDependencies,
62
            $newSourcesWithDependencies
63
        ));
64
    }
65
66
    /**
67
     * @param string[] $definedApiClassNames
68
     *
69
     * @return iterable|Change[]
70
     */
71
    private function makeSymbolsIterator(
72
        array $definedApiClassNames,
73
        ClassReflector $pastSourcesWithDependencies,
74
        ClassReflector $newSourcesWithDependencies
75
    ) : iterable {
76
        foreach ($definedApiClassNames as $apiClassName) {
77
            /** @var ReflectionClass $oldSymbol */
78
            $oldSymbol = $pastSourcesWithDependencies->reflect($apiClassName);
79
80
            yield from $this->examineSymbol($oldSymbol, $newSourcesWithDependencies);
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type iterable|Roave\BackwardCompatibility\Change[].
Loading history...
81
        }
82
    }
83
84
    private function examineSymbol(
85
        ReflectionClass $oldSymbol,
86
        ClassReflector $newSourcesWithDependencies
87
    ) : Generator {
88
        try {
89
            /** @var ReflectionClass $newClass */
90
            $newClass = $newSourcesWithDependencies->reflect($oldSymbol->getName());
91
        } catch (IdentifierNotFound $exception) {
92
            yield Change::removed(sprintf('Class %s has been deleted', $oldSymbol->getName()), true);
93
94
            return;
95
        }
96
97
        if ($oldSymbol->isInterface()) {
98
            yield from $this->interfaceBasedComparisons->__invoke($oldSymbol, $newClass);
99
100
            return;
101
        }
102
103
        if ($oldSymbol->isTrait()) {
104
            yield from $this->traitBasedComparisons->__invoke($oldSymbol, $newClass);
105
106
            return;
107
        }
108
109
        yield from $this->classBasedComparisons->__invoke($oldSymbol, $newClass);
110
    }
111
}
112