8000 Merge pull request #14 from symfony-cmf/chain-match-request · dawehner/symfony@ae2693c · GitHub
[go: up one dir, main page]

Skip to content

Commit ae2693c

Browse files
committed
Merge pull request symfony#14 from symfony-cmf/chain-match-request
use the new matchRequest of symfony 2.1 for the chain router
2 parents c00d656 + 959a762 commit ae2693c

File tree

2 files changed

+177
-5
lines changed

2 files changed

+177
-5
lines changed

ChainRouter.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
namespace Symfony\Cmf\Component\Routing;
44

55
use Symfony\Component\Routing\RouterInterface;
6+
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
67
use Symfony\Component\Routing\RequestContext;
78
use Symfony\Component\Routing\RequestContextAwareInterface;
89
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
910
use Symfony\Component\Routing\Exception\RouteNotFoundException;
1011
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
1112
use Symfony\Component\Routing\RouteCollection;
13+
use Symfony\Component\HttpFoundation\Request;
1214
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
1315
use Symfony\Component\HttpKernel\Log\LoggerInterface;
1416

@@ -20,7 +22,7 @@
2022
* @author Henrik Bjornskov <henrik@bjrnskov.dk>
2123
* @author Magnus Nordlander <magnus@e-butik.se>
2224
*/
23-
class ChainRouter implements RouterInterface, WarmableInterface
25+
class ChainRouter implements RouterInterface, RequestMatcherInterface, WarmableInterface
2426
{
2527
/**
2628
* @var \Symfony\Component\Routing\RequestContext
@@ -106,6 +108,8 @@ protected function sortRouters()
106108
/**
107109
* Loops through all routes and tries to match the passed url.
108110
*
111+
* Note: You should use matchRequest if you can.
112+
*
109113
* @param string $url
110114
* @throws ResourceNotFoundException $e
111115
* @throws MethodNotAllowedException $e
@@ -115,17 +119,18 @@ public function match($url)
115119
{
116120
$methodNotAllowed = null;
117121

122+
/** @var $router RouterInterface */
118123
foreach ($this->all() as $router) {
119124
try {
120125
return $router->match($url);
121126
} catch (ResourceNotFoundException $e) {
122127
if ($this->logger) {
123-
$this->logger->addInfo('Router '.get_class($router).' was not able to match, message "'.$e->getMessage().'"');
128+
$this->logger->info('Router '.get_class($router).' was not able to match, message "'.$e->getMessage().'"');
124129
}
125130
// Needs special care
126131
} catch (MethodNotAllowedException $e) {
127132
if ($this->logger) {
128-
$this->logger->addInfo('Router '.get_class($router).' throws MethodNotAllowedException with message "'.$e->getMessage().'"');
133+
$this->logger->info('Router '.get_class($router).' throws MethodNotAllowedException with message "'.$e->getMessage().'"');
129134
}
130135
$methodNotAllowed = $e;
131136
}
@@ -134,6 +139,44 @@ public function match($url)
134139
throw $methodNotAllowed ?: new ResourceNotFoundException("None of the routers in the chain matched '$url'");
135140
}
136141

142+
/**
143+
* Loops through all routes and tries to match the passed request.
144+
*
145+
* @param Request $request the request to match
146+
*
147+
* @throws ResourceNotFoundException $e
148+
* @throws MethodNotAllowedException $e
149+
*
150+
* @return array
151+
*/
152+
public function matchRequest(Request $request)
153+
{
154+
$methodNotAllowed = null;
155+
156+
foreach ($this->all() as $router) {
157+
try {
158+
// the request/url match logic is the same as in Symfony/Component/HttpKernel/EventListener/RouterListener.php
159+
// matching requests is more powerful than matching URLs only, so try that first
160+
if ($router instanceof RequestMatcherInterface) {
161+
return $router->matchRequest($request);
162+
}
163+
return $router->match($request->getPathInfo());
164+
} catch (ResourceNotFoundException $e) {
165+
if ($this->logger) {
166+
$this->logger->info('Router '.get_class($router).' was not able to match, message "'.$e->getMessage().'"');
167+
}
168+
// Needs special care
169+
} catch (MethodNotAllowedException $e) {
170+
if ($this->logger) {
171+
$this->logger->info('Router '.get_class($router).' throws MethodNotAllowedException with message "'.$e->getMessage().'"');
172+
}
173+
$methodNotAllowed = $e;
174+
}
175+
}
176+
177+
throw $methodNotAllowed ?: new ResourceNotFoundException("None of the routers in the chain matched this request");
178+
}
179+
137180
/**
138181
* Loops through all registered routers and returns a router if one is found.
139182
* It will always return the first route generated.
@@ -151,7 +194,7 @@ public function generate($name, $parameters = array(), $absolute = false)
151194
return $router->generate($name, $parameters, $absolute);
152195
} catch (RouteNotFoundException $e) {
153196
if ($this->logger) {
154-
$this->logger->addInfo($e->getMessage());
197+
$this->logger->info($e->getMessage());
155198
}
156199
}
157200
}

Tests/Routing/ChainRouterTest.php

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Symfony\Cmf\Component\Routing\Tests\Routing;
44

55
use Symfony\Component\Routing\RouteCollection;
6+
use Symfony\Component\HttpFoundation\Request;
67

78
use Symfony\Cmf\Component\Routing\ChainRouter;
89
use Symfony\Cmf\Component\Routing\Test\CmfUnitTestCase;
@@ -11,7 +12,7 @@ class ChainRouterTest extends CmfUnitTestCase
1112
{
1213
public function setUp()
1314
{
14-
$this->router = new ChainRouter();
15+
$this->router = new ChainRouter($this->getMock('Symfony\Component\HttpKernel\Log\LoggerInterface'));
1516
$this->context = $this->getMock('Symfony\\Component\\Routing\\RequestContext');
1617
}
1718

@@ -163,6 +164,49 @@ public function testMatch()
163164
$this->assertEquals(array('test'), $result);
164165
}
165166

167+
/**
168+
* The first usable match is used, no further routers are queried once a match is found
169+
*/
170+
public function testMatchRequest()
171+
{
172+
$url = '/test';
173+
list($lower, $low, $high) = $this->createRouterMocks();
174+
175+
$highest = $this->getMock('Symfony\\Cmf\\Component\\Routing\\Tests\\Routing\\RequestMatcher');
176+
177+
$request = Request::create('/test');
178+
179+
$highest
180+
->expects($this->once())
181+
->method('matchRequest')
182+
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException))
183+
;
184+
$high
185+
->expects($this->once())
186+
->method('match')
187+
->with($url)
188+
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException))
189+
;
190+
$low
191+
->expects($this->once())
192+
->method('match')
193+
->with($url)
194+
->will($this->returnValue(array('test')))
195+
;
196+
$lower
197+
->expects($this->never())
198+
->method('match')
199+
;
200+
201+
$this->router->add($lower, 5);
202+
$this->router->add($low, 10);
203+
$this->router->add($high, 100);
204+
$this->router->add($highest, 200);
205+
206+
$result = $this->router->matchRequest($request);
207+
$this->assertEquals(array('test'), $result);
208+
}
209+
166210
/**
167211
* If there is a method not allowed but another router matches, that one is used
168212
*/
@@ -190,6 +234,33 @@ public function testMatchAndNotAllowed()
190234
$this->assertEquals(array('test'), $result);
191235
}
192236

