6
6
use PhpSlides \Foundation \Application ;
7
7
use PhpSlides \Interface \MapInterface ;
8
8
9
+
9
10
/**
10
- * Map Configuration
11
+ * Class MapRoute
12
+ *
13
+ * This class is responsible for mapping and matching routes against the current request URI and HTTP method.
14
+ * It extends the Controller class and implements the MapInterface interface.
15
+ *
16
+ * @author dconco <info@dconco.dev>
17
+ * @version 1.4.0
18
+ * @package PhpSlides
11
19
*/
12
20
class MapRoute extends Controller implements MapInterface
13
21
{
22
+ /**
23
+ * @var string|array $route The route(s) to be mapped.
24
+ */
14
25
private static string |array $ route ;
26
+
27
+ /**
28
+ * @var string $request_uri The URI of the current request.
29
+ */
15
30
private static string $ request_uri ;
31
+
32
+ /**
33
+ * @var array $method An array to store HTTP methods for routing.
34
+ */
16
35
private static array $ method ;
17
36
37
+
18
38
/**
19
- * Validating $route methods
39
+ * Matches the given HTTP method and route against the current request URI.
40
+ *
41
+ * @param string $method The HTTP method(s) to match, separated by '|'.
42
+ * @param string|array $route The route pattern(s) to match.
43
+ * @return bool|array Returns false if no match is found, or an array with the matched method, route, and parameters if a match is found.
20
44
*
21
- * @param int $method
22
- * @param string|array $route
45
+ * The function performs the following steps:
46
+ * - Sets the HTTP method(s) to match.
47
+ * - Normalizes the request URI by removing leading and trailing slashes and converting to lowercase.
48
+ * - Normalizes the route pattern(s) by removing leading and trailing slashes and converting to lowercase.
49
+ * - Checks if the route contains a pattern and resolves it if necessary.
50
+ * - Extracts parameter names from the route pattern.
51
+ * - Matches the request URI against the route pattern and extracts parameter values.
52
+ * - Constructs a regex pattern to match the route.
53
+ * - Checks if the request method is allowed for the matched route.
54
+ * - Returns an array with the matched method, route, and parameters if a match is found.
55
+ * - Returns false if no match is found.
23
56
*/
24
57
public function match (string $ method , string |array $ route ): bool |array
25
58
{
@@ -31,13 +64,34 @@ public function match(string $method, string|array $route): bool|array
31
64
* ----------------------------------------------
32
65
*/
33
66
self ::$ request_uri = strtolower (
34
- preg_replace ("/(^\/)|(\/$)/ " , '' , Application::$ request_uri ),
67
+ preg_replace ("/(^\/)|(\/$)/ " , '' , Application::$ request_uri ),
35
68
);
36
69
self ::$ request_uri = empty (self ::$ request_uri ) ? '/ ' : self ::$ request_uri ;
37
70
38
71
self ::$ route = is_array ($ route )
39
- ? $ route
40
- : strtolower (preg_replace ("/(^\/)|(\/$)/ " , '' , $ route ));
72
+ ? $ route
73
+ : strtolower (preg_replace ("/(^\/)|(\/$)/ " , '' , $ route ));
74
+
75
+ // Firstly, resolve route with pattern
76
+ if (is_array (self ::$ route ))
77
+ {
78
+ foreach (self ::$ route as $ value )
79
+ {
80
+ if (str_starts_with ('pattern: ' , $ value ))
81
+ {
82
+ $ pattern = true ;
83
+ }
84
+ }
85
+
86
+ if ($ pattern === true )
87
+ {
88
+ return $ this ->pattern ();
89
+ }
90
+ }
91
+ else if (str_starts_with ('pattern: ' , self ::$ route ))
92
+ {
93
+ return $ this ->pattern ();
94
+ }
41
95
42
96
// will store all the parameters value in this array
43
97
$ req = [];
@@ -47,12 +101,14 @@ public function match(string $method, string|array $route): bool|array
47
101
$ paramKey = [];
48
102
49
103
// finding if there is any {?} parameter in $route
50
- if (is_string (self ::$ route )) {
104
+ if (is_string (self ::$ route ))
105
+ {
51
106
preg_match_all ('/(?<={).+?(?=})/ ' , self ::$ route , $ paramMatches );
52
107
}
53
108
54
109
// if the route does not contain any param call routing();
55
- if (empty ($ paramMatches [0 ] ?? []) || is_array (self ::$ route )) {
110
+ if (empty ($ paramMatches ) || is_array (self ::$ route ))
111
+ {
56
112
/**
57
113
* ------------------------------------------------------
58
114
* | Check if $callback is a callable function
@@ -64,7 +120,8 @@ public function match(string $method, string|array $route): bool|array
64
120
}
65
121
66
122
// setting parameters names
67
- foreach ($ paramMatches [0 ] as $ key ) {
123
+ foreach ($ paramMatches [0 ] as $ key )
124
+ {
68
125
$ paramKey [] = $ key ;
69
126
}
70
127
@@ -75,8 +132,10 @@ public function match(string $method, string|array $route): bool|array
75
132
$ indexNum = [];
76
133
77
134
// storing index number, where {?} parameter is required with the help of regex
78
- foreach ($ uri as $ index => $ param ) {
79
- if (preg_match ('/{.*}/ ' , $ param )) {
135
+ foreach ($ uri as $ index => $ param )
136
+ {
137
+ if (preg_match ('/{.*}/ ' , $ param ))
138
+ {
80
139
$ indexNum [] = $ index ;
81
140
}
82
141
}
@@ -93,14 +152,16 @@ public function match(string $method, string|array $route): bool|array
93
152
* | Running for each loop to set the exact index number with reg expression this will help in matching route
94
153
* ----------------------------------------------------------------------------------
95
154
*/
96
- foreach ($ indexNum as $ key => $ index ) {
155
+ foreach ($ indexNum as $ key => $ index )
156
+ {
97
157
/**
98
158
* --------------------------------------------------------------------------------
99
159
* | In case if req uri with param index is empty then return because URL is not valid for this route
100
160
* --------------------------------------------------------------------------------
101
161
*/
102
162
103
- if (empty ($ reqUri [$ index ])) {
163
+ if (empty ($ reqUri [$ index ]))
164
+ {
104
165
return false ;
105
166
}
106
167
@@ -124,64 +185,146 @@ public function match(string $method, string|array $route): bool|array
124
185
$ reqUri = str_replace ('/ ' , '\\/ ' , $ reqUri );
125
186
126
187
// now matching route with regex
127
- if (preg_match ("/ $ reqUri/ " , self ::$ route )) {
188
+ if (preg_match ("/ $ reqUri/ " , self ::$ route ))
189
+ {
128
190
// checks if the requested method is of the given route
129
191
if (
130
- !in_array ($ _SERVER ['REQUEST_METHOD ' ], self ::$ method ) &&
131
- !in_array ('optional ' , self ::$ method )
132
- ) {
192
+ !in_array ($ _SERVER ['REQUEST_METHOD ' ], self ::$ method ) &&
193
+ !in_array ('* ' , self ::$ method )
194
+ )
195
+ {
133
196
http_response_code (405 );
134
197
exit ('Method Not Allowed ' );
135
198
}
136
199
137
200
return [
138
- 'method ' => $ _SERVER ['REQUEST_METHOD ' ],
139
- 'route ' => self ::$ route ,
140
- 'params_value ' => $ req_value ,
141
- 'params ' => $ req ,
201
+ 'method ' => $ _SERVER ['REQUEST_METHOD ' ],
202
+ 'route ' => self ::$ route ,
203
+ 'params_value ' => $ req_value ,
204
+ 'params ' => $ req ,
142
205
];
143
206
}
144
207
145
208
return false ;
146
209
}
147
210
148
- private function match_routing (): bool |array
211
+
212
+ /**
213
+ * Matches the current request URI and method against the defined routes.
214
+ *
215
+ * This method checks if the current request URI matches any of the defined routes
216
+ * and if the request method is allowed for the matched route. If a match is found,
217
+ * it returns an array containing the request method and the matched route. If no
218
+ * match is found, it returns false.
219
+ *
220
+ * @return bool|array Returns an array with 'method' and 'route' keys if a match is found, otherwise false.
221
+ */
222
+ private function match_routing (): bool |array
149
223
{
150
224
$ uri = [];
151
225
$ str_route = '' ;
152
226
153
- if (is_array (self ::$ route )) {
154
- for ($ i = 0 ; $ i < count (self ::$ route ); $ i ++) {
227
+ if (is_array (self ::$ route ))
228
+ {
229
+ for ($ i = 0 ; $ i < count (self ::$ route ); $ i ++)
230
+ {
155
231
$ each_route = preg_replace ("/(^\/)|(\/$)/ " , '' , self ::$ route [$ i ]);
156
232
157
233
empty ($ each_route )
158
- ? array_push ($ uri , strtolower ('/ ' ))
159
- : array_push ($ uri , strtolower ($ each_route ));
234
+ ? array_push ($ uri , strtolower ('/ ' ))
235
+ : array_push ($ uri , strtolower ($ each_route ));
160
236
}
161
- } else {
237
+ }
238
+ else
239
+ {
162
240
$ str_route = empty (self ::$ route ) ? '/ ' : self ::$ route ;
163
241
}
164
242
165
243
if (
166
- in_array (self ::$ request_uri , $ uri ) ||
167
- self ::$ request_uri === $ str_route
168
- ) {
244
+ in_array (self ::$ request_uri , $ uri ) ||
245
+ self ::$ request_uri === $ str_route
246
+ )
247
+ {
169
248
if (
170
- !in_array ($ _SERVER ['REQUEST_METHOD ' ], self ::$ method ) &&
171
- !in_array ('optional ' , self ::$ method )
172
- ) {
249
+ !in_array ($ _SERVER ['REQUEST_METHOD ' ], self ::$ method ) &&
250
+ !in_array ('* ' , haystack: self ::$ method )
251
+ )
252
+ {
173
253
http_response_code (405 );
174
254
exit ('Method Not Allowed ' );
175
255
}
176
256
177
- $ method = implode ('| ' , self ::$ method );
178
-
179
257
return [
180
- 'method ' => $ _SERVER ['REQUEST_METHOD ' ],
181
- 'route ' => self ::$ route ,
258
+ 'method ' => $ _SERVER ['REQUEST_METHOD ' ],
259
+ 'route ' => self ::$ route ,
182
260
];
183
- } else {
261
+ }
262
+ else
263
+ {
184
264
return false ;
185
265
}
186
266
}
267
+
268
+
269
+ /**
270
+ * Validates and matches a route pattern.
271
+ *
272
+ * This method checks if the route is an array and iterates through each value to find a pattern match.
273
+ * If a pattern match is found, it validates the pattern and returns the matched result.
274
+ * If no match is found in the array, it returns false.
275
+ * If the route is not an array, it directly validates the pattern and returns the result.
276
+ *
277
+ * @return array|bool The matched pattern as an array if found, or false if no match is found.
278
+ */
279
+ private function pattern (): array |bool
280
+ {
281
+ if (is_array (self ::$ route ))
282
+ {
283
+ foreach (self ::$ route as $ value )
284
+ {
285
+ if (str_starts_with ('pattern: ' , $ value ))
286
+ {
287
+ $ matched = $ this ->validatePattern ($ value );
288
+
289
+ if ($ matched )
290
+ {
291
+ return $ matched ;
292
+ }
293
+ }
294
+ }
295
+ return false ;
296
+ }
297
+
298
+ return $ this ->validatePattern (self ::$ route );
299
+ }
300
+
301
+
302
+ /**
303
+ * Validates the given pattern against the request URI and checks the request method.
304
+ *
305
+ * @param string $pattern The pattern to validate.
306
+ * @return array|bool Returns an array with the request method and route if the pattern matches, otherwise false.
307
+ */
308
+ private function validatePattern (string $ pattern ): array |bool
309
+ {
310
+ $ pattern = trim (substr ($ pattern , 8 ));
311
+
312
+ if (fnmatch ($ pattern , self ::$ request_uri ))
313
+ {
314
+ if (
315
+ !in_array ($ _SERVER ['REQUEST_METHOD ' ], self ::$ method ) &&
316
+ !in_array ('* ' , self ::$ method )
317
+ )
318
+ {
319
+ http_response_code (405 );
320
+ exit ('Method Not Allowed ' );
321
+ }
322
+
323
+ return [
324
+ 'method ' => $ _SERVER ['REQUEST_METHOD ' ],
325
+ 'route ' => self ::$ route ,
326
+ ];
327
+ }
328
+ return false ;
329
+ }
187
330
}
0 commit comments