Skip to content

Commit e5b11f4

Browse files
committed
Custom exceptions, enhancement & refactoring.
1 parent 9cc689e commit e5b11f4

7 files changed

+78
-24
lines changed

Src/InvalidMiddlewareForPipeError.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* Middleware type invalid exception.
4+
*
5+
* @package TheWebSolver\Codegarage\Library
6+
*/
7+
8+
declare( strict_types = 1 );
9+
10+
namespace TheWebSolver\Codegarage\Lib;
11+
12+
use TypeError;
13+
14+
class InvalidMiddlewareForPipeError extends TypeError {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* PSR implementation not found exception.
4+
*
5+
* @package TheWebSolver\Codegarage\Library
6+
*/
7+
8+
declare( strict_types = 1 );
9+
10+
namespace TheWebSolver\Codegarage\Lib;
11+
12+
use RuntimeException;
13+
14+
class MiddlewarePsrNotFoundException extends RuntimeException {}

Src/Pipeline.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public function sealWith( Closure $fallback ): static {
134134
}
135135

136136
/**
137-
* Appends additional pipes onto the pipeline.
137+
* Appends additional pipes to the pipeline stack.
138138
*
139139
* @param string|Pipe|Closure(mixed $subject, Closure $next, mixed ...$use): mixed
140140
* @phpstan-param class-string<Pipe>|Pipe|Closure(mixed $subject, Closure $next, mixed ...$use): mixed $pipe
@@ -146,10 +146,11 @@ public function pipe( string|Closure|Pipe $pipe ): static {
146146
}
147147

148148
/**
149-
* Runs the provided return pipe after passing through all pipes.
149+
* Gets the transformed subject after passing through one last pipe.
150150
*
151151
* @param Closure(mixed $subject, mixed ...$use): mixed $return
152-
* @throws Throwable When a pipe abrupt the pipeline by throwing an exception & sealWith not used.
152+
* @throws InvalidPipeError When pipe type could not be resolved.
153+
* @throws UnexpectedPipelineException When a pipe abrupt the pipeline by throwing an exception & sealWith not used.
153154
*/
154155
public function then( Closure $return ): mixed {
155156
$use = $this->use ?? array();
@@ -159,11 +160,22 @@ public function then( Closure $return ): mixed {
159160
try {
160161
return array_reduce( $pipes, $this->chain( ... ), $return )( $subject, ...$use );
161162
} catch ( Throwable $e ) {
162-
return ( $catcher = $this->catcher ?? null ) ? $catcher( $e, ...$use ) : throw $e;
163+
if ( $catcher = $this->catcher ?? null ) {
164+
return $catcher( $e, ...$use );
165+
}
166+
167+
return $e instanceof InvalidPipeError
168+
? throw $e
169+
: throw new UnexpectedPipelineException( $e->getMessage(), $e->getCode(), $e );
163170
}
164171
}
165172

166-
/** Passes through pipes in the pipeline and returns the transformed result. */
173+
/**
174+
* Passes through pipes in the pipeline and returns the transformed result.
175+
*
176+
* @throws InvalidPipeError When pipe type could not be resolved.
177+
* @throws UnexpectedPipelineException When a pipe abrupt the pipeline by throwing an exception & sealWith not used.
178+
*/
167179
public function thenReturn() {
168180
return $this->then( return: static fn( $transformed ) => $transformed );
169181
}

Src/PipelineBridge.php

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
use Closure;
1313
use Throwable;
14-
use TypeError;
15-
use LogicException;
1614
use Psr\Http\Message\ResponseInterface as Response;
1715
use Psr\Http\Server\MiddlewareInterface as Middleware;
1816
use TheWebSolver\Codegarage\Lib\PipeInterface as Pipe;
@@ -50,35 +48,36 @@ public function handle( mixed $subject, Closure $next, mixed ...$use ): mixed {
5048
}
5149

5250
/**
53-
* @throws LogicException When invoked on projects that doesn't implement PSR7 & PSR15.
54-
* @throws TypeError When middleware creation fails due to invalid classname.
51+
* @throws MiddlewarePsrNotFoundException When invoked on projects that doesn't implement PSR7 & PSR15.
52+
* @throws InvalidMiddlewareForPipeError When middleware creation fails due to invalid classname.
53+
* @throws UnexpectedPipelineException When could not determine thrown exception.
5554
*/
5655
public static function toMiddleware( mixed $middleware ): object {
5756
$interface = static::hasMiddlewareInterfaceAdapter()
5857
? static::$middlewareInterface
59-
: '\\Psr\\Http\\Server\\MiddlewareInterface';
60-
61-
if ( ! interface_exists( $interface ) ) {
62-
throw new LogicException( 'Cannot find implementation of PSR15 HTTP Server Middleware.' );
63-
}
58+
: (
59+
! interface_exists( $default = '\\Psr\\Http\\Server\\MiddlewareInterface' )
60+
? throw new MiddlewarePsrNotFoundException( 'Cannot find PSR15 HTTP Server Middleware.' )
61+
: $default
62+
);
6463

6564
$provided = $middleware;
6665
$isClassName = is_string( $middleware ) && class_exists( $middleware );
6766

6867
try {
69-
$middleware = ( match ( true ) {
68+
$middleware = match ( true ) {
7069
// Middleware classname is a non-existing classname, then default to null.
7170
default => null,
7271
$middleware instanceof Closure => $middleware,
7372
$isClassName => static::make( $middleware )->process( ... ),
7473
is_a( $middleware, $interface ) => $middleware->process( ... ),
75-
} );
74+
};
7675

7776
if ( null === $middleware ) {
78-
throw new TypeError(
77+
throw new InvalidMiddlewareForPipeError(
7978
sprintf(
8079
'Invalid or Non-existing class "%1$s". Middleware must be a Closure, an'
81-
. ' instance of %2$sor classname of a class that implements %2$s.',
80+
. ' instance of %2$s or a concrete\'s classname that implements %2$s.',
8281
$isClassName ? $provided : $provided::class,
8382
$interface
8483
)
@@ -87,11 +86,15 @@ public static function toMiddleware( mixed $middleware ): object {
8786

8887
return static::getMiddlewareAdapter( $middleware );
8988
} catch ( Throwable $e ) {
90-
if ( $e instanceof TypeError || ! is_string( $middleware ) ) {
89+
if ( $e instanceof InvalidMiddlewareForPipeError ) {
9190
throw $e;
9291
}
9392

94-
throw new TypeError(
93+
if ( ! is_string( $middleware ) ) {
94+
throw new UnexpectedPipelineException( $e->getMessage(), $e->getCode(), $e );
95+
}
96+
97+
throw new InvalidMiddlewareForPipeError(
9598
sprintf(
9699
'The given middleware classname: "%1$s" must be an instance of "%2$s".',
97100
$middleware,

Src/UnexpectedPipelineException.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* Unknown pipeline exception.
4+
*
5+
* @package TheWebSolver\Codegarage\Library
6+
*/
7+
8+
namespace TheWebSolver\Codegarage\Lib;
9+
10+
use Exception;
11+
12+
class UnexpectedPipelineException extends Exception {}

Tests/BridgeTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace TheWebSolver\Codegarage\Lib;
1111

12-
use LogicException;
1312
use MiddlewareAdapter;
1413
use Psr7Adapter\Request;
1514
use Psr7Adapter\Response;
@@ -73,8 +72,8 @@ public function process(
7372

7473
// Must always throw exception if core PSR-15 implementation not used.
7574
if ( ! $this->PSRPackageInstalled ) {
76-
$this->expectException( LogicException::class );
77-
$this->expectExceptionMessage( 'Cannot find implementation of PSR15 HTTP Server Middleware.' );
75+
$this->expectException( MiddlewarePsrNotFoundException::class );
76+
$this->expectExceptionMessage( 'Cannot find PSR15 HTTP Server Middleware.' );
7877

7978
PipelineBridge::toMiddleware( middleware: '' );
8079
}

Tests/PipelineTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public function testPipeSealer(): void {
162162
);
163163

164164
// When "Pipeline::sealWith()" is not used, exception is thrown.
165-
$this->expectException( RuntimeException::class );
165+
$this->expectException( UnexpectedPipelineException::class );
166166

167167
( new Pipeline() )
168168
->send( subject: 'test' )

0 commit comments

Comments
 (0)