lint
This commit is contained in:
parent
8b71ef9c0d
commit
d804bb1fdb
|
@ -77,7 +77,7 @@ class RemoteLogger extends \WC_Log_Handler {
|
||||||
'host' => SafeGlobalFunctionProxy::wp_parse_url( SafeGlobalFunctionProxy::home_url(), PHP_URL_HOST ) ?? 'Unable to retrieve host',
|
'host' => SafeGlobalFunctionProxy::wp_parse_url( SafeGlobalFunctionProxy::home_url(), PHP_URL_HOST ) ?? 'Unable to retrieve host',
|
||||||
'tags' => array( 'woocommerce', 'php' ),
|
'tags' => array( 'woocommerce', 'php' ),
|
||||||
'properties' => array(
|
'properties' => array(
|
||||||
'wc_version' => $this->get_wc_version(), // TODO check this
|
'wc_version' => $this->get_wc_version(),
|
||||||
'php_version' => phpversion(),
|
'php_version' => phpversion(),
|
||||||
'wp_version' => SafeGlobalFunctionProxy::get_bloginfo( 'version' ) ?? 'Unable to retrieve wp version',
|
'wp_version' => SafeGlobalFunctionProxy::get_bloginfo( 'version' ) ?? 'Unable to retrieve wp version',
|
||||||
'request_uri' => $this->sanitize_request_uri( filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL ) ),
|
'request_uri' => $this->sanitize_request_uri( filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL ) ),
|
||||||
|
@ -250,7 +250,7 @@ class RemoteLogger extends \WC_Log_Handler {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( SafeGlobalFunctionProxy::is_wp_error( $response ) ) { // TODO: check this because the proxy doesn't return a WP_Error
|
if ( SafeGlobalFunctionProxy::is_wp_error( $response ) ) {
|
||||||
SafeGlobalFunctionProxy::wc_get_logger()->error( 'Failed to send the log to the remote logging service: ' . $response->get_error_message(), array( 'source' => 'remote-logging' ) );
|
SafeGlobalFunctionProxy::wc_get_logger()->error( 'Failed to send the log to the remote logging service: ' . $response->get_error_message(), array( 'source' => 'remote-logging' ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,16 @@ class RemoteLogger extends \WC_Log_Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current version is the latest, we don't want to log errors.
|
// If the current version is the latest, we don't want to log errors.
|
||||||
return version_compare( $this->get_wc_version(), $new_version, '>=' ); // TODO check this
|
return version_compare( $this->get_wc_version(), $new_version, '>=' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current WooCommerce version.
|
||||||
|
*
|
||||||
|
* @return string The current WooCommerce version.
|
||||||
|
*/
|
||||||
|
private function get_wc_version() {
|
||||||
|
return WC()->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -475,7 +484,7 @@ class RemoteLogger extends \WC_Log_Handler {
|
||||||
$whitelist = apply_filters( 'woocommerce_remote_logger_request_uri_whitelist', $default_whitelist );
|
$whitelist = apply_filters( 'woocommerce_remote_logger_request_uri_whitelist', $default_whitelist );
|
||||||
|
|
||||||
$parsed_url = SafeGlobalFunctionProxy::wp_parse_url( $request_uri );
|
$parsed_url = SafeGlobalFunctionProxy::wp_parse_url( $request_uri );
|
||||||
if ( ! isset( $parsed_url['query'] ) ) { // TODO: make sure this is failsafe
|
if ( ! is_array( $parsed_url ) || ! isset( $parsed_url['query'] ) ) {
|
||||||
return $request_uri;
|
return $request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,126 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Automattic\WooCommerce\Internal\Logging;
|
|
||||||
|
|
||||||
use Automattic\Jetpack\Constants;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UseNonBuiltInFunctions Trait
|
|
||||||
*
|
|
||||||
* This trait creates a wrapper for non-built-in functions for safety.
|
|
||||||
*
|
|
||||||
* @since 9.4.0
|
|
||||||
* @package Automattic\WooCommerce\Internal\Logging
|
|
||||||
*/
|
|
||||||
class SafeGlobalFunctionProxy {
|
|
||||||
|
|
||||||
private static function maybe_load_missing_function($name) {
|
|
||||||
$function_map = array(
|
|
||||||
'wp_parse_url' => ABSPATH . WPINC . '/http.php',
|
|
||||||
'home_url' => ABSPATH . WPINC . '/link-template.php',
|
|
||||||
'get_bloginfo' => ABSPATH . WPINC . '/general-template.php',
|
|
||||||
'get_option' => ABSPATH . WPINC . '/option.php',
|
|
||||||
'get_site_transient' => ABSPATH . WPINC . '/option.php',
|
|
||||||
'set_site_transient' => ABSPATH . WPINC . '/option.php',
|
|
||||||
'wp_safe_remote_post' => ABSPATH . WPINC . '/http.php',
|
|
||||||
'is_wp_error' => ABSPATH . WPINC . '/load.php',
|
|
||||||
'get_plugin_updates' => array( ABSPATH . 'wp-admin/includes/update.php', ABSPATH . 'wp-admin/includes/plugin.php' ),
|
|
||||||
'wp_get_environment_type' => ABSPATH . WPINC . '/load.php',
|
|
||||||
'wp_json_encode' => ABSPATH . WPINC . '/functions.php',
|
|
||||||
'wc_get_logger' => WC_ABSPATH . 'includes/class-wc-logger.php',
|
|
||||||
'wc_print_r' => WC_ABSPATH . 'includes/wc-core-functions.php',
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( ! function_exists( $name ) ) {
|
|
||||||
if ( isset( $function_map[ $name ] ) ) {
|
|
||||||
$files = (array) $function_map[ $name ];
|
|
||||||
foreach ($files as $file) {
|
|
||||||
require_once $file;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Exception("Function $name does not exist and could not be loaded.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy for trapping all calls on SafeGlobalFunctionProxy.
|
|
||||||
* Use this for calling WP and WC global functions safely.
|
|
||||||
* Example usage:
|
|
||||||
*
|
|
||||||
* SafeGlobalFunctionProxy::wp_parse_url('https://example.com', PHP_URL_PATH);
|
|
||||||
*
|
|
||||||
* @since 9.4.0
|
|
||||||
* @param string $name The name of the function to call.
|
|
||||||
* @param array $arguments The arguments to pass to the function.
|
|
||||||
* @return mixed The result of the function call, or null if an error occurs.
|
|
||||||
*/
|
|
||||||
public static function __callStatic($name, $arguments) {
|
|
||||||
set_error_handler(static function (int $type, string $message, string $file, int $line) {
|
|
||||||
if (__FILE__ === $file) {
|
|
||||||
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
|
||||||
$file = $trace[2]['file'] ?? $file;
|
|
||||||
$line = $trace[2]['line'] ?? $line;
|
|
||||||
}
|
|
||||||
throw new ErrorException($message, 0, $type, $file, $line);
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
self::maybe_load_missing_function($name);
|
|
||||||
$results = call_user_func_array($name, $arguments);
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
self::log_wrapper_error($name, $e->getMessage(), $arguments);
|
|
||||||
$results = null;
|
|
||||||
} finally {
|
|
||||||
restore_error_handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get_wc_version wrapper.
|
|
||||||
*
|
|
||||||
* @return string The WooCommerce version.
|
|
||||||
*
|
|
||||||
* @throws \Exception If get_wc_version function does not exist.
|
|
||||||
*/
|
|
||||||
protected function get_wc_version() {
|
|
||||||
try {
|
|
||||||
return Constants::get_constant( 'WC_VERSION' ) ?? 'unknown';
|
|
||||||
} catch ( \Throwable $e ) {
|
|
||||||
self::log_wrapper_error(
|
|
||||||
__FUNCTION__,
|
|
||||||
$e->getMessage(),
|
|
||||||
array()
|
|
||||||
);
|
|
||||||
|
|
||||||
return 'Unable to retrieve';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log wrapper function errors to "local logging" for debugging.
|
|
||||||
*
|
|
||||||
* @param string $function_name The name of the wrapped function.
|
|
||||||
* @param string $error_message The error message.
|
|
||||||
* @param array $context Additional context for the error.
|
|
||||||
*/
|
|
||||||
protected function log_wrapper_error( $function_name, $error_message, $context = array() ) {
|
|
||||||
self::maybe_load_missing_function('wc_get_logger');
|
|
||||||
|
|
||||||
wc_get_logger()->error(
|
|
||||||
'[Wrapper function error] ' . sprintf( 'Error in %s: %s', $function_name, $error_message ),
|
|
||||||
array_merge(
|
|
||||||
array(
|
|
||||||
'function' => $function_name,
|
|
||||||
'source' => 'remote-logging',
|
|
||||||
),
|
|
||||||
$context
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Internal\Logging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SafeGlobalFunctionProxy Class
|
||||||
|
*
|
||||||
|
* This class creates a wrapper for non-built-in functions for safety.
|
||||||
|
*
|
||||||
|
* @since 9.4.0
|
||||||
|
* @package Automattic\WooCommerce\Internal\Logging
|
||||||
|
*/
|
||||||
|
class SafeGlobalFunctionProxy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load missing function if we know where to find it.
|
||||||
|
* Modify this file to add more functions to the map.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the function to load.
|
||||||
|
* @return void
|
||||||
|
* @throws \Exception If the function is missing and could not be loaded.
|
||||||
|
*/
|
||||||
|
private static function maybe_load_missing_function( $name ) {
|
||||||
|
$function_map = array(
|
||||||
|
'wp_parse_url' => ABSPATH . WPINC . '/http.php',
|
||||||
|
'home_url' => ABSPATH . WPINC . '/link-template.php',
|
||||||
|
'get_bloginfo' => ABSPATH . WPINC . '/general-template.php',
|
||||||
|
'get_option' => ABSPATH . WPINC . '/option.php',
|
||||||
|
'get_site_transient' => ABSPATH . WPINC . '/option.php',
|
||||||
|
'set_site_transient' => ABSPATH . WPINC . '/option.php',
|
||||||
|
'wp_safe_remote_post' => ABSPATH . WPINC . '/http.php',
|
||||||
|
'is_wp_error' => ABSPATH . WPINC . '/load.php',
|
||||||
|
'get_plugin_updates' => array( ABSPATH . 'wp-admin/includes/update.php', ABSPATH . 'wp-admin/includes/plugin.php' ),
|
||||||
|
'wp_get_environment_type' => ABSPATH . WPINC . '/load.php',
|
||||||
|
'wp_json_encode' => ABSPATH . WPINC . '/functions.php',
|
||||||
|
'wc_get_logger' => WC_ABSPATH . 'includes/class-wc-logger.php',
|
||||||
|
'wc_print_r' => WC_ABSPATH . 'includes/wc-core-functions.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! function_exists( $name ) ) {
|
||||||
|
if ( isset( $function_map[ $name ] ) ) {
|
||||||
|
$files = (array) $function_map[ $name ];
|
||||||
|
foreach ( $files as $file ) {
|
||||||
|
require_once $file;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new \Exception( sprintf( 'Function %s does not exist and could not be loaded.', esc_html( $name ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy for trapping all calls on SafeGlobalFunctionProxy.
|
||||||
|
* Use this for calling WP and WC global functions safely.
|
||||||
|
* Example usage:
|
||||||
|
*
|
||||||
|
* SafeGlobalFunctionProxy::wp_parse_url('https://example.com', PHP_URL_PATH);
|
||||||
|
*
|
||||||
|
* @since 9.4.0
|
||||||
|
* @param string $name The name of the function to call.
|
||||||
|
* @param array $arguments The arguments to pass to the function.
|
||||||
|
* @return mixed The result of the function call, or null if an error occurs.
|
||||||
|
*/
|
||||||
|
public static function __callStatic( $name, $arguments ) {
|
||||||
|
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler -- Custom error handler is necessary to convert errors to exceptions
|
||||||
|
set_error_handler(
|
||||||
|
static function ( int $type, string $message, string $file, int $line ) {
|
||||||
|
if ( __FILE__ === $file ) {
|
||||||
|
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace -- Used to adjust file and line number for accurate error reporting
|
||||||
|
$trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3 );
|
||||||
|
$file = $trace[2]['file'] ?? $file;
|
||||||
|
$line = $trace[2]['line'] ?? $line;
|
||||||
|
}
|
||||||
|
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception is thrown here but handled securely elsewhere
|
||||||
|
throw new \ErrorException( $message, 0, $type, $file, $line );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
self::maybe_load_missing_function( $name );
|
||||||
|
$results = call_user_func_array( $name, $arguments );
|
||||||
|
} catch ( \Throwable $e ) {
|
||||||
|
self::log_wrapper_error( $name, $e->getMessage(), $arguments );
|
||||||
|
$results = null;
|
||||||
|
} finally {
|
||||||
|
restore_error_handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log wrapper function errors to "local logging" for debugging.
|
||||||
|
*
|
||||||
|
* @param string $function_name The name of the wrapped function.
|
||||||
|
* @param string $error_message The error message.
|
||||||
|
* @param array $context Additional context for the error.
|
||||||
|
*/
|
||||||
|
protected static function log_wrapper_error( $function_name, $error_message, $context = array() ) {
|
||||||
|
self::maybe_load_missing_function( 'wc_get_logger' );
|
||||||
|
|
||||||
|
wc_get_logger()->error(
|
||||||
|
'[Wrapper function error] ' . sprintf( 'Error in %s: %s', $function_name, $error_message ),
|
||||||
|
array_merge(
|
||||||
|
array(
|
||||||
|
'function' => $function_name,
|
||||||
|
'source' => 'remote-logging',
|
||||||
|
),
|
||||||
|
$context
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue