Skip to content

Commit 9d6d604

Browse files
committed
PSR-7, PSR-11, and PSR-15 integration.
1 parent 59f7a1e commit 9d6d604

25 files changed

+905
-651
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@
66
!phpunit.xml.dist
77
!LICENSE
88
!/*.md
9+
!phpcs.xml.dist
10+
!phpstan.dist.neon
911
!/Src
1012
!/Tests/
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php // phpcs:disable Squiz.Commenting.FunctionComment.ParamNameNoMatch, Squiz.Commenting.FunctionComment.IncorrectTypeHint
2+
declare(strict_types = 1);
3+
4+
namespace TheWebSolver\Codegarage\Lib\Interfaces;
5+
6+
use Closure;
7+
use Throwable;
8+
use TheWebSolver\Codegarage\Lib\InvalidPipe;
9+
use TheWebSolver\Codegarage\Lib\InvalidPipeline;
10+
use TheWebSolver\Codegarage\Lib\PipeInterface as Handler;
11+
12+
interface ChainOfResponsibility {
13+
/**
14+
* Provides additional arguments that can be used by all registered pipes.
15+
*/
16+
public function use( mixed ...$globalArgsForEachPipe ): static;
17+
18+
/**
19+
* Provides subject to be transformed by all registered pipes.
20+
*/
21+
public function send( mixed $subject ): static;
22+
23+
/**
24+
* Registers a single pipe to transform the subject.
25+
*
26+
* Pipes registered using this method before `ChainOfResponsibility::through()` method
27+
* must be deferred and must transform the subject only after pipes registered using
28+
* `ChainOfResponsibility::through()` method has transformed the subject, if any.
29+
*
30+
* @param class-string<Handler>|Handler|Closure(mixed $subject, Closure $next, mixed ...$args): mixed $handler
31+
*/
32+
public function pipe( string|Closure|Handler $handler ): static;
33+
34+
/**
35+
* Registers pipes to transform the subject.
36+
*
37+
* Subject must be transformed in the same order pipes are registered.
38+
*
39+
* @param array<class-string<Handler>|Handler|Closure(mixed $subject, Closure $next, mixed ...$args): mixed> $pipes
40+
*/
41+
public function through( array $pipes ): static;
42+
43+
/**
44+
* Catches any exception thrown during transformation of subject and returns the fallback value.
45+
*
46+
* @param Closure(Throwable $exception, mixed ...$args): mixed $fallback
47+
*/
48+
public function sealWith( Closure $fallback ): static;
49+
50+
/**
51+
* Returns the transformed subject after passing through all registered pipes and current pipe handle.
52+
*
53+
* @param Closure(mixed $subject, mixed ...$args): mixed $handle
54+
* @throws InvalidPipe When pipe type could not be resolved.
55+
* @throws InvalidPipeline When a pipe abrupt the pipeline by throwing an exception & sealWith not used.
56+
*/
57+
public function then( Closure $handle ): mixed;
58+
59+
/**
60+
* Returns the transformed subject after passing through all registered pipes.
61+
*
62+
* @throws InvalidPipe When pipe type could not be resolved.
63+
* @throws InvalidPipeline When a pipe abrupt the pipeline by throwing an exception & sealWith not used.
64+
*/
65+
public function thenReturn(): mixed;
66+
}

Src/InvalidMiddlewareForPipe.php

-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
<?php
2-
/**
3-
* Middleware type invalid exception.
4-
*
5-
* @package TheWebSolver\Codegarage\Library
6-
*/
7-
82
declare( strict_types = 1 );
93

104
namespace TheWebSolver\Codegarage\Lib;

Src/InvalidPipe.php

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
11
<?php
2-
/**
3-
* Exception when invalid pipe given.
4-
*
5-
* @package TheWebSolver\Codegarage\Library
6-
*/
7-
82
declare( strict_types = 1 );
93

104
namespace TheWebSolver\Codegarage\Lib;
@@ -18,8 +12,10 @@ public static function from( mixed $pipe ): self {
1812

1913
private function __construct( mixed $pipe ) {
2014
parent::__construct(
21-
message: ! is_string( $pipe ) ? '' : "Invalid pipe classname given: {$pipe}.",
22-
code: 400
15+
code: 400,
16+
message: ! is_string( $pipe )
17+
? 'Invalid pipe given: ' . get_debug_type( $pipe )
18+
: "Invalid pipe classname given: {$pipe}.",
2319
);
2420
}
2521
}

