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

defaultParameterValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 9
nc 1
nop 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