1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Spiral\Core; |
6
|
|
|
|
7
|
|
|
use Psr\Container\ContainerExceptionInterface; |
8
|
|
|
use Psr\Container\ContainerInterface; |
9
|
|
|
use Spiral\Core\Exception\ControllerException; |
10
|
|
|
use Spiral\Core\Exception\Resolver\ArgumentResolvingException; |
11
|
|
|
use Spiral\Core\Exception\Resolver\InvalidArgumentException; |
12
|
|
|
use Spiral\Interceptors\Context\CallContext; |
13
|
|
|
use Spiral\Interceptors\HandlerInterface; |
14
|
|
|
use Spiral\Interceptors\Internal\ActionResolver; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Provides ability to call controllers in IoC scope. |
18
|
|
|
* |
19
|
|
|
* Make sure to bind ScopeInterface in your container. |
20
|
|
|
* |
21
|
|
|
* @deprecated will be removed in Spiral v4.0 |
22
|
|
|
*/ |
23
|
|
|
abstract class AbstractCore implements CoreInterface, HandlerInterface |
|
|
|
|
24
|
|
|
{ |
25
|
|
|
/** @internal */ |
26
|
|
|
protected ResolverInterface $resolver; |
27
|
|
|
|
28
|
|
|
public function __construct( |
29
|
|
|
/** @internal */ |
30
|
|
|
protected ContainerInterface $container |
31
|
|
|
) { |
32
|
|
|
// resolver is usually the container itself |
33
|
|
|
/** @psalm-suppress MixedAssignment */ |
34
|
|
|
$this->resolver = $container->get(ResolverInterface::class); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @psalm-assert class-string $controller |
39
|
|
|
* @psalm-assert non-empty-string $action |
40
|
|
|
*/ |
41
|
|
|
public function callAction(string $controller, string $action, array $parameters = []): mixed |
42
|
|
|
{ |
43
|
|
|
$method = ActionResolver::pathToReflection($controller, $action); |
44
|
|
|
|
45
|
|
|
// Validate method |
46
|
|
|
ActionResolver::validateControllerMethod($method); |
47
|
|
|
|
48
|
|
|
return $this->invoke($method, $parameters); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
public function handle(CallContext $context): mixed |
52
|
|
|
{ |
53
|
|
|
$target = $context->getTarget(); |
54
|
|
|
$reflection = $target->getReflection(); |
55
|
|
|
return $reflection instanceof \ReflectionMethod |
56
|
|
|
? $this->invoke($reflection, $context->getArguments()) |
57
|
|
|
: $this->callAction($target->getPath()[0], $target->getPath()[1], $context->getArguments()); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
protected function resolveArguments(\ReflectionMethod $method, array $parameters): array |
61
|
|
|
{ |
62
|
|
|
foreach ($method->getParameters() as $parameter) { |
63
|
|
|
$name = $parameter->getName(); |
64
|
|
|
if ( |
65
|
|
|
\array_key_exists($name, $parameters) && |
66
|
|
|
$parameters[$name] === null && |
67
|
|
|
$parameter->isDefaultValueAvailable() |
68
|
|
|
) { |
69
|
|
|
/** @psalm-suppress MixedAssignment */ |
70
|
|
|
$parameters[$name] = $parameter->getDefaultValue(); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
// getting the set of arguments should be sent to requested method |
75
|
|
|
return $this->resolver->resolveArguments($method, $parameters); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @throws \Throwable |
80
|
|
|
*/ |
81
|
|
|
public function invoke(\ReflectionMethod $method, array $arguments): mixed |
82
|
|
|
{ |
83
|
|
|
try { |
84
|
|
|
$args = $this->resolveArguments($method, $arguments); |
85
|
|
|
} catch (ArgumentResolvingException | InvalidArgumentException $e) { |
86
|
|
|
throw new ControllerException( |
|
|
|
|
87
|
|
|
\sprintf( |
88
|
|
|
'Missing/invalid parameter %s of `%s`->`%s`', |
89
|
|
|
$e->getParameter(), |
90
|
|
|
$method->getDeclaringClass()->getName(), |
91
|
|
|
$method->getName(), |
92
|
|
|
), |
93
|
|
|
ControllerException::BAD_ARGUMENT, |
94
|
|
|
$e, |
95
|
|
|
); |
96
|
|
|
} catch (ContainerExceptionInterface $e) { |
97
|
|
|
throw new ControllerException( |
|
|
|
|
98
|
|
|
$e->getMessage(), |
99
|
|
|
ControllerException::ERROR, |
100
|
|
|
$e, |
101
|
|
|
); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
$container = $this->container; |
105
|
|
|
return ContainerScope::runScope( |
106
|
|
|
$container, |
107
|
|
|
/** @psalm-suppress MixedArgument */ |
108
|
|
|
static fn(): mixed => $method->invokeArgs($container->get($method->getDeclaringClass()->getName()), $args) |
109
|
|
|
); |
110
|
|
|
} |
111
|
|
|
} |
112
|
|
|
|
This interface has been deprecated. The supplier of the interface has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.