api_failures[] = [ 'timestamp' => current_time('mysql'), 'endpoint' => $endpoint, 'status_code' => $status_code, 'error' => $error_message, 'api_key' => $api_key ? substr($api_key, 0, 8) . '...' : null, ]; // Keep only last 10 failures if (count($this->api_failures) > 10) { array_shift($this->api_failures); } // Log to local error log $this->log_error([ 'type' => 'api_failure', 'level' => 'warn', 'endpoint' => $endpoint, 'status_code' => $status_code, 'error' => $error_message, ]); // Report to backend if 3+ failures if (count($this->api_failures) >= 3) { $this->report_to_backend([ 'type' => 'api_failures', 'count' => count($this->api_failures), 'last_error' => end($this->api_failures), ]); } // Store in transient for admin notice set_transient('wpquotepro_api_error', [ 'endpoint' => $endpoint, 'status' => $status_code, 'message' => $error_message, 'time' => current_time('mysql'), ], 12 * HOUR_IN_SECONDS); } /** * Generic error logging */ private function log_error($data) { $this->error_count++; // Write to WordPress error log wpquotepro_log($data); // Store in transient for admin dashboard $errors = get_transient('wpquotepro_recent_errors') ?: []; array_push($errors, [ 'data' => $data, 'time' => current_time('mysql'), ]); // Keep only last 20 errors if (count($errors) > 20) { array_shift($errors); } set_transient('wpquotepro_recent_errors', $errors, 24 * HOUR_IN_SECONDS); } /** * Report error to backend */ public function report_to_backend($error_data) { $api_key = get_option('wpquotepro_api_key'); $site_url = get_option('wpquotepro_site_url'); if (!$api_key || !$site_url) { return; } $endpoint = WPQUOTEPRO_BACKEND_BASE . '/api/v1/plugin/report-error'; if (!$endpoint) { return; } $body = array_merge([ 'api_key' => $api_key, 'site_url' => $site_url, 'plugin_version' => WPQUOTEPRO_VERSION, 'php_version' => PHP_VERSION, 'wordpress_version' => get_bloginfo('version'), 'timestamp' => current_time('mysql'), ], $error_data); wp_remote_post($endpoint, [ 'timeout' => 5, 'sslverify' => true, 'body' => json_encode($body), 'headers' => ['Content-Type' => 'application/json'], 'blocking' => false, ]); } /** * Show admin notices for critical issues */ public function show_admin_notices() { if (!current_user_can('manage_options')) { return; } // API error notice $api_error = get_transient('wpquotepro_api_error'); if ($api_error) { ?>
GresQuote: