csv_handler.php

4.83 KB
10/07/2025 03:39
PHP
csv_handler.php
<?php
// php/csv_handler.php

/**
 * Reads data from a CSV file (simulated for key_metrics.csv).
 *
 * @param string $fileName The name of the CSV file to read (e.g., 'key_metrics.csv').
 * @return array|null The CSV data formatted for the dashboard, or null/error array on failure.
 */
function readCsvFile(string $fileName): ?array
{
    error_log("CSV Handler: Called for file '$fileName'");

    $baseDataPath = __DIR__.'/../data/'; // Assumes 'data' folder is one level up from 'php'
    $filePath = realpath($baseDataPath.$fileName);

    // Security check: Ensure the resolved path is within the intended data directory
    // And that the filename is one of the allowed ones (expanded whitelist)
    $allowedFiles = [
        'key_metrics.csv',
        'sample_data.csv',
        'sales_data.csv',
        'user_analytics.csv',
        'financial_report.csv'
    ];
    if (!$filePath || strpos($filePath, realpath($baseDataPath)) !== 0 || !in_array(basename($filePath), $allowedFiles)) {
        error_log("CSV Handler Error: Invalid, unauthorized or non-existent file path requested: $fileName");
        return ['error' => "Invalid or unauthorized file path for CSV: $fileName"];
    }

    if (!file_exists($filePath) || !is_readable($filePath)) {
        // Simulate data if actual file not found but is 'key_metrics.csv' for demo purposes
        if ($fileName === 'key_metrics.csv') {
            error_log("CSV Handler: File '$fileName' not found, providing simulation.");
            return [
                // Structure expected by displayDataAsCards in script.js
                ['title' => 'Total Orders', 'value' => rand(100, 500), 'icon' => 'shopping_cart', 'description' => 'Past 30 days'],
                ['title' => 'Active Users', 'value' => rand(1000, 5000), 'icon' => 'people_alt', 'description' => 'Currently online'],
                ['title' => 'Conversion Rate', 'value' => rand(1, 15).'%', 'icon' => 'ads_click', 'description' => 'Lead to purchase'],
                ['title' => 'Support Tickets', 'value' => rand(5, 50), 'icon' => 'support_agent', 'description' => 'Open tickets'],
                ['title' => 'Server Uptime', 'value' => '99.'.rand(90, 99).'%', 'icon' => 'dns', 'description' => 'Past 24 hours']
            ];
        }
        error_log("CSV Handler Error: File not found or not readable: $filePath");
        return ['error' => "CSV file not found or not readable: $fileName"];
    }

    // Actual CSV parsing if file exists
    $data = [];
    $header = null;
    if (($handle = fopen($filePath, 'r')) !== false) {
        if (($row = fgetcsv($handle)) !== false) {
            $header = array_map('trim', $row); // Trim header names
        }
        while (($row = fgetcsv($handle)) !== false) {
            if ($header && count($header) == count($row)) {
                $data[] = array_combine($header, $row);
            } else {
                // If no header or mismatched column count, store as simple array (or error out)
                // For this dashboard, we generally expect headers.
                error_log("CSV Handler: Row with mismatched column count or no header for file $fileName.");
                // $data[] = $row; // uncomment if you want to allow non-headered or mismatched data
            }
        }
        fclose($handle);
    } else {
        error_log("CSV Handler Error: Could not open file: $filePath");
        return ['error' => "Could not open CSV file: $fileName"];
    }

    // If the file is key_metrics.csv, ensure it has title and value for cards.
    // The data_provider.php will typically handle this transformation based on the 'source' type.
    // This is more of a validation/defaulting step within the handler itself.
    if ($fileName === 'key_metrics.csv') {
        $formattedData = [];
        foreach ($data as $item) {
            $formattedItem = [
                'title' => $item['title'] ?? 'N/A',
                'value' => $item['value'] ?? 'N/A',
                'icon' => $item['icon'] ?? null, // Optional
                'description' => $item['description'] ?? null // Optional
            ];
            $formattedData[] = $formattedItem;
        }
        return $formattedData;
    }

    // For generic CSVs that might be used for tables
    if (!empty($data) && is_array($data[0])) {
        return [
            'columns' => array_keys($data[0]),
            'rows' => $data
        ];
    }

    return $data; // Return raw parsed data or empty if issues
}; // Example of how you might call this (not used by data_provider.php directly like this); /*
if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
    header('Content-Type: application/json');
    $testFile = $_GET['file'] ?? 'key_metrics.csv';
    $simulatedData = readCsvFile($testFile);
    if (isset($simulatedData['error'])) {
        http_response_code(400); // Or 404 if file not found
    }
    echo json_encode($simulatedData);
}