Completed
Push — master ( bb1ab9...4cd17e )
by Sinnarasa
02:25
created

Router::handle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 3
Metric Value
c 5
b 0
f 3
dl 0
loc 8
rs 9.4285
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
namespace JetFire\Routing;
4
5
/**
6
 * Class Router
7
 * @package JetFire\Routing
8
 */
9
class Router
10
{
11
12
    /**
13
     * @var Route
14
     */
15
    public $route;
16
    /**
17
     * @var RouteCollection
18
     */
19
    public $collection;
20
    /**
21
     * @var ResponseInterface
22
     */
23
    public $response;
24
    /**
25
     * @var
26
     */
27
    public $middleware;
28
    /**
29
     * @var
30
     */
31
    public $dispatcher;
32
33
    /**
34
     * @var array
35
     */
36
    private $config = [
37
        'matcher'            => ['JetFire\Routing\Match\RoutesMatch', 'JetFire\Routing\Match\SmartMatch'],
38
        'viewExtension'      => ['.html', '.php', '.json', '.xml'],
39
        'viewCallback'       => [],
40
        'di'                 => '',
41
        'generateRoutesPath' => false,
42
    ];
43
44
    /**
45
     * @param RouteCollection $collection
46
     * @param ResponseInterface $response
47
     * @param Route $route
48
     */
49
    public function __construct(RouteCollection $collection,ResponseInterface $response = null,Route $route = null)
50
    {
51
        $this->collection = $collection;
52
        $this->response = is_null($response)? new Response() : $response;
53
        $this->response->setStatusCode(404);
54
        $this->route = is_null($response)? new Route() : $route;
55
        $this->config['di'] = function($class){
56
            return new $class;
57
        };
58
    }
59
60
    /**
61
     * @param array $config
62
     */
63
    public function setConfig($config)
64
    {
65
        $this->config = array_merge($this->config, $config);
66
    }
67
68
    /**
69
     * @return array
70
     */
71
    public function getConfig()
72
    {
73
        return $this->config;
74
    }
75
76
    /**
77
     * @param string $matcher
78
     */
79
    public function addMatcher($matcher){
80
        $this->config['matcher'][] = $matcher;
81
    }
82
83
    /**
84
     * @description main function
85
     */
86
    public function run()
87
    {
88
        $this->setUrl();
89
        if ($this->config['generateRoutesPath']) $this->collection->generateRoutesPath();
90
        if ($this->match()) {
91
            $this->handle();
92
            $this->callTarget();
93
        }
94
        $this->callResponse();
95
    }
96
97
    /**
98
     * @param null $url
99
     */
100
    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...
101
    {
102
        if (is_null($url))
103
            $url = (isset($_GET['url'])) ? $_GET['url'] : substr(str_replace(str_replace('/index.php', '', $_SERVER['SCRIPT_NAME']), '', $_SERVER['REQUEST_URI']), 1);
104
        $this->route->setUrl('/' . trim(explode('?', $url)[0], '/'));
105
    }
106
107
    /**
108
     * @return bool
109
     */
110
    public function match()
111
    {
112
        foreach ($this->config['matcher'] as $matcher) {
113
            $this->config['matcherInstance'][$matcher] = new $matcher($this);
114
            if (call_user_func([$this->config['matcherInstance'][$matcher], 'match']))
115
                return true;
116
        }
117
        return false;
118
    }
119
120
    /**
121
     * @return mixed
122
     */
123
    public function callTarget()
124
    {
125
        $target = $this->route->getTarget('dispatcher');
126
        if(!empty($target)) {
127
            $this->dispatcher = new $target($this->route, $this->response);
128
            return call_user_func([$this->dispatcher, 'call']);
129
        }
130
        return null;
131
    }
132
133
    /**
134
     * @description handle middleware
135
     */
136
    private function handle()
137
    {
138
        $this->middleware = new Middleware($this);
139
        $this->middleware->globalMiddleware();
140
        $this->middleware->blockMiddleware();
141
        $this->middleware->classMiddleware();
142
        $this->middleware->routeMiddleware();
143
    }
144
145
    /**
146
     * @param array $responses
147
     */
148
    public function setResponses($responses = [])
149
    {
150
        $this->route->addDetail('response_templates', $responses);
151
    }
152
153
    /**
154
     * @description set response code
155
     */
156
    public function callResponse()
157
    {
158
        if (isset($this->route->getDetail()['response_templates']) && isset($this->route->getDetail()['response_templates'][$code = $this->response->getStatusCode()])) {
159
            $this->route->setCallback($this->route->getDetail()['response_templates'][$code]);
160
            foreach($this->config['matcherInstance'] as $matcher) {
161
                foreach (call_user_func([$matcher, 'getMatcher']) as $match)
162
                    if (call_user_func([$matcher, $match])){ $this->callTarget(); break; }
163
            }
164
            $this->response->setStatusCode($code);
165
        }
166
        $this->response->send();
167
    }
168
}
169