Skip to content

Commit aa5379f

Browse files
authored
Fix #61: Add support callable middlewares (#69)
1 parent 6915ff1 commit aa5379f

File tree

4 files changed

+71
-15
lines changed

4 files changed

+71
-15
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- Chg #68: Remove wrapper factory (@rustamwin)
66
- New #68: Add `ParametersResolverInterface` to resolve parameters of middleware that are provided as callable (@rustamwin)
7+
- Enh #69: Add support for callable middlewares (@rustamwin)
8+
- Enh #69: Add debug info to callable wrapper (@rustamwin)
79

810
## 4.0.0 November 10, 2022
911

src/MiddlewareFactory.php

+13-7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public function __construct(
4444
* - A callable with
4545
* `function(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface`
4646
* signature.
47+
* - Any callable.
4748
* - A controller handler action in format `[TestController::class, 'index']`. `TestController` instance will
4849
* be created and `index()` method will be executed.
4950
* - A function returning a middleware. The middleware returned will be executed.
@@ -87,11 +88,11 @@ private function isMiddlewareClassDefinition(array|callable|string $definition):
8788
}
8889

8990
/**
90-
* @psalm-assert-if-true array{0:class-string, 1:non-empty-string}|Closure $definition
91+
* @psalm-assert-if-true array{0:class-string, 1:non-empty-string}|callable $definition
9192
*/
9293
private function isCallableDefinition(array|callable|string $definition): bool
9394
{
94-
if ($definition instanceof Closure) {
95+
if (is_callable($definition)) {
9596
return true;
9697
}
9798

@@ -125,15 +126,15 @@ private function isArrayDefinition(array|callable|string $definition): bool
125126
}
126127

127128
/**
128-
* @param array{0:class-string, 1:non-empty-string}|Closure $callable
129+
* @param array{0:class-string, 1:non-empty-string}|callable $callable
129130
*/
130-
private function wrapCallable(array|Closure $callable): MiddlewareInterface
131+
private function wrapCallable(array|callable $callable): MiddlewareInterface
131132
{
132-
if (is_array($callable)) {
133-
return $this->createActionWrapper($callable[0], $callable[1]);
133+
if (is_callable($callable)) {
134+
return $this->createCallableWrapper($callable);
134135
}
135136

136-
return $this->createCallableWrapper($callable);
137+
return $this->createActionWrapper($callable[0], $callable[1]);
137138
}
138139

139140
private function createCallableWrapper(callable $callback): MiddlewareInterface
@@ -171,6 +172,11 @@ public function process(
171172
throw new InvalidMiddlewareDefinitionException($this->callback);
172173
}
173174

175+
public function __debugInfo(): array
176+
{
177+
return ['callback' => $this->callback];
178+
}
179+
174180
/**
175181
* @return \ReflectionParameter[]
176182
*/

tests/MiddlewareFactoryTest.php

+40-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Yiisoft\Middleware\Dispatcher\InvalidMiddlewareDefinitionException;
1616
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
1717
use Yiisoft\Middleware\Dispatcher\ParametersResolverInterface;
18+
use Yiisoft\Middleware\Dispatcher\Tests\Support\InvokeableAction;
1819
use Yiisoft\Middleware\Dispatcher\Tests\Support\SimpleParametersResolver;
1920
use Yiisoft\Middleware\Dispatcher\Tests\Support\UseParamsController;
2021
use Yiisoft\Middleware\Dispatcher\Tests\Support\UseParamsMiddleware;
@@ -110,6 +111,45 @@ public function testCreateFromClosureWithResolver(): void
110111
);
111112
}
112113

114+
public function testCreateCallableFromArrayWithInstance(): void
115+
{
116+
$container = $this->getContainer();
117+
$controller = new TestController();
118+
$middleware = $this
119+
->getMiddlewareFactory($container)
120+
->create([$controller, 'index']);
121+
self::assertSame(
122+
'yii',
123+
$middleware
124+
->process(
125+
$this->createMock(ServerRequestInterface::class),
126+
$this->createMock(RequestHandlerInterface::class)
127+
)
128+
->getHeaderLine('test')
129+
);
130+
self::assertSame(
131+
[$controller, 'index'],
132+
$middleware->__debugInfo()['callback']
133+
);
134+
}
135+
136+
public function testCreateCallableObject(): void
137+
{
138+
$container = $this->getContainer();
139+
$middleware = $this
140+
->getMiddlewareFactory($container)
141+
->create(new InvokeableAction());
142+
self::assertSame(
143+
'yii',
144+
$middleware
145+
->process(
146+
$this->createMock(ServerRequestInterface::class),
147+
$this->createMock(RequestHandlerInterface::class)
148+
)
149+
->getHeaderLine('test')
150+
);
151+
}
152+
113153
public function testCreateFromClosureMiddleware(): void
114154
{
115155
$container = $this->getContainer([TestController::class => new TestController()]);
@@ -259,14 +299,6 @@ public function testInvalidMiddlewareWithWrongArrayType(): void
259299
->create(['class' => TestController::class, 'index']);
260300
}
261301

262-
public function testInvalidMiddlewareWithWrongArrayWithInstance(): void
263-
{
264-
$this->expectException(InvalidMiddlewareDefinitionException::class);
265-
$this
266-
->getMiddlewareFactory()
267-
->create([new TestController(), 'index']);
268-
}
269-
270302
public function testInvalidMiddlewareWithWrongArrayWithIntItems(): void
271303
{
272304
$this->expectException(InvalidMiddlewareDefinitionException::class);

tests/Support/InvokeableAction.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Middleware\Dispatcher\Tests\Support;
6+
7+
use Nyholm\Psr7\Response;
8+
use Psr\Http\Message\ResponseInterface;
9+
10+
final class InvokeableAction
11+
{
12+
public function __invoke(): ResponseInterface
13+
{
14+
return new Response(200, ['test' => 'yii']);
15+
}
16+
}

0 commit comments

Comments
 (0)