1 | <?php |
||
44 | abstract class AbstractRoute |
||
45 | { |
||
46 | /** @const string Identifier for catch-all parameters in a route path */ |
||
47 | const CATCHALL_IDENTIFIER = '/**'; |
||
48 | /** @const string Identifier for normal parameters in a route path */ |
||
49 | const PARAM_IDENTIFIER = '/*'; |
||
50 | /** @const string Quoted version of the normal parameter identifier */ |
||
51 | const QUOTED_PARAM_IDENTIFIER = '/\*'; |
||
52 | /** @const string A regular expression that cathes from a / to the end */ |
||
53 | const REGEX_CATCHALL = '(/.*)?'; |
||
54 | /** @const string A regular expression that cathes one parameter */ |
||
55 | const REGEX_SINGLE_PARAM = '/([^/]+)'; |
||
56 | /** @const string A regular expression that cathes one ending parameter */ |
||
57 | const REGEX_ENDING_PARAM = '#/\(\[\^/\]\+\)#'; |
||
58 | /** @const string A regular expression that cathes one optional parameter */ |
||
59 | const REGEX_OPTIONAL_PARAM = '(?:/([^/]+))?'; |
||
60 | /** @const string A regular expression that identifies invalid parameters */ |
||
61 | const REGEX_INVALID_OPTIONAL_PARAM = '#\(\?\:/\(\[\^/\]\+\)\)\?/#'; |
||
62 | |||
63 | /** @var string The HTTP method for this route (GET, POST, ANY, etc) */ |
||
64 | public $method = ''; |
||
65 | /** @var string The pattern for this route (like /users/*) */ |
||
66 | public $pattern = ''; |
||
67 | /** @var string The generated regex to match the route pattern */ |
||
68 | public $regexForMatch = ''; |
||
69 | /** |
||
70 | * @var string The generated regex for creating URIs from parameters |
||
71 | * @see Respect\Rest\AbstractRoute::createURI |
||
72 | */ |
||
73 | public $regexForReplace = ''; |
||
74 | /** |
||
75 | * @var array A list of routines appended to this route |
||
76 | * @see Respect\Rest\Routines\AbstractRoutine |
||
77 | */ |
||
78 | public $routines = array(); |
||
79 | /** |
||
80 | * @var array A list of side routes to be used |
||
81 | * @see Respect\Rest\Routes\AbstractRoute |
||
82 | */ |
||
83 | public $sideRoutes = array(); |
||
84 | |||
85 | /** @var array A virtualhost applied to this route (deprecated) */ |
||
86 | public $virtualHost = null; |
||
87 | |||
88 | /** |
||
89 | * Returns the RelfectionFunctionAbstract object for the passed method |
||
90 | * |
||
91 | * @param string $method The HTTP method (GET, POST, etc) |
||
92 | */ |
||
93 | abstract public function getReflection($method); |
||
94 | |||
95 | /** |
||
96 | * Runs the target method/params into this route |
||
97 | * |
||
98 | * @param string $method The HTTP method (GET, POST, etc) |
||
99 | * @param array $params A list of params to pass to the target |
||
100 | */ |
||
101 | abstract public function runTarget($method, &$params); |
||
102 | |||
103 | /** |
||
104 | * @param string $method The HTTP method (GET, POST, etc) |
||
105 | * @param string $pattern The pattern for this route path |
||
106 | */ |
||
107 | 130 | public function __construct($method, $pattern) |
|
115 | |||
116 | /** |
||
117 | * A magic routine builder and composite appender |
||
118 | * |
||
119 | * @param string $method The HTTP method (GET, POST, etc) |
||
120 | * @param array $arguments Arguments to pass to this routine constructor |
||
121 | * @see Respect\Rest\Routes\AbstractRoute::appendRoutine |
||
122 | * |
||
123 | * @return AbstractRoute The route itselt |
||
124 | */ |
||
125 | 54 | public function __call($method, $arguments) |
|
126 | { |
||
127 | 54 | $reflection = new ReflectionClass( |
|
128 | 54 | 'Respect\\Rest\\Routines\\'.ucfirst($method) |
|
129 | ); |
||
130 | |||
131 | 54 | return $this->appendRoutine($reflection->newInstanceArgs($arguments)); |
|
132 | } |
||
133 | |||
134 | /** |
||
135 | * Appends a pre-built routine to this route |
||
136 | * |
||
137 | * @param Routinable $routine A routine to be appended |
||
138 | * @see Respect\Rest\Routes\AbstractRoute::__call |
||
139 | * |
||
140 | * @return AbstractRoute The route itselt |
||
141 | */ |
||
142 | 56 | public function appendRoutine(Routinable $routine) |
|
143 | { |
||
144 | 56 | $key = $routine instanceof Unique |
|
145 | 43 | ? get_class($routine) |
|
146 | 56 | : spl_object_hash($routine); |
|
147 | |||
148 | 56 | $this->routines[$key] = $routine; |
|
149 | |||
150 | 56 | return $this; |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * Creates an URI for this route with the passed parameters, replacing |
||
155 | * them in the declared pattern. /hello/* with ['tom'] returns /hello/tom |
||
156 | * |
||
157 | * @param mixed $param1 Some parameter |
||
158 | * @param mixed $etc This route accepts as many parameters you can pass |
||
159 | * |
||
160 | * @see Respect\Rest\Request::$params |
||
161 | * |
||
162 | * @return string the created URI |
||
163 | */ |
||
164 | 1 | public function createUri($param1 = null, $etc = null) |
|
173 | |||
174 | /** |
||
175 | * Passes a request through all this routes ProxyableWhen routines |
||
176 | * |
||
177 | * @param Request $request The request you want to process |
||
178 | * @param array $params Parameters for the processed request |
||
179 | * @see Respect\Rest\Routines\ProxyableWhen |
||
180 | * |
||
181 | * @see Respect\Rest\Request::$params |
||
182 | * |
||
183 | * @return bool always true \,,/ |
||
184 | */ |
||
185 | 114 | public function matchRoutines(Request $request, $params = array()) |
|
201 | |||
202 | /** |
||
203 | * Checks if a request passes for this route |
||
204 | * |
||
205 | * @param Request $request The request you want to process |
||
206 | * @param array $params Parameters for the processed request |
||
207 | * |
||
208 | * @see Respect\Rest\Request::$params |
||
209 | * |
||
210 | * @return bool as true as xkcd (always true) |
||
211 | */ |
||
212 | 121 | public function match(Request $request, &$params = array()) |
|
213 | { |
||
214 | 121 | $params = array(); |
|
215 | 121 | $matchUri = $request->uri; |
|
216 | |||
217 | 121 | foreach ($this->routines as $routine) { |
|
218 | 56 | if ($routine instanceof IgnorableFileExtension) { |
|
219 | 37 | $matchUri = preg_replace( |
|
220 | 37 | '#(\.[\w\d\-_.~\+]+)*$#', |
|
221 | 37 | '', |
|
222 | 37 | $request->uri |
|
223 | ); |
||
224 | } |
||
225 | } |
||
226 | |||
227 | 121 | if (!preg_match($this->regexForMatch, $matchUri, $params)) { |
|
228 | 19 | return false; |
|
229 | } |
||
230 | |||
231 | 119 | array_shift($params); |
|
232 | |||
233 | if ( |
||
234 | 119 | false !== stripos($this->pattern, '/**') |
|
235 | 119 | && false !== stripos(end($params), '/') |
|
236 | ) { |
||
237 | 5 | $lastParam = array_pop($params); |
|
238 | 5 | $params[] = explode('/', ltrim($lastParam, '/')); |
|
239 | } elseif ( |
||
240 | 115 | false !== stripos($this->pattern, '/**') && !isset($params[0]) |
|
241 | ) { |
||
242 | 2 | $params[] = array(); // callback expects a parameter give it |
|
243 | } |
||
244 | |||
245 | 119 | return true; |
|
246 | } |
||
247 | |||
248 | /** |
||
249 | * This creates a regular expression that matches a route pattern and |
||
250 | * extracts it's parameters |
||
251 | * |
||
252 | * @param string $pattern The pattern for the regex creation |
||
253 | * |
||
254 | * @return array A matcher regex and a replacer regex for createUri() |
||
255 | */ |
||
256 | 130 | protected function createRegexPatterns($pattern) |
|
279 | |||
280 | /** |
||
281 | * Extracts the catch-all parameter from a pattern and modifies the passed |
||
282 | * parameter to remove that. Yes, we're modifying by reference. |
||
283 | * |
||
284 | * @param string $pattern The pattern for the regex creation |
||
285 | * |
||
286 | * @return string The catch-all parameter or empty string |
||
287 | */ |
||
288 | 130 | protected function extractCatchAllPattern(&$pattern) |
|
309 | |||
310 | /** |
||
311 | * Identifies using regular expressions a sequence of parameters in the end |
||
312 | * of a pattern and make the latest ones optional for the matcher regex |
||
313 | * |
||
314 | * @param string $quotedPattern a preg_quoted route pattern |
||
315 | */ |
||
316 | 130 | protected function fixOptionalParams($quotedPattern) |
|
337 | } |
||
338 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.