Completed
Pull Request — master (#38)
by Marco
03:08
created

ParameterDefaultValueChanged   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 59
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 5
dl 0
loc 59
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B compare() 0 32 3
A defaultParameterValues() 0 14 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\ApiCompare\Comparator\BackwardsCompatibility\FunctionBased;
6
7
use Roave\ApiCompare\Change;
8
use Roave\ApiCompare\Changes;
9
use Roave\ApiCompare\Formatter\ReflectionFunctionAbstractName;
10
use Roave\BetterReflection\Reflection\ReflectionFunctionAbstract;
11
use Roave\BetterReflection\Reflection\ReflectionMethod;
12
use Roave\BetterReflection\Reflection\ReflectionParameter;
13
use function assert;
14
15
/**
16
 * A default value for a parameter should not change, as that can lead to change in expected execution
17
 * behavior.
18
 */
19
final class ParameterDefaultValueChanged implements FunctionBased
20
{
21
    /** @var ReflectionFunctionAbstractName */
22
    private $formatFunction;
23
24
    public function __construct()
25
    {
26
        $this->formatFunction = new ReflectionFunctionAbstractName();
27
    }
28
29
    public function compare(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
30
    {
31
        $fromParametersWithDefaults = $this->defaultParameterValues($fromFunction);
32
        $toParametersWithDefaults   = $this->defaultParameterValues($toFunction);
33
34
        $changes = Changes::new();
35
36
        foreach (array_intersect_key($fromParametersWithDefaults, $toParametersWithDefaults) as $parameterIndex => $parameter) {
37
            assert($parameter instanceof ReflectionParameter);
38
39
            $defaultValueFrom = $parameter->getDefaultValue();
40
            $defaultValueTo   = $toParametersWithDefaults[$parameterIndex]->getDefaultValue();
41
42
            if ($defaultValueFrom === $defaultValueTo) {
43
                continue;
44
            }
45
46
            $changes = $changes->mergeWith(Changes::fromArray([
47
                Change::changed(
48
                    sprintf(
49
                        'Default parameter value for for parameter $%s of %s changed from %s to %s',
50
                        $parameter->getName(),
51
                        $this->formatFunction->__invoke($fromFunction),
52
                        var_export($defaultValueFrom, true),
53
                        var_export($defaultValueTo, true)
54
                    ),
55
                    true
56
                ),
57
            ]));
58
        }
59
60
        return $changes;
61
    }
62
63
    /** @return ReflectionParameter[] indexed by parameter index */
64
    private function defaultParameterValues(ReflectionFunctionAbstract $function) : array
65
    {
66
        $optionalParameters = array_values(array_filter(
67
            $function->getParameters(),
68
            function (ReflectionParameter $parameter) : bool {
69
                return $parameter->isDefaultValueAvailable();
70
            }
71
        ));
72
73
        return array_combine(
74
            array_map(function (ReflectionParameter $parameter) : int {
75
                return $parameter->getPosition();
76
            }, $optionalParameters),
77
            $optionalParameters
78
        );
79
    }
80
}
81