From a6413da67a4579866f0fd0323ddb23a7b6b9654a Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 18 Sep 2026 17:00:53 +0000
Subject: [PATCH] =Cleaning up the Integrations setup a bit, started the Helcim integration work too

---
 inc/managers/Errors.php |  513 ++------------------------------------------------------
 1 files changed, 20 insertions(+), 493 deletions(-)

diff --git a/inc/managers/Errors.php b/inc/managers/Errors.php
index e45050c..40d0252 100644
--- a/inc/managers/Errors.php
+++ b/inc/managers/Errors.php
@@ -13,503 +13,30 @@
 class Errors
 {
 	use Instance;
-    protected int $notification_threshold = 5; // Critical errors within 1 hour
 
-    protected array $error_levels = [
-        'debug' => 0,
-        'info' => 1,
-        'warning' => 2,
-        'error' => 3,
-        'critical' => 4
-    ];
-
-	protected CustomTable $table;
-
-    private function __construct()
-    {
-		$this->defineTables();
-//        global $wpdb;
-//        $this->wpdb = $wpdb;
-//		$this->tableName = $wpdb->prefix . BASE . 'error_log';
-
-        add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
-
-        // Hook our send function to the cron event
-        add_action('jvb_daily_error_summary', [$this, 'sendErrorSummary']);
-
-        jvb_register_do_once('error_admin_action_registered', [$this, 'registerAdminAction']);
-//        add_filter(BASE.'admin_action_filter', [$this, 'adminActionFilter'], 10, 3);
-    }
-
-	public function defineTables():void
+	/**
+	 * @param string $message
+	 * @param array $context
+	 * @return void
+	 */
+	public static function log(string $message, array $context = []):void
 	{
-		$table = CustomTable::for('error_log');
-		$table->setColumns([
-			'id'			=> 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
-			'error_type'	=> 'varchar(50) NOT NULL',
-			'component'		=> 'varchar(100) NOT NULL',
-			'method'		=> 'varchar(100) DEFAULT NULL',
-			'page_url'		=> 'varchar(255) DEFAULT NULL',
-			'message'		=> 'text NOT NULL',
-			'context'		=> 'JSON',
-			'severity'		=> 'ENUM(\'high\',\'normal\',\'low\') DEFAULT \'normal\'',
-			'user_id'		=> $table->getUserIDType().' DEFAULT NULL',
-			'user_was_logged_in'	=> 'tinyint(1) NOT NULL',
-			'source'		=> 'ENUM(\'frontend\', \'backend\') NOT NULL',
-			'created_at'	=> 'timestamp DEFAULT CURRENT_TIMESTAMP',
-		]);
-
-		$table->setKeys([
-			['key' => 'PRIMARY', 'value' => 'id'],
-			'`created_at` (`created_at`)',
-			'`component_severity_date` (`component`, `severity`, `created_at`)',
-			'`error_type_date` (`error_type`, `created_at`)',
-			'`severity_date` (`severity`, `created_at`)'
-		]);
-
-		$table->defineTable();
-		$this->table = $table;
-	}
-    public function registerAdminAction():void
-    {
-        $admin = AdminPages::getInstance();
-
-        $admin->registerSubpage(
-            'Error Log',
-            'Errors',
-            'manage_options',
-            'jvb-error-log',
-            [$this, 'renderAdminPage'],
-        );
-    }
-
-    /**
-     * Process error log operations queued through OperationQueue
-     *
-     * @param WP_Error|array $result The result we are filtering
-     * @param object $operation The operation information
-     * @param array $data The current chunk of data to process
-     *
-     * @return WP_Error|array Either the unfiltered WP_Error, or the result of the operation
-     */
-    public function processOperation(WP_Error|array $result, object $operation, array $data):WP_Error|array
-    {
-        if ($operation->type !== 'error_log') {
-            return $result;
-        }
-
-        try {
-
-            // Extract error data
-            $component = sanitize_text_field($data['component'] ?? '');
-            $message = sanitize_textarea_field($data['message'] ?? '');
-            $context = $data['context'] ?? [];
-            $severity = sanitize_text_field($data['severity'] ?? 'error');
-
-            // Validate severity level
-            if (!array_key_exists($severity, $this->error_levels)) {
-                $severity = 'error'; // Default to error if invalid severity provided
-            }
-
-            // Determine error type from context or use component as fallback
-            $error_type = sanitize_text_field($context['error_type'] ?? $component);
-
-            // Store context as JSON
-            $context_json = json_encode($context);
-            if (json_last_error() !== JSON_ERROR_NONE) {
-                // If JSON encoding fails, store only basic info
-                $context_json = json_encode([
-                    'error' => 'Failed to encode original context',
-                    'json_error' => json_last_error_msg()
-                ]);
-            }
-
-            // Insert into database
-            $result = $this->table->insert(
-                [
-                    'error_type' => $error_type,
-                    'component' => $component,
-                    'message' => $message,
-                    'context' => $context_json,
-                    'severity' => $severity,
-                    'user_id' => get_current_user_id(),
-                    'created_at' => current_time('mysql')
-                ]
-            );
-
-            if (!$result) {
-                // If insert fails, log to PHP error log as fallback
-                error_log("[ErrorHandler] Database insert failed: " . $this->table->getLastError());
-                return [
-					'success'	=> false,
-					'message'	=> "[ErrorHandler] Database insert failed: " . $this->table->getLastError()
-				];
-            }
-
-            // Potentially track error metrics or trigger additional actions for critical errors
-            if ($severity === 'critical') {
-                $this->checkErrorThreshold($error_type, $component);
-            }
-
-            return [
-                'success' => true,
-                'result'	=> $result
-            ];
-
-        } catch (Exception $e) {
-            // Fallback to PHP error log if our error handler itself fails
-            error_log("[ErrorHandler Exception] " . $e->getMessage());
-            return [
-				'success'	=> false,
-				'message'	=> $e->getMessage()
-			];
-        }
-    }
-
-    /**
-     * Check if error threshold has been reached for a specific error type/component
-     * and take additional actions if needed
-     *
-     * @param string $error_type The type of error
-     * @param string $component The component where the error occurred
-     */
-    protected function checkErrorThreshold(string $error_type, string $component)
-    {
-        // Get count of similar critical errors in the last hour
-		$count = $this->table->count([
-			'error_type' => $error_type,
-			'component' => $component,
-			'severity' => $this->error_levels[$error_type],
-			'created_at' => ['>','DATE_SUB(NOW(), INTERVAL 1 HOUR)']
-		]);
-
-        // If threshold reached, take additional actions (e.g., notify developers)
-        if ($count >= $this->notification_threshold) {
-            // You could send an urgent notification, Slack message, etc.
-            $admin_email = get_option('admin_email');
-            $subject = "[URGENT] Error Threshold Exceeded for {$component}";
-            $message = "The error '{$error_type}' in component '{$component}' has occurred {$count} times in the last hour.";
-
-            wp_mail($admin_email, $subject, $message);
-        }
-    }
-
-
-    /**
-     * @param string $component Where the error is being logged from
-     * @param string $message The error message, usually extracted from $e->getMessage())
-     * @param array $context Additional context (i.e: data that was attempted to be acted on)
-     * @param string $severity
-     *
-     * @return array
-     */
-	public function log(string $component, string $message, array $context = [], string $severity = 'error'): array
-	{
-		try {
-			// Validate severity
-			if (!array_key_exists($severity, $this->error_levels)) {
-				$severity = 'error';
-			}
-
-			// Extract info
-			$error_type = sanitize_text_field($context['error_type'] ?? $component);
-			$method = isset($context['method']) ? sanitize_text_field($context['method']) : null;
-			$page_url = isset($context['url']) ? esc_url_raw($context['url']) : null;
-			$user_id = get_current_user_id();
-			$user_was_logged_in = $user_id > 0 || (!empty($context['isLoggedIn']));
-
-			// Determine source from context
-			$source = $context['source'] ?? (isset($context['url']) ? 'frontend' : 'backend');
-
-			$result = $this->table->insert(
-				[
-					'error_type' => $error_type,
-					'component' => $component,
-					'method' => $method,
-					'page_url' => $page_url,
-					'message' => sanitize_textarea_field($message),
-					'context' => json_encode($context),
-					'severity' => $severity,
-					'user_id' => $user_id ?: null,
-					'user_was_logged_in' => $user_was_logged_in ? 1 : 0,
-					'source' => $source,
-					'created_at' => current_time('mysql')
-				]);
-
-			if (!$result) {
-				error_log("[ErrorHandler] Database insert failed: " . $this->table->getLastError());
-				return ['success' => false, 'message' => $this->table->getLastError()];
-			}
-
-			if ($severity === 'critical') {
-				$this->checkErrorThreshold($error_type, $component);
-			}
-
-			return ['success' => true, 'id' => $result];
-
-		} catch (Exception $e) {
-			error_log("[ErrorHandler Exception] " . $e->getMessage());
-			return ['success' => false, 'message' => $e->getMessage()];
+		$msg = '{'.BASE.'}';
+		if (array_key_exists('class', $context)) {
+			$msg .= '['.$context['class'].']';
+			unset($context['class']);
 		}
-	}
-
-    /**
-     * @param string $component What class or function logs the error
-     * @param string $message Details on the error
-     * @param array $context additional context of the data that was being processed
-     *
-     * @return bool Whether the notification is sent successfully
-     */
-	protected function notifyAdmin(string $component, string $message, array $context):bool
-	{
-		$admin_email = get_option('admin_email');
-		$subject = "[" . get_bloginfo('name') . " Critical Error] {$component}";
-
-		$body = Emails::getInstance()->alert(
-			'A critical error has occurred and requires immediate attention',
-			'error'
-		);
-
-		$body .= Emails::getInstance()->h2('Error Details');
-		$body .= Emails::getInstance()->card(
-			'<p><strong>Component:</strong> ' . esc_html($component) . '</p>' .
-			'<p><strong>Message:</strong></p>' .
-			Emails::getInstance()->codeBlock($message),
-			'Error Information'
-		);
-
+		if (array_key_exists('method', $context)) {
+			$msg .= '::'.$context['method'];
+			unset($context['method']);
+		}
+		if (array_key_exists('function', $context)) {
+			$msg .= $context['function'];
+			unset($context['function']);
+		}
+		error_log($msg.' '.$message);
 		if (!empty($context)) {
-			$body .= Emails::getInstance()->h3('Additional Context');
-			$body .= Emails::getInstance()->codeBlock(json_encode($context, JSON_PRETTY_PRINT));
+			error_log('Context: '.print_r($context, true));
 		}
-
-		return Emails::getInstance()->sendEmail($admin_email, $subject, $body, 'CRITICAL ERROR');
 	}
-
-    /**
-     * Gather summary of the most important errors
-	 * @param ?string $start_date Defaults to today
-	 * @param ?string $end_date Defaults to today
-     * @return array
-     */
-	public function gatherErrorSummary(?string $start_date = null, ?string $end_date = null): array
-	{
-		if (!$start_date) {
-			$start_date = gmdate('Y-m-d 00:00:00', strtotime('-1 day'));
-		}
-		if (!$end_date) {
-			$end_date = gmdate('Y-m-d 23:59:59');
-		}
-
-		// Most frequent error patterns (deduplicated by component/method/message)
-		$frequent = $this->table->getMany([
-			'where' => [
-				'created_at'	=> ['BETWEEN', "{$start_date} AND {$end_date}"]
-			]
-		]);
-
-		return [
-			'errors'	=> $frequent,
-			'date_range' => ['start' => $start_date, 'end' => $end_date]
-		];
-	}
-
-    /**
-     * Send daily error summary email to administrator
-     * @return bool Whether email is sent
-     */
-	public function sendErrorSummary():bool
-	{
-		$summary = $this->gatherErrorSummary();
-
-		if (empty($summary['frequent']) && empty($summary['critical'])) {
-			return false;
-		}
-
-		$admin_email = get_option('admin_email');
-		$site_name = get_bloginfo('name');
-		$yesterday = date('Y-m-d', strtotime('-1 day'));
-		$subject = "[{$site_name}] Daily Error Summary - " . date('Y-m-d');
-
-		// Header with alert
-		$body = Emails::getInstance()->h1('Daily Error Summary');
-		$body .= sprintf('<p>Error summary for <strong>%s</strong></p>', $yesterday);
-
-		// Summary stats in a grid
-		if (!empty($summary['stats'])) {
-			$stats = [
-				Emails::getInstance()->stat($summary['stats']->total_errors, 'Total Errors'),
-				Emails::getInstance()->stat($summary['stats']->critical_count, 'Critical', 'Requires attention'),
-				Emails::getInstance()->stat($summary['stats']->error_count, 'Errors'),
-				Emails::getInstance()->stat($summary['stats']->warning_count, 'Warnings')
-			];
-			$body .= Emails::getInstance()->grid($stats, 4);
-		}
-
-		// Alert if critical errors exist
-		if (!empty($summary['critical'])) {
-			$body .= Emails::getInstance()->alert(
-				sprintf('Found %d critical errors that need immediate attention', count($summary['critical'])),
-				'error'
-			);
-		}
-
-		$body .= Emails::getInstance()->spacer();
-
-		// Frequent errors section
-		if (!empty($summary['frequent'])) {
-			$body .= Emails::getInstance()->h2('Most Frequent Errors');
-
-			foreach ($summary['frequent'] as $error) {
-				$cardContent = Emails::getInstance()->badge($error->count . 'x', 'warning') . ' ';
-				$cardContent .= '<strong>' . esc_html($error->error_type) . '</strong>';
-				$cardContent .= '<p style="margin:10px 0 5px 0;font-size:13px;">' . esc_html(wp_trim_words($error->message, 15)) . '</p>';
-				$cardContent .= '<p style="margin:0;font-size:12px;color:' . Emails::getInstance()->colours['dark-200'] . ';">
-                Source: ' . esc_html($error->source) . ' |
-                Logged in: ' . $error->logged_in_count . ' |
-                Logged out: ' . $error->logged_out_count . '
-            </p>';
-
-				$body .= Emails::getInstance()->card($cardContent, $error->component);
-			}
-		}
-
-		// Critical errors section
-		if (!empty($summary['critical'])) {
-			$body .= Emails::getInstance()->spacer(30);
-			$body .= Emails::getInstance()->h2('Recent Critical Errors');
-
-			foreach ($summary['critical'] as $error) {
-				$cardContent = '<p><strong>Time:</strong> ' . esc_html($error->created_at) . '</p>';
-				$cardContent .= '<p><strong>Message:</strong></p>';
-				$cardContent .= Emails::getInstance()->codeBlock($error->message);
-
-				// Include context if available
-				if (!empty($error->context)) {
-					$context = json_decode($error->context, true);
-					if (is_array($context)) {
-						$cardContent .= '<p><strong>Context:</strong></p>';
-						$cardContent .= Emails::getInstance()->codeBlock(json_encode($context, JSON_PRETTY_PRINT));
-					}
-				}
-
-				$body .= Emails::getInstance()->card($cardContent, $error->component . ': ' . $error->error_type);
-			}
-		}
-
-		// Dashboard link
-		$admin_url = admin_url('admin.php?page=jvb-error-logs');
-		$body .= Emails::getInstance()->spacer(30);
-		$body .= Emails::getInstance()->button($admin_url, 'View Detailed Logs');
-
-		return Emails::getInstance()->sendEmail($admin_email, $subject, $body, 'ERROR SUMMARY');
-	}
-
-    /**
-     * Get HTML version of the error summary for nicer emails
-     *
-     * @param array $summary The error summary data
-     * @return string HTML formatted error summary
-     */
-    protected function getHtmlErrorSummary(array $summary):string
-    {
-        $html = '<div style="font-family: sans-serif; max-width: 800px; margin: 0 auto;">';
-        $html .= '<h1 style="color:#FF0080;border-bottom:2px solid #1B1B1B;padding-bottom:10px;">Error Summary</h1>';
-
-        // Frequent errors table
-        if (!empty($summary['frequent'])) {
-            $html .= '<h2>Most Frequent Errors</h2>';
-            $html .= '<table style="width: 100%; border-collapse: collapse; margin-bottom: 20px;">';
-            $html .= '<tr style="background-color: #1B1B1B; color: #EFEFEF;">';
-            $html .= '<th style="padding: 8px; text-align: left; border: 1px solid #ddd;">Component</th>';
-            $html .= '<th style="padding: 8px; text-align: left; border: 1px solid #ddd;">Error Type</th>';
-            $html .= '<th style="padding: 8px; text-align: left; border: 1px solid #ddd;">Message</th>';
-            $html .= '<th style="padding: 8px; text-align: center; border: 1px solid #ddd;">Count</th>';
-            $html .= '</tr>';
-
-            foreach ($summary['frequent'] as $error) {
-                $html .= '<tr>';
-                $html .= '<td style="padding:8px;border:1px solid #ddd;">' . esc_html($error->component) . '</td>';
-                $html .= '<td style="padding:8px;border:1px solid #ddd;">' . esc_html($error->error_type) . '</td>';
-                $html .= '<td style="padding:8px;border:1px solid #ddd;">' . esc_html(wp_trim_words($error->message, 10, '...')) . '</td>';
-                $html .= '<td style="padding:8px;border:1px solid #ddd;text-align:center;"><strong>' . esc_html($error->count) . '</strong></td>';
-                $html .= '</tr>';
-            }
-
-            $html .= '</table>';
-        }
-
-        // Critical errors section
-        if (!empty($summary['critical'])) {
-            $html .= '<h2>Recent Critical Errors</h2>';
-
-            foreach ($summary['critical'] as $error) {
-                $html .= '<div style="margin-bottom: 20px; padding: 15px; border-left: 4px solid #FF0080; background-color: #fff9fb;">';
-                $html .= '<h3 style="margin-top: 0; color: #1B1B1B;">' . esc_html($error->component) . ': ' . esc_html($error->error_type) . '</h3>';
-                $html .= '<p><strong>Time:</strong> ' . esc_html($error->created_at) . '</p>';
-                $html .= '<p><strong>Message:</strong> ' . esc_html($error->message) . '</p>';
-
-                // Context display
-                if (!empty($error->context)) {
-                    $context = json_decode($error->context, true);
-                    if (is_array($context)) {
-                        $html .= '<div style="margin-top: 10px;">';
-                        $html .= '<strong>Context:</strong>';
-                        $html .= '<pre style="background-color: #f5f5f5; padding: 10px; border-radius: 4px; overflow: auto; max-height: 200px;">';
-                        $html .= esc_html(json_encode($context, JSON_PRETTY_PRINT));
-                        $html .= '</pre>';
-                        $html .= '</div>';
-                    }
-                }
-
-                $html .= '</div>';
-            }
-        }
-
-        // Dashboard link
-        $admin_url = admin_url('admin.php?page=jvb-error-logs');
-        $html .= '<p style="margin-top: 30px; padding-top: 15px; border-top: 1px solid #ddd;">';
-        $html .= '<a href="' . esc_url($admin_url) . '" style="display: inline-block; background-color: #FF0080; color: white; padding: 10px 15px; text-decoration: none; border-radius: 4px;">View All Errors in Dashboard</a>';
-        $html .= '</p>';
-
-        $html .= '</div>';
-
-        return $html;
-    }
-
-    public function renderAdminPage()
-    {
-        ?>
-        <h1>Error Logs</h1>
-        <?php
-    }
-
-    public function getErrors(WP_REST_Request $request) {
-        $params = $this->buildParams($request);
-
-    }
-
-
-
-    protected function buildParams(WP_REST_Request $request):array {
-        $allowedSeverity = [
-            'all',
-            'notice',
-            'warning',
-            'error',
-            'critical',
-        ];
-        $allowedComponents = [
-            'all',
-            //Get all components
-        ];
-        $severity = $request->get_param('severity')??'all';
-        $component = $request->get_param('component')??'all';
-
-        return [
-            'page'  => (int)$request->get_param('page'),
-            'severity'  => (in_array($severity, $allowedSeverity)) ? $severity : 'all',
-            'component' => (in_array($component, $allowedComponents)) ? $component : 'all',
-        ];
-    }
 }

--
Gitblit v1.10.0