RouterTrait::action()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace CoffeeCode\Router;
4
5
trait RouterTrait
6
{
7
    /** @var array */
8
    protected $routes;
9
10
    /** @var string */
11
    protected $path;
12
13
    /** @var string */
14
    protected $httpMethod;
15
16
    /**
17
     * @param string $name
18
     * @param array|null $data
19
     * @return string|null
20
     */
21
    public function route(string $name, array $data = null): ?string
22
    {
23
        foreach ($this->routes as $http_verb) {
24
            foreach ($http_verb as $route_item) {
25
                if (!empty($route_item["name"]) && $route_item["name"] == $name) {
26
                    return $this->treat($route_item, $data);
27
                }
28
            }
29
        }
30
        return null;
31
    }
32
33
    /**
34
     * @param string $route
35
     * @param array|null $data
36
     */
37
    public function redirect(string $route, array $data = null): void
38
    {
39
        if ($name = $this->route($route, $data)) {
40
            header("Location: {$name}");
41
            exit;
42
        }
43
44
        if (filter_var($route, FILTER_VALIDATE_URL)) {
45
            header("Location: {$route}");
46
            exit;
47
        }
48
49
        $route = (substr($route, 0, 1) == "/" ? $route : "/{$route}");
50
        header("Location: {$this->projectUrl}{$route}");
51
        exit;
52
    }
53
54
    /**
55
     * @param string $method
56
     * @param string $route
57
     * @param string|callable $handler
58
     * @param null|string
59
     */
60
    protected function addRoute(string $method, string $route, $handler, string $name = null): void
61
    {
62
        if ($route == "/") {
63
            $this->addRoute($method, "", $handler, $name);
64
        }
65
66
        $removeGroupFromPath = $this->group ? str_replace($this->group, "", $this->path) : $this->path;
67
        $pathAssoc = trim($removeGroupFromPath, "/");
68
        $routeAssoc = trim($route, "/");
69
70
        preg_match_all("~\{\s* ([a-zA-Z_][a-zA-Z0-9_-]*) \}~x", $routeAssoc, $keys, PREG_SET_ORDER);
71
        $routeDiff = array_values(array_diff_assoc(explode("/", $pathAssoc), explode("/", $routeAssoc)));
72
73
        $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

73
        $this->/** @scrutinizer ignore-call */ 
74
               formSpoofing();
Loading history...
74
        $offset = 0;
75
        foreach ($keys as $key) {
76
            $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...
77
        }
78
79
        $route = (!$this->group ? $route : "/{$this->group}{$route}");
80
        $data = $this->data;
81
        $namespace = $this->namespace;
82
        $router = function () use ($method, $handler, $data, $route, $name, $namespace) {
83
            return [
84
                "route" => $route,
85
                "name" => $name,
86
                "method" => $method,
87
                "handler" => $this->handler($handler, $namespace),
88
                "action" => $this->action($handler),
89
                "data" => $data
90
            ];
91
        };
92
93
        $route = preg_replace('~{([^}]*)}~', "([^/]+)", $route);
94
        $this->routes[$method][$route] = $router();
95
    }
96
97
    /**
98
     * @param $handler
99
     * @param $namespace
100
     * @return string|callable
101
     */
102
    private function handler($handler, $namespace)
103
    {
104
        return (!is_string($handler) ? $handler : "{$namespace}\\" . explode($this->separator, $handler)[0]);
105
    }
106
107
    /**
108
     * @param $handler
109
     * @return null|string
110
     */
111
    private function action($handler): ?string
112
    {
113
        return (!is_string($handler) ?: (explode($this->separator, $handler)[1] ?? null));
114
    }
115
116
    /**
117
     * @param array $route_item
118
     * @param array|null $data
119
     * @return string|null
120
     */
121
    private function treat(array $route_item, array $data = null): ?string
122
    {
123
        $route = $route_item["route"];
124
        if (!empty($data)) {
125
            $arguments = [];
126
            $params = [];
127
            foreach ($data as $key => $value) {
128
                if (!strstr($route, "{{$key}}")) {
129
                    $params[$key] = $value;
130
                }
131
                $arguments["{{$key}}"] = $value;
132
            }
133
            $route = $this->process($route, $arguments, $params);
134
        }
135
136
        return "{$this->projectUrl}{$route}";
137
    }
138
139
    /**
140
     * @param string $route
141
     * @param array $arguments
142
     * @param array|null $params
143
     * @return string
144
     */
145
    private function process(string $route, array $arguments, array $params = null): string
146
    {
147
        $params = (!empty($params) ? "?" . http_build_query($params) : null);
148
        return str_replace(array_keys($arguments), array_values($arguments), $route) . "{$params}";
149
    }
150
}