Warning: error_log(/home/topautol/public_html/../storage/log/errors.log): Failed to open stream: No such file or directory in /home/topautol/public_html/engine/Helper/ErrorHandler.php on line 40
https://topautolink.com/ - Engine\Core\Router\UrlDispatcher::doDispatch(): Return value must be of type Engine\Core\Router\DispatchedRoute, none returned
Exception

Error reason:

Engine\Core\Router\UrlDispatcher::doDispatch(): Return value must be of type Engine\Core\Router\DispatchedRoute, none returned: url(/home/topautol/public_html/engine/Core/Router/UrlDispatcher.php)

Request method: GET
http://topautolink.com/sitemap.xml
File and line, where an error has been reported
File: /home/topautol/public_html/engine/Core/Router/UrlDispatcher.php
1
<?php
2
3
namespace Engine\Core\Router;
4
5
class UrlDispatcher
6
{
7
    /**
8
     * @var string[]
9
     */
10
    private array $methods = [
11
        'GET',
12
        'POST'
13
    ];
14
15
    /**
16
     * @var array[]
17
     */
18
    private array $routes = [
19
        'GET'  => [],
20
        'POST' => []
21
    ];
22
23
    /**
24
     * @var string[]
25
     */
26
    private array $patterns = [
27
        'int' => '[0-9]+',
28
        'str' => '[a-zA-Z\.\-_%]+',
29
        'any' => '[a-zA-Z0-9\.\-_%]+'
30
    ];
31
32
    /**
33
     * @param $key
34
     * @param $pattern
35
     */
36
    public function addPattern($key, $pattern): void
37
    {
38
        $this->patterns[$key] = $pattern;
39
    }
40
41
    /**
42
     * @param $method
43
     * @return array
44
     */
45
    public function routes($method): array
46
    {
47
        return $this->routes[$method] ?? [];
48
    }
49
50
    /**
51
     * @param $method
52
     * @param $pattern
53
     * @param $controller
54
     */
55
    public function register($method, $pattern, $controller): void
56
    {
57
        $transfer = $this->transferPattern($pattern);
58
59
        $this->routes[strtoupper($method)][$transfer] = $controller;
60
    }
61
62
    /**
63
     * @param $pattern
64
     * @return string|string[]|null
65
     */
66
    private function transferPattern($pattern): array|string|null
67
    {
68
        if(!str_contains($pattern, '(')) {
69
            return $pattern;
70
        }
71
72
        return preg_replace_callback(
73
            '#\((\w+):(\w+)\)#',
74
            [$this, 'replacePattern'],
75
            $pattern
76
        );
77
    }
78
79
    /**
80
     * @param $matches
81
     * @return string
82
     */
83
    private function replacePattern($matches): string
84
    {
85
        return '(?<' .$matches[1]. '>' . strtr($matches[2], $this->patterns) . ')';
86
    }
87
88
    /**
89
     * @param $parameters
90
     * @return mixed
91
     */
92
    private function processParam($parameters): mixed
93
    {
94
        foreach ($parameters as $index => $parameter)
95
        {
96
            if(is_int($index))
97
            {
98
                unset($parameters[$index]);
99
            }
100
        }
101
102
        return $parameters;
103
    }
104
105
    /**
106
     * @param $method
107
     * @param $uri
108
     * @return DispatchedRoute
109
     */
110
    public function dispatch($method, $uri): DispatchedRoute
111
    {
112
        $routes = $this->routes(strtoupper($method));
113
114
        if(array_key_exists($uri, $routes)) {
115
            return new DispatchedRoute($routes[$uri]);
116
        }
117
118
        return $this->doDispatch($method, $uri);
119
    }
120
121
    /**
122
     * @param $method
123
     * @param $uri
124
     * @return DispatchedRoute
125
     */
126
    private function doDispatch($method, $uri): DispatchedRoute
127
    {
128
        foreach ($this->routes($method) as $route => $controller) {
129
            $pattern = '#^' . $route . '$#s';
130
131
            if(preg_match($pattern, $uri, $parameters))
132
            {
133
                return new DispatchedRoute($controller, $this->processParam($parameters));
134
            }
135
        }
136
    }
137
}