Skip to content

Commit 48d6305

Browse files
authored
Remove pipeline interface (#27)
1 parent 5762bfe commit 48d6305

7 files changed

+74
-98
lines changed

README.md

+36-8
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@ To use a dispatcher, you need to create it first:
3737
```php
3838
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
3939
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
40-
use Yiisoft\Middleware\Dispatcher\MiddlewareStack;
4140

4241
$dispatcher = new MiddlewareDispatcher(
4342
new MiddlewareFactory($diContainer),
44-
new MiddlewareStack($eventDispatcher)
43+
$eventDispatcher
4544
);
4645
```
4746

@@ -87,14 +86,43 @@ executed first. For each middleware
8786
`\Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware` and `\Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware`
8887
events are triggered.
8988

90-
### Customizing dispatcher
89+
### Customizing definition syntax
9190

92-
There are two possibilities customizing middleare dispatcher:
91+
Middleware definition syntax could be customized by providing your own `MiddlewareFactoryInterface` implementation:
9392

94-
1. Providing custom implementation of `MiddlewareFactoryInterface`. There you can introduce custom syntax for defining
95-
middleware or feed middleware created with additional data.
96-
2. Providing custom implementation of `MiddlewarePiplineInterface`. There you can customize in which order and
97-
how exactly middleware are executed.
93+
```php
94+
use \Yiisoft\Middleware\Dispatcher\MiddlewareFactoryInterface;
95+
96+
class CoolMiddlewareFactory implements MiddlewareFactoryInterface
97+
{
98+
private MiddlewareFactoryInterface $middlewareFactory;
99+
100+
public function __construct(MiddlewareFactoryInterface $middlewareFactory) {
101+
$this->middlewareFactory = $middlewareFactory;
102+
}
103+
104+
public function create($middlewareDefinition): MiddlewareInterface
105+
{
106+
if (is_string($middlewareDefinition) && strpos($middlewareDefinition, '@') === 0) {
107+
return createMiddleware($middlewareDefinition);
108+
}
109+
110+
$this->middlewareFactory->create($middlewareDefinition);
111+
}
112+
}
113+
```
114+
115+
Then it could be used like the following:
116+
117+
```php
118+
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
119+
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
120+
121+
$dispatcher = new MiddlewareDispatcher(
122+
new CoolMiddlewareFactory(new MiddlewareFactory($diContainer)),
123+
$eventDispatcher
124+
);
125+
```
98126

99127
## Testing
100128

config/web.php

-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44

55
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
66
use Yiisoft\Middleware\Dispatcher\MiddlewareFactoryInterface;
7-
use Yiisoft\Middleware\Dispatcher\MiddlewarePipelineInterface;
8-
use Yiisoft\Middleware\Dispatcher\MiddlewareStack;
97

108
return [
11-
MiddlewarePipelineInterface::class => MiddlewareStack::class,
129
MiddlewareFactoryInterface::class => MiddlewareFactory::class,
1310
];

src/MiddlewareDispatcher.php

+13-12
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Yiisoft\Middleware\Dispatcher;
66

7+
use Psr\EventDispatcher\EventDispatcherInterface;
78
use Psr\Http\Message\ResponseInterface;
89
use Psr\Http\Message\ServerRequestInterface;
910
use Psr\Http\Server\MiddlewareInterface;
@@ -14,21 +15,21 @@ final class MiddlewareDispatcher
1415
/**
1516
* Contains a middleware pipeline handler.
1617
*
17-
* @var MiddlewarePipelineInterface The middleware pipeline.
18+
* @var MiddlewareStack The middleware stack.
1819
*/
19-
private MiddlewarePipelineInterface $pipeline;
20-
20+
private ?MiddlewareStack $stack = null;
2121
private MiddlewareFactoryInterface $middlewareFactory;
22+
private EventDispatcherInterface $eventDispatcher;
2223

2324
/**
2425
* @var array[]|callable[]|string[]
2526
*/
2627
private array $middlewareDefinitions = [];
2728

28-
public function __construct(MiddlewareFactoryInterface $middlewareFactory, MiddlewarePipelineInterface $pipeline)
29+
public function __construct(MiddlewareFactoryInterface $middlewareFactory, EventDispatcherInterface $eventDispatcher)
2930
{
3031
$this->middlewareFactory = $middlewareFactory;
31-
$this->pipeline = $pipeline;
32+
$this->eventDispatcher = $eventDispatcher;
3233
}
3334

3435
/**
@@ -41,11 +42,11 @@ public function dispatch(
4142
ServerRequestInterface $request,
4243
RequestHandlerInterface $fallbackHandler
4344
): ResponseInterface {
44-
if ($this->pipeline->isEmpty()) {
45-
$this->pipeline = $this->pipeline->build($this->buildMiddlewares(), $fallbackHandler);
45+
if ($this->stack === null) {
46+
$this->stack = new MiddlewareStack($this->buildMiddlewares(), $fallbackHandler, $this->eventDispatcher);
4647
}
4748

48-
return $this->pipeline->handle($request);
49+
return $this->stack->handle($request);
4950
}
5051

5152
/**
@@ -70,11 +71,11 @@ public function dispatch(
7071
*/
7172
public function withMiddlewares(array $middlewareDefinitions): self
7273
{
73-
$clone = clone $this;
74-
$clone->middlewareDefinitions = $middlewareDefinitions;
75-
$clone->pipeline->reset();
74+
$new = clone $this;
75+
$new->middlewareDefinitions = $middlewareDefinitions;
76+
$new->stack = null;
7677

77-
return $clone;
78+
return $new;
7879
}
7980

8081
/**

src/MiddlewarePipelineInterface.php

-35
This file was deleted.

src/MiddlewareStack.php

+21-29
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use Yiisoft\Middleware\Dispatcher\Event\AfterMiddleware;
1414
use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware;
1515

16-
final class MiddlewareStack implements MiddlewarePipelineInterface
16+
final class MiddlewareStack implements RequestHandlerInterface
1717
{
1818
/**
1919
* Contains a stack of middleware wrapped in handlers.
@@ -22,55 +22,47 @@ final class MiddlewareStack implements MiddlewarePipelineInterface
2222
* @var RequestHandlerInterface|null stack of middleware
2323
*/
2424
private ?RequestHandlerInterface $stack = null;
25-
2625
private EventDispatcherInterface $eventDispatcher;
26+
private RequestHandlerInterface $fallbackHandler;
27+
private array $middlewares;
2728

2829
/**
30+
* @param MiddlewareInterface[] $middlewares Middlewares.
31+
* @param RequestHandlerInterface $fallbackHandler Fallback handler
2932
* @param EventDispatcherInterface $eventDispatcher Event dispatcher to use for triggering before/after middleware
3033
* events.
3134
*/
32-
public function __construct(EventDispatcherInterface $eventDispatcher)
33-
{
34-
$this->eventDispatcher = $eventDispatcher;
35-
}
36-
37-
public function build(array $middlewares, RequestHandlerInterface $fallbackHandler): MiddlewarePipelineInterface
35+
public function __construct(array $middlewares, RequestHandlerInterface $fallbackHandler, EventDispatcherInterface $eventDispatcher)
3836
{
39-
$handler = $fallbackHandler;
40-
foreach ($middlewares as $middleware) {
41-
$handler = $this->wrap($middleware, $handler);
37+
if ($middlewares === []) {
38+
throw new RuntimeException('Stack is empty.');
4239
}
4340

44-
$new = clone $this;
45-
$new->stack = $handler;
46-
47-
return $new;
41+
$this->middlewares = $middlewares;
42+
$this->fallbackHandler = $fallbackHandler;
43+
$this->eventDispatcher = $eventDispatcher;
4844
}
4945

5046
public function handle(ServerRequestInterface $request): ResponseInterface
5147
{
52-
if ($this->isEmpty()) {
53-
throw new RuntimeException('Stack is empty.');
48+
if ($this->stack === null) {
49+
$this->build();
5450
}
5551

5652
/** @psalm-suppress PossiblyNullReference */
5753
return $this->stack->handle($request);
5854
}
5955

60-
/**
61-
* Reset the stack.
62-
*/
63-
public function reset(): void
56+
private function build(): void
6457
{
65-
$this->stack = null;
66-
}
58+
$handler = $this->fallbackHandler;
6759

68-
/**
69-
* @return bool Whether stack is empty.
70-
*/
71-
public function isEmpty(): bool
72-
{
73-
return $this->stack === null;
60+
/** @var MiddlewareInterface $middleware */
61+
foreach ($this->middlewares as $middleware) {
62+
$handler = $this->wrap($middleware, $handler);
63+
}
64+
65+
$this->stack = $handler;
7466
}
7567

7668
/**

tests/MiddlewareDispatcherTest.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Yiisoft\Middleware\Dispatcher\Event\BeforeMiddleware;
1717
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
1818
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
19-
use Yiisoft\Middleware\Dispatcher\MiddlewareStack;
2019
use Yiisoft\Middleware\Dispatcher\Tests\Support\FailMiddleware;
2120
use Yiisoft\Middleware\Dispatcher\Tests\Support\TestController;
2221
use Yiisoft\Middleware\Dispatcher\Tests\Support\TestMiddleware;
@@ -201,13 +200,13 @@ private function createDispatcher(ContainerInterface $container = null, ?EventDi
201200
if ($container === null) {
202201
return new MiddlewareDispatcher(
203202
new MiddlewareFactory($this->createContainer()),
204-
new MiddlewareStack($eventDispatcher)
203+
$eventDispatcher
205204
);
206205
}
207206

208207
return new MiddlewareDispatcher(
209208
new MiddlewareFactory($container),
210-
new MiddlewareStack($eventDispatcher)
209+
$eventDispatcher
211210
);
212211
}
213212

tests/MiddlewareStackTest.php

+2-8
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,10 @@ class MiddlewareStackTest extends TestCase
1515
{
1616
public function testHandleEmpty(): void
1717
{
18-
$stack = new MiddlewareStack(new SimpleEventDispatcher());
19-
2018
$this->expectException(RuntimeException::class);
2119
$this->expectExceptionMessage('Stack is empty.');
22-
$stack->handle($this->createMock(ServerRequestInterface::class));
23-
}
2420

25-
public function testImmutability(): void
26-
{
27-
$stack = new MiddlewareStack(new SimpleEventDispatcher());
28-
self::assertNotSame($stack, $stack->build([], $this->createMock(RequestHandlerInterface::class)));
21+
$stack = new MiddlewareStack([], $this->createMock(RequestHandlerInterface::class), new SimpleEventDispatcher());
22+
$stack->handle($this->createMock(ServerRequestInterface::class));
2923
}
3024
}

0 commit comments

Comments
 (0)