Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7d30407

Browse files
committed
Merge pull request symfony#11 from lolautruche/chainRouterSorting
Performance improvement: Ensures that routers sorting is being done only once in ChainRouter
2 parents 09455f7 + 546d9e6 commit 7d30407

2 files changed

Lines changed: 100 additions & 4 deletions

File tree

ChainRouter.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ class ChainRouter implements RouterInterface, WarmableInterface
2525
private $context;
2626
private $logger;
2727

28+
/**
29+
* @var \Symfony\Component\Routing\RouterInterface[] Array of routers, sorted by priority
30+
*/
31+
protected $sortedRouters;
32+
2833
public function __construct(LoggerInterface $logger = null)
2934
{
3035
$this->logger = $logger;
@@ -53,6 +58,7 @@ public function add(RouterInterface $router, $priority = 0)
5358
}
5459

5560
$this->routers[$priority][] = $router;
61+
$this->sortedRouters = array();
5662
}
5763

5864
/**
@@ -62,14 +68,29 @@ public function add(RouterInterface $router, $priority = 0)
6268
*/
6369
public function all()
6470
{
71+
if (empty($this->sortedRouters)) {
72+
$this->sortedRouters = $this->sortRouters();
73+
}
74+
75+
return $this->sortedRouters;
76+
}
77+
78+
/**
79+
* Sort routers by priority.
80+
* The highest priority number is the highest priority (reverse sorting)
81+
*
82+
* @return \Symfony\Component\Routing\RouterInterface[]
83+
*/
84+
protected function sortRouters()
85+
{
86+
$sortedRouters = array();
6587
krsort($this->routers);
66-
$routers = array();
6788

68-
foreach ($this->routers as $all) {
69-
$routers = array_merge($routers, $all);
89+
foreach ($this->routers as $routers) {
90+
$sortedRouters = array_merge($sortedRouters, $routers);
7091
}
7192

72-
return $routers;
93+
return $sortedRouters;
7394
}
7495

7596
/**

Tests/Routing/ChainRouterTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,81 @@ public function testPriority()
3030
), $this->router->all());
3131
}
3232

33+
/**
34+
* Routers are supposed to be sorted only once.
35+
* This test will check that by trying to get all routers several times.
36+
*
37+
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::sortRouters
38+
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::all
39+
*/
40+
public function testSortRouters()
41+
{
42+
list($low, $medium, $high) = $this->createRouterMocks();
43+
// We're using a mock here and not $this->router because we need to ensure that the sorting operation is done only once.
44+
$router = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\ChainRouter', array('sortRouters'));
45+
$router
46+
->expects($this->once())
47+
->method('sortRouters')
48+
->will(
49+
$this->returnValue(
50+
array($high, $medium, $low)
51+
)
52+
)
53+
;
54+
55+
$router->add($low, 10);
56+
$router->add($medium, 50);
57+
$router->add($high, 100);
58+
$expectedSortedRouters = array($high, $medium, $low);
59+
// Let's get all routers 5 times, we should only sort once.
60+
for ($i = 0; $i < 5; ++$i) {
61+
$this->assertSame($expectedSortedRouters, $router->all());
62+
}
63+
}
64+
65+
/**
66+
* This test ensures that if a router is being added on the fly, the sorting is reset.
67+
*
68+
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::sortRouters
69+
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::all
70+
* @covers \Symfony\Cmf\Component\Routing\ChainRouter::add
71+
*/
72+
public function testReSortRouters()
73+
{
74+
list($low, $medium, $high) = $this->createRouterMocks();
75+
$highest = clone $high;
76+
// We're using a mock here and not $this->router because we need to ensure that the sorting operation is done only once.
77+
$router = $this->buildMock('Symfony\\Cmf\\Component\\Routing\\ChainRouter', array('sortRouters'));
78+
$router
79+
->expects($this->at(0))
80+
->method('sortRouters')
81+
->will(
82+
$this->returnValue(
83+
array($high, $medium, $low)
84+
)
85+
)
86+
;
87+
// The second time sortRouters() is called, we're supposed to get the newly added router ($highest)
88+
$router
89+
->expects($this->at(1))
90+
->method('sortRouters')
91+
->will(
92+
$this->returnValue(
93+
array($highest, $high, $medium, $low)
94+
)
95+
)
96+
;
97+
98+
$router->add($low, 10);
99+
$router->add($medium, 50);
100+
$router->add($high, 100);
101+
$this->assertSame(array($high, $medium, $low), $router->all());
102+
103+
// Now adding another router on the fly, sorting must have been reset
104+
$router->add($highest, 101);
105+
$this->assertSame(array($highest, $high, $medium, $low), $router->all());
106+
}
107+
33108
/**
34109
* context must be propagated to chained routers and be stored locally
35110
*/

0 commit comments

Comments
 (0)