Completed
Push — master ( b01d16...d9d1e2 )
by Ruben
03:30
created

ParameterResolver::findParameter()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.4444
c 0
b 0
f 0
cc 8
nc 7
nop 2
1
<?php
2
3
namespace Spatie\ResourceLinks;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Routing\Route;
7
use Illuminate\Support\Arr;
8
use ReflectionParameter;
9
10
class ParameterResolver
11
{
12
    /** @var \Illuminate\Database\Eloquent\Model|null */
13
    private $model;
14
15
    /** @var array */
16
    private $defaultParameters;
17
18
    public function __construct(?Model $model, array $defaultParameters = [])
19
    {
20
        $this->model = $model;
21
22
        $this->defaultParameters = $defaultParameters;
23
    }
24
25
    public function forRoute(Route $route): array
26
    {
27
        $providedParameters = $this->getProvidedParameters();
28
29
        return collect($route->signatureParameters())
30
            ->mapWithKeys(function (ReflectionParameter $signatureParameter) use ($providedParameters) {
31
                return [
32
                    $signatureParameter->getName() => $this->findParameter(
33
                        $signatureParameter,
34
                        $providedParameters
35
                    ),
36
                ];
37
            })
38
            ->reject(function ($parameter) {
39
                return $parameter === null;
40
            })->all();
41
    }
42
43
    private function getProvidedParameters(): array
44
    {
45
        return $this->defaultParameters;
46
    }
47
48
    private function findParameter(ReflectionParameter $signatureParameter, array &$providedParameters)
49
    {
50
        if ($this->expectsModelAsParameter($signatureParameter)) {
51
            return $this->model;
52
        }
53
54
        if ($this->parameterWithKeyExists($signatureParameter, $providedParameters)) {
55
            return Arr::pull($providedParameters, $signatureParameter->getName());
56
        }
57
58
        if ($this->expectsPrimitiveParameter($signatureParameter)) {
59
            return $this->searchPrimitiveParameter($signatureParameter, $providedParameters);
60
        }
61
62
        foreach ($providedParameters as $index => $providedParameter) {
63
            if (! is_object($providedParameter) || $signatureParameter->getClass() === null) {
64
                continue;
65
            }
66
67
            if ($signatureParameter->getClass()->isInstance($providedParameter)) {
68
                return Arr::pull($providedParameters, $index);
69
            }
70
        }
71
72
        return null;
73
    }
74
75
    private function expectsModelAsParameter(ReflectionParameter $signatureParameter): bool
76
    {
77
        if ($this->model === null) {
78
            return false;
79
        }
80
81
        if ($signatureParameter->getClass() === null) {
82
            return false;
83
        }
84
85
        return $signatureParameter->getClass()->isInstance($this->model);
86
    }
87
88
    private function parameterWithKeyExists(
89
        ReflectionParameter $signatureParameter,
90
        array $providedParameters
91
    ): bool {
92
        return array_key_exists(
93
            $signatureParameter->getName(),
94
            $providedParameters
95
        );
96
    }
97
98
    private function expectsPrimitiveParameter(
99
        ReflectionParameter $signatureParameter
100
    ): bool {
101
        if($signatureParameter->getType() === null){
102
            return false;
103
        }
104
105
        return $signatureParameter->getType()->isBuiltin();
106
    }
107
108
    private function searchPrimitiveParameter(
109
        ReflectionParameter $signatureParameter,
110
        array &$providedParameters
111
    ) {
112
        foreach ($providedParameters as $index => $providedParameter) {
113
            if ($this->getParameterPrimitiveType($providedParameter) === $signatureParameter->getType()->getName()) {
114
                return Arr::pull($providedParameters, $index);
115
            }
116
        }
117
118
        return null;
119
    }
120
121
    private function getParameterPrimitiveType($parameter): string
122
    {
123
        $typeName = gettype($parameter);
124
125
        return strtr($typeName, [
126
            'boolean' => 'bool',
127
            'integer' => 'int',
128
        ]);
129
    }
130
}
131