data_source.php

4.42 KB
10/07/2025 06:35
PHP
data_source.php
<?php
//ini_set('display_errors', 1); // For debugging, remove in production
//error_reporting(E_ALL);

header('Content-Type: application/json');

// --- Security: Prevent Directory Traversal ---
$widgetId = $_GET['widget_id'] ?? null;
if (!$widgetId || !preg_match('/^[a-zA-Z0-9_-]+$/', $widgetId)) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid or missing Widget ID.']);
    exit;
}

// --- Load Config ---
$configFile = __DIR__.'/../configs/widgets/'.$widgetId.'.json';
if (!file_exists($configFile)) {
    http_response_code(404);
    echo json_encode(['error' => 'Configuration file not found for '.htmlspecialchars($widgetId)]);
    exit;
}
$config = json_decode(file_get_contents($configFile), true);

$data = [];
$sourceType = $config['dataSource']['type'];

// --- Pagination ---
$paginationEnabled = $config['displayOptions']['pagination']['enabled'] ?? false;
$page = (int) ($_GET['page'] ?? 1);
$limit = (int) ($config['displayOptions']['pagination']['limit'] ?? 10);
$offset = ($page - 1) * $limit;
$totalRecords = 0;

try {
    switch ($sourceType) {
        case 'db':
            $dbConf = $config['dataSource']['connection'];
            $query = $config['dataSource']['query'];
            $pdo = new PDO(
                "mysql:host={$dbConf['host']};dbname={$dbConf['dbname']};charset=utf8mb4",
                $dbConf['user'],
                $dbConf['password']
            );
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            if ($paginationEnabled) {
                // Get total records for pagination
                $countQuery = "SELECT COUNT(*) FROM (".$query.") AS total_count_query";
                $totalRecords = (int) $pdo->query($countQuery)->fetchColumn();
                // Add LIMIT and OFFSET to the original query
                $query .= " LIMIT :limit OFFSET :offset";
            }

            $stmt = $pdo->prepare($query);

            if ($paginationEnabled) {
                $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
                $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
            }

            $stmt->execute();
            $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
            break;

        case 'api':
            $apiConf = $config['dataSource']['request'];
            $ch = curl_init($apiConf['endpoint']);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $apiConf['method'] ?? 'GET');
            $headers = [];
            foreach ($apiConf['headers'] ?? [] as $key => $value) {
                $headers[] = "$key: $value";
            }
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if (curl_errno($ch) || $httpCode >= 400) {
                throw new Exception("API request failed. HTTP Code: {$httpCode}. Error: ".curl_error($ch));
            }
            curl_close($ch);

            $fullData = json_decode($response, true);
            if ($paginationEnabled) {
                $totalRecords = count($fullData);
                $data = array_slice($fullData, $offset, $limit);
            } else {
                $data = $fullData;
            }
            break;

        case 'csv':
            $csvPath = __DIR__.'/../'.$config['dataSource']['path'];
            if (!file_exists($csvPath)) {
                throw new Exception("CSV file not found at {$csvPath}");
            }

            $file = fopen($csvPath, 'r');
            $headers = fgetcsv($file, 0, ",", '"', '\\');
            $fullData = [];
            while (($row = fgetcsv($file, 0, ",", '"', '\\')) !== false) {
                $fullData[] = array_combine($headers, $row);
            }
            fclose($file);

            if ($paginationEnabled) {
                $totalRecords = count($fullData);
                $data = array_slice($fullData, $offset, $limit);
            } else {
                $data = $fullData;
            }
            break;
    }
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => 'Data source error']);
    exit;
}

$responsePayload = [
    'data' => $data
];

if ($paginationEnabled) {
    $responsePayload['pagination'] = [
        'totalRecords' => $totalRecords,
        'currentPage' => $page,
        'limit' => $limit,
        'totalPages' => ceil($totalRecords / $limit)
    ];
}

echo json_encode($responsePayload);