ParameterByReferenceChanged::referenceToString()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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