Test Failed
Pull Request — master (#1095)
by Aleksei
10:19
created

AbstractCore::callAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 8
rs 10
cc 1
nc 1
nop 3
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
0 ignored issues
show
Deprecated Code introduced by
The interface Spiral\Core\CoreInterface has been deprecated: Use {@see HandlerInterface} instead. ( Ignorable by Annotation )

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

23
abstract class AbstractCore implements /** @scrutinizer ignore-deprecated */ CoreInterface, HandlerInterface

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.

Loading history...
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(
0 ignored issues
show
Deprecated Code introduced by
The class Spiral\Core\Exception\ControllerException has been deprecated: will be removed in Spiral v4.0 ( Ignorable by Annotation )

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

86
            throw /** @scrutinizer ignore-deprecated */ new ControllerException(
Loading history...
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(
0 ignored issues
show
Deprecated Code introduced by
The class Spiral\Core\Exception\ControllerException has been deprecated: will be removed in Spiral v4.0 ( Ignorable by Annotation )

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

97
            throw /** @scrutinizer ignore-deprecated */ new ControllerException(
Loading history...
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