getMessage(), $error->getFile(), $error->getLine() ); // PHP reports subclasses of ParseError and CompileError as E_ERROR, so match exact classes. $error_types = array( \ParseError::class => E_PARSE, \CompileError::class => E_COMPILE_ERROR, ); try { wc_get_logger()->critical( $log_message, array( 'source' => 'store-api', 'error' => array( 'type' => $error_types[ get_class( $error ) ] ?? E_ERROR, 'file' => $error->getFile(), 'line' => $error->getLine(), ), // Same shape the fatal-error shutdown handler logs, so log handlers and readers see one trace format. 'backtrace' => array_slice( explode( "\n", $error->getTraceAsString() ), 0, self::MAX_BACKTRACE_FRAMES ), // These failures reached remote logging as fatals before the dispatchers caught them. 'remote-logging' => true, ) ); } catch ( \Throwable $logging_error ) { // Logging must not prevent the safe response, but a failure that also broke logging should not vanish. error_log( $log_message . ' (logging failed: ' . $logging_error->getMessage() . ')' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } $message = $public_message ?? __( 'Internal server error', 'woocommerce' ); $data = array( 'status' => 500 ); if ( self::can_expose_details() ) { $message = $error->getMessage(); $data['exception_class'] = get_class( $error ); } return new WP_Error( 'woocommerce_rest_unknown_server_error', $message, $data ); } /** * Whether the current request may receive the failure message and class. * * @return bool */ private static function can_expose_details(): bool { /** * Filters whether unexpected Store API failures include the error message and exception class in the response. * * Details are only ever sent to users who can manage WooCommerce; this filter cannot bypass that check. It defaults to WP_DEBUG so store staff can debug a production store without enabling debug mode site-wide. * * @since 11.3.0 * * @param bool $expose_error_details Whether to include the error message and exception class. Defaults to WP_DEBUG. * * @return bool */ $expose_error_details = (bool) apply_filters( 'woocommerce_store_api_expose_error_details', Constants::is_true( 'WP_DEBUG' ) ); return $expose_error_details && current_user_can( 'manage_woocommerce' ); } }