Completed
Push — master ( fab173...3e8504 )
by Sinnarasa
04:56
created

Router::addMatcher()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
dl 0
loc 4
rs 10
c 2
b 0
f 1
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace JetFire\Routing;
4
5
use JetFire\Routing\Matcher\ArrayMatcher;
6
use ReflectionClass;
7
use ReflectionMethod;
8
9
/**
10
 * Class Router
11
 * @package JetFire\Routing
12
 */
13
class Router
14
{
15
16
    /**
17
     * @var Route
18
     */
19
    public $route;
20
    /**
21
     * @var RouteCollection
22
     */
23
    public $collection;
24
    /**
25
     * @var ResponseInterface
26
     */
27
    public $response;
28
    /**
29
     * @var array
30
     */
31
    public $middlewareCollection = [];
32
    /**
33
     * @var array
34
     */
35
    public $matcher = [];
36
    /**
37
     * @var
38
     */
39
    public $dispatcher;
40
    /**
41
     * @var array
42
     */
43
    private $config = [
44
        'templateExtension' => ['.html', '.php', '.json', '.xml'],
45
        'templateCallback' => [],
46
        'di' => '',
47
        'generateRoutesPath' => false,
48
    ];
49
50
    /**
51
     * @param RouteCollection $collection
52
     * @param ResponseInterface $response
53
     * @param Route $route
54
     */
55
    public function __construct(RouteCollection $collection, ResponseInterface $response = null, Route $route = null)
56
    {
57
        $this->collection = $collection;
58
        $this->response = is_null($response) ? new Response() : $response;
59
        $this->route = is_null($route) ? new Route() : $route;
60
        $this->config['di'] = function ($class) {
61
            return new $class;
62
        };
63
    }
64
65
    /**
66
     * @param array $config
67
     */
68
    public function setConfig($config)
69
    {
70
        $this->config = array_merge($this->config, $config);
71
    }
72
73
    /**
74
     * @return array
75
     */
76
    public function getConfig()
77
    {
78
        return $this->config;
79
    }
80
81
    /**
82
     * @param object|array $middleware
83
     */
84
    public function setMiddleware($middleware)
85
    {
86
        $this->middlewareCollection = is_array($middleware)
87
            ? $middleware
88
            : [$middleware];
89
    }
90
91
    /**
92
     * @param MiddlewareInterface $middleware
93
     */
94
    public function addMiddleware(MiddlewareInterface $middleware)
95
    {
96
        $this->middlewareCollection[] = $middleware;
97
    }
98
99
    /**
100
     * @param object|array $matcher
101
     */
102
    public function setMatcher($matcher)
103
    {
104
        $this->matcher = is_array($matcher)
105
            ? $matcher
106
            : [$matcher];
107
    }
108
109
    /**
110
     * @param string $matcher
111
     */
112
    public function addMatcher($matcher)
113
    {
114
        $this->matcher[] = $matcher;
115
    }
116
117
    /**
118
     * @description main function
119
     */
120
    public function run()
121
    {
122
        $this->setUrl();
123
        if ($this->config['generateRoutesPath']) $this->collection->generateRoutesPath();
124
        if ($this->match() === true) {
125
            $this->callMiddleware('before');
126
            if (!in_array(substr($this->response->getStatusCode(), 0, 1), [3,4,5])) {
127
                $this->callTarget();
128
            }
129
        }else{
130
            $this->response->setStatusCode(404);
131
        }
132
        $this->callMiddleware('after');
133
        return $this->response->send();
134
    }
135
136
    /**
137
     * @description call the middleware before and after the target
138
     * @param $action
139
     */
140
    private function callMiddleware($action)
141
    {
142
        foreach ($this->middlewareCollection as $middleware) {
143
            if ($middleware instanceof MiddlewareInterface) {
144
                foreach ($middleware->getCallbacks() as $callback) {
145
                    if (method_exists($middleware, $callback)) {
146
                        call_user_func_array([$middleware, $callback], [$action]);
147
                    }
148
                }
149
            }
150
        }
151
    }
152
153
    /**
154
     * @param null $url
155
     */
156
    public function setUrl($url = null)
0 ignored issues
show
Coding Style introduced by
setUrl uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
setUrl uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
157
    {
158
        if (is_null($url))
159
            $url = (isset($_GET['url'])) ? $_GET['url'] : substr(str_replace(str_replace('/index.php', '', $_SERVER['SCRIPT_NAME']), '', $_SERVER['REQUEST_URI']), 1);
160
        $this->route->setUrl('/' . trim(explode('?', $url)[0], '/'));
161
    }
162
163
    /**
164
     * @return bool
165
     */
166
    public function match()
167
    {
168
        foreach ($this->matcher as $key => $matcher) {
169
            if (call_user_func([$this->matcher[$key], 'match'])) return true;
170
        }
171
        return false;
172
    }
173
174
    /**
175
     * @description call the target for the request uri
176
     */
177
    public function callTarget()
178
    {
179
        $target = is_array($this->route->getTarget('dispatcher')) ? $this->route->getTarget('dispatcher') : [$this->route->getTarget('dispatcher')];
180
        if (!empty($target)) {
181
            foreach ($target as $call) {
182
                $this->dispatcher = new $call($this);
183
                call_user_func([$this->dispatcher, 'call']);
184
            }
185
        }
186
    }
187
}
188