Issues (36)

src/Concerns/ResolvesMethodDependencies.php (6 issues)

1
<?php
2
3
namespace Larapie\Actions\Concerns;
4
5
use Illuminate\Database\Eloquent\ModelNotFoundException;
6
use Illuminate\Support\Facades\Validator;
7
use Illuminate\Support\Str;
8
use Illuminate\Validation\ValidationException;
9
use Larapie\Actions\Exception\MethodDoesNotExistException;
10
use ReflectionMethod;
11
use ReflectionParameter;
12
13
trait ResolvesMethodDependencies
14
{
15 54
    protected function resolveAndCall($instance, $method, $extras = [])
16
    {
17 54
        if (! method_exists($instance, $method)) {
18 1
            throw new MethodDoesNotExistException("method $method not found on ".get_class($instance));
19
        }
20
21 53
        $parameters = $this->resolveMethodDependencies($instance, $method, $extras);
22
23 52
        return $instance->{$method}(...$parameters);
24
    }
25
26 53
    protected function resolveMethodDependencies($instance, $method, $extras = [])
27
    {
28 53
        $reflector = new ReflectionMethod($instance, $method);
29
30 53
        $handler = function ($parameter) use ($extras) {
31 28
            return $this->resolveDependency($parameter, $extras);
32 53
        };
33
34 53
        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
$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
$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 5
            if (! $key) {
61
                throw (new ValidationException(Validator::make([], [
62
                    $parameterName => 'required',
63
                ])))->redirectTo($this->getRedirectUrl());
0 ignored issues
show
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

63
                ])))->redirectTo($this->/** @scrutinizer ignore-call */ getRedirectUrl());
Loading history...
64
            }
65
66 5
            $instance = $this->resolveRouteBinding($instance, $value);
67
        }
68
69 5
        if ($key) {
70 4
            $this->updateAttributeWithResolvedInstance($key, $instance);
71
        }
72
73 5
        return $instance;
74
    }
75
76 5
    protected function resolveRouteBinding($instance, $value)
77
    {
78 5
        if (! $model = $instance->resolveRouteBinding($value)) {
79 1
            throw (new ModelNotFoundException())->setModel(get_class($instance));
80
        }
81
82 4
        return $model;
83
    }
84
85 28
    protected function findAttributeFromParameter($name, $extras = [])
86
    {
87 28
        $routeAttributes = $this->runningAs('controller') ? $this->getAttributesFromRoute($this->request) : [];
0 ignored issues
show
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

87
        $routeAttributes = $this->/** @scrutinizer ignore-call */ runningAs('controller') ? $this->getAttributesFromRoute($this->request) : [];
Loading history...
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

87
        $routeAttributes = $this->runningAs('controller') ? $this->/** @scrutinizer ignore-call */ getAttributesFromRoute($this->request) : [];
Loading history...
88 28
        $attributes = array_merge($this->attributes, $routeAttributes, $extras);
89
90 28
        if (array_key_exists($name, $attributes)) {
91 25
            return [$name, $attributes[$name]];
92
        }
93 10
        if (array_key_exists($snakedName = Str::snake($name), $attributes)) {
94 1
            return [$snakedName, $attributes[$snakedName]];
95
        }
96 9
    }
97
98 4
    public function updateAttributeWithResolvedInstance($key, $instance)
99
    {
100 4
        if ($this->runningAs('controller') && $this->request->has($key)) {
101 1
            return;
102
        }
103
104 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...
105
    }
106
}
107