<?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);