Skip to content

Commit 8294d20

Browse files
authored
Merge pull request #3069 from ddrv-fork/array-routes
Classname/Method Callable Arrays
2 parents 090498e + 2b8774e commit 8294d20

2 files changed

Lines changed: 63 additions & 6 deletions

File tree

Slim/CallableResolver.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function __construct(?ContainerInterface $container = null)
5151
*/
5252
public function resolve($toResolve): callable
5353
{
54+
$toResolve = $this->prepareToResolve($toResolve);
5455
if (is_callable($toResolve)) {
5556
return $this->bindToContainer($toResolve);
5657
}
@@ -90,6 +91,7 @@ public function resolveMiddleware($toResolve): callable
9091
*/
9192
private function resolveByPredicate($toResolve, callable $predicate, string $defaultMethod): callable
9293
{
94+
$toResolve = $this->prepareToResolve($toResolve);
9395
if (is_callable($toResolve)) {
9496
return $this->bindToContainer($toResolve);
9597
}
@@ -144,6 +146,9 @@ private function resolveSlimNotation(string $toResolve): array
144146
$instance = $this->container->get($class);
145147
} else {
146148
if (!class_exists($class)) {
149+
if ($method) {
150+
$class .= '::' . $method . '()';
151+
}
147152
throw new RuntimeException(sprintf('Callable %s does not exist', $class));
148153
}
149154
$instance = new $class($this->container);
@@ -187,4 +192,22 @@ private function bindToContainer(callable $callable): callable
187192
}
188193
return $callable;
189194
}
195+
196+
/**
197+
* @param string|callable $toResolve
198+
* @return string|callable
199+
*/
200+
private function prepareToResolve($toResolve)
201+
{
202+
if (!is_array($toResolve)) {
203+
return $toResolve;
204+
}
205+
$candidate = $toResolve;
206+
$class = array_shift($candidate);
207+
$method = array_shift($candidate);
208+
if (is_string($class) && is_string($method)) {
209+
return $class . ':' . $method;
210+
}
211+
return $toResolve;
212+
}
190213
}

tests/CallableResolverTest.php

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ public function testSlimCallable()
133133
$this->assertEquals(3, CallableTest::$CalledCount);
134134
}
135135

136+
public function testSlimCallableAsArray()
137+
{
138+
$resolver = new CallableResolver(); // No container injected
139+
$callable = $resolver->resolve([CallableTest::class, 'toCall']);
140+
$callableRoute = $resolver->resolveRoute([CallableTest::class, 'toCall']);
141+
$callableMiddleware = $resolver->resolveMiddleware([CallableTest::class, 'toCall']);
142+
143+
$callable();
144+
$this->assertEquals(1, CallableTest::$CalledCount);
145+
146+
$callableRoute();
147+
$this->assertEquals(2, CallableTest::$CalledCount);
148+
149+
$callableMiddleware();
150+
$this->assertEquals(3, CallableTest::$CalledCount);
151+
}
152+
136153
public function testSlimCallableContainer()
137154
{
138155
/** @var ContainerInterface $container */
@@ -150,6 +167,23 @@ public function testSlimCallableContainer()
150167
$this->assertEquals($container, CallableTest::$CalledContainer);
151168
}
152169

170+
public function testSlimCallableAsArrayContainer()
171+
{
172+
/** @var ContainerInterface $container */
173+
$container = $this->containerProphecy->reveal();
174+
$resolver = new CallableResolver($container);
175+
$resolver->resolve([CallableTest::class, 'toCall']);
176+
$this->assertEquals($container, CallableTest::$CalledContainer);
177+
178+
CallableTest::$CalledContainer = null;
179+
$resolver->resolveRoute([CallableTest::class, 'toCall']);
180+
$this->assertEquals($container, CallableTest::$CalledContainer);
181+
182+
CallableTest::$CalledContainer = null;
183+
$resolver->resolveMiddleware([CallableTest::class ,'toCall']);
184+
$this->assertEquals($container, CallableTest::$CalledContainer);
185+
}
186+
153187
public function testContainer()
154188
{
155189
$this->containerProphecy->has('callable_service')->willReturn(true);
@@ -441,7 +475,7 @@ public function testMiddlewareFunctionNotFoundThrowException()
441475
public function testClassNotFoundThrowException()
442476
{
443477
$this->expectException(RuntimeException::class);
444-
$this->expectExceptionMessage('Callable Unknown does not exist');
478+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
445479

446480
/** @var ContainerInterface $container */
447481
$container = $this->containerProphecy->reveal();
@@ -452,7 +486,7 @@ public function testClassNotFoundThrowException()
452486
public function testRouteClassNotFoundThrowException()
453487
{
454488
$this->expectException(RuntimeException::class);
455-
$this->expectExceptionMessage('Callable Unknown does not exist');
489+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
456490

457491
/** @var ContainerInterface $container */
458492
$container = $this->containerProphecy->reveal();
@@ -463,7 +497,7 @@ public function testRouteClassNotFoundThrowException()
463497
public function testMiddlewareClassNotFoundThrowException()
464498
{
465499
$this->expectException(RuntimeException::class);
466-
$this->expectExceptionMessage('Callable Unknown does not exist');
500+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
467501

468502
/** @var ContainerInterface $container */
469503
$container = $this->containerProphecy->reveal();
@@ -474,7 +508,7 @@ public function testMiddlewareClassNotFoundThrowException()
474508
public function testCallableClassNotFoundThrowException()
475509
{
476510
$this->expectException(RuntimeException::class);
477-
$this->expectExceptionMessage('is not resolvable');
511+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
478512

479513
/** @var ContainerInterface $container */
480514
$container = $this->containerProphecy->reveal();
@@ -485,7 +519,7 @@ public function testCallableClassNotFoundThrowException()
485519
public function testRouteCallableClassNotFoundThrowException()
486520
{
487521
$this->expectException(RuntimeException::class);
488-
$this->expectExceptionMessage('is not resolvable');
522+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
489523

490524
/** @var ContainerInterface $container */
491525
$container = $this->containerProphecy->reveal();
@@ -496,7 +530,7 @@ public function testRouteCallableClassNotFoundThrowException()
496530
public function testMiddlewareCallableClassNotFoundThrowException()
497531
{
498532
$this->expectException(RuntimeException::class);
499-
$this->expectExceptionMessage('is not resolvable');
533+
$this->expectExceptionMessage('Callable Unknown::notFound() does not exist');
500534

501535
/** @var ContainerInterface $container */
502536
$container = $this->containerProphecy->reveal();

0 commit comments

Comments
 (0)