Completed
Push — master ( 3b4c18...beba29 )
by Sinnarasa
04:35
created

Middleware::callHandler()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 18
rs 8.8571
c 2
b 0
f 0
cc 5
eloc 13
nc 8
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 $class) {
104
                if (class_exists($class)) return $this->callHandler($class);
105
            }
106
        }
107
        return true;
108
    }
109
110
    /**
111
     * @description block middleware
112
     * @param $action
113
     * @return bool|mixed
114
     */
115 View Code Duplication
    public function blockMiddleware($action)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
116
    {
117
        if (isset($this->middleware[$action]['block_middleware'])) {
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
                        if (class_exists($block)) {
123
                            if ($this->callHandler($block) === false) return false;
124
                        }
125
                    }
126
                } elseif (is_string($blocks) && class_exists($blocks)) {
127
                    return $this->callHandler($blocks);
128
                }
129
            }
130
        }
131
        return true;
132
    }
133
134
    /**
135
     * @description controller middleware
136
     * @param $action
137
     * @return bool|mixed
138
     */
139 View Code Duplication
    public function classMiddleware($action)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
140
    {
141
        if (isset($this->middleware[$action]['class_middleware'])) {
142
            $ctrl = str_replace('\\', '/', $this->router->route->getTarget('controller'));
143
            if (isset($this->middleware[$action]['class_middleware'][$ctrl]) && class_exists($this->router->route->getTarget('controller'))) {
144
                $classes = $this->middleware[$action]['class_middleware'][$ctrl];
145
                if (is_array($classes)) {
146
                    foreach ($classes as $class) {
147
                        if ($this->callHandler($class) === false) return false;
148
                    }
149
                } elseif (is_string($classes)) {
150
                    return $this->callHandler($classes);
151
                }
152
            }
153
        }
154
        return true;
155
    }
156
157
    /**
158
     * @description route middleware
159
     * @param $action
160
     * @return bool|mixed
161
     */
162
    public function routeMiddleware($action)
163
    {
164
        if (isset($this->middleware[$action]['route_middleware'])) {
165
            if (isset($this->router->route->getPath()['middleware']) && class_exists($this->middleware[$action]['route_middleware'][$this->router->route->getPath()['middleware']])) {
166
                $classes = $this->middleware[$action]['route_middleware'][$this->router->route->getPath()['middleware']];
167
                if (is_array($classes)) {
168
                    foreach ($classes as $class) {
169
                        if ($this->callHandler($class) === false) return false;
170
                    }
171
                } elseif (is_string($classes)) {
172
                    return $this->callHandler($classes);
173
                }
174
            }
175
        }
176
        return true;
177
    }
178
179
    /**
180
     * @param $class
181
     * @return mixed
182
     */
183
    private function callHandler($class)
184
    {
185
        $class = explode('@', $class);
186
        $method = isset($class[1]) ? $class[1] : 'handle';
187
        $instance = call_user_func($this->router->getConfig()['di'], $class[0]);
188
        if (method_exists($instance, $method)) {
189
            $reflectionMethod = new ReflectionMethod($instance, $method);
190
            $dependencies = [];
191
            foreach ($reflectionMethod->getParameters() as $arg) {
192
                if (!is_null($arg->getClass())) {
193
                    $dependencies[] = $this->getClass($arg->getClass()->name);
194
                }
195
            }
196
            $dependencies = array_merge($dependencies, [$this->router->route]);
197
            return $reflectionMethod->invokeArgs($instance, $dependencies);
198
        }
199
        return true;
200
    }
201
202
    /**
203
     * @param $class
204
     * @return Route|RouteCollection|Router|mixed
205
     */
206
    private function getClass($class)
207
    {
208
        switch ($class) {
209
            case Route::class:
210
                return $this->router->route;
211
            case Router::class:
212
                return $this->router;
213
            case RouteCollection::class:
214
                return $this->router->collection;
215
            case Response::class:
216
                return $this->router->response;
217
            default:
218
                return call_user_func_array($this->router->getConfig()['di'], [$class]);
219
        }
220
    }
221
}
222