Src/InvalidPipeline.php

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
<?php
2-
/**
3-
* Unknown pipeline exception.
4-
*
5-
* @package TheWebSolver\Codegarage\Library
6-
*/
2+
declare( strict_types = 1 );
73

84
namespace TheWebSolver\Codegarage\Lib;
95

Src/Pipe.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
declare( strict_types = 1 );
3+
4+
namespace TheWebSolver\Codegarage\Lib;
5+
6+
use Closure;
7+
use Throwable;
8+
use Psr\Container\ContainerInterface;
9+
10+
class Pipe implements PipeInterface {
11+
/** @param Closure(mixed $subject, Closure $next, mixed ...$args): mixed $handler */
12+
// phpcs:ignore Squiz.Commenting.FunctionComment.IncorrectTypeHint
13+
public function __construct( private readonly Closure $handler ) {}
14+
15+
public function handle( mixed $subject, Closure $next, mixed ...$args ): mixed {
16+
return ( $this->handler )( $subject, $next, ...$args );
17+
}
18+
19+
public static function create(
20+
string|Closure|PipeInterface $handler,
21+
?ContainerInterface $container = null
22+
): PipeInterface {
23+
try {
24+
$pipe = ! is_string( $handler ) ? $handler : ( $container?->get( $handler ) ?? new $handler() );
25+
26+
return match ( true ) {
27+
$pipe instanceof self => $pipe,
28+
$pipe instanceof PipeInterface => new self( $pipe->handle( ... ) ),
29+
$pipe instanceof Closure => new self( $pipe ),
30+
default => throw InvalidPipe::from( $handler ),
31+
};
32+
} catch ( Throwable $thrown ) {
33+
throw Pipeline::normalizeException( $thrown );
34+
}
35+
}
36+
}

Src/PipeInterface.php

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
<?php
2-
/**
3-
* The pipeline handler to handle given subject/request.
4-
*
5-
* @package TheWebSolver\Codegarage\Library
6-
*/
7-
82
declare( strict_types = 1 );
93

104
namespace TheWebSolver\Codegarage\Lib;
115

126
use Closure;
137

148
interface PipeInterface {
9+
// phpcs:disable Squiz.Commenting.FunctionComment.ParamNameNoMatch
1510
/**
1611
* Handles the given subject and returns the transformed data.
1712
*
1813
* @param mixed $subject The subject to be transformed by the pipe.
19-
* @param Closure(mixed $subject, mixed ...$use): mixed $next
20-
* @param mixed ...$use The global args that may or may not be in use
14+
* @param Closure(mixed $subject, mixed ...$args): mixed $next
15+
* @param mixed ...$args The global args that may or may not be in use
2116
* for the current pipeline.
22-
* @since 1.0
2317
*/
24-
public function handle( mixed $subject, Closure $next, mixed ...$use ): mixed;
18+
// phpcs:ignore Squiz.Commenting.FunctionComment.IncorrectTypeHint
19+
public function handle( mixed $subject, Closure $next, mixed ...$args ): mixed;
2520
}

Src/PipeResponseHandler.php

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
<?php
2-
/**
3-
* Server Request Handler that returns the middleware response hydrated by the pipe.
4-
*
5-
* @package TheWebSolver\Codegarage\Library
6-
*/
7-
82
declare( strict_types = 1 );
93

10-
namespace TheWebSolver\Codegarage\Lib;
4+
namespace TheWebSolver\Codegarage\Lib\Psr;
115

126
use Psr\Http\Message\ResponseInterface;
137
use Psr\Http\Message\ServerRequestInterface;
148
use Psr\Http\Server\RequestHandlerInterface;
159

16-
class PipeResponseHandler implements RequestHandlerInterface {
10+
class RequestHandler implements RequestHandlerInterface {
1711
public function __construct( private readonly ResponseInterface $response ) {}
1812

1913
public function handle( ServerRequestInterface $request ): ResponseInterface {

0 commit comments

Comments
 (0)