22
22
class PipelineBridge {
23
23
public const MIDDLEWARE_RESPONSE = 'middlewareResponse ' ;
24
24
25
+ /** @phpstan-param class-string */
26
+ private static string $ middlewareInterface ;
27
+ /** @phpstan-param class-string */
28
+ private static string $ middlewareClass ;
29
+ /** @var \Psr\Container\ContainerInterface */
30
+ private static object $ container ;
31
+
25
32
/**
26
33
* @param string|Pipe|Closure(mixed $subject, Closure $next, mixed ...$use): mixed $from
27
34
* @throws InvalidPipeError When invalid pipe given.
28
35
*/
29
36
public static function toPipe ( string |Closure |Pipe $ from ): Pipe {
30
- return new class ( $ from ) implements Pipe {
31
- public function __construct ( private readonly string |Closure |Pipe $ pipe ) {}
37
+ $ pipe = Pipeline::resolve ( pipe: $ from );
38
+
39
+ return new class ( $ pipe ) implements Pipe {
40
+ public function __construct ( private readonly Closure $ pipe ) {}
32
41
33
42
/**
34
43
* @param mixed $subject
35
44
* @param Closure(mixed $subject, mixed ...$use): mixed $next
36
45
*/
37
46
public function handle ( mixed $ subject , Closure $ next , mixed ...$ use ): mixed {
38
- return $ next ( Pipeline:: resolve ( $ this ->pipe )( $ subject , $ next , ...$ use ) );
47
+ return $ next ( ( $ this ->pipe )( $ subject , $ next , ...$ use ) );
39
48
}
40
49
};
41
50
}
42
51
43
52
/**
44
- * @param string|Closure|Middleware $middleware
45
- * @return Middleware
46
- * @throws LogicException When invoked on projects that doesn't implement PSR7 & PSR15
53
+ * @throws LogicException When invoked on projects that doesn't implement PSR7 & PSR15.
47
54
* @throws TypeError When middleware creation fails due to invalid classname.
48
55
* @throws Throwable When unknown error occurs.
49
56
*/
50
- public static function toMiddleware ( $ middleware ) {
51
- $ interface = '\\Psr \\Http \\Server \\MiddlewareInterface ' ;
57
+ public static function toMiddleware ( mixed $ middleware ): object {
58
+ $ interface = static ::hasMiddlewareInterfaceAdapter ()
59
+ ? static ::$ middlewareInterface
60
+ : '\\Psr \\Http \\Server \\MiddlewareInterface ' ;
52
61
53
62
if ( ! interface_exists ( $ interface ) ) {
54
63
throw new LogicException (
@@ -62,10 +71,10 @@ public static function toMiddleware( $middleware ) {
62
71
try {
63
72
$ middleware = ( match ( true ) {
64
73
// Middleware classname is a non-existing classname, then default to null.
65
- default => null ,
66
- $ middleware instanceof Closure => $ middleware ,
67
- $ isClassName => ( new $ middleware() )->process ( ... ),
68
- $ middleware instanceof Middleware => $ middleware ->process ( ... ),
74
+ default => null ,
75
+ $ middleware instanceof Closure => $ middleware ,
76
+ $ isClassName => static :: make ( $ middleware )->process ( ... ),
77
+ is_a ( $ middleware, $ interface ) => $ middleware ->process ( ... ),
69
78
} );
70
79
71
80
if ( null === $ middleware ) {
@@ -74,18 +83,12 @@ public static function toMiddleware( $middleware ) {
74
83
'Non-existing class "%1$s". Middleware must be a Closure, an instance of %2$s '
75
84
. ' or classname of a class that implements %2$s. ' ,
76
85
$ provided ,
77
- $ interface
86
+ static :: $ middlewareInterface
78
87
)
79
88
);
80
89
}
81
90
82
- return new class ( $ middleware ) implements Middleware {
83
- public function __construct ( private readonly Closure $ middleware ) {}
84
-
85
- public function process ( Request $ request , Handler $ handler ): Response {
86
- return ( $ this ->middleware )( $ request , $ handler );
87
- }
88
- };
91
+ return static ::getMiddlewareAdapter ( $ middleware );
89
92
} catch ( Throwable $ e ) {
90
93
if ( ! is_string ( $ middleware ) ) {
91
94
throw $ e ;
@@ -95,22 +98,62 @@ public function process( Request $request, Handler $handler ): Response {
95
98
sprintf (
96
99
'The given middleware classname: "%1$s" must be an instance of "%2$s". ' ,
97
100
$ middleware ,
98
- $ interface
101
+ static :: $ middlewareInterface
99
102
)
100
103
);
101
104
}//end try
102
105
}
103
106
104
107
/** @param string|Closure|Middleware $middleware */
105
108
public static function middlewareToPipe ( $ middleware ): Pipe {
109
+ // Because Pipe::handle() wraps this function with the next pipe, we do not need to...
110
+ // ...manually wrap middleware with $next & let createPipe take care of it.
111
+ // If we do so, same middleware will recreate response multiple times
112
+ // making our app less performant which we don't want at all cost.
106
113
return self ::toPipe (
107
- // Because Pipe::handle() wraps this function with the next pipe, we do not need to...
108
- static fn ( Response $ r , Closure $ next , Request $ request , Handler $ handler ) =>
109
- // ...manually wrap middleware with $next & let createPipe take care of it.
110
- // If we do so, same middleware will recreate response multiple times
111
- // making our app less performant which we don't want at all cost.
112
- self ::toMiddleware ( $ middleware )
113
- ->process ( $ request ->withAttribute ( self ::MIDDLEWARE_RESPONSE , $ r ), $ handler )
114
+ static fn ( $ r , $ next , $ request , $ handler ) => self ::toMiddleware ( $ middleware )
115
+ ->process ( $ request ->withAttribute ( static ::MIDDLEWARE_RESPONSE , $ r ), $ handler )
114
116
);
115
117
}
118
+
119
+ public static function make ( string $ className ): object {
120
+ return isset ( static ::$ container ) && static ::$ container ->has ( id: $ className )
121
+ ? static ::$ container ->get ( id: $ className )
122
+ : new $ className ();
123
+ }
124
+
125
+ /** @param \Psr\Container\ContainerInterface $container */
126
+ public static function setApp ( object $ container ): void {
127
+ static ::$ container = $ container ;
128
+ }
129
+
130
+ public static function setMiddlewareAdapter ( string $ interface , string $ className ): void {
131
+ static ::$ middlewareInterface = $ interface ;
132
+ static ::$ middlewareClass = $ className ;
133
+ }
134
+
135
+ public static function resetMiddlewareAdapter (): void {
136
+ static ::$ middlewareInterface = '' ;
137
+ static ::$ middlewareClass = '' ;
138
+ }
139
+
140
+ private static function getMiddlewareAdapter ( Closure $ middleware ): object {
141
+ return static ::hasMiddlewareClassAdapter ()
142
+ ? new static::$ middlewareClass ( $ middleware )
143
+ : new class ( $ middleware ) implements Middleware {
144
+ public function __construct ( private readonly Closure $ middleware ) {}
145
+
146
+ public function process ( Request $ request , Handler $ handler ): Response {
147
+ return ( $ this ->middleware )( $ request , $ handler );
148
+ }
149
+ };
150
+ }
151
+
152
+ private static function hasMiddlewareInterfaceAdapter (): bool {
153
+ return isset ( static ::$ middlewareInterface ) && interface_exists ( static ::$ middlewareInterface );
154
+ }
155
+
156
+ private static function hasMiddlewareClassAdapter (): bool {
157
+ return isset ( static ::$ middlewareClass ) && class_exists ( static ::$ middlewareClass );
158
+ }
116
159
}
0 commit comments