Passed
Push — master ( 0a787f...f7fce9 )
by refat
05:37
created

Route::getProperRoute()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 28
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 5
eloc 12
nc 4
nop 0
dl 0
loc 28
rs 9.5555
c 4
b 0
f 0
1
<?php
2
3
namespace System;
4
5
use Exception;
6
7
class Route
8
{
9
  const NEXT = '_NEXT_';
10
11
  private $app;
12
13
  private $routes = [];
14
15
  public $current = [];
16
17
  private $prefix;
18
19
  private $basController;
20
21
  private $groupMiddleware = [];
22
23
  public function __construct(Application $app)
24
  {
25
    $this->app = $app;
26
  }
27
28
  public function add($url, $action, $requestMethos = 'GET', $middleware = [])
29
  {
30
    $url = $this->setPrefix($url);
31
32
    $action = $this->setAction($action);
33
34
    $middleware = $this->setMiddleware($middleware);
35
36
    $routes = [
37
      'url'         => $url,
38
      'pattern'     => $this->generatePattern($url),
39
      'action'      => $this->getAction($action),
40
      'method'      => $requestMethos,
41
      'middleware'  => $middleware
42
    ];
43
44
    $this->routes[] = $routes;
45
46
    return $this;
47
  }
48
49
  private function setPrefix($url)
50
  {
51
    if ($this->prefix) {
52
53
      if ($this->prefix !== '/') {
54
55
        $url = $this->prefix . $url;
56
57
        $url = rtrim($url, '/');
58
      }
59
    }
60
61
    return $url;
62
  }
63
64
  private function setAction($action)
65
  {
66
    if ($this->basController) {
67
68
      $action = $this->basController . '/' . $action;
69
    }
70
71
    return $action;
72
  }
73
74
  private function setMiddleware($middleware)
75
  {
76
    if (!is_array($middleware)) {
77
78
      $middleware = [$middleware];
79
    }
80
81
    $middleware = array_merge($this->groupMiddleware, $middleware);
82
83
    return $middleware;
84
  }
85
86
  public function group($groupOptions, callable $callback)
87
  {
88
    $prefix = $groupOptions['prefix'];
89
    $controller = $groupOptions['controller'];
90
    $middleware = $groupOptions['middleware'];
91
92
    $url = ltrim($this->app->request->url(), '/');
93
    $check = '/' . explode('/', $url)[0];
94
95
    if ($check !== $prefix) {
96
97
      return $this;
98
    }
99
100
    $this->prefix = $prefix;
101
    $this->basController = $controller;
102
    $this->groupMiddleware = $middleware;
103
104
    $callback($this);
105
106
    return $this;
107
  }
108
109
  public function package($url, $controller)
110
  {
111
    $this->add("$url", "$controller");
112
    $this->add("$url/add", "$controller@add", "POST");
113
    $this->add("$url/submit", "$controller@submit", "POST");
114
    $this->add("$url/edit/:id", "$controller@edit", "POST");
115
    $this->add("$url/save/:id", "$controller@save", "POST");
116
    $this->add("$url/delete/:id", "$controller@delete", "POST");
117
118
    return $this;
119
  }
120
121
  public function generatePattern($url)
122
  {
123
    $pattern = '#^';
124
    $pattern .= str_replace([':text', ':id'], ['([a-zA-Z0-9-]+)', '(\d+)'], strtolower($url));
125
    $pattern .= '$#';
126
127
    return $pattern;
128
  }
129
130
  public function getAction($action)
131
  {
132
    $action = str_replace('/', '\\', $action);
133
134
    $action = (strpos($action, '@') != 0) ? $action : $action . '@index';
135
136
    $action = explode('@', $action);
137
138
    return $action;
139
  }
140
141
  public function getProperRoute()
142
  {
143
    foreach ($this->routes as $route) {
144
145
      if ($this->isMatching($route['pattern']) && $this->isMatchingRequestMethod($route['method'])) {
146
147
        $this->current = $route;
148
149
        $continue = $this->continue($route['middleware']);
150
151
        if ($continue == static::NEXT) {
152
153
          list($controller, $method) = $route['action'];
154
155
          $arguments = $this->getArgumentsFor($route['pattern']);
156
157
          $output = (string) $this->app->load->action($controller, $method, $arguments);
158
159
          return $output;
160
        }
161
162
        break;
163
      }
164
    }
165
166
    $output = (string) $this->app->load->action('notFound', 'index', []);
167
168
    return $output;
169
  }
170
171
  public function isMatching($pattern)
172
  {
173
    $url = $this->app->request->url();
174
175
    $url = strtolower($url);
176
177
    return preg_match($pattern, $url);
178
  }
179
180
  private function isMatchingRequestMethod($method)
181
  {
182
    $allowMethods = ['GET', 'POST'];
183
184
    if ($method == 'BOTH') {
185
186
      return $this->checkRequestMethodsBoth($allowMethods);
187
    }
188
189
    if (is_array($method)) {
190
191
      return $this->checkRequestMethodsArray($method, $allowMethods);
192
    }
193
194
    return $this->app->request->method() == $method;
195
  }
196
197
  private function checkRequestMethodsArray($methods = null, $allowMethods)
198
  {
199
    if (count($methods) == 1) {
200
201
      return $this->app->request->method() == $methods[0];
202
203
    } else {
204
205
      if (array_equal($methods, $allowMethods)) {
206
207
        return true;
208
      }
209
210
      return false;
211
    }
212
  }
213
214
  private function checkRequestMethodsBoth($allowMethods)
215
  {
216
    if (in_array($this->app->request->method(), $allowMethods)) {
217
218
      return true;
219
    }
220
221
    return false;
222
  }
223
224
  public function getArgumentsFor($pattern)
225
  {
226
    $url = $this->app->request->url();
227
228
    preg_match($pattern, $url, $matches);
229
230
    array_shift($matches);
231
232
    return $matches;
233
  }
234
235
  public function getCurrent($key)
236
  {
237
    return $this->current[$key];
238
  }
239
240
  private function middleware($middleware)
241
  {
242
    $middlewareInterface = 'App\\Middleware\\MiddlewaresInterface';
243
244
    $middlewares = $this->app->alias['middlewares'];
245
246
    $middlewareClass = $middlewares[$middleware];
247
248
    if (!in_array($middlewareInterface, class_implements($middlewareClass))) {
249
250
      throw new Exception("$middlewareClass not Implement");
251
    }
252
253
    $middlewareObject = new $middlewareClass;
254
255
    $output = $middlewareObject->handle($this->app, static::NEXT);
256
257
    return $output;
258
  }
259
260
  private function continue($middlewares)
261
  {
262
    if (!empty($middlewares)) {
263
264
      foreach ($middlewares as $middleware) {
265
266
        $output = $this->middleware($middleware);
267
268
        if ($output !== static::NEXT) {
269
270
          return $output;
271
        }
272
273
      }
274
275
    }
276
277
    return static::NEXT;
278
  }
279
}