| 148 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
namespace Illuminate\Routing;
|
|
|
4 |
|
|
|
5 |
use Illuminate\Support\Arr;
|
|
|
6 |
use Illuminate\Support\Reflector;
|
|
|
7 |
use ReflectionClass;
|
|
|
8 |
use ReflectionFunctionAbstract;
|
|
|
9 |
use ReflectionMethod;
|
|
|
10 |
use ReflectionParameter;
|
|
|
11 |
use stdClass;
|
|
|
12 |
|
|
|
13 |
trait RouteDependencyResolverTrait
|
|
|
14 |
{
|
|
|
15 |
/**
|
|
|
16 |
* Resolve the object method's type-hinted dependencies.
|
|
|
17 |
*
|
|
|
18 |
* @param array $parameters
|
|
|
19 |
* @param object $instance
|
|
|
20 |
* @param string $method
|
|
|
21 |
* @return array
|
|
|
22 |
*/
|
|
|
23 |
protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
|
|
|
24 |
{
|
|
|
25 |
if (! method_exists($instance, $method)) {
|
|
|
26 |
return $parameters;
|
|
|
27 |
}
|
|
|
28 |
|
|
|
29 |
return $this->resolveMethodDependencies(
|
|
|
30 |
$parameters, new ReflectionMethod($instance, $method)
|
|
|
31 |
);
|
|
|
32 |
}
|
|
|
33 |
|
|
|
34 |
/**
|
|
|
35 |
* Resolve the given method's type-hinted dependencies.
|
|
|
36 |
*
|
|
|
37 |
* @param array $parameters
|
|
|
38 |
* @param \ReflectionFunctionAbstract $reflector
|
|
|
39 |
* @return array
|
|
|
40 |
*/
|
|
|
41 |
public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
|
|
|
42 |
{
|
|
|
43 |
$instanceCount = 0;
|
|
|
44 |
|
|
|
45 |
$values = array_values($parameters);
|
|
|
46 |
|
|
|
47 |
$skippableValue = new stdClass;
|
|
|
48 |
|
|
|
49 |
foreach ($reflector->getParameters() as $key => $parameter) {
|
|
|
50 |
$instance = $this->transformDependency($parameter, $parameters, $skippableValue);
|
|
|
51 |
|
|
|
52 |
if ($instance !== $skippableValue) {
|
|
|
53 |
$instanceCount++;
|
|
|
54 |
|
|
|
55 |
$this->spliceIntoParameters($parameters, $key, $instance);
|
|
|
56 |
} elseif (! isset($values[$key - $instanceCount]) &&
|
|
|
57 |
$parameter->isDefaultValueAvailable()) {
|
|
|
58 |
$this->spliceIntoParameters($parameters, $key, $parameter->getDefaultValue());
|
|
|
59 |
}
|
|
|
60 |
}
|
|
|
61 |
|
|
|
62 |
return $parameters;
|
|
|
63 |
}
|
|
|
64 |
|
|
|
65 |
/**
|
|
|
66 |
* Attempt to transform the given parameter into a class instance.
|
|
|
67 |
*
|
|
|
68 |
* @param \ReflectionParameter $parameter
|
|
|
69 |
* @param array $parameters
|
|
|
70 |
* @param object $skippableValue
|
|
|
71 |
* @return mixed
|
|
|
72 |
*/
|
|
|
73 |
protected function transformDependency(ReflectionParameter $parameter, $parameters, $skippableValue)
|
|
|
74 |
{
|
|
|
75 |
$className = Reflector::getParameterClassName($parameter);
|
|
|
76 |
|
|
|
77 |
// If the parameter has a type-hinted class, we will check to see if it is already in
|
|
|
78 |
// the list of parameters. If it is we will just skip it as it is probably a model
|
|
|
79 |
// binding and we do not want to mess with those; otherwise, we resolve it here.
|
|
|
80 |
if ($className && ! $this->alreadyInParameters($className, $parameters)) {
|
|
|
81 |
$isEnum = method_exists(ReflectionClass::class, 'isEnum') && (new ReflectionClass($className))->isEnum();
|
|
|
82 |
|
|
|
83 |
return $parameter->isDefaultValueAvailable()
|
|
|
84 |
? ($isEnum ? $parameter->getDefaultValue() : null)
|
|
|
85 |
: $this->container->make($className);
|
|
|
86 |
}
|
|
|
87 |
|
|
|
88 |
return $skippableValue;
|
|
|
89 |
}
|
|
|
90 |
|
|
|
91 |
/**
|
|
|
92 |
* Determine if an object of the given class is in a list of parameters.
|
|
|
93 |
*
|
|
|
94 |
* @param string $class
|
|
|
95 |
* @param array $parameters
|
|
|
96 |
* @return bool
|
|
|
97 |
*/
|
|
|
98 |
protected function alreadyInParameters($class, array $parameters)
|
|
|
99 |
{
|
|
|
100 |
return ! is_null(Arr::first($parameters, fn ($value) => $value instanceof $class));
|
|
|
101 |
}
|
|
|
102 |
|
|
|
103 |
/**
|
|
|
104 |
* Splice the given value into the parameter list.
|
|
|
105 |
*
|
|
|
106 |
* @param array $parameters
|
|
|
107 |
* @param string $offset
|
|
|
108 |
* @param mixed $value
|
|
|
109 |
* @return void
|
|
|
110 |
*/
|
|
|
111 |
protected function spliceIntoParameters(array &$parameters, $offset, $value)
|
|
|
112 |
{
|
|
|
113 |
array_splice(
|
|
|
114 |
$parameters, $offset, 0, [$value]
|
|
|
115 |
);
|
|
|
116 |
}
|
|
|
117 |
}
|