Completed
Push — master ( 27b3bc...05aecd )
by Daniel
03:41
created

RpcControllerResolver::getContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Cmobi\RabbitmqBundle\Rpc\Controller;
4
5
use Cmobi\RabbitmqBundle\Rpc\Request\RpcRequest;
6
use Psr\Log\LoggerInterface;
7
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
8
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
9
10
class RpcControllerResolver
11
{
12
    use ContainerAwareTrait;
13
14
    private $logger;
15
16
    public function __construct(LoggerInterface $logger = null)
17
    {
18
        $this->logger = $logger;
19
    }
20
21
    /**
22
     * @return \Symfony\Component\DependencyInjection\ContainerInterface
23
     */
24
    public function getContainer()
25
    {
26
        return $this->container;
27
    }
28
29
    public function getController(RpcRequest $request)
30
    {
31
        if (!$controller = $request->attributes->get('_controller')) {
32
            if (null !== $this->logger) {
33
                $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
34
            }
35
36
            return false;
37
        }
38
39
        if (is_array($controller)) {
40
            return $controller;
41
        }
42
43
        if (is_object($controller)) {
44
            if (method_exists($controller, '__invoke')) {
45
                return $controller;
46
            }
47
48
            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...Rpc\Request\RpcRequest>.

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...
49
        }
50
51
        if (false === strpos($controller, ':')) {
52
            if (method_exists($controller, '__invoke')) {
53
                return $this->instantiateController($controller);
54
            } elseif (function_exists($controller)) {
55
                return $controller;
56
            }
57
        }
58
59
        $callable = $this->createController($controller);
60
61
        if (!is_callable($callable)) {
62
            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...Rpc\Request\RpcRequest>.

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...
63
        }
64
65
        return $callable;
66
    }
67
68
    public function getArguments(RpcRequest $request, $controller)
69
    {
70
        if (is_array($controller)) {
71
            $r = new \ReflectionMethod($controller[0], $controller[1]);
72
        } elseif (is_object($controller) && !$controller instanceof \Closure) {
73
            $r = new \ReflectionObject($controller);
74
            $r = $r->getMethod('__invoke');
75
        } else {
76
            $r = new \ReflectionFunction($controller);
77
        }
78
79
        return $this->doGetArguments($request, $controller, $r->getParameters());
80
    }
81
82
    protected function doGetArguments(RpcRequest $request, $controller, array $parameters)
83
    {
84
        $attributes = $request->attributes->all();
85
        $arguments = [];
86
87
        foreach ($parameters as $param) {
88
89
            if (array_key_exists($param->name, $attributes)) {
90
                if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) {
91
                    $arguments = array_merge($arguments, array_values($attributes[$param->name]));
92
                } else {
93
                    $arguments[] = $attributes[$param->name];
94
                }
95
            } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
96
                $arguments[] = $request;
97
            } elseif ($param->isDefaultValueAvailable()) {
98
                $arguments[] = $param->getDefaultValue();
99
            } else {
100
                if (is_array($controller)) {
101
                    $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
102
                } elseif (is_object($controller)) {
103
                    $repr = get_class($controller);
104
                } else {
105
                    $repr = $controller;
106
                }
107
108
                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));
109
            }
110
        }
111
112
        return $arguments;
113
    }
114
115
    protected function createController($controller)
116
    {
117
        if (false === strpos($controller, '::')) {
118
            throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
119
        }
120
121
        list($class, $method) = explode('::', $controller, 2);
122
123
        if (!class_exists($class)) {
124
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
125
        }
126
127
        return [$this->instantiateController($class), $method];
128
    }
129
130
    protected function instantiateController($class)
131
    {
132
        $controller = new $class();
133
134
        if ($controller instanceof ContainerAwareInterface) {
135
            $controller->setContainer($this->container);
136
        }
137
138
        return $controller;
139
    }
140
}
141