Passed
Pull Request — master (#38)
by Marco
02:40
created

ParameterByReferenceChanged::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
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_intersect_key;
13
use function array_values;
14
use function sprintf;
15
16
/**
17
 * A parameter passed by-value and a parameter passed by-reference are wildly different, so changing
18
 * the by-ref flag can lead to unexpected state mutations or lack thereof, and should therefore be
19
 * considered a BC break.
20
 */
21
final class ParameterByReferenceChanged implements FunctionBased
22
{
23
    /** @var ReflectionFunctionAbstractName */
24
    private $formatFunction;
25
26
    public function __construct()
27
    {
28
        $this->formatFunction = new ReflectionFunctionAbstractName();
29
    }
30
31
    public function compare(ReflectionFunctionAbstract $fromFunction, ReflectionFunctionAbstract $toFunction) : Changes
32
    {
33
        /** @var ReflectionParameter[] $fromParameters */
34
        $fromParameters = array_values($fromFunction->getParameters());
35
        /** @var ReflectionParameter[] $toParameters */
36
        $toParameters = array_values($toFunction->getParameters());
37
38
        $changes = Changes::new();
39
40
        foreach (array_intersect_key($fromParameters, $toParameters) as $parameterIndex => $commonParameter) {
41
            $changes = $changes->mergeWith($this->compareParameter($commonParameter, $toParameters[$parameterIndex]));
42
        }
43
44
        return $changes;
45
    }
46
47
    private function compareParameter(ReflectionParameter $fromParameter, ReflectionParameter $toParameter) : Changes
48
    {
49
        $fromByReference = $fromParameter->isPassedByReference();
50
        $toByReference   = $toParameter->isPassedByReference();
51
52
        if ($fromByReference === $toByReference) {
53
            return Changes::new();
54
        }
55
56
        return Changes::fromArray([
57
            Change::changed(
58
                sprintf(
59
                    'The parameter $%s of %s changed from %s to %s',
60
                    $fromParameter->getName(),
61
                    $this->formatFunction->__invoke($fromParameter->getDeclaringFunction()),
62
                    $this->referenceToString($fromByReference),
63
                    $this->referenceToString($toByReference)
64
                ),
65
                true
66
            ),
67
        ]);
68
    }
69
70
    private function referenceToString(bool $reference) : string
71
    {
72
        return $reference ? 'by-reference' : 'by-value';
73
    }
74
}
75