44
55namespace SPC \exception ;
66
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 ;
712use ZM \Logger \ConsoleColor ;
813
914class ExceptionHandler
@@ -26,21 +31,27 @@ class ExceptionHandler
2631 WrongUsageException::class,
2732 ];
2833
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+
2940 public static function handleSPCException (SPCException $ e ): void
3041 {
3142 // XXX error: yyy
3243 $ 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 ()}" ,
3849 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 ()}" ,
4253 WrongUsageException::class => $ e ->getMessage (),
43- default => "Unknown SPC exception {$ class }: {$ e ->getMessage ()}" ,
54+ default => "✗ Unknown SPC exception {$ class }: {$ e ->getMessage ()}" ,
4455 };
4556 self ::logError ($ head_msg );
4657
@@ -54,25 +65,32 @@ public static function handleSPCException(SPCException $e): void
5465 self ::logError ("---------------------------------------- \n" );
5566
5667 // 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 ' ]}" ));
6170 } 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 }" ));
6381 } 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 ));
6583 }
66- self ::logError ('' );
6784
6885 // get command execution info
6986 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 ()));
7189 if ($ cd = $ e ->getCd ()) {
72- self ::logError ('✗ Command executed in: ' . ConsoleColor::yellow ($ cd ));
90+ self ::logError ('Command executed in: ' . ConsoleColor::yellow ($ cd ));
7391 }
7492 if ($ env = $ e ->getEnv ()) {
75- self ::logError ('✗ Command inline env variables: ' );
93+ self ::logError ('Command inline env variables: ' );
7694 foreach ($ env as $ k => $ v ) {
7795 self ::logError (ConsoleColor::yellow ("{$ k }= {$ v }" ), 4 );
7896 }
@@ -81,46 +99,40 @@ public static function handleSPCException(SPCException $e): void
8199
82100 // validation error
83101 if ($ e instanceof ValidationException) {
84- self ::logError ('✗ Failed validation module: ' . ConsoleColor::yellow ($ e ->getValidationModuleString ()));
102+ self ::logError ('Failed validation module: ' . ConsoleColor::yellow ($ e ->getValidationModuleString ()));
85103 }
86104
87105 // environment error
88106 if ($ e instanceof EnvironmentException) {
89- self ::logError ('✗ Failed environment check: ' . ConsoleColor::yellow ($ e ->getMessage ()));
107+ self ::logError ('Failed environment check: ' . ConsoleColor::yellow ($ e ->getMessage ()));
90108 if (($ solution = $ e ->getSolution ()) !== null ) {
91- self ::logError ('✗ Solution: ' . ConsoleColor::yellow ($ solution ));
109+ self ::logError ('Solution: ' . ConsoleColor::yellow ($ solution ));
92110 }
93111 }
94112
95113 // get patch info
96114 if ($ e instanceof PatchException) {
97- self ::logError ("✗ Failed patch module: {$ e ->getPatchModule ()}" );
115+ self ::logError ("Failed patch module: {$ e ->getPatchModule ()}" );
98116 }
99117
100118 // get internal trace
101119 if ($ e instanceof SPCInternalException) {
102- self ::logError ('✗ Internal trace: ' );
120+ self ::logError ('Internal trace: ' );
103121 self ::logError (ConsoleColor::gray ("{$ e ->getTraceAsString ()}\n" ), 4 );
104122 }
105123
106124 // 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 ' ));
124136 }
125137
126138 self ::logError ("\n---------------------------------------- \n" );
@@ -142,20 +154,67 @@ public static function handleSPCException(SPCException $e): void
142154 public static function handleDefaultException (\Throwable $ e ): void
143155 {
144156 $ 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" );
146158 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 ;
149166 }
150167
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
152174 {
153175 $ spc_log = fopen (SPC_OUTPUT_LOG , 'a ' );
154176 $ msg = explode ("\n" , (string ) $ message );
155177 foreach ($ msg as $ v ) {
156178 $ line = str_pad ($ v , strlen ($ v ) + $ indent_space , ' ' , STR_PAD_LEFT );
157179 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+ }
159218 }
160219 }
161220}
0 commit comments