ParameterTypeChanged::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\BackwardCompatibility\DetectChanges\BCBreak\FunctionBased;
6
7
use Roave\BackwardCompatibility\Change;
8
use Roave\BackwardCompatibility\Changes;
9
use Roave\BackwardCompatibility\Formatter\ReflectionFunctionAbstractName;
10
use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract;
11
use Roave\BetterReflection\Reflection\ReflectionParameter;
12
use Roave\BetterReflection\Reflection\ReflectionType;
13
use function array_intersect_key;
14
use function Safe\sprintf;
15
16
/**
17
 * Detects a change in a parameter type
18
 *
19
 * This is mostly useful for methods, where a change in a parameter type is not allowed in
20
 * inheritance/interface scenarios.
21
 */
22
final class ParameterTypeChanged implements FunctionBased
23
{
24
    /** @var ReflectionFunctionAbstractName */
25
    private $formatFunction;
26
27
    public function __construct()
28
    {
29
        $this->formatFunction = new ReflectionFunctionAbstractName();
30
    }
31
32
    public function __invoke(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
33
    {
34
        return Changes::fromIterator($this->checkSymbols(
35
            $fromFunction->getParameters(),
36
            $toFunction->getParameters()
37
        ));
38
    }
39
40
    /**
41
     * @param ReflectionParameter[] $from
42
     * @param ReflectionParameter[] $to
43
     *
44
     * @return iterable|Change[]
45
     */
46
    private function checkSymbols(array $from, array $to) : iterable
47
    {
48
        foreach (array_intersect_key($from, $to) as $index => $commonParameter) {
49
            yield from $this->compareParameter($commonParameter, $to[$index]);
0 ignored issues
show
Bug Best Practice introduced by
The expression YieldFromNode returns the type Generator which is incompatible with the documented return type Roave\BackwardCompatibility\Change[]|iterable.
Loading history...
50
        }
51
    }
52
53
    /**
54
     * @return iterable|Change[]
55
     */
56
    private function compareParameter(ReflectionParameter $fromParameter, ReflectionParameter $toParameter) : iterable
57
    {
58
        $fromType = $this->typeToString($fromParameter->getType());
59
        $toType   = $this->typeToString($toParameter->getType());
60
61
        if ($fromType !== $toType) {
62
            yield Change::changed(
0 ignored issues
show
Bug Best Practice introduced by
The expression yield Roave\BackwardComp...omType, $toType), true) returns the type Generator which is incompatible with the documented return type Roave\BackwardCompatibility\Change[]|iterable.
Loading history...
63
                sprintf(
64
                    'The parameter $%s of %s changed from %s to %s',
65
                    $fromParameter->getName(),
66
                    $this->formatFunction->__invoke($fromParameter->getDeclaringFunction()),
67
                    $fromType,
68
                    $toType
69
                ),
70
                true
71
            );
72
        }
73
    }
74
75
    private function typeToString(?ReflectionType $type) : string
76
    {
77
        if (! $type) {
78
            return 'no type';
79
        }
80
81
        return ($type->allowsNull() ? '?' : '')
82
            . $type->__toString();
83
    }
84
}
85