Completed
Push — master ( f89e11...f7925b )
by Arthur
03:41 queued 10s
created

resolveContainerDependency()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.3244

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 20
ccs 8
cts 11
cp 0.7272
rs 9.9332
cc 4
nc 5
nop 4
crap 4.3244
1
<?php
2
3
namespace Larapie\Actions\Concerns;
4
5
use Illuminate\Database\Eloquent\ModelNotFoundException;
6
use Illuminate\Support\Str;
7
use Illuminate\Validation\ValidationException;
8
use Illuminate\Support\Facades\Validator;
9
use Larapie\Actions\Exception\MethodDoesNotExistException;
10
use ReflectionMethod;
11
use ReflectionParameter;
12
13
trait ResolvesMethodDependencies
14
{
15 49
    protected function resolveAndCall($instance, $method, $extras = [])
16
    {
17 49
        if (!method_exists($instance, $method)) {
18 1
            throw new MethodDoesNotExistException("method $method not found on " . get_class($instance));
19
        }
20
21 48
        $parameters = $this->resolveMethodDependencies($instance, $method, $extras);
22
23 47
        return $instance->{$method}(...$parameters);
24
    }
25
26 48
    protected function resolveMethodDependencies($instance, $method, $extras = [])
27
    {
28 48
        $reflector = new ReflectionMethod($instance, $method);
29
30
        $handler = function ($parameter) use ($extras) {
31 28
            return $this->resolveDependency($parameter, $extras);
32 48
        };
33
34 48
        return array_map($handler, $reflector->getParameters());
35
    }
36
37 28
    protected function resolveDependency(ReflectionParameter $parameter, $extras = [])
38
    {
39 28
        [$key, $value] = $this->findAttributeFromParameter($parameter->name, $extras);
40 28
        $class = $parameter->getClass();
41
42 28
        if ($key && (!$class || $value instanceof $class->name)) {
0 ignored issues
show
introduced by
$class is of type ReflectionClass, thus it always evaluated to true.
Loading history...
43 22
            return $value;
44
        }
45
46 14
        if ($class) {
0 ignored issues
show
introduced by
$class is of type ReflectionClass, thus it always evaluated to true.
Loading history...
47 6
            return $this->resolveContainerDependency($class->name, $key, $value, $parameter->name);
48
        }
49
50 8
        if ($parameter->isDefaultValueAvailable()) {
51 1
            return $parameter->getDefaultValue();
52
        }
53 8
    }
54
55 6
    protected function resolveContainerDependency($class, $key, $value, ?string $parameterName = null)
56
    {
57 6
        $instance = app($class);
58
59 6
        if (method_exists($instance, 'resolveRouteBinding')) {
60
61 5
            if (!$key) {
62
                throw (new ValidationException(Validator::make([], [
63
                    $parameterName => 'required'
64
                ])))->redirectTo($this->getRedirectUrl());
0 ignored issues
show
Bug introduced by
It seems like getRedirectUrl() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

64
                ])))->redirectTo($this->/** @scrutinizer ignore-call */ getRedirectUrl());
Loading history...
65
            }
66
67 5
            $instance = $this->resolveRouteBinding($instance, $value);
68
        }
69
70 5
        if ($key) {
71 4
            $this->updateAttributeWithResolvedInstance($key, $instance);
72
        }
73
74 5
        return $instance;
75
    }
76
77 5
    protected function resolveRouteBinding($instance, $value)
78
    {
79 5
        if (!$model = $instance->resolveRouteBinding($value)) {
80 1
            throw (new ModelNotFoundException())->setModel(get_class($instance));
81
        }
82
83 4
        return $model;
84
    }
85
86 28
    protected function findAttributeFromParameter($name, $extras = [])
87
    {
88 28
        $routeAttributes = $this->runningAs('controller') ? $this->getAttributesFromRoute($this->request) : [];
0 ignored issues
show
Bug introduced by
It seems like getAttributesFromRoute() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
        $routeAttributes = $this->runningAs('controller') ? $this->/** @scrutinizer ignore-call */ getAttributesFromRoute($this->request) : [];
Loading history...
Bug introduced by
It seems like runningAs() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
        $routeAttributes = $this->/** @scrutinizer ignore-call */ runningAs('controller') ? $this->getAttributesFromRoute($this->request) : [];
Loading history...
89 28
        $attributes = array_merge($this->attributes, $routeAttributes, $extras);
90
91 28
        if (array_key_exists($name, $attributes)) {
92 25
            return [$name, $attributes[$name]];
93
        }
94 10
        if (array_key_exists($snakedName = Str::snake($name), $attributes)) {
95 1
            return [$snakedName, $attributes[$snakedName]];
96
        }
97 9
    }
98
99 4
    public function updateAttributeWithResolvedInstance($key, $instance)
100
    {
101 4
        if ($this->runningAs('controller') && $this->request->has($key)) {
102 1
            return;
103
        }
104
105 3
        return $this->attributes[$key] = $instance;
0 ignored issues
show
Bug Best Practice introduced by
The property attributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
106
    }
107
}
108