@@ -36,16 +36,28 @@ class HtmlErrorRenderer implements ErrorRendererInterface
36
36
private $ charset ;
37
37
private $ fileLinkFormat ;
38
38
private $ projectDir ;
39
- private $ requestStack ;
39
+ private $ outputBuffering ;
40
40
private $ logger ;
41
41
42
- public function __construct (bool $ debug = false , string $ charset = null , $ fileLinkFormat = null , string $ projectDir = null , RequestStack $ requestStack = null , LoggerInterface $ logger = null )
42
+ /**
43
+ * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
44
+ * @param bool|callable $outputBuffering The output buffering as a string or a callable that should return it
45
+ */
46
+ public function __construct ($ debug = false , string $ charset = null , $ fileLinkFormat = null , string $ projectDir = null , $ outputBuffering = '' , LoggerInterface $ logger = null )
43
47
{
48
+ if (!\is_bool ($ debug ) && !\is_callable ($ debug )) {
49
+ throw new \TypeError (sprintf ('Argument 1 passed to %s() must be a boolean or a callable, %s given. ' , __METHOD__ , \is_object ($ debug ) ? \get_class ($ debug ) : \gettype ($ debug )));
50
+ }
51
+
52
+ if (!\is_string ($ outputBuffering ) && !\is_callable ($ outputBuffering )) {
53
+ throw new \TypeError (sprintf ('Argument 5 passed to %s() must be a string or a callable, %s given. ' , __METHOD__ , \is_object ($ outputBuffering ) ? \get_class ($ outputBuffering ) : \gettype ($ outputBuffering )));
54
+ }
55
+
44
56
$ this ->debug = $ debug ;
45
57
$ this ->charset = $ charset ?: (ini_get ('default_charset ' ) ?: 'UTF-8 ' );
46
58
$ this ->fileLinkFormat = $ fileLinkFormat ?: (ini_get ('xdebug.file_link_format ' ) ?: get_cfg_var ('xdebug.file_link_format ' ));
47
59
$ this ->projectDir = $ projectDir ;
48
- $ this ->requestStack = $ requestStack ;
60
+ $ this ->outputBuffering = $ outputBuffering ;
49
61
$ this ->logger = $ logger ;
50
62
}
51
63
@@ -57,7 +69,7 @@ public function render(\Throwable $exception): FlattenException
57
69
$ exception = FlattenException::createFromThrowable ($ exception , null , [
58
70
'Content-Type ' => 'text/html; charset= ' .$ this ->charset ,
59
71
]);
60
-
72
+
61
73
return $ exception ->setAsString ($ this ->renderException ($ exception ));
62
74
}
63
75
@@ -81,42 +93,61 @@ public function getStylesheet(): string
81
93
return $ this ->include ('assets/css/exception.css ' );
82
94
}
83
95
96
+ public static function isDebug (RequestStack $ requestStack , bool $ debug ): \Closure
97
+ {
98
+ return static function () use ($ requestStack , $ debug ): bool {
99
+ if (!$ request = $ requestStack ->getCurrentRequest ()) {
100
+ return $ debug ;
101
+ }
102
+
103
+ return $ debug && $ request ->attributes ->getBoolean ('showException ' , true );
104
+ };
105
+ }
106
+
107
+ public static function getAndCleanOutputBuffering (RequestStack $ requestStack ): \Closure
108
+ {
109
+ return static function () use ($ requestStack ): string {
110
+ if (!$ request = $ requestStack ->getCurrentRequest ()) {
111
+ return '' ;
112
+ }
113
+
114
+ $ startObLevel = $ request ->headers ->get ('X-Php-Ob-Level ' , -1 );
115
+
116
+ if (ob_get_level () <= $ startObLevel ) {
117
+ return '' ;
118
+ }
119
+
120
+ Response::closeOutputBuffers ($ startObLevel + 1 , true );
121
+
122
+ return ob_get_clean ();
123
+ };
124
+ }
125
+
84
126
private function renderException (FlattenException $ exception , string $ debugTemplate = 'views/exception_full.html.php ' ): string
85
127
{
128
+ $ debug = \is_bool ($ this ->debug ) ? $ this ->debug : ($ this ->debug )($ exception );
86
129
$ statusText = $ this ->escape ($ exception ->getStatusText ());
87
130
$ statusCode = $ this ->escape ($ exception ->getStatusCode ());
88
131
89
- if (!$ this -> debug ) {
132
+ if (!$ debug ) {
90
133
return $ this ->include ('views/error.html.php ' , [
91
134
'statusText ' => $ statusText ,
92
135
'statusCode ' => $ statusCode ,
93
136
]);
94
137
}
95
138
96
139
$ exceptionMessage = $ this ->escape ($ exception ->getMessage ());
97
- $ request = $ this ->requestStack ? $ this ->requestStack ->getCurrentRequest () : null ;
98
140
99
141
return $ this ->include ($ debugTemplate , [
100
142
'exception ' => $ exception ,
101
143
'exceptionMessage ' => $ exceptionMessage ,
102
144
'statusText ' => $ statusText ,
103
145
'statusCode ' => $ statusCode ,
104
146
'logger ' => $ this ->logger instanceof DebugLoggerInterface ? $ this ->logger : null ,
105
- 'currentContent ' => $ request ? $ this ->getAndCleanOutputBuffering ( $ request -> headers -> get ( ' X-Php-Ob-Level ' , - 1 )) : '' ,
147
+ 'currentContent ' => \is_string ( $ this -> outputBuffering ) ? $ this ->outputBuffering : ( $ this -> outputBuffering )() ,
106
148
]);
107
149
}
108
150
109
- private function getAndCleanOutputBuffering (int $ startObLevel ): string
110
- {
111
- if (ob_get_level () <= $ startObLevel ) {
112
- return '' ;
113
- }
114
-
115
- Response::closeOutputBuffers ($ startObLevel + 1 , true );
116
-
117
- return ob_get_clean ();
118
- }
119
-
120
151
/**
121
152
* Formats an array as a string.
122
153
*/
@@ -312,7 +343,7 @@ private function include(string $name, array $context = []): string
312
343
{
313
344
extract ($ context , EXTR_SKIP );
314
345
ob_start ();
315
- include __DIR__ . '/../Resources/ ' .$ name ;
346
+ include __DIR__ . '/../Resources/ ' .$ name ;
316
347
317
348
return trim (ob_get_clean ());
318
349
}
0 commit comments