Completed
Push — master ( f743de...f8a04a )
by Daniel
03:18
created

RpcControllerResolver   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 30
c 1
b 0
f 0
lcom 0
cbo 3
dl 0
loc 115
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
D getController() 0 38 10
A getArguments() 0 13 4
C doGetArguments() 0 32 11
A createController() 0 14 3
A instantiateController() 0 4 1
1
<?php
2
3
namespace Cmobi\RabbitmqBundle\Rpc\Controller;
4
5
use Cmobi\RabbitmqBundle\Rpc\Request\JsonRpcRequest;
6
use Psr\Log\LoggerInterface;
7
8
class RpcControllerResolver
9
{
10
    private $logger;
11
12
    public function __construct(LoggerInterface $logger = null)
13
    {
14
        $this->logger = $logger;
15
    }
16
17
    public function getController(JsonRpcRequest $request)
18
    {
19
        if (!$controller = $request->attributes->get('_controller')) {
20
            if (null !== $this->logger) {
21
                $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
22
            }
23
24
            return false;
25
        }
26
27
        if (is_array($controller)) {
28
            return $controller;
29
        }
30
31
        if (is_object($controller)) {
32
            if (method_exists($controller, '__invoke')) {
33
                return $controller;
34
            }
35
36
            throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
0 ignored issues
show
Bug introduced by
The method getPathInfo() does not seem to exist on object<Cmobi\RabbitmqBun...Request\JsonRpcRequest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
37
        }
38
39
        if (false === strpos($controller, ':')) {
40
            if (method_exists($controller, '__invoke')) {
41
                return $this->instantiateController($controller);
42
            } elseif (function_exists($controller)) {
43
                return $controller;
44
            }
45
        }
46
47
        $callable = $this->createController($controller);
48
49
        if (!is_callable($callable)) {
50
            throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', $controller, $request->getPathInfo()));
0 ignored issues
show
Bug introduced by
The method getPathInfo() does not seem to exist on object<Cmobi\RabbitmqBun...Request\JsonRpcRequest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
51
        }
52
53
        return $callable;
54
    }
55
56
    public function getArguments(JsonRpcRequest $request, $controller)
57
    {
58
        if (is_array($controller)) {
59
            $r = new \ReflectionMethod($controller[0], $controller[1]);
60
        } elseif (is_object($controller) && !$controller instanceof \Closure) {
61
            $r = new \ReflectionObject($controller);
62
            $r = $r->getMethod('__invoke');
63
        } else {
64
            $r = new \ReflectionFunction($controller);
65
        }
66
67
        return $this->doGetArguments($request, $controller, $r->getParameters());
68
    }
69
70
    protected function doGetArguments(JsonRpcRequest $request, $controller, array $parameters)
71
    {
72
        $attributes = $request->attributes->all();
73
        $arguments = [];
74
75
        foreach ($parameters as $param) {
76
77
            if (array_key_exists($param->name, $attributes)) {
78
                if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) {
79
                    $arguments = array_merge($arguments, array_values($attributes[$param->name]));
80
                } else {
81
                    $arguments[] = $attributes[$param->name];
82
                }
83
            } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
84
                $arguments[] = $request;
85
            } elseif ($param->isDefaultValueAvailable()) {
86
                $arguments[] = $param->getDefaultValue();
87
            } else {
88
                if (is_array($controller)) {
89
                    $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
90
                } elseif (is_object($controller)) {
91
                    $repr = get_class($controller);
92
                } else {
93
                    $repr = $controller;
94
                }
95
96
                throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
97
            }
98
        }
99
100
        return $arguments;
101
    }
102
103
    protected function createController($controller)
104
    {
105
        if (false === strpos($controller, '::')) {
106
            throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
107
        }
108
109
        list($class, $method) = explode('::', $controller, 2);
110
111
        if (!class_exists($class)) {
112
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
113
        }
114
115
        return array($this->instantiateController($class), $method);
116
    }
117
118
    protected function instantiateController($class)
119
    {
120
        return new $class();
121
    }
122
}
123