AlkantarClanX12

Your IP : 216.73.217.24


Current Path : /www/capitalgmcbuickregina_830/public/wp-content/plugins/leadbox/includes/
Upload File :
Current File : /www/capitalgmcbuickregina_830/public/wp-content/plugins/leadbox/includes/health-check.php

<?php

/**
 * Dealership Health Check Module
 * Add this code to your existing core plugin
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class DealershipHealthCheck
{

    private $secret_key;
    private $inventory_file_path;
    private $max_file_age = 7200; // 120 minutes in seconds
    private $max_response_time = 10; // seconds
    private $min_new_vehicles = 5;
    private $min_used_vehicles = 5;

    public function __construct()
    {
        // In the construct, we ONLY register hooks.
        // Logic that uses WP functions should go in those hooks.

        $this->inventory_file_path = WP_CONTENT_DIR . '/uploads/data/inventory.json';

        // Execute late initialization (key generation and constant adjustments) on 'init'
        add_action('init', array($this, 'late_initialization'), 0);

        // Register REST API endpoint (can be done in the constructor).
        add_action('rest_api_init', array($this, 'register_health_endpoint'));

        // Add admin menu page (admin_menu is called late enough)
        add_action('admin_menu', array($this, 'add_admin_menu'));

        // Add settings link on plugins page (optional - if you want)
        add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'add_settings_link'));
    }

    /**
     * Logic that requires loaded functions from the WordPress core.
     * Runs in the 'init' hook.
     */
    public function late_initialization()
    {
        // Generate or retrieve the secret key
        $this->secret_key = get_option('dealership_health_check_secret');
        if (empty($this->secret_key)) {
            $this->secret_key = wp_generate_password(32, false);
            update_option('dealership_health_check_secret', $this->secret_key);
        }

        // Apply customizations from wp-config.php (WITHOUT "Undefined constant" error)
        // The constant is used without the '$' prefix since defined() guarantees its existence.
        /*
        // If the constant is defined, use its value; otherwise, use the class's default value.
        if (defined('HEALTH_CHECK_MAX_FILE_AGE')) {
            $this->max_file_age = HEALTH_CHECK_MAX_FILE_AGE;
        }

        if (defined('HEALTH_CHECK_MIN_NEW_VEHICLES')) {
            $this->min_new_vehicles = HEALTH_CHECK_MIN_NEW_VEHICLES;
        }

        if (defined('HEALTH_CHECK_MIN_USED_VEHICLES')) {
            $this->min_used_vehicles = HEALTH_CHECK_MIN_USED_VEHICLES;
        }
            */
    }

    /**
     * Add admin submenu page under Leadbox Settings
     */
    public function add_admin_menu()
    {
        // We use add_submenu_page() to nest the page.
        // The first parameter is the parent menu slug. We assume 'leadbox-settings'.
        add_submenu_page(
            'leadbox-settings',                // Parent menu SLUG
            'Health Check',                    // Page title
            'Health Check',                    // Menu title
            'manage_options',                  // Capability required
            'dealership-health-check',         // Menu slug 
            array($this, 'render_admin_page')  // Callback function
        );
    }

    /**
     * IMPORTANT NOTE: We no longer need the add_settings_link() method
     * that uses plugin_basename(__FILE__) because the menu now loads
     * when the parent plugin registers its menu. You can keep the filter,
     * but the link on the plugins page will now point to the submenu.
     */

    /**
     * Add settings link on plugins page
     */
    public function add_settings_link($links)
    {
        $settings_link = '<a href="' . admin_url('admin.php?page=dealership-health-check') . '">View Health Check</a>';
        array_unshift($links, $settings_link);
        return $links;
    }

    /**
     * Render admin page
     */
    public function render_admin_page()
    {
        // Handle secret key regeneration
        if (isset($_POST['regenerate_key']) && check_admin_referer('regenerate_health_check_key')) {
            $this->secret_key = wp_generate_password(32, false);
            update_option('dealership_health_check_secret', $this->secret_key);
            echo '<div class="notice notice-success"><p>Secret key regenerated successfully!</p></div>';
        }

        // Handle test health check
        $test_result = null;
        if (isset($_POST['test_health_check']) && check_admin_referer('test_health_check')) {
            $test_result = $this->run_test_check();
        }

        // We use home_url() which returns the base URL of the site, which is better for these cases.
        $health_url = rest_url('lbx/health') . '?key=' . $this->secret_key;
        $site_url = get_site_url();
        $site_name = get_bloginfo('name');

?>
        <div class="wrap">
            <h1>
                <span class="dashicons dashicons-heart" style="font-size: 30px; width: 30px; height: 30px;"></span>
                Dealership Health Check
            </h1>

            <div class="card" style="max-width: 800px; margin-top: 20px;">
                <h2>Health Check Endpoint</h2>
                <p>Use this URL in Uptime Robot to monitor your website's critical functionality.</p>

                <table class="form-table">
                    <tr>
                        <th scope="row">Site Name:</th>
                        <td><strong><?php echo esc_html($site_name); ?></strong></td>
                    </tr>
                    <tr>
                        <th scope="row">Site URL:</th>
                        <td><?php echo esc_html($site_url); ?></td>
                    </tr>
                    <tr>
                        <th scope="row">Health Check URL:</th>
                        <td>
                            <input type="text" readonly value="<?php echo esc_attr($health_url); ?>"
                                style="width: 100%; font-family: monospace; padding: 8px;"
                                onclick="this.select();" />
                            <p class="description">Click to select, then copy this entire URL for Uptime Robot</p>
                        </td>
                    </tr>
                    <tr>
                        <th scope="row">Secret Key:</th>
                        <td>
                            <code style="background: #f0f0f1; padding: 8px; display: block; word-break: break-all;">
                                <?php echo esc_html($this->secret_key); ?>
                            </code>
                            <p class="description">Keep this secure. Only share with authorized personnel.</p>
                        </td>
                    </tr>
                </table>

                <form method="post" style="margin-top: 20px;">
                    <?php wp_nonce_field('regenerate_health_check_key'); ?>
                    <button type="submit" name="regenerate_key" class="button button-secondary"
                        onclick="return confirm('This will invalidate your current Uptime Robot configuration. Continue?');">
                        Regenerate Secret Key
                    </button>
                </form>
            </div>

            <div class="card" style="max-width: 800px; margin-top: 20px;">
                <h2>Test Health Check</h2>
                <p>Test your health check configuration without using Uptime Robot.</p>

                <form method="post">
                    <?php wp_nonce_field('test_health_check'); ?>
                    <button type="submit" name="test_health_check" class="button button-primary">
                        Run Health Check Now
                    </button>
                </form>

                <?php if ($test_result): ?>
                    <div style="margin-top: 20px; padding: 15px; background: <?php echo $test_result['status'] === 'healthy' ? '#d4edda' : '#f8d7da'; ?>; border-left: 4px solid <?php echo $test_result['status'] === 'healthy' ? '#28a745' : '#dc3545'; ?>;">
                        <h3 style="margin-top: 0;">
                            <?php if ($test_result['status'] === 'healthy'): ?>
                                ✅ Status: Healthy
                            <?php else: ?>
                                ❌ Status: Unhealthy
                            <?php endif; ?>
                        </h3>
                        <p><strong>Response Time:</strong> <?php echo $test_result['response_time']; ?>s</p>

                        <table class="widefat" style="margin-top: 15px;">
                            <thead>
                                <tr>
                                    <th>Check</th>
                                    <th>Status</th>
                                    <th>Details</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach ($test_result['checks'] as $check_name => $check_data): ?>
                                    <tr>
                                        <td><strong><?php echo esc_html(ucwords(str_replace('_', ' ', $check_name))); ?></strong></td>
                                        <td>
                                            <?php if ($check_data['passed']): ?>
                                                <span style="color: #28a745;">✓ Passed</span>
                                            <?php else: ?>
                                                <span style="color: #dc3545;">✗ Failed</span>
                                            <?php endif; ?>
                                        </td>
                                        <td>
                                            <?php echo esc_html($check_data['message']); ?>
                                            <?php if (isset($check_data['new_vehicles'])): ?>
                                                <br><small>New: <?php echo $check_data['new_vehicles']; ?> | Used: <?php echo $check_data['used_vehicles']; ?></small>
                                            <?php endif; ?>
                                            <?php if (isset($check_data['last_modified'])): ?>
                                                <br><small>Last Modified: <?php echo $check_data['last_modified']; ?></small>
                                            <?php endif; ?>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                <?php endif; ?>
            </div>

            <div class="card" style="max-width: 800px; margin-top: 20px;">
                <h2>What Gets Monitored</h2>
                <ul style="line-height: 1.8;">
                    <li><strong>Database:</strong> WordPress database connectivity</li>
                    <li><strong>File Exists:</strong> Inventory file at /wp-content/uploads/data/inventory.json</li>
                    <li><strong>File Age:</strong> Must be updated within <?php echo ($this->max_file_age / 60); ?> minutes</li>
                    <li><strong>Vehicle Counts:</strong> Valid JSON with at least <?php echo $this->min_new_vehicles; ?> vehicles</li>
                    <li><strong>Response Time:</strong> Check must complete in under <?php echo $this->max_response_time; ?> seconds</li>
                </ul>
            </div>

            <div class="card" style="max-width: 800px; margin-top: 20px;">
                <h2>Quick Setup for Uptime Robot</h2>
                <ol style="line-height: 1.8;">
                    <li>Copy the <strong>Health Check URL</strong> above</li>
                    <li>Log in to Uptime Robot → Add New Monitor</li>
                    <li>Monitor Type: <strong>HTTP(s)</strong></li>
                    <li>Friendly Name: <strong><?php echo esc_html($site_name); ?> - Health Check</strong></li>
                    <li>URL: Paste the Health Check URL</li>
                    <li>Monitoring Interval: <strong>5 minutes</strong></li>
                    <li>Monitor Timeout: <strong>30 seconds</strong></li>
                    <li>Click <strong>Create Monitor</strong></li>
                </ol>
                <p><a href="<?php echo admin_url('admin.php?page=dealership-health-check-docs'); ?>" class="button">View Full Documentation</a></p>
            </div>
        </div>

        <style>
            .card h2 {
                margin-top: 0;
            }

            .form-table th {
                width: 200px;
            }
        </style>
<?php
    }

    /**
     * Run test health check
     */
    private function run_test_check()
    {
        $start_time = microtime(true);

        $checks = array();
        $overall_status = 'healthy';

        // Run all checks
        $checks['database'] = $this->check_database();
        if (!$checks['database']['passed']) {
            $overall_status = 'unhealthy';
        }

        $checks['file_exists'] = $this->check_file_exists();
        if (!$checks['file_exists']['passed']) {
            $overall_status = 'unhealthy';
        }

        if ($checks['file_exists']['passed']) {
            $checks['file_age'] = $this->check_file_age();
            if (!$checks['file_age']['passed']) {
                $overall_status = 'unhealthy';
            }

            // Vehicle counts validates JSON implicitly
            $checks['vehicle_counts'] = $this->check_vehicle_counts();
            if (!$checks['vehicle_counts']['passed']) {
                $overall_status = 'unhealthy';
            }
        }

        $response_time = round(microtime(true) - $start_time, 3);
        $checks['response_time'] = array(
            'passed' => $response_time < $this->max_response_time,
            'message' => $response_time . 's',
            'threshold' => $this->max_response_time . 's'
        );

        if ($response_time >= $this->max_response_time) {
            $overall_status = 'unhealthy';
        }

        return array(
            'status' => $overall_status,
            'checks' => $checks,
            'response_time' => $response_time
        );
    }

    /**
     * Register the health check REST endpoint
     */
    public function register_health_endpoint()
    {
        register_rest_route('lbx', '/health', array(
            'methods' => 'GET',
            'callback' => array($this, 'health_check'),
            'permission_callback' => '__return_true'
        ));
    }

    /**
     * Main health check callback
     */
    public function health_check($request)
    {
        $start_time = microtime(true);

        // Verify secret key
        $provided_key = $request->get_param('key');
        if ($provided_key !== $this->secret_key) {
            return new WP_REST_Response(array(
                'status' => 'error',
                'message' => 'Invalid or missing authentication key'
            ), 401);
        }

        $checks = array();
        $overall_status = 'healthy';

        // 1. Database connectivity check
        $db_check = $this->check_database();
        $checks['database'] = $db_check;
        if (!$db_check['passed']) {
            $overall_status = 'unhealthy';
        }

        // 2. Inventory file exists check
        $file_exists = $this->check_file_exists();
        $checks['file_exists'] = $file_exists;
        if (!$file_exists['passed']) {
            $overall_status = 'unhealthy';
        }

        // 3. File age check
        if ($file_exists['passed']) {
            $file_age = $this->check_file_age();
            $checks['file_age'] = $file_age;
            if (!$file_age['passed']) {
                $overall_status = 'unhealthy';
            }

            // 4. Vehicle count check (validates JSON implicitly)
            $vehicle_count = $this->check_vehicle_counts();
            $checks['vehicle_counts'] = $vehicle_count;
            if (!$vehicle_count['passed']) {
                $overall_status = 'unhealthy';
            }
        }

        // Calculate response time
        $response_time = round(microtime(true) - $start_time, 3);
        $checks['response_time'] = array(
            'passed' => $response_time < $this->max_response_time,
            'message' => $response_time . 's',
            'threshold' => $this->max_response_time . 's'
        );

        if ($response_time >= $this->max_response_time) {
            $overall_status = 'unhealthy';
        }

        // Determine HTTP status code
        $http_status = ($overall_status === 'healthy') ? 200 : 503;

        // Return response
        return new WP_REST_Response(array(
            'status' => $overall_status,
            'timestamp' => current_time('c'),
            'checks' => $checks,
            'response_time' => $response_time
        ), $http_status);
    }

    /**
     * Check database connectivity
     */
    private function check_database()
    {
        global $wpdb;

        try {
            $result = $wpdb->get_var("SELECT 1");

            if ($result == 1) {
                return array(
                    'passed' => true,
                    'message' => 'Database connection successful'
                );
            } else {
                return array(
                    'passed' => false,
                    'message' => 'Database query returned unexpected result'
                );
            }
        } catch (Exception $e) {
            return array(
                'passed' => false,
                'message' => 'Database connection failed: ' . $e->getMessage()
            );
        }
    }

    /**
     * Check if inventory file exists
     */
    private function check_file_exists()
    {
        if (file_exists($this->inventory_file_path)) {
            return array(
                'passed' => true,
                'message' => 'Inventory file exists'
            );
        } else {
            return array(
                'passed' => false,
                'message' => 'Inventory file not found at: ' . $this->inventory_file_path
            );
        }
    }

    /**
     * Check inventory file age
     */
    private function check_file_age()
    {
        $file_modified_time = filemtime($this->inventory_file_path);
        $current_time = time();
        $age_in_seconds = $current_time - $file_modified_time;
        $age_in_minutes = round($age_in_seconds / 60);

        if ($age_in_seconds <= $this->max_file_age) {
            return array(
                'passed' => true,
                'message' => 'File age: ' . $age_in_minutes . ' minutes',
                'last_modified' => date('Y-m-d H:i:s', $file_modified_time)
            );
        } else {
            return array(
                'passed' => false,
                'message' => 'File is too old: ' . $age_in_minutes . ' minutes (max: 120 minutes)',
                'last_modified' => date('Y-m-d H:i:s', $file_modified_time)
            );
        }
    }



    /**
     * Check vehicle counts (new and used)
     * Also validates JSON structure implicitly
     */
    private function check_vehicle_counts()
    {
        // Read inventory file
        $json_content = file_get_contents($this->inventory_file_path);

        if ($json_content === false) {
            return array(
                'passed' => false,
                'message' => 'Failed to read inventory file'
            );
        }

        // Parse JSON
        $data = json_decode($json_content, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            return array(
                'passed' => false,
                'message' => 'Invalid JSON: ' . json_last_error_msg()
            );
        }

        // Validate structure
        if (!isset($data['vehicles']) || !is_array($data['vehicles'])) {
            return array(
                'passed' => false,
                'message' => 'JSON structure invalid: missing or invalid "vehicles" array'
            );
        }

        // Count vehicles
        $new_count = 0;
        $used_count = 0;

        foreach ($data['vehicles'] as $vehicle) {
            if (isset($vehicle['condition'])) {
                if ($vehicle['condition'] === 'New') {
                    $new_count++;
                } elseif ($vehicle['condition'] === 'Used') {
                    $used_count++;
                }
            }
        }

        // Check thresholds
        $passed = (($new_count+$used_count) >= $this->min_new_vehicles);

        $messages = array();
        if ($new_count < $this->min_new_vehicles) {
            $messages[] = "Insufficient new vehicles: {$new_count} (minimum: {$this->min_new_vehicles})";
        }
        if ($used_count < $this->min_used_vehicles) {
            $messages[] = "Insufficient used vehicles: {$used_count} (minimum: {$this->min_used_vehicles})";
        }

        if ($passed) {
            return array(
                'passed' => true,
                'message' => "Vehicle counts OK (JSON valid)",
                'new_vehicles' => $new_count,
                'used_vehicles' => $used_count
            );
        } else {
            return array(
                'passed' => false,
                'message' => implode('; ', $messages),
                'new_vehicles' => $new_count,
                'used_vehicles' => $used_count
            );
        }
    }
}

// Initialize the health check module
// Add this line to your existing plugin's main file:
// new DealershipHealthCheck();