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

ParameterByReferenceChanged   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 52
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 7
dl 0
loc 52
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A compare() 0 14 2
A __construct() 0 3 1
A referenceToString() 0 3 2
A compareParameter() 0 19 2
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
14
/**
15
 * A parameter passed by-value and a parameter passed by-reference are wildly different, so changing
16
 * the by-ref flag can lead to unexpected state mutations or lack thereof, and should therefore be
17
 * considered a BC break.
18
 */
19
final class ParameterByReferenceChanged 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
        /** @var ReflectionParameter[] $fromParameters */
32
        $fromParameters = array_values($fromFunction->getParameters());
33
        /** @var ReflectionParameter[] $toParameters */
34
        $toParameters = array_values($toFunction->getParameters());
35
36
        $changes = Changes::new();
37
38
        foreach (array_intersect_key($fromParameters, $toParameters) as $parameterIndex => $commonParameter) {
39
            $changes = $changes->mergeWith($this->compareParameter($commonParameter, $toParameters[$parameterIndex]));
40
        }
41
42
        return $changes;
43
    }
44
45
    private function compareParameter(ReflectionParameter $fromParameter, ReflectionParameter $toParameter) : Changes
46
    {
47
        $fromByReference = $fromParameter->isPassedByReference();
48
        $toByReference   = $toParameter->isPassedByReference();
49
50
        if ($fromByReference === $toByReference) {
51
            return Changes::new();
52
        }
53
54
        return Changes::fromArray([
55
            Change::changed(
56
                sprintf(
57
                    'The parameter $%s of %s changed from %s to %s',
58
                    $fromParameter->getName(),
59
                    $this->formatFunction->__invoke($fromParameter->getDeclaringFunction()),
60
                    $this->referenceToString($fromByReference),
61
                    $this->referenceToString($toByReference)
62
                ),
63
                true
64
            ),
65
        ]);
66
    }
67
68
    private function referenceToString(bool $reference) : string
69
    {
70
        return $reference ? 'by-reference' : 'by-value';
71
    }
72
}
73