Failed Conditions
Push — master ( 298f38...e9d38a )
by Arnold
10s
created

RouteAction::getFunctionArgs()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 16
cts 16
cp 1
rs 8.439
c 0
b 0
f 0
nc 6
cc 6
eloc 16
nop 2
crap 6
1
<?php
2
3
namespace Jasny\Controller;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
use Psr\Http\Message\ResponseInterface;
7
8
/**
9
 * Execute controller on given route
10
 */
11
trait RouteAction
12
{
13
    /**
14
     * Get request, set for controller
15
     *
16
     * @return ServerRequestInterface
17
     */
18
     abstract public function getRequest();
19
20
     /**
21
     * Get response. set for controller
22
     *
23
     * @return ResponseInterface
24
     */
25
     abstract public function getResponse();
26
27
    /**
28
     * Run the controller
29
     *
30
     * @return ResponseInterface
31
     */
32 9
    public function run() {
33 9
        $request = $this->getRequest();
34 9
        $route = $request->getAttribute('route');
35 9
        $method = $this->getActionMethod(isset($route->action) ? $route->action : 'default');
36
        
37 9
        if (!method_exists($this, $method)) {
38 1
            return $this->setResponseError(404, 'Not Found');
39
        }
40
41
        try {
42 8
            $args = isset($route->args) ? 
43 8
                $route->args :
44 8
                $this->getFunctionArgs($route, new \ReflectionMethod($this, $method));            
45 8
        } catch (\RuntimeException $e) {
46 2
            return $this->setResponseError(400, 'Bad Request');   
47
        }
48
49 6
        $response = call_user_func_array([$this, $method], $args);
50
51 6
        return $response ?: $this->getResponse();        
52
    }
53
54
    /**
55
     * Get the method name of the action
56
     * 
57
     * @param string $action
58
     * @return string
59
     */
60 9
    protected function getActionMethod($action)
61
    {
62 9
        return \Jasny\camelcase($action) . 'Action';
63
    }
64
65
    /**
66
     * Get the arguments for a function from a route using reflection
67
     * 
68
     * @param object $route
69
     * @param \ReflectionFunctionAbstract $refl
70
     * @return array
71
     */
72 6
    protected function getFunctionArgs($route, \ReflectionFunctionAbstract $refl)
73
    {
74 6
        $args = [];
75 6
        $params = $refl->getParameters();
76
77 6
        foreach ($params as $param) {
78 6
            $key = $param->name;
79
80 6
            if (property_exists($route, $key)) {
81 4
                $value = $route->{$key};
82 4
            } else {
83 4
                if (!$param->isOptional()) {
84
                    $fn = $refl instanceof \ReflectionMethod
85 2
                        ? $refl->class . ':' . $refl->name
86 2
                        : $refl->name;
87
88 2
                    throw new \RuntimeException("Missing argument '$key' for $fn()");
89
                }
90
                
91 2
                $value = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
92
            }
93
94 4
            $args[$key] = $value;
95 4
        }
96
        
97 4
        return $args;
98
    }
99
100
    /**
101
     * Set response to error state
102
     *
103
     * @param int $code
104
     * @param string $message 
105
     * @return ResponseInterface
106
     */
107 3
    protected function setResponseError($code, $message)
108
    {
109 3
        $response = $this->getResponse();
110
111 3
        $errorResponse = $response->withStatus($code);
112 3
        $errorResponse->getBody()->write($message);
113
114 3
        return $errorResponse;
115
    }
116
}
117
118