237+
/**
238+
* If there is a method not allowed but another router matches, that one is used
239+
*/
240+
public function testMatchRequestAndNotAllowed()
241+
{
242+
$url = '/test';
243+
list($low, $high) = $this->createRouterMocks();
244+
245+
$high
246+
->expects($this->once())
247+
->method('match')
248+
->with($url)
249+
->will($this->throwException(new \Symfony\Component\Routing\Exception\MethodNotAllowedException(array())))
250+
;
251+
$low
252+
->expects($this->once())
253+
->method('match')
254+
->with($url)
255+
->will($this->returnValue(array('test')))
256+
;
257+
$this->router->add($low, 10);
258+
$this->router->add($high, 100);
259+
260+
$result = $this->router->matchRequest(Request::create('/test'));
261+
$this->assertEquals(array('test'), $result);
262+
}
263+
193264
/**
194265
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
195266
*/
@@ -216,6 +287,32 @@ public function testMatchNotFound()
216287
$this->router->match('/test');
217288
}
218289

290+
/**
291+
* @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
292+
*/
293+
public function testMatchRequestNotFound()
294+
{
295+
$url = '/test';
296+
list($low, $high) = $this->createRouterMocks();
297+
298+
$high
299+
->expects($this->once())
300+
->method('match')
301+
->with($url)
302+
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException))
303+
;
304+
$low
305+
->expects($this->once())
306+
->method('match')
307+
->with($url)
308+
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException))
309+
;
310+
$this->router->add($low, 10);
311+
$this->router->add($high, 100);
312+
313+
$this->router->matchRequest(Request::create('/test'));
314+
}
315+
219316
/**
220317
* If any of the routers throws a not allowed exception and no other matches, we need to see this
221318
*
@@ -244,6 +341,34 @@ public function testMatchMethodNotAllowed()
244341
$this->router->match('/test');
245342
}
246343

344+
/**
345+
* If any of the routers throws a not allowed exception and no other matches, we need to see this
346+
*
347+
* @expectedException \Symfony\Component\Routing\Exception\MethodNotAllowedException
348+
*/
349+
public function testMatchRequestMethodNotAllowed()
350+
{
351+
$url = '/test';
352+
list($low, $high) = $this->createRouterMocks();
353+
354+
$high
355+
->expects($this->once())
356+
->method('match')
357+
->with($url)
358+
->will($this->throwException(new \Symfony\Component\Routing\Exception\MethodNotAllowedException(array())))
359+
;
360+
$low
361+
->expects($this->once())
362+
->method('match')
363+
->with($url)
364+
->will($this->throwException(new \Symfony\Component\Routing\Exception\ResourceNotFoundException))
365+
;
366+
$this->router->add($low, 10);
367+
$this->router->add($high, 100);
368+
369+
$this->router->matchRequest(Request::create('/test'));
370+
}
371+
247372
public function testGenerate()
248373
{
249374
$url = '/test';
@@ -371,3 +496,7 @@ protected function createRouterMocks()
371496
abstract class WarmableRouterMock implements \Symfony\Component\Routing\RouterInterface, \Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface
372497
{
373498
}
499+
500+
abstract class RequestMatcher implements \Symfony\Component\Routing\RouterInterface, \Symfony\Component\Routing\Matcher\RequestMatcherInterface
501+
{
502+
}

0 commit comments

Comments
 (0)
0