Issues (20)

Mezon/Router/UrlParser.php (3 issues)

Labels
Severity
1
<?php
2
declare(strict_types = 1);
3
namespace Mezon\Router;
4
5
use Mezon\Router\Types\BaseType;
6
7
/**
8
 * Trait UrlParser
9
 *
10
 * @package Router
11
 * @author Dodonov A.A.
12
 * @version v.1.0 (2021/09/27)
13
 * @copyright Copyright (c) 2021, http://aeon.su
14
 */
15
trait UrlParser
16
{
17
18
    use UrlParserBase;
19
20
    /**
21
     * Cache for regular expressions
22
     *
23
     * @var string[]
24
     */
25
    private $cachedRegExps = [];
26
27
    /**
28
     * Cached parameters for route
29
     *
30
     * @var array<string, string[]>
31
     */
32
    private $cachedParameters = [];
33
34
    /**
35
     * Method compiles route pattern string in regex string.
36
     * For example [i:id]/some-str in ([\[0-9\]])/some-str
37
     *
38
     * @param string $routerPattern
39
     *            router pattern
40
     * @return string regexp pattern
41
     * @psalm-suppress MixedMethodCall
42
     */
43
    private function _getRouteMatcherRegExPattern(string $routerPattern): string
44
    {
45
        $key = $routerPattern;
46
47
        // try read from cache
48
        if (isset($this->cachedRegExps[$key])) {
49
            return $this->cachedRegExps[$key];
50
        }
51
52
        // parsing routes
53
        $compiledRouterPattern = $routerPattern;
54
        foreach ($this->types as $typeClass) {
55
            $compiledRouterPattern = preg_replace(
56
                '/' . $typeClass::searchRegExp() . '/',
57
                '(' . $typeClass::parserRegExp() . ')',
58
                $compiledRouterPattern);
59
        }
60
61
        // final setup + save in cache
62
        $this->cachedRegExps[$key] = $compiledRouterPattern;
63
64
        return $compiledRouterPattern;
65
    }
66
67
    /**
68
     * Method returns all parameter names in the route
69
     *
70
     * @param string $routerPattern
71
     *            route
72
     * @return string[] names
73
     */
74
    private function _getParameterNames(string $routerPattern): array
75
    {
76
        if (isset($this->cachedParameters[$routerPattern])) {
77
            return $this->cachedParameters[$routerPattern];
78
        }
79
80
        $regExPattern = [];
81
82
        foreach (array_keys($this->types) as $typeName) {
83
            $regExPattern[] = $typeName;
84
        }
85
86
        $regExPattern = '\[(' . implode('|', $regExPattern) . '):(' . BaseType::PARAMETER_NAME_REGEXP . ')\]';
87
88
        $names = [];
89
        preg_match_all('/' . str_replace('/', '\\/', $regExPattern) . '/', $routerPattern, $names);
90
91
        $return = [];
92
93
        foreach ($names[2] as $name) {
94
            $return[] = $name;
95
        }
96
97
        $this->cachedParameters[$routerPattern] = $return;
98
99
        return $return;
100
    }
101
102
    /**
103
     * Method warms cache
104
     */
105
    public function warmCache(): void
106
    {
107
        foreach (SupportedRequestMethods::getListOfSupportedRequestMethods() as $requestMethod) {
108
            /** @var array{bunch: array} $bunch */
109
            foreach ($this->paramRoutes[$requestMethod] as $bunch) {
110
                /** @var array{pattern: string} $route */
111
                foreach ($bunch['bunch'] as $route) {
112
                    $this->_getRouteMatcherRegExPattern($route['pattern']);
113
114
                    $this->_getParameterNames($route['pattern']);
115
                }
116
            }
117
        }
118
119
        $this->compileRegexpForBunches();
0 ignored issues
show
It seems like compileRegexpForBunches() 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

119
        $this->/** @scrutinizer ignore-call */ 
120
               compileRegexpForBunches();
Loading history...
120
    }
121
122
    /**
123
     * Method searches dynamic route processor
124
     *
125
     * @param string $route
126
     *            route
127
     * @param string $requestMethod
128
     *            request method
129
     * @return array{0: string, 1:string}|callable|string|false route's handler or false in case the handler was not found
130
     */
131
    protected function getDynamicRouteProcessor(string $route, string $requestMethod = '')
132
    {
133
        $bunches = $this->paramRoutes[$requestMethod == '' ? $this->getRequestMethod() : $requestMethod];
0 ignored issues
show
It seems like getRequestMethod() 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

133
        $bunches = $this->paramRoutes[$requestMethod == '' ? $this->/** @scrutinizer ignore-call */ getRequestMethod() : $requestMethod];
Loading history...
134
135
        /** @var array{bunch: string[], regexp: string} $bunch */
136
        foreach ($bunches as $bunch) {
137
            $matches = [];
138
139
            if (preg_match($bunch['regexp'], $route, $matches)) {
140
                /** @var array{pattern: string, callback: callable} $routeData */
141
                $routeData = $bunch['bunch'][count($matches)];
142
143
                $names = $this->_getParameterNames($routeData['pattern']);
144
145
                $this->parameters = [];
146
                foreach ($names as $i => $name) {
147
                    /** @var string[] $matches */
148
                    $this->parameters[$name] = $matches[(int) $i + 1];
149
                }
150
151
                $this->setCalledRoute($routeData['pattern']);
0 ignored issues
show
It seems like setCalledRoute() 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

151
                $this->/** @scrutinizer ignore-call */ 
152
                       setCalledRoute($routeData['pattern']);
Loading history...
152
153
                return $routeData['callback'];
154
            }
155
        }
156
157
        // match was not found
158
        return false;
159
    }
160
}
161