Passed
Branch master (4a9da3)
by refat
08:08 queued 04:03
created

Route::group()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 14
c 2
b 0
f 0
nc 2
nop 2
dl 0
loc 22
rs 9.7998
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 $middlewareFrom;
22
23
  private $groupMiddleware = [];
24
25
  public function __construct(Application $app)
26
  {
27
    $this->app = $app;
28
  }
29
30
  public function add($url, $action, $requestMethos = 'GET', $middleware = [])
31
  {
32
33
    if ($this->prefix) {
34
35
      if ($this->prefix !== '/') {
36
37
        $url = $this->prefix . $url;
38
39
        $url = rtrim($url, '/');
40
      }
41
    }
42
43
    if ($this->basController) {
44
      $action = $this->basController . '/' . $action;
45
    }
46
47
    if ($this->groupMiddleware) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->groupMiddleware of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
48
49
      if (is_array($middleware)) {
50
51
        $middleware = array_merge($this->groupMiddleware[0], $middleware);
52
53
      } else {
54
55
        array_push($this->groupMiddleware[0], $middleware);
56
57
        $middleware = $this->groupMiddleware[0];
58
      }
59
    }
60
61
    $routes = [
62
      'url'       => $url,
63
      'pattern'   => $this->generatePattern($url),
64
      'action'    => $this->getAction($action),
65
      'method'    => $requestMethos,
66
      'middleware' => $middleware
67
    ];
68
69
    $this->routes[] = $routes;
70
71
    return $this;
72
  }
73
74
  public function group($groupOptions, callable $callback)
75
  {
76
    $prefix = $groupOptions['prefix'];
77
    $controller = $groupOptions['controller'];
78
    $middlewareFrom = array_shift($groupOptions['middleware']);
79
    $middleware = $groupOptions['middleware'];
80
81
    $url = ltrim($this->app->request->url(), '/');
1 ignored issue
show
Bug Best Practice introduced by
The property request does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
82
    $check = '/' . explode('/', $url)[0];
83
84
    if ($check !== $prefix) {
85
      return $this;
86
    }
87
88
    $this->prefix = $prefix;
89
    $this->basController = $controller;
90
    $this->middlewareFrom = $middlewareFrom;
91
    $this->groupMiddleware = $middleware;
92
93
    $callback($this);
94
95
    return $this;
96
  }
97
98
  public function package($url, $controller)
99
  {
100
    $this->add("$url", "$controller");
101
    $this->add("$url/add", "$controller@add", "POST");
102
    $this->add("$url/submit", "$controller@submit", "POST");
103
    $this->add("$url/edit/:id", "$controller@edit", "POST");
104
    $this->add("$url/save/:id", "$controller@save", "POST");
105
    $this->add("$url/delete/:id", "$controller@delete", "POST");
106
107
    return $this;
108
  }
109
110
  public function generatePattern($url)
111
  {
112
    $pattern = '#^';
113
    $pattern .= str_replace([':text', ':id'], ['([a-zA-Z0-9-]+)', '(\d+)'], $url);
114
    $pattern .= '$#';
115
116
    return $pattern;
117
  }
118
119
  public function getAction($action)
120
  {
121
    $action = str_replace('/', '\\', $action);
122
123
    $action = (strpos($action, '@') != 0) ? $action : $action . '@index';
124
125
    $action = explode('@', $action);
126
127
    return $action;
128
  }
129
130
  public function getProperRoute()
131
  {
132
    foreach ($this->routes as $route) {
133
134
      if ($this->isMatching($route['pattern']) && $this->isMatchingRequestMethod($route['method'])) {
135
136
        $this->current = $route;
137
138
        $output = '';
139
140
        if ($route['middleware']) {
141
142
          if (is_array($route['middleware'])) {
143
144
            foreach ($route['middleware'] as $middleware) {
145
146
              $output = $this->middleware($middleware);
147
148
              if ($output != '') {
149
                break;
150
              }
151
            }
152
153
          } else {
154
155
            $output = $this->middleware($route['middleware']);
156
157
            if ($output != '') break;
158
          }
159
        }
160
161
        if ($output == '') {
162
163
          list($controller, $method) = $route['action'];
164
165
          $arguments = $this->getArgumentsFor($route['pattern']);
166
167
          $output = (string) $this->app->load->action($controller, $method, $arguments);
1 ignored issue
show
Bug Best Practice introduced by
The property load does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
168
169
          return $output;
170
171
        }
172
        break;
173
      }
174
    }
175
176
    $output = (string) $this->app->load->action('notFound', 'index', []);
177
178
    return $output;
179
  }
180
181
  public function isMatching($pattern)
182
  {
183
    $url = $this->app->request->url();
1 ignored issue
show
Bug Best Practice introduced by
The property request does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
184
185
    $url = strtolower($url);
186
187
    return preg_match($pattern, $url);
188
  }
189
190
  private function isMatchingRequestMethod($method)
191
  {
192
    $methods = ['GET', 'POST'];
193
194
    if (($method == 'both') && in_array($this->app->request->method(), $methods)) {
1 ignored issue
show
Bug Best Practice introduced by
The property request does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
195
      return true;
196
    }
197
198
    if (is_array($method)) {
199
200
      if (count($method) == 1) {
201
202
        $method = $method[0];
203
204
      } else if (count($method) == 2) {
205
206
        if (in_array($method[0], $methods) && in_array($method[1], $methods)) {
207
          return true;
208
        }
209
210
      } else {
211
212
        return false;
213
      }
214
    }
215
216
    return $this->app->request->method() == $method;
217
  }
218
219
  public function getArgumentsFor($pattern)
220
  {
221
    $url = $this->app->request->url();
1 ignored issue
show
Bug Best Practice introduced by
The property request does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
222
223
    preg_match($pattern, $url, $matches);
224
225
    array_shift($matches);
226
227
    return $matches;
228
  }
229
230
  public function getCurrent($key)
231
  {
232
    return $this->current[$key];
233
  }
234
235
  private function middleware($middleware, $from = 'admin')
236
  {
237
    $middlewareInterface = 'App\\Middleware\\MiddlewaresInterface';
238
239
    $middlewares = $this->app->alias['middlewares'][$from];
1 ignored issue
show
Bug Best Practice introduced by
The property alias does not exist on System\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
240
241
    $middlewareClass = $middlewares[$middleware];
242
243
    if (!in_array($middlewareInterface, class_implements($middlewareClass))) {
244
      throw new Exception("$middlewareClass not Implement");
245
    }
246
247
    $middlewareObject = new $middlewareClass;
248
249
    $output = $middlewareObject->handle($this->app, static::NEXT);
250
251
    if ($output && $output === static::NEXT) {
252
      $output = '';
253
    }
254
255
    return $output;
256
  }
257
}