Completed
Push — master ( b5a902...024bcd )
by Changwan
04:42
created

SingletonControllerPsrLoader::middleware()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 7
ccs 0
cts 7
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Router\Loader;
3
4
use Psr\Container\ContainerInterface;
5
use Psr\Container\NotFoundExceptionInterface;
6
use Psr\Http\Message\ServerRequestInterface;
7
use ReflectionClass;
8
use RuntimeException;
9
use ReflectionException;
10
use Wandu\Router\Contracts\LoaderInterface;
11
use Wandu\Router\Contracts\MiddlewareInterface;
12
use Wandu\Router\Exception\HandlerNotFoundException;
13
14
class SingletonControllerPsrLoader implements LoaderInterface
15
{
16
    /** @var \Psr\Container\ContainerInterface */
17
    protected $container;
18
19
    /**
20
     * @param \Psr\Container\ContainerInterface $container
21
     */
22
    public function __construct(ContainerInterface $container)
23
    {
24
        $this->container = $container;
25
    }
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    public function middleware(string $className, ServerRequestInterface $request): MiddlewareInterface
31
    {
32
        if ($this->container->has($className)) {
33
            return $this->container->get($className);
34
        }
35
        throw new HandlerNotFoundException($className);
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function execute(string $className, string $methodName, ServerRequestInterface $request)
42
    {
43
        if ($this->container->has($className)) {
44
            $object = $this->container->get($className);
45
            try {
46
                $reflMethod = (new ReflectionClass($className))->getMethod($methodName);
47
            } catch (ReflectionException $e) {
48
                $reflMethod = null;
49
            }
50
            if ($reflMethod) {
51
                $arguments = $this->getArguments($reflMethod, $request);
52
                return call_user_func_array([$object, $methodName], $arguments);
53
            }
54
            if (method_exists($object, '__call')) {
55
                return $object->__call($methodName, [$request]);
56
            }
57
        }
58
        throw new HandlerNotFoundException($className, $methodName);
59
    }
60
61
    public function getArguments(\ReflectionFunctionAbstract $refl, ServerRequestInterface $request)
62
    {
63
        $arguments = [];
64
        // it from container Resolver..
65
        foreach ($refl->getParameters() as $param) {
66
            $paramClass = $param->getClass();
67
            if ($paramClass) { // #2.
68
                if ($paramClass->isInstance($request)) {
69
                    $arguments[] = $request;
70
                    continue;
71
                }
72
                $paramClassName = $paramClass->getName();
0 ignored issues
show
Bug introduced by
Consider using $paramClass->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
73
                if ($attribute = $request->getAttribute($paramClassName)) {
74
                    $arguments[] = $attribute;
75
                    continue;
76
                }
77
                if ($this->container->has($paramClassName)) {
78
                    try {
79
                        $arguments[] = $this->container->get($paramClassName);
80
                        continue;
81
                    } catch (NotFoundExceptionInterface $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
82
                    }
83
                }
84
            }
85
            if ($param->isDefaultValueAvailable()) {
86
                $arguments[] = $param->getDefaultValue();
87
                continue;
88
            }
89
            if ($attribute = $request->getAttribute($param->getName())) {
0 ignored issues
show
Bug introduced by
Consider using $param->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
90
                $arguments[] = $attribute;
91
                continue;
92
            }
93
            throw new RuntimeException("not found parameter named \"{$param->getName()}\".");
0 ignored issues
show
Bug introduced by
Consider using $param->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
94
        }
95
        return $arguments;
96
    }
97
}
98