Passed
Push — master ( 4a13e9...769a42 )
by Sinnarasa
02:19
created

Middleware::callHandler()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 24
rs 6.7272
cc 7
eloc 17
nc 16
nop 1
1
<?php
2
3
namespace JetFire\Routing;
4
5
use ReflectionMethod;
6
7
8
/**
9
 * Class Middleware
10
 * @package JetFire\Routing
11
 */
12
class Middleware implements MiddlewareInterface
13
{
14
15
    /**
16
     * @var Router
17
     */
18
    private $router;
19
20
    /**
21
     * @var array
22
     */
23
    private $callbacks = [
24
        'globalMiddleware',
25
        'blockMiddleware',
26
        'classMiddleware',
27
        'routeMiddleware',
28
    ];
29
30
    /**
31
     * @var array
32
     */
33
    private $middleware = [];
34
35
    /**
36
     * @param Router $router
37
     */
38
    public function __construct(Router $router)
39
    {
40
        $this->router = $router;
41
    }
42
43
    /**
44
     * @return array
45
     */
46
    public function getMiddleware()
47
    {
48
        return $this->middleware;
49
    }
50
51
    /**
52
     * @param $middleware
53
     * @return mixed|void
54
     */
55
    public function setBeforeCallback($middleware)
56
    {
57
        $this->setMiddleware('before', $middleware);
58
    }
59
60
    /**
61
     * @param $middleware
62
     * @return mixed|void
63
     */
64
    public function setAfterCallback($middleware)
65
    {
66
        $this->setMiddleware('after', $middleware);
67
    }
68
69
    /**
70
     * @param $action
71
     * @param $middleware
72
     */
73
    private function setMiddleware($action, $middleware)
74
    {
75
        if (is_string($middleware)) {
76
            $middleware = rtrim($middleware, '/');
77
        }
78
        if (is_array($middleware)) {
79
            $this->middleware[$action] = $middleware;
80
        } elseif (is_file($middleware) && is_array($mid = include $middleware)) {
81
            $this->middleware[$action] = $mid;
82
        } else {
83
            throw new \InvalidArgumentException('Accepted argument for setMiddleware are array and array file');
84
        }
85
    }
86
87
    /**
88
     * @return Router
89
     */
90
    public function getCallbacks()
91
    {
92
        return $this->callbacks;
93
    }
94
95
    /**
96
     * @description global middleware
97
     * @param $action
98
     * @return bool|mixed
99
     */
100
    public function globalMiddleware($action)
101
    {
102
        if (isset($this->middleware[$action]['global_middleware'])) {
103
            foreach ($this->middleware[$action]['global_middleware'] as $callback) {
104
                $this->callHandler($callback);
105
            }
106
        }
107
        return true;
108
    }
109
110
    /**
111
     * @description block middleware
112
     * @param $action
113
     * @return bool|mixed
114
     */
115
    public function blockMiddleware($action)
116
    {
117 View Code Duplication
        if (isset($this->middleware[$action]['block_middleware'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
            if (isset($this->middleware[$action]['block_middleware'][$this->router->route->getTarget('block')])) {
119
                $blocks = $this->middleware[$action]['block_middleware'][$this->router->route->getTarget('block')];
120
                if (is_array($blocks)) {
121
                    foreach ($blocks as $block) {
122
                        $this->callHandler($block);
123
                    }
124
                } elseif (is_string($blocks)) {
125
                    return $this->callHandler($blocks);
126
                }
127
            }
128
        }
129
        return true;
130
    }
131
132
    /**
133
     * @description controller middleware
134
     * @param $action
135
     * @return bool|mixed
136
     */
137
    public function classMiddleware($action)
138
    {
139
        if (isset($this->middleware[$action]['class_middleware'])) {
140
            $ctrl = str_replace('\\', '/', $this->router->route->getTarget('controller'));
141
            if (isset($this->middleware[$action]['class_middleware'][$ctrl]) && class_exists($this->router->route->getTarget('controller'))) {
142
                $classes = $this->middleware[$action]['class_middleware'][$ctrl];
143
                if (is_array($classes)) {
144
                    foreach ($classes as $class) {
145
                        $this->callHandler($class);
146
                    }
147
                } elseif (is_string($classes)) {
148
                    return $this->callHandler($classes);
149
                }
150
            }
151
        }
152
        return true;
153
    }
154
155
    /**
156
     * @description route middleware
157
     * @param $action
158
     * @return bool|mixed
159
     */
160
    public function routeMiddleware($action)
161
    {
162
        if (isset($this->middleware[$action]['route_middleware'])) {
163 View Code Duplication
            if (isset($this->router->route->getPath()['middleware']) && class_exists($this->middleware[$action]['route_middleware'][$this->router->route->getPath()['middleware']])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
                $classes = $this->middleware[$action]['route_middleware'][$this->router->route->getPath()['middleware']];
165
                if (is_array($classes)) {
166
                    foreach ($classes as $class) {
167
                        $this->callHandler($class);
168
                    }
169
                } elseif (is_string($classes)) {
170
                    return $this->callHandler($classes);
171
                }
172
            }
173
        }
174
        return true;
175
    }
176
177
    /**
178
     * @param $callback
179
     * @return mixed
180
     */
181
    private function callHandler($callback)
182
    {
183
        $callback = explode('@', $callback);
184
        $method = isset($callback[1]) ? $callback[1] : 'handle';
185
        if(class_exists($callback[0])) {
186
            $instance = call_user_func($this->router->getConfig()['di'], $callback[0]);
187
            if (method_exists($instance, $method)) {
188
                $reflectionMethod = new ReflectionMethod($instance, $method);
189
                $dependencies = [];
190
                foreach ($reflectionMethod->getParameters() as $arg) {
191
                    if (!is_null($arg->getClass())) {
192
                        $dependencies[] = $this->getClass($arg->getClass()->name);
193
                    }
194
                }
195
                $dependencies = array_merge($dependencies, [$this->router->route]);
196
                $response = $reflectionMethod->invokeArgs($instance, $dependencies);
197
                if($response instanceof ResponseInterface) {
198
                    $this->router->response = $response;
199
                }
200
                return $response;
201
            }
202
        }
203
        return true;
204
    }
205
206
    /**
207
     * @param $class
208
     * @return Route|RouteCollection|Router|mixed
209
     */
210
    private function getClass($class)
211
    {
212
        switch ($class) {
213
            case Route::class:
214
                return $this->router->route;
215
            case Router::class:
216
                return $this->router;
217
            case RouteCollection::class:
218
                return $this->router->collection;
219
            case ResponseInterface::class:
220
                return $this->router->response;
221
            default:
222
                return call_user_func_array($this->router->getConfig()['di'], [$class]);
223
        }
224
    }
225
}
226