Completed
Push — master ( fdda97...b0b47a )
by Arman
17s queued 11s
created

MvcManager::collectParams()   B

Complexity

Conditions 9
Paths 2

Size

Total Lines 37
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
c 0
b 0
f 0
dl 0
loc 37
rs 8.0555
cc 9
nc 2
nop 4
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 1.0.0
13
 */
14
15
namespace Quantum\Mvc;
16
17
use Quantum\Exceptions\ExceptionMessages;
18
use Quantum\Middleware\MiddlewareManager;
19
use Quantum\Exceptions\RouteException;
20
use Quantum\Factory\ServiceFactory;
21
use Quantum\Factory\ModelFactory;
22
use Quantum\Factory\ViewFactory;
23
use Quantum\Libraries\Csrf\Csrf;
24
use Quantum\Http\Response;
25
use Quantum\Http\Request;
26
27
/**
28
 * MvcManager Class
29
 *
30
 * MvcManager class determine the controller, action of current module based on
31
 * current route
32
 *
33
 * @package Quantum
34
 * @subpackage MVC
35
 * @category MVC
36
 */
37
class MvcManager
38
{
39
40
    /**
41
     * @var object
42
     */
43
    private $controller;
44
45
    /**
46
     * @var string
47
     */
48
    private $action;
49
50
    /**
51
     * Run MVC
52
     * @param Request $request
53
     * @param Response $response
54
     * @throws RouteException
55
     * @throws \ReflectionException
56
     */
57
    public function runMvc(Request $request, Response $response)
58
    {
59
60
        if ($request->getMethod() != 'OPTIONS') {
61
62
            if (current_middlewares()) {
63
                list($request, $response) = (new MiddlewareManager())->applyMiddlewares($request, $response);
64
            }
65
66
            $routeArgs = current_route_args();
67
68
            $callback = route_callback();
69
70
            if ($callback){
0 ignored issues
show
introduced by
$callback is of type Closure, thus it always evaluated to true.
Loading history...
71
                call_user_func_array($callback, $this->getCallbackArgs($routeArgs, $callback, $request, $response));
72
            } else {
73
74
                $this->controller = $this->getController();
75
76
                $this->action = $this->getAction();
77
78
                if ($this->controller->csrfVerification ?? true) {
79
                    Csrf::checkToken($request, \session());
80
                }
81
82
                if (method_exists($this->controller, '__before')) {
83
                    call_user_func_array(array($this->controller, '__before'), $this->getArgs($routeArgs, '__before', $request, $response));
84
                }
85
86
                call_user_func_array(array($this->controller, $this->action), $this->getArgs($routeArgs, $this->action, $request, $response));
87
88
                if (method_exists($this->controller, '__after')) {
89
                    call_user_func_array(array($this->controller, '__after'), $this->getArgs($routeArgs, '__after', $request, $response));
90
                }
91
            }
92
        }
93
94
    }
95
96
    /**
97
     * Get Controller
98
     *
99
     * @return object
100
     * @throws RouteException
101
     */
102
    private function getController()
103
    {
104
        $controllerPath = modules_dir() . DS . current_module() . DS . 'Controllers' . DS . current_controller() . '.php';
105
106
        if (!file_exists($controllerPath)) {
107
            throw new RouteException(_message(ExceptionMessages::CONTROLLER_NOT_FOUND, current_controller()));
108
        }
109
110
        require_once $controllerPath;
111
112
        $controllerClass = '\\Modules\\' . current_module() . '\\Controllers\\' . current_controller();
113
114
        if (!class_exists($controllerClass, false)) {
115
            throw new RouteException(_message(ExceptionMessages::CONTROLLER_NOT_DEFINED, current_controller()));
116
        }
117
118
        return new $controllerClass();
119
    }
120
121
    /**
122
     * Get Action
123
     *
124
     * @return string
125
     * @throws RouteException
126
     */
127
    private function getAction()
128
    {
129
        $action = current_action();
130
131
        if (!method_exists($this->controller, $action)) {
0 ignored issues
show
Bug introduced by
It seems like $action can also be of type null; however, parameter $method of method_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

131
        if (!method_exists($this->controller, /** @scrutinizer ignore-type */ $action)) {
Loading history...
132
            throw new RouteException(_message(ExceptionMessages::ACTION_NOT_DEFINED, $action));
133
        }
134
135
        return $action;
136
    }
137
138
    /**
139
     * Get Args
140
     * @param  array $routeArgs
141
     * @param  string $action
142
     * @param Request $request
143
     * @param Response $response
144
     * @return array
145
     * @throws \ReflectionException
146
     */
147
    private function getArgs($routeArgs, $action, Request $request, Response $response)
148
    {
149
        $reflaction = new \ReflectionMethod($this->controller, $action);
150
        $params = $reflaction->getParameters();
151
152
        return $this->collectParams($routeArgs, $params, $request, $response);
153
    }
154
155
    /**
156
     * Get Callback Args
157
     *
158
     * @param  array $routeArgs
159
     * @param  \Closure $callback
160
     * @param Request $request
161
     * @param Response $response
162
     * @return array
163
     * @throws \ReflectionFunction
164
     */
165
    private function getCallbackArgs($routeArgs, $callback, Request $request, Response $response) {
166
167
        $reflaction = new \ReflectionFunction($callback);
168
        $params = $reflaction->getParameters();
169
170
        return $this->collectParams($routeArgs, $params, $request, $response);
171
    }
172
173
    /**
174
     * Collect Params
175
     *
176
     * @param  array $routeArgs
177
     * @param  array $params
178
     * @param Request $request
179
     * @param Response $response
180
     * @return array
181
     */
182
    private function collectParams($routeArgs, $params, Request $request, Response $response)
183
    {
184
        $args = [];
185
186
        if (count($params)) {
187
            foreach ($params as $param) {
188
                $paramType = $param->getType();
189
190
                if ($paramType) {
191
                    switch ($paramType) {
192
                        case 'Quantum\Http\Request':
193
                            array_push($args, $request);
194
                            break;
195
                        case 'Quantum\Http\Response':
196
                            array_push($args, $response);
197
                            break;
198
                        case 'Quantum\Factory\ServiceFactory':
199
                            array_push($args, new ServiceFactory());
200
                            break;
201
                        case 'Quantum\Factory\ModelFactory':
202
                            array_push($args, new ModelFactory());
203
                            break;
204
                        case 'Quantum\Factory\ViewFactory':
205
                            array_push($args, new ViewFactory());
206
                            break;
207
                        default :
208
                            array_push($args, current($routeArgs));
209
                            next($routeArgs);
210
                    }
211
                } else {
212
                    array_push($args, current($routeArgs));
213
                    next($routeArgs);
214
                }
215
            }
216
        }
217
218
        return $args;
219
    }
220
221
}
222