1
|
|
|
<?php namespace Garden; |
2
|
|
|
|
3
|
|
|
abstract class Route { |
4
|
|
|
/// Constants /// |
5
|
|
|
|
6
|
|
|
const MAP_QUERY = 'query'; // map to the querystring. |
7
|
|
|
const MAP_INPUT = 'input'; // map to the input (post). |
8
|
|
|
const MAP_DATA = 'data'; // map to the querystring or input depending on the method. |
9
|
|
|
|
10
|
|
|
/// Properties /// |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @var array[string] An array of allowed http methods for this route. |
14
|
|
|
*/ |
15
|
|
|
protected $methods; |
16
|
|
|
|
17
|
|
|
protected $pattern; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var array An array of parameter conditions. |
21
|
|
|
*/ |
22
|
|
|
protected $conditions; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var array An array of global parameter conditions. |
26
|
|
|
*/ |
27
|
|
|
protected static $globalConditions; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var array An array of parameter mappings. |
31
|
|
|
*/ |
32
|
|
|
protected $mappings; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var bool Whether or not to match the path with the file extension. |
36
|
|
|
*/ |
37
|
|
|
protected $matchFullPath; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var array An array of global parameter mappings. |
41
|
|
|
*/ |
42
|
|
|
protected static $globalMappings = [ |
43
|
|
|
'data' => Route::MAP_DATA, |
44
|
|
|
'query' => Route::MAP_QUERY, |
45
|
|
|
'input' => Route::MAP_INPUT |
46
|
|
|
]; |
47
|
|
|
|
48
|
|
|
/// Methods /// |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Create and return a new route. |
52
|
|
|
* |
53
|
|
|
* @param string $pattern The pattern for the route. |
54
|
|
|
* @param callable|string $callback Either a callback to map the route to or a string representing |
55
|
|
|
* a format for {@link sprintf()}. |
56
|
|
|
* @return \Garden\Route Returns the new route. |
57
|
|
|
*/ |
58
|
44 |
|
public static function create($pattern, $callback) { |
59
|
44 |
|
if (is_callable($callback)) { |
60
|
10 |
|
$route = new CallbackRoute($pattern, $callback); |
61
|
|
|
} else { |
62
|
34 |
|
$route = new ResourceRoute($pattern, $callback); |
63
|
|
|
} |
64
|
44 |
|
return $route; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Dispatch the route. |
69
|
|
|
* |
70
|
|
|
* @param Request $request The current request we are dispatching against. |
71
|
|
|
* @param array &$args The args to pass to the dispatch. |
72
|
|
|
* These are the arguments returned from {@link Route::matches()}. |
73
|
|
|
*/ |
74
|
|
|
abstract public function dispatch(Request $request, array &$args); |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Gets or sets the route's conditions. |
78
|
|
|
* |
79
|
|
|
* @param array|null $conditions An array of conditions to set. |
80
|
|
|
* @return Route|array |
81
|
|
|
*/ |
82
|
35 |
View Code Duplication |
public function conditions($conditions = null) { |
|
|
|
|
83
|
35 |
|
if ($this->conditions === null) { |
84
|
35 |
|
$this->conditions = []; |
85
|
|
|
} |
86
|
|
|
|
87
|
35 |
|
if (is_array($conditions)) { |
88
|
35 |
|
$conditions = array_change_key_case($conditions); |
89
|
|
|
|
90
|
35 |
|
$this->conditions = array_replace( |
91
|
35 |
|
$this->conditions, |
92
|
|
|
$conditions |
93
|
|
|
); |
94
|
35 |
|
return $this; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $this->conditions; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Gets or sets the allowed http methods for this route. |
102
|
|
|
* |
103
|
|
|
* @param array|string|null $methods Set a new set of allowed methods or pass null to get the current methods. |
104
|
|
|
* @return Route|array Returns the current methods or `$this` for fluent calls. |
105
|
|
|
*/ |
106
|
1 |
|
public function methods($methods = null) { |
107
|
1 |
|
if ($methods === null) { |
108
|
|
|
return $this->methods; |
109
|
|
|
} |
110
|
|
|
|
111
|
1 |
|
$this->methods = array_map('strtoupper', (array)$methods); |
112
|
1 |
|
return $this; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Gets/sets the global conditions. |
117
|
|
|
* |
118
|
|
|
* @param array|null $conditions An array of conditions to set. |
119
|
|
|
* @return array The current global conditions. |
120
|
|
|
*/ |
121
|
34 |
View Code Duplication |
public static function globalConditions($conditions = null) { |
|
|
|
|
122
|
34 |
|
if (self::$globalConditions === null) { |
123
|
1 |
|
self::$globalConditions = []; |
124
|
|
|
} |
125
|
|
|
|
126
|
34 |
|
if (is_array($conditions)) { |
127
|
34 |
|
$conditions = array_change_key_case($conditions); |
128
|
|
|
|
129
|
34 |
|
self::$globalConditions = array_replace( |
130
|
34 |
|
self::$globalConditions, |
131
|
|
|
$conditions |
132
|
|
|
); |
133
|
|
|
} |
134
|
|
|
|
135
|
34 |
|
return self::$globalConditions; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Gets or sets the mappings array that maps parameter names to mappings. |
140
|
|
|
* |
141
|
|
|
* @param array|null $mappings An array of mappings to set. |
142
|
|
|
* @return Route|array Returns the current mappings or `$this` for fluent calls. |
143
|
|
|
*/ |
144
|
|
View Code Duplication |
public function mappings($mappings = null) { |
|
|
|
|
145
|
|
|
if ($this->mappings === null) { |
146
|
|
|
$this->mappings = []; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
if (is_array($mappings)) { |
150
|
|
|
$mappings = array_change_key_case($mappings); |
151
|
|
|
|
152
|
|
|
$this->mappings = array_replace( |
153
|
|
|
$this->mappings, |
154
|
|
|
$mappings |
155
|
|
|
); |
156
|
|
|
return $this; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
return $this->mappings; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Gets or sets the global mappings array that maps parameter names to mappings. |
164
|
|
|
* |
165
|
|
|
* @param array|null $mappings An array of mappings to set. |
166
|
|
|
* @return array Returns the current global mappings. |
167
|
|
|
*/ |
168
|
|
View Code Duplication |
public static function globalMappings($mappings = null) { |
|
|
|
|
169
|
|
|
if (self::$globalMappings === null) { |
170
|
|
|
self::$globalMappings = []; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
if (is_array($mappings)) { |
174
|
|
|
$mappings = array_change_key_case($mappings); |
175
|
|
|
|
176
|
|
|
self::$globalMappings = array_replace( |
177
|
|
|
self::$globalMappings, |
178
|
|
|
$mappings |
179
|
|
|
); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
return self::$globalMappings; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Determine whether or not a parameter is mapped to special request data. |
187
|
|
|
* |
188
|
|
|
* @param string $name The name of the parameter to check. |
189
|
|
|
* @return bool Returns true if the parameter is mapped, false otherwise. |
190
|
|
|
*/ |
191
|
10 |
|
protected function isMapped($name) { |
192
|
10 |
|
$name = strtolower($name); |
193
|
10 |
|
return isset($this->mappings[$name]) || isset(self::$globalMappings[$name]); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Get the mapped data for a parameter. |
198
|
|
|
* |
199
|
|
|
* @param string $name The name of the parameter. |
200
|
|
|
* @param Request $request The {@link Request} to get the data from. |
201
|
|
|
* @return array|null Returns the mapped data or null if there is no data. |
202
|
|
|
*/ |
203
|
2 |
|
protected function mappedData($name, Request $request) { |
204
|
2 |
|
$name = strtolower($name); |
205
|
|
|
|
206
|
2 |
|
if (isset($this->mappings[$name])) { |
207
|
|
|
$mapping = $this->mappings[$name]; |
208
|
2 |
|
} elseif (isset(self::$globalMappings[$name])) { |
209
|
2 |
|
$mapping = self::$globalMappings[$name]; |
210
|
|
|
} else { |
211
|
|
|
return null; |
212
|
|
|
} |
213
|
|
|
|
214
|
2 |
|
switch (strtolower($mapping)) { |
215
|
2 |
|
case self::MAP_DATA: |
216
|
|
|
$result = $request->getData(); |
217
|
|
|
break; |
218
|
2 |
|
case self::MAP_INPUT: |
219
|
2 |
|
$result = $request->getInput(); |
220
|
2 |
|
break; |
221
|
|
|
case self::MAP_QUERY: |
222
|
|
|
$result = $request->getQuery(); |
223
|
|
|
break; |
224
|
|
|
default: |
225
|
|
|
return null; |
226
|
|
|
} |
227
|
2 |
|
return $result; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Try matching a route to a request. |
232
|
|
|
* |
233
|
|
|
* @param Request $request The request to match the route with. |
234
|
|
|
* @param Application $app The application instantiating the route. |
235
|
|
|
* @return array|null Whether or not the route matches the request. |
236
|
|
|
* If the route matches an array of args is returned, otherwise the function returns null. |
237
|
|
|
*/ |
238
|
|
|
abstract public function matches(Request $request, Application $app); |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Tests whether or not a route matches the allowed methods for this route. |
242
|
|
|
* |
243
|
|
|
* @param Request $request The request to test. |
244
|
|
|
* @return bool Returns `true` if the route allows the method, otherwise `false`. |
245
|
|
|
*/ |
246
|
44 |
|
protected function matchesMethods(Request $request) { |
247
|
44 |
|
if (empty($this->methods)) { |
248
|
43 |
|
return true; |
249
|
|
|
} |
250
|
1 |
|
return in_array($request->getMethod(), $this->methods); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* Gets or sets the route pattern. |
255
|
|
|
* |
256
|
|
|
* @param string|null $pattern The route pattern. |
257
|
|
|
* @return string Returns the pattern. |
258
|
|
|
*/ |
259
|
44 |
|
public function pattern($pattern = null) { |
260
|
44 |
|
if ($pattern !== null) { |
261
|
44 |
|
$this->pattern = '/'.ltrim($pattern, '/'); |
262
|
|
|
} |
263
|
44 |
|
return $this->pattern; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Get whether or not to match the path with the extension. |
268
|
|
|
* |
269
|
|
|
* @return boolean Returns **true** if the path should be matched with the file extension or **false** otherwise. |
270
|
|
|
*/ |
271
|
44 |
|
public function getMatchFullPath() { |
272
|
44 |
|
return $this->matchFullPath; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Set whether or not to match the path with the extension. |
277
|
|
|
* |
278
|
|
|
* @param boolean $matchFullPath The new value for the property. |
279
|
|
|
* @return Route Returns `$this` for fluent calls. |
280
|
|
|
*/ |
281
|
1 |
|
public function setMatchFullPath($matchFullPath) { |
282
|
1 |
|
$this->matchFullPath = $matchFullPath; |
283
|
1 |
|
return $this; |
284
|
|
|
} |
285
|
|
|
} |
286
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.