Completed
Push — master ( 901cc6...ad6830 )
by James
15s queued 11s
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\ReflectionParameter;
12
use function array_combine;
13
use function array_filter;
14
use function array_intersect_key;
15
use function array_map;
16
use function array_values;
17
use function assert;
18
use function sprintf;
19
use function var_export;
20
21
/**
22
 * A default value for a parameter should not change, as that can lead to change in expected execution
23
 * behavior.
24
 */
25
final class ParameterDefaultValueChanged implements FunctionBased
26
{
27
    /** @var ReflectionFunctionAbstractName */
28
    private $formatFunction;
29
30
    public function __construct()
31
    {
32
        $this->formatFunction = new ReflectionFunctionAbstractName();
33
    }
34
35
    public function compare(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
36
    {
37
        $fromParametersWithDefaults = $this->defaultParameterValues($fromFunction);
38
        $toParametersWithDefaults   = $this->defaultParameterValues($toFunction);
39
40
        $changes = Changes::new();
41
42
        foreach (array_intersect_key($fromParametersWithDefaults, $toParametersWithDefaults) as $parameterIndex => $parameter) {
43
            assert($parameter instanceof ReflectionParameter);
44
45
            $defaultValueFrom = $parameter->getDefaultValue();
46
            $defaultValueTo   = $toParametersWithDefaults[$parameterIndex]->getDefaultValue();
47
48
            if ($defaultValueFrom === $defaultValueTo) {
49
                continue;
50
            }
51
52
            $changes = $changes->mergeWith(Changes::fromArray([
53
                Change::changed(
54
                    sprintf(
55
                        'Default parameter value for for parameter $%s of %s changed from %s to %s',
56
                        $parameter->getName(),
57
                        $this->formatFunction->__invoke($fromFunction),
58
                        var_export($defaultValueFrom, true),
59
                        var_export($defaultValueTo, true)
60
                    ),
61
                    true
62
                ),
63
            ]));
64
        }
65
66
        return $changes;
67
    }
68
69
    /** @return ReflectionParameter[] indexed by parameter index */
70
    private function defaultParameterValues(ReflectionFunctionAbstract $function) : array
71
    {
72
        $optionalParameters = array_values(array_filter(
73
            $function->getParameters(),
74
            function (ReflectionParameter $parameter) : bool {
75
                return $parameter->isDefaultValueAvailable();
76
            }
77
        ));
78
79
        return array_combine(
80
            array_map(function (ReflectionParameter $parameter) : int {
81
                return $parameter->getPosition();
82
            }, $optionalParameters),
83
            $optionalParameters
84
        );
85
    }
86
}
87