4
4
5
5
namespace SPC \exception ;
6
6
7
+ use SPC \builder \BuilderBase ;
8
+ use SPC \builder \freebsd \BSDBuilder ;
9
+ use SPC \builder \linux \LinuxBuilder ;
10
+ use SPC \builder \macos \MacOSBuilder ;
11
+ use SPC \builder \windows \WindowsBuilder ;
7
12
use ZM \Logger \ConsoleColor ;
8
13
9
14
class ExceptionHandler
@@ -26,21 +31,27 @@ class ExceptionHandler
26
31
WrongUsageException::class,
27
32
];
28
33
34
+ /** @var null|BuilderBase Builder binding */
35
+ private static ?BuilderBase $ builder = null ;
36
+
37
+ /** @var array<string, mixed> Build PHP extra info binding */
38
+ private static array $ build_php_extra_info = [];
39
+
29
40
public static function handleSPCException (SPCException $ e ): void
30
41
{
31
42
// XXX error: yyy
32
43
$ head_msg = match ($ class = get_class ($ e )) {
33
- BuildFailureException::class => "Build failed: {$ e ->getMessage ()}" ,
34
- DownloaderException::class => "Download failed: {$ e ->getMessage ()}" ,
35
- EnvironmentException::class => "Environment check failed: {$ e ->getMessage ()}" ,
36
- ExecutionException::class => "Command execution failed: {$ e ->getMessage ()}" ,
37
- FileSystemException::class => "File system error: {$ e ->getMessage ()}" ,
44
+ BuildFailureException::class => "✗ Build failed: {$ e ->getMessage ()}" ,
45
+ DownloaderException::class => "✗ Download failed: {$ e ->getMessage ()}" ,
46
+ EnvironmentException::class => "⚠ Environment check failed: {$ e ->getMessage ()}" ,
47
+ ExecutionException::class => "✗ Command execution failed: {$ e ->getMessage ()}" ,
48
+ FileSystemException::class => "✗ File system error: {$ e ->getMessage ()}" ,
38
49
InterruptException::class => "⚠ Build interrupted by user: {$ e ->getMessage ()}" ,
39
- PatchException::class => "Patch apply failed: {$ e ->getMessage ()}" ,
40
- SPCInternalException::class => "SPC internal error: {$ e ->getMessage ()}" ,
41
- ValidationException::class => "Validation failed: {$ e ->getMessage ()}" ,
50
+ PatchException::class => "✗ Patch apply failed: {$ e ->getMessage ()}" ,
51
+ SPCInternalException::class => "✗ SPC internal error: {$ e ->getMessage ()}" ,
52
+ ValidationException::class => "⚠ Validation failed: {$ e ->getMessage ()}" ,
42
53
WrongUsageException::class => $ e ->getMessage (),
43
- default => "Unknown SPC exception {$ class }: {$ e ->getMessage ()}" ,
54
+ default => "✗ Unknown SPC exception {$ class }: {$ e ->getMessage ()}" ,
44
55
};
45
56
self ::logError ($ head_msg );
46
57
@@ -54,25 +65,32 @@ public static function handleSPCException(SPCException $e): void
54
65
self ::logError ("---------------------------------------- \n" );
55
66
56
67
// get the SPCException module
57
- if ($ php_info = $ e ->getBuildPHPInfo ()) {
58
- self ::logError ('✗ Failed module: ' . ConsoleColor::yellow ("PHP builder {$ php_info ['builder_class ' ]} for {$ php_info ['os ' ]}" ));
59
- } elseif ($ lib_info = $ e ->getLibraryInfo ()) {
60
- self ::logError ('✗ Failed module: ' . ConsoleColor::yellow ("library {$ lib_info ['library_name ' ]} builder for {$ lib_info ['os ' ]}" ));
68
+ if ($ lib_info = $ e ->getLibraryInfo ()) {
69
+ self ::logError ('Failed module: ' . ConsoleColor::yellow ("library {$ lib_info ['library_name ' ]} builder for {$ lib_info ['os ' ]}" ));
61
70
} elseif ($ ext_info = $ e ->getExtensionInfo ()) {
62
- self ::logError ('✗ Failed module: ' . ConsoleColor::yellow ("shared extension {$ ext_info ['extension_name ' ]} builder " ));
71
+ self ::logError ('Failed module: ' . ConsoleColor::yellow ("shared extension {$ ext_info ['extension_name ' ]} builder " ));
72
+ } elseif (self ::$ builder ) {
73
+ $ os = match (get_class (self ::$ builder )) {
74
+ WindowsBuilder::class => 'Windows ' ,
75
+ MacOSBuilder::class => 'macOS ' ,
76
+ LinuxBuilder::class => 'Linux ' ,
77
+ BSDBuilder::class => 'FreeBSD ' ,
78
+ default => 'Unknown OS ' ,
79
+ };
80
+ self ::logError ('Failed module: ' . ConsoleColor::yellow ("Builder for {$ os }" ));
63
81
} elseif (!in_array ($ class , self ::KNOWN_EXCEPTIONS )) {
64
- self ::logError ('✗ Failed From: ' . ConsoleColor::yellow ('Unknown SPC module ' . $ class ));
82
+ self ::logError ('Failed From: ' . ConsoleColor::yellow ('Unknown SPC module ' . $ class ));
65
83
}
66
- self ::logError ('' );
67
84
68
85
// get command execution info
69
86
if ($ e instanceof ExecutionException) {
70
- self ::logError ('✗ Failed command: ' . ConsoleColor::yellow ($ e ->getExecutionCommand ()));
87
+ self ::logError ('' );
88
+ self ::logError ('Failed command: ' . ConsoleColor::yellow ($ e ->getExecutionCommand ()));
71
89
if ($ cd = $ e ->getCd ()) {
72
- self ::logError ('✗ Command executed in: ' . ConsoleColor::yellow ($ cd ));
90
+ self ::logError ('Command executed in: ' . ConsoleColor::yellow ($ cd ));
73
91
}
74
92
if ($ env = $ e ->getEnv ()) {
75
- self ::logError ('✗ Command inline env variables: ' );
93
+ self ::logError ('Command inline env variables: ' );
76
94
foreach ($ env as $ k => $ v ) {
77
95
self ::logError (ConsoleColor::yellow ("{$ k }= {$ v }" ), 4 );
78
96
}
@@ -81,46 +99,40 @@ public static function handleSPCException(SPCException $e): void
81
99
82
100
// validation error
83
101
if ($ e instanceof ValidationException) {
84
- self ::logError ('✗ Failed validation module: ' . ConsoleColor::yellow ($ e ->getValidationModuleString ()));
102
+ self ::logError ('Failed validation module: ' . ConsoleColor::yellow ($ e ->getValidationModuleString ()));
85
103
}
86
104
87
105
// environment error
88
106
if ($ e instanceof EnvironmentException) {
89
- self ::logError ('✗ Failed environment check: ' . ConsoleColor::yellow ($ e ->getMessage ()));
107
+ self ::logError ('Failed environment check: ' . ConsoleColor::yellow ($ e ->getMessage ()));
90
108
if (($ solution = $ e ->getSolution ()) !== null ) {
91
- self ::logError ('✗ Solution: ' . ConsoleColor::yellow ($ solution ));
109
+ self ::logError ('Solution: ' . ConsoleColor::yellow ($ solution ));
92
110
}
93
111
}
94
112
95
113
// get patch info
96
114
if ($ e instanceof PatchException) {
97
- self ::logError ("✗ Failed patch module: {$ e ->getPatchModule ()}" );
115
+ self ::logError ("Failed patch module: {$ e ->getPatchModule ()}" );
98
116
}
99
117
100
118
// get internal trace
101
119
if ($ e instanceof SPCInternalException) {
102
- self ::logError ('✗ Internal trace: ' );
120
+ self ::logError ('Internal trace: ' );
103
121
self ::logError (ConsoleColor::gray ("{$ e ->getTraceAsString ()}\n" ), 4 );
104
122
}
105
123
106
124
// get the full build info if possible
107
- if (($ info = $ e ->getBuildPHPExtraInfo ()) && defined ('DEBUG_MODE ' )) {
108
- self ::logError ('✗ Build PHP extra info: ' );
109
- $ maxlen = 0 ;
110
- foreach ($ info as $ k => $ v ) {
111
- $ maxlen = max (strlen ($ k ), $ maxlen );
112
- }
113
- foreach ($ info as $ k => $ v ) {
114
- if (is_string ($ v )) {
115
- self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ($ v ), 4 );
116
- } elseif (is_array ($ v ) && !is_assoc_array ($ v )) {
117
- $ first = array_shift ($ v );
118
- self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ($ first ), 4 );
119
- foreach ($ v as $ vs ) {
120
- self ::logError (str_pad ('' , $ maxlen + 2 ) . ConsoleColor::yellow ($ vs ), 4 );
121
- }
122
- }
123
- }
125
+ if ($ info = ExceptionHandler::$ build_php_extra_info ) {
126
+ self ::logError ('' , output_log: defined ('DEBUG_MODE ' ));
127
+ self ::logError ('Build PHP extra info: ' , output_log: defined ('DEBUG_MODE ' ));
128
+ self ::printArrayInfo ($ info );
129
+ }
130
+
131
+ // get the full builder options if possible
132
+ if ($ e ->getBuildPHPInfo ()) {
133
+ $ info = $ e ->getBuildPHPInfo ();
134
+ self ::logError ('' , output_log: defined ('DEBUG_MODE ' ));
135
+ self ::logError ('Builder function: ' . ConsoleColor::yellow ($ info ['builder_function ' ]), output_log: defined ('DEBUG_MODE ' ));
124
136
}
125
137
126
138
self ::logError ("\n---------------------------------------- \n" );
@@ -142,20 +154,67 @@ public static function handleSPCException(SPCException $e): void
142
154
public static function handleDefaultException (\Throwable $ e ): void
143
155
{
144
156
$ class = get_class ($ e );
145
- self ::logError ("Unhandled exception {$ class }: { $ e -> getMessage ()} \n\t{$ e ->getMessage ()}\n" );
157
+ self ::logError ("✗ Unhandled exception {$ class }: \n\t{$ e ->getMessage ()}\n" );
146
158
self ::logError ('Stack trace: ' );
147
- self ::logError (ConsoleColor::gray ($ e ->getTraceAsString ()), 4 );
148
- self ::logError ('Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues ' );
159
+ self ::logError (ConsoleColor::gray ($ e ->getTraceAsString ()) . PHP_EOL , 4 );
160
+ self ::logError ('⚠ Please report this exception to: https://github.com/crazywhalecc/static-php-cli/issues ' );
161
+ }
162
+
163
+ public static function bindBuilder (?BuilderBase $ bind_builder ): void
164
+ {
165
+ self ::$ builder = $ bind_builder ;
149
166
}
150
167
151
- private static function logError ($ message , int $ indent_space = 0 ): void
168
+ public static function bindBuildPhpExtraInfo (array $ build_php_extra_info ): void
169
+ {
170
+ self ::$ build_php_extra_info = $ build_php_extra_info ;
171
+ }
172
+
173
+ private static function logError ($ message , int $ indent_space = 0 , bool $ output_log = true ): void
152
174
{
153
175
$ spc_log = fopen (SPC_OUTPUT_LOG , 'a ' );
154
176
$ msg = explode ("\n" , (string ) $ message );
155
177
foreach ($ msg as $ v ) {
156
178
$ line = str_pad ($ v , strlen ($ v ) + $ indent_space , ' ' , STR_PAD_LEFT );
157
179
fwrite ($ spc_log , strip_ansi_colors ($ line ) . PHP_EOL );
158
- echo ConsoleColor::red ($ line ) . PHP_EOL ;
180
+ if ($ output_log ) {
181
+ echo ConsoleColor::red ($ line ) . PHP_EOL ;
182
+ }
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Print array info to console and log.
188
+ */
189
+ private static function printArrayInfo (array $ info ): void
190
+ {
191
+ $ log_output = defined ('DEBUG_MODE ' );
192
+ $ maxlen = 0 ;
193
+ foreach ($ info as $ k => $ v ) {
194
+ $ maxlen = max (strlen ($ k ), $ maxlen );
195
+ }
196
+ foreach ($ info as $ k => $ v ) {
197
+ if (is_string ($ v )) {
198
+ if ($ v === '' ) {
199
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ('"" ' ), 4 , $ log_output );
200
+ } else {
201
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ($ v ), 4 , $ log_output );
202
+ }
203
+ } elseif (is_array ($ v ) && !is_assoc_array ($ v )) {
204
+ if ($ v === []) {
205
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ('[] ' ), 4 , $ log_output );
206
+ continue ;
207
+ }
208
+ $ first = array_shift ($ v );
209
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow ($ first ), 4 , $ log_output );
210
+ foreach ($ v as $ vs ) {
211
+ self ::logError (str_pad ('' , $ maxlen + 2 ) . ConsoleColor::yellow ($ vs ), 4 , $ log_output );
212
+ }
213
+ } elseif (is_bool ($ v ) || is_null ($ v )) {
214
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::cyan ($ v === true ? 'true ' : ($ v === false ? 'false ' : 'null ' )), 4 , $ log_output );
215
+ } else {
216
+ self ::logError ($ k . ': ' . str_pad ('' , $ maxlen - strlen ($ k )) . ConsoleColor::yellow (json_encode ($ v , JSON_PRETTY_PRINT )), 4 , $ log_output );
217
+ }
159
218
}
160
219
}
161
220
}
0 commit comments