Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 84888b4

Browse files
svyckaweierophinney
authored andcommitted
Added listeners for ProblemDetailsMiddleware
1 parent 65f8013 commit 84888b4

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/ProblemDetailsMiddleware.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
*/
2424
class ProblemDetailsMiddleware implements MiddlewareInterface
2525
{
26+
/**
27+
* @var callable[]
28+
*/
29+
private $listeners = [];
30+
2631
/**
2732
* @var ProblemDetailsResponseFactory
2833
*/
@@ -52,13 +57,38 @@ public function process(ServerRequestInterface $request, DelegateInterface $dele
5257
}
5358
} catch (Throwable $e) {
5459
$response = $this->responseFactory->createResponseFromThrowable($request, $e);
60+
$this->triggerListeners($e, $request, $response);
5561
} finally {
5662
restore_error_handler();
5763
}
5864

5965
return $response;
6066
}
6167

68+
/**
69+
* Attach an error listener.
70+
*
71+
* Each listener receives the following three arguments:
72+
*
73+
* - Throwable $error
74+
* - ServerRequestInterface $request
75+
* - ResponseInterface $response
76+
*
77+
* These instances are all immutable, and the return values of
78+
* listeners are ignored; use listeners for reporting purposes
79+
* only.
80+
*
81+
* @param callable $listener
82+
*/
83+
public function attachListener(callable $listener)
84+
{
85+
if (\in_array($listener, $this->listeners, true)) {
86+
return;
87+
}
88+
89+
$this->listeners[] = $listener;
90+
}
91+
6292
/**
6393
* Can the middleware act as an error handler?
6494
*
@@ -98,4 +128,19 @@ private function createErrorHandler() : callable
98128
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
99129
};
100130
}
131+
132+
/**
133+
* Trigger all error listeners.
134+
*
135+
* @param Throwable $error
136+
* @param ServerRequestInterface $request
137+
* @param ResponseInterface $response
138+
* @return void
139+
*/
140+
private function triggerListeners($error, ServerRequestInterface $request, ResponseInterface $response) : void
141+
{
142+
array_walk($this->listeners, function ($listener) use ($error, $request, $response) {
143+
$listener($error, $request, $response);
144+
});
145+
}
101146
}

test/ProblemDetailsMiddlewareTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,37 @@ public function testRethrowsCaughtExceptionIfUnableToNegotiateAcceptHeader() : v
148148
$this->expectExceptionCode(507);
149149
$middleware->process($this->request->reveal(), $delegate->reveal());
150150
}
151+
152+
/**
153+
* @dataProvider acceptHeaders
154+
*/
155+
public function testErrorHandlingTriggersListeners(string $accept) : void
156+
{
157+
$this->request->getHeaderLine('Accept')->willReturn($accept);
158+
159+
$exception = new TestAsset\RuntimeException('Thrown!', 507);
160+
161+
$delegate = $this->prophesize(DelegateInterface::class);
162+
$delegate
163+
->{HANDLER_METHOD}(Argument::that([$this->request, 'reveal']))
164+
->willThrow($exception);
165+
166+
$expected = $this->prophesize(ResponseInterface::class)->reveal();
167+
$this->responseFactory
168+
->createResponseFromThrowable($this->request->reveal(), $exception)
169+
->willReturn($expected);
170+
171+
$listener = function ($error, $request, $response) use ($exception, $expected) {
172+
$this->assertSame($exception, $error, 'Listener did not receive same exception as was raised');
173+
$this->assertSame($this->request->reveal(), $request, 'Listener did not receive same request');
174+
$this->assertSame($expected, $response, 'Listener did not receive same response');
175+
};
176+
$listener2 = clone $listener;
177+
$this->middleware->attachListener($listener);
178+
$this->middleware->attachListener($listener2);
179+
180+
$result = $this->middleware->process($this->request->reveal(), $delegate->reveal());
181+
182+
$this->assertSame($expected, $result);
183+
}
151184
}

0 commit comments

Comments
 (0)