Completed
Push — master ( 1143dd...fab173 )
by Sinnarasa
04:27
created

Middleware::handle()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 24
rs 6.7272
cc 7
eloc 17
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
    protected $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
     */
99
    public function globalMiddleware($action)
100
    {
101
        if (isset($this->middleware[$action]['global_middleware'])) {
102
            $this->callHandlers($this->middleware[$action]['global_middleware']);
103
        }
104
    }
105
106
    /**
107
     * @description block middleware
108
     * @param $action
109
     */
110
    public function blockMiddleware($action)
111
    {
112 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...
113
            if (isset($this->middleware[$action]['block_middleware'][$this->router->route->getTarget('block')])) {
114
                $blocks = $this->middleware[$action]['block_middleware'][$this->router->route->getTarget('block')];
115
                $this->callHandlers($blocks);
116
            }
117
        }
118
    }
119
120
    /**
121
     * @description controller middleware
122
     * @param $action
123
     */
124
    public function classMiddleware($action)
125
    {
126
        if (isset($this->middleware[$action]['class_middleware'])) {
127
            $ctrl = str_replace('\\', '/', $this->router->route->getTarget('controller'));
128
            if (isset($this->middleware[$action]['class_middleware'][$ctrl]) && class_exists($this->router->route->getTarget('controller'))) {
129
                $classes = $this->middleware[$action]['class_middleware'][$ctrl];
130
                $this->callHandlers($classes);
131
            }
132
        }
133
    }
134
135
    /**
136
     * @description route middleware
137
     * @param $action
138
     */
139
    public function routeMiddleware($action)
140
    {
141
        if (isset($this->middleware[$action]['route_middleware'])) {
142 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...
143
                $classes = $this->middleware[$action]['route_middleware'][$this->router->route->getPath()['middleware']];
144
                $this->callHandlers($classes);
145
            }
146
        }
147
    }
148
149
    /**
150
     * @param $handlers
151
     */
152
    private function callHandlers($handlers){
153
        $handlers = is_array($handlers) ? $handlers : [$handlers];
154
        foreach ($handlers as $handler) {
155
            if($this->handle($handler) !== true){
156
                break;
157
            }
158
        }
159
    }
160
161
    /**
162
     * @param $callback
163
     * @return mixed
164
     */
165
    private function handle($callback)
166
    {
167
        $callback = explode('@', $callback);
168
        $response = true;
169
        $method = isset($callback[1]) ? $callback[1] : 'handle';
170
        if (class_exists($callback[0])) {
171
            $instance = call_user_func($this->router->getConfig()['di'], $callback[0]);
172
            if (method_exists($instance, $method)) {
173
                $reflectionMethod = new ReflectionMethod($instance, $method);
174
                $dependencies = [];
175
                foreach ($reflectionMethod->getParameters() as $arg) {
176
                    if (!is_null($arg->getClass())) {
177
                        $dependencies[] = $this->getClass($arg->getClass()->name);
178
                    }
179
                }
180
                $dependencies = array_merge($dependencies, [$this->router->route]);
181
                $response = $reflectionMethod->invokeArgs($instance, $dependencies);
182
                if ($response instanceof ResponseInterface) {
183
                    $this->router->response = $response;
184
                }
185
            }
186
        }
187
        return $response;
188
    }
189
190
    /**
191
     * @param $class
192
     * @return Route|RouteCollection|Router|mixed
193
     */
194
    private function getClass($class)
195
    {
196
        switch ($class) {
197
            case Route::class:
198
                return $this->router->route;
199
            case Router::class:
200
                return $this->router;
201
            case RouteCollection::class:
202
                return $this->router->collection;
203
            case ResponseInterface::class:
204
                return $this->router->response;
205
            default:
206
                return call_user_func_array($this->router->getConfig()['di'], [$class]);
207
        }
208
    }
209
}
210