Skip to content

Commit 01aae23

Browse files
committed
Cache routes by action to avoid redundant O(N) iterations
1 parent d15edaf commit 01aae23

2 files changed

Lines changed: 31 additions & 13 deletions

File tree

src/Codeception/Module/Symfony/CacheTrait.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@ public function _getContainer(): ContainerInterface
3232
protected function getInternalDomains(): array
3333
{
3434
if (isset($this->state['internalDomains'])) {
35-
/** @var list<non-empty-string> $domains */
36-
$domains = $this->state['internalDomains'];
37-
38-
return $domains;
35+
/** @var list<non-empty-string> */
36+
return $this->state['internalDomains'];
3937
}
4038

4139
$domains = [];
@@ -48,12 +46,14 @@ protected function getInternalDomains(): array
4846
}
4947
}
5048

51-
return $this->state['internalDomains'] = array_values(array_unique($domains));
49+
/** @var list<non-empty-string> $domains */
50+
$domains = array_values(array_unique($domains));
51+
return $this->state['internalDomains'] = $domains;
5252
}
5353

54-
protected function clearInternalDomainsCache(): void
54+
protected function clearRouterCache(): void
5555
{
56-
unset($this->state['internalDomains']);
56+
unset($this->state['internalDomains'], $this->state['cachedRoutes']);
5757
}
5858

5959
/**
@@ -64,7 +64,6 @@ protected function clearInternalDomainsCache(): void
6464
*/
6565
protected function grabCachedService(string $expectedClass, array $serviceIds): ?object
6666
{
67-
/** @var ?string $serviceId */
6867
$serviceId = $this->state[$expectedClass] ??= (function () use ($serviceIds, $expectedClass): ?string {
6968
foreach ($serviceIds as $id) {
7069
if ($this->getService($id) instanceof $expectedClass) {
@@ -75,7 +74,7 @@ protected function grabCachedService(string $expectedClass, array $serviceIds):
7574
return null;
7675
})();
7776

78-
if ($serviceId === null) {
77+
if (!is_string($serviceId)) {
7978
return null;
8079
}
8180

src/Codeception/Module/Symfony/RouterAssertionsTrait.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function amOnRoute(string $routeName, array $params = []): void
5555
public function invalidateCachedRouter(): void
5656
{
5757
$this->unpersistService('router');
58-
$this->clearInternalDomainsCache();
58+
$this->clearRouterCache();
5959
}
6060

6161
/**
@@ -118,15 +118,34 @@ private function getCurrentRouteMatch(string $routeName): array
118118

119119
private function findRouteByActionOrFail(string $action): string
120120
{
121-
foreach ($this->grabRouterService()->getRouteCollection()->all() as $name => $route) {
122-
$ctrl = $route->getDefault('_controller');
123-
if (is_string($ctrl) && str_ends_with($ctrl, $action)) {
121+
foreach ($this->getCachedRoutes() as $ctrl => $name) {
122+
if (str_ends_with($ctrl, $action)) {
124123
return $name;
125124
}
126125
}
126+
127127
Assert::fail(sprintf("Action '%s' does not exist.", $action));
128128
}
129129

130+
/** @return array<string, string> */
131+
private function getCachedRoutes(): array
132+
{
133+
if (isset($this->state['cachedRoutes'])) {
134+
/** @var array<string, string> */
135+
return $this->state['cachedRoutes'];
136+
}
137+
138+
$routes = [];
139+
foreach ($this->grabRouterService()->getRouteCollection()->all() as $name => $route) {
140+
$ctrl = $route->getDefault('_controller');
141+
if (is_string($ctrl) && !isset($routes[$ctrl])) {
142+
$routes[$ctrl] = (string) $name;
143+
}
144+
}
145+
146+
return $this->state['cachedRoutes'] = $routes;
147+
}
148+
130149
private function assertRouteExists(string $routeName): void
131150
{
132151
$this->assertNotNull(

0 commit comments

Comments
 (0)