Browse code

REGEX routes

RafaƂ Szklarczyk authored on 26/11/2019 16:16:53
Showing 2 changed files
... ...
@@ -11,19 +11,26 @@ class RouteInfo{
11 11
     public $result;
12 12
     // The route name
13 13
     public $name;
14
+    // The type the route - should be one of defined in the class constants
15
+    public $type;
14 16
     // BeforeAction event handlers;
15 17
     public $beforeAction;
16 18
     // AfterAction event handlers;
17 19
     public $afterAction;
18 20
     // AfterResult event handlers;
19 21
     public $afterResult;
22
+
23
+    //RouteInfo types:
24
+    public const L3 = "L3";
25
+    public const REGEX = "REGEX";
20 26
        
21
-    public function __construct($method, $path, $result, $name = '')
27
+    public function __construct($method, $path, $result, $name = '', $type = self::L3)
22 28
     {
23 29
         $this->path = $path;
24 30
         $this->method = $method;
25 31
         $this->result = $result;
26 32
         $this->name = $name;
33
+        $this->type = $type;
27 34
         $this->beforeAction = array();
28 35
         $this->afterAction = array();
29 36
         $this->afterResult = array();
... ...
@@ -25,6 +25,12 @@ class Router{
25 25
         return $this;
26 26
     }
27 27
 
28
+    public function add_preg($method, $path, $result, $name = ''){
29
+        $this->routes[] = new RouteInfo($method, $path, $result, $name, RouteInfo::REGEX);
30
+        if(isset($name)&&$name!='') $this->routeNameIndex[$name] = &$this->routes[count($this->routes)-1];
31
+        return $this;
32
+    }
33
+
28 34
     public function add404($result){
29 35
         return $this->add('404', '', $result, _L3_ROUTE_404_NAME);
30 36
     }
... ...
@@ -53,6 +59,32 @@ class Router{
53 59
         return $this->add('ANY', $path, $result, $name);
54 60
     }
55 61
 
62
+    // Regular expression based routes
63
+
64
+    public function get_preg($path, $result, $name = ''){
65
+        return $this->add_preg('GET', $path, $result, $name);
66
+    }
67
+
68
+    public function post_preg($path, $result, $name = ''){
69
+        return $this->add_preg('POST', $path, $result, $name);
70
+    }
71
+
72
+    public function put_preg($path, $result, $name = ''){
73
+        return $this->add_preg('PUT', $path, $result, $name);
74
+    }
75
+
76
+    public function patch_preg($path, $result, $name = ''){
77
+        return $this->add_preg('PATCH', $path, $result, $name);
78
+    }
79
+
80
+    public function delete_preg($path, $result, $name = ''){
81
+        return $this->add_preg('DELETE', $path, $result, $name);
82
+    }
83
+
84
+    public function any_preg($path, $result, $name = ''){
85
+        return $this->add_preg('ANY', $path, $result, $name);
86
+    }
87
+
56 88
     public function addBeforeAction($event_handler){
57 89
         $this->routes[count($this->routes)-1]->addBeforeAction($event_handler);
58 90
         return $this;
... ...
@@ -74,36 +106,49 @@ class Router{
74 106
         $curi = count($auri);
75 107
 			
76 108
         foreach ($this->routes as $routeInfo) {
77
-            
78
-            $route = $routeInfo->path;
79
-            $method = $routeInfo->method;
80
-            if($method=='ANY' || strpos($request->method,$method)!==false){
81
-                $aroute = explode('/', trim($route, "/ \t\n\r\0\x0B"));
82
-                //print_r($aroute);
83
-                if($curi==count($aroute)){ //compare path element count
84
-                    //optimistic assumption :)
85
-                    $matchResult = true;
86
-                    for($i = 0; $i<$curi; $i++){
87
-                        $pathPartName = trim($aroute[$i],'{}');
88
-                        if($aroute[$i]==$pathPartName){
89
-                            if($auri[$i]!=$pathPartName){
90
-                                //echo "diffrence found";
91
-                                $matchResult = false;
92
-                                break;
109
+            if($routeInfo->type == RouteInfo::L3){
110
+                $route = $routeInfo->path;
111
+                $method = $routeInfo->method;
112
+                if($method=='ANY' || strpos($request->method,$method)!==false){
113
+                    $aroute = explode('/', trim($route, "/ \t\n\r\0\x0B"));
114
+                    //print_r($aroute);
115
+                    if($curi==count($aroute)){ //compare path element count
116
+                        //optimistic assumption :)
117
+                        $matchResult = true;
118
+                        for($i = 0; $i<$curi; $i++){
119
+                            $pathPartName = trim($aroute[$i],'{}');
120
+                            if($aroute[$i]==$pathPartName){
121
+                                if($auri[$i]!=$pathPartName){
122
+                                    //echo "diffrence found";
123
+                                    $matchResult = false;
124
+                                    break;
125
+                                }
93 126
                             }
94
-                        }
95
-                        else{ // {...} found -> catch $uri variable
96
-                            $value = $auri[$i];
97
-                            $valueKey = explode(':', $pathPartName);
98
-                            //validation
99
-                            if(isset($valueKey[1]) && $valueKey[1]=='int'){
100
-                                $value = intval($value);
127
+                            else{ // {...} found -> catch $uri variable
128
+                                $value = $auri[$i];
129
+                                $valueKey = explode(':', $pathPartName);
130
+                                //validation
131
+                                if(isset($valueKey[1]) && $valueKey[1]=='int'){
132
+                                    $value = intval($value);
133
+                                }
134
+                                //value store...
135
+                                $this->parsedParameters[$valueKey[0]] = $value;
101 136
                             }
102
-                            //value store...
103
-                            $this->parsedParameters[$valueKey[0]] = $value;
137
+                        }
138
+                        if($matchResult){ // match found
139
+                            $this->depth = $curi;
140
+                            $this->routeInfo = $routeInfo;
141
+                            return $routeInfo->result;
104 142
                         }
105 143
                     }
106
-                    if($matchResult){ // match found
144
+                }
145
+            }
146
+            if($routeInfo->type == RouteInfo::REGEX){
147
+                $route_pattern = $routeInfo->path;
148
+                $method = $routeInfo->method;
149
+                if($method=='ANY' || strpos($request->method, $method)!==false){
150
+                    if(\preg_match($route_pattern, $request->path, $match)){
151
+                        $this->parsedParameters = $match;
107 152
                         $this->depth = $curi;
108 153
                         $this->routeInfo = $routeInfo;
109 154
                         return $routeInfo->result;
... ...
@@ -142,12 +187,15 @@ class Router{
142 187
 
143 188
     public function link($name, $parameters){
144 189
         $route = $this->routeNameIndex[$name];
190
+        if($route->type == RouteInfo::REGEX){
191
+            throw new \Exception("Method Router::link not applicable to REGEX routes.");
192
+        }
145 193
         $fields = array_keys($parameters);
146 194
         $values = array_values($parameters);
147 195
         array_walk($fields, function (&$item, $key){
148 196
             $item = "/\{".$item."\}/";
149 197
         });
150
-        return preg_replace($fields, $values, $route->Path);
198
+        return preg_replace($fields, $values, $route->path);
151 199
     }
152 200
 
153 201
     public function getParameter($name){