Passed
Pull Request — master (#30)
by Nícollas
02:50
created

RouterTrait::resetMiddlewares()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace CoffeeCode\Router;
4
5
trait RouterTrait
6
{
7
    /** @var array */
8
    protected $routes;
9
10
    /** @var string */
11
    protected $patch;
12
13
    /** @var string */
14
    protected $httpMethod;
15
16
    /** @var string|array */
17
    protected $currentMiddleware;
18
19
    /**
20
     * @param string $name
21
     * @param array|null $data
22
     * @return string|null
23
     */
24
    public function route(string $name, array $data = null): ?string
25
    {
26
        foreach ($this->routes as $http_verb) {
27
            foreach ($http_verb as $route_item) {
28
                if (!empty($route_item["name"]) && $route_item["name"] == $name) {
29
                    return $this->treat($route_item, $data);
30
                }
31
            }
32
        }
33
        return null;
34
    }
35
36
    /**
37
     * @var array|string $middleware
38
     */
39
    protected function middlewares($middleware)
40
    {
41
        $this->currentMiddleware = $middleware;
42
    }
43
44
    /** @return void */
45
    protected function resetMiddlewares()
46
    {
47
        $this->currentMiddleware = '';
48
    }
49
50
    /**
51
     * @param string $route
52
     * @param array|null $data
53
     */
54
    public function redirect(string $route, array $data = null): void
55
    {
56
        if ($name = $this->route($route, $data)) {
57
            header("Location: {$name}");
58
            exit;
59
        }
60
61
        if (filter_var($route, FILTER_VALIDATE_URL)) {
62
            header("Location: {$route}");
63
            exit;
64
        }
65
66
        $route = (substr($route, 0, 1) == "/" ? $route : "/{$route}");
67
        header("Location: {$this->projectUrl}{$route}");
68
        exit;
69
    }
70
71
    /**
72
     * @param string $method
73
     * @param string $route
74
     * @param string|callable $handler
75
     * @param null|string
76
     */
77
    protected function addRoute(string $method, string $route, $handler, string $name = null)
78
    {
79
        if ($route == "/") {
80
            $this->addRoute($method, "", $handler, $name);
81
        }
82
83
        preg_match_all("~\{\s* ([a-zA-Z_][a-zA-Z0-9_-]*) \}~x", $route, $keys, PREG_SET_ORDER);
84
        $routeDiff = array_values(array_diff(explode("/", $this->patch), explode("/", $route)));
85
86
        $this->formSpoofing();
0 ignored issues
show
Bug introduced by
It seems like formSpoofing() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

86
        $this->/** @scrutinizer ignore-call */ 
87
               formSpoofing();
Loading history...
87
        $offset = ($this->group ? 1 : 0);
88
        foreach ($keys as $key) {
89
            $this->data[$key[1]] = ($routeDiff[$offset++] ?? null);
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
90
        }
91
92
        $route = (!$this->group ? $route : "/{$this->group}{$route}");
93
        $data = $this->data;
94
        $namespace = $this->namespace;
95
        $router = function () use ($method, $handler, $data, $route, $name, $namespace) {
96
            return [
97
                "route" => $route,
98
                "name" => $name,
99
                "method" => $method,
100
                "handler" => $this->handler($handler, $namespace),
101
                "middleware" => $this->currentMiddleware,
102
                "action" => $this->action($handler),
103
                "data" => $data
104
            ];
105
        };
106
107
        $route = preg_replace('~{([^}]*)}~', "([^/]+)", $route);
108
        $this->routes[$method][$route] = $router();
109
110
        return $this;
111
    }
112
113
    /**
114
     * @param $handler
115
     * @param $namespace
116
     * @return string|callable
117
     */
118
    private function handler($handler, $namespace)
119
    {
120
        return (!is_string($handler) ? $handler : "{$namespace}\\" . explode($this->separator, $handler)[0]);
121
    }
122
123
    /**
124
     * @param $handler
125
     * @return null|string
126
     */
127
    private function action($handler): ?string
128
    {
129
        return (!is_string($handler) ?: (explode($this->separator, $handler)[1] ?? null));
130
    }
131
132
    /**
133
     * @param array $route_item
134
     * @param array|null $data
135
     * @return string|null
136
     */
137
    private function treat(array $route_item, array $data = null): ?string
138
    {
139
        $route = $route_item["route"];
140
        if (!empty($data)) {
141
            $arguments = [];
142
            $params = [];
143
            foreach ($data as $key => $value) {
144
                if (!strstr($route, "{{$key}}")) {
145
                    $params[$key] = $value;
146
                }
147
                $arguments["{{$key}}"] = $value;
148
            }
149
            $route = $this->process($route, $arguments, $params);
150
        }
151
152
        return "{$this->projectUrl}{$route}";
153
    }
154
155
    /**
156
     * @param string $route
157
     * @param array $arguments
158
     * @param array|null $params
159
     * @return string
160
     */
161
    private function process(string $route, array $arguments, array $params = null): string
162
    {
163
        $params = (!empty($params) ? "?" . http_build_query($params) : null);
164
        return str_replace(array_keys($arguments), array_values($arguments), $route) . "{$params}";
165
    }
166
}