Fix deployed data rendering and database fallback
This commit is contained in:
@@ -28,6 +28,7 @@ $action = $segments[2] ?? null;
|
||||
|
||||
// Coba koneksi DB — jika gagal, pakai demo mode
|
||||
$dbOk = false;
|
||||
$dbError = '';
|
||||
try {
|
||||
require_once __DIR__ . '/../config/database.php';
|
||||
$testDb = getDB();
|
||||
@@ -37,10 +38,21 @@ try {
|
||||
} catch (Throwable $e) {
|
||||
// DB tidak tersedia — pakai demo mode
|
||||
$dbOk = false;
|
||||
$dbError = $e->getMessage();
|
||||
}
|
||||
|
||||
// ── DEMO MODE (tanpa database) ──────────────────────────────
|
||||
if (!$dbOk) {
|
||||
if (!in_array($method, ['GET', 'OPTIONS'], true)) {
|
||||
http_response_code(503);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Database belum siap, data tidak bisa disimpan. Periksa DB_HOST, DB_USER, DB_PASSWORD, dan schema webgis_kemiskinan.',
|
||||
'errors' => ['database' => $dbError],
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
demoRouter($resource, $id, $action, $method);
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,57 @@
|
||||
<?php
|
||||
define('DB_HOST', getenv('DB_HOST'));
|
||||
define('DB_NAME', getenv('DB_NAME'));
|
||||
define('DB_USER', getenv('DB_USER'));
|
||||
define('DB_PASS', getenv('DB_PASSWORD'));
|
||||
function env_first_db(array $keys, string $default = ''): string {
|
||||
foreach ($keys as $key) {
|
||||
$value = getenv($key);
|
||||
if ($value !== false && $value !== '') return $value;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
define('DB_HOST', env_first_db(['DB_HOST', 'MYSQL_HOST', 'MARIADB_HOST'], 'database'));
|
||||
define('DB_NAME', env_first_db(['WEBGIS_V3_DB_NAME', 'DB_NAME'], 'webgis_kemiskinan'));
|
||||
define('DB_USER', env_first_db(['DB_USER', 'MYSQL_USER', 'MARIADB_USER'], 'root'));
|
||||
define('DB_PASS', env_first_db(['DB_PASSWORD', 'MYSQL_PASSWORD', 'MARIADB_PASSWORD'], ''));
|
||||
define('DB_CHAR', getenv('DB_CHAR') ?: 'utf8mb4');
|
||||
|
||||
function getDB(): PDO {
|
||||
static $pdo = null;
|
||||
if ($pdo === null) {
|
||||
$dsn = "mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=".DB_CHAR;
|
||||
$serverDsn = "mysql:host=".DB_HOST.";charset=".DB_CHAR;
|
||||
$server = new PDO($serverDsn, DB_USER, DB_PASS, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
]);
|
||||
|
||||
$safeDb = preg_replace('/[^a-zA-Z0-9_]/', '', DB_NAME);
|
||||
$server->exec("CREATE DATABASE IF NOT EXISTS `$safeDb` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
|
||||
$dsn = "mysql:host=".DB_HOST.";dbname=".$safeDb.";charset=".DB_CHAR;
|
||||
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
]);
|
||||
|
||||
ensureWebgisV3Schema($pdo);
|
||||
}
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
function ensureWebgisV3Schema(PDO $pdo): void {
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'role'");
|
||||
if ($stmt->fetch()) return;
|
||||
|
||||
$schemaFile = __DIR__ . '/../sql/schema.sql';
|
||||
if (!is_file($schemaFile)) return;
|
||||
|
||||
$sql = file_get_contents($schemaFile);
|
||||
$sql = preg_replace('/CREATE DATABASE IF NOT EXISTS\s+`?webgis_kemiskinan`?.*?;/is', '', $sql);
|
||||
$sql = preg_replace('/USE\s+`?webgis_kemiskinan`?\s*;/i', '', $sql);
|
||||
$sql = preg_replace('/^\s*--.*$/m', '', $sql);
|
||||
|
||||
foreach (array_filter(array_map('trim', explode(';', $sql))) as $statement) {
|
||||
if ($statement === '') continue;
|
||||
$pdo->exec($statement);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-3
@@ -316,6 +316,17 @@ const layerJalan = L.layerGroup().addTo(map);
|
||||
const layerParsil = L.layerGroup().addTo(map);
|
||||
const layerRusak = L.layerGroup().addTo(map);
|
||||
|
||||
function parseGeojsonSafe(raw){
|
||||
try {
|
||||
const gj = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||
if (!gj || !gj.geometry || !gj.geometry.type) return null;
|
||||
return gj;
|
||||
} catch(e) {
|
||||
console.warn('GeoJSON tidak valid:', raw);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
// 2. WARNA & IKON
|
||||
// =============================================================
|
||||
@@ -688,7 +699,8 @@ async function loadJalan(q=''){
|
||||
if(!data.length){ list.innerHTML='<div class="empty-state"><i class="fas fa-road"></i><p>'+(q?'Tidak ada hasil pencarian':'Belum ada data jalan')+'</p></div>'; return; }
|
||||
list.innerHTML='';
|
||||
data.forEach(item=>{
|
||||
const gj = JSON.parse(item.geojson);
|
||||
const gj = parseGeojsonSafe(item.geojson);
|
||||
if (!gj) { console.warn('Lewati data jalan tanpa geometry valid', item); return; }
|
||||
const style = WARNA_JALAN[item.status_jalan]||WARNA_JALAN['Kabupaten'];
|
||||
const layer = L.geoJSON(gj,{style}).addTo(layerJalan);
|
||||
layer.bindPopup(`
|
||||
@@ -739,7 +751,8 @@ async function loadParsil(q=''){
|
||||
if(!data.length){ list.innerHTML='<div class="empty-state"><i class="fas fa-map"></i><p>'+(q?'Tidak ada hasil pencarian':'Belum ada data parsil')+'</p></div>'; return; }
|
||||
list.innerHTML='';
|
||||
data.forEach(item=>{
|
||||
const gj = JSON.parse(item.geojson);
|
||||
const gj = parseGeojsonSafe(item.geojson);
|
||||
if (!gj) { console.warn('Lewati data parsil tanpa geometry valid', item); return; }
|
||||
const style = WARNA_PARSIL[item.status_kepemilikan]||WARNA_PARSIL['SHM'];
|
||||
const layer = L.geoJSON(gj,{style}).addTo(layerParsil);
|
||||
layer.bindPopup(`
|
||||
@@ -794,7 +807,8 @@ async function loadRusak(q=''){
|
||||
if(!data.length){ list.innerHTML='<div class="empty-state"><i class="fas fa-exclamation-triangle"></i><p>'+(q?'Tidak ada hasil pencarian':'Belum ada data jalan rusak')+'</p></div>'; return; }
|
||||
list.innerHTML='';
|
||||
data.forEach(item=>{
|
||||
const gj = JSON.parse(item.geojson);
|
||||
const gj = parseGeojsonSafe(item.geojson);
|
||||
if (!gj || !Array.isArray(gj.geometry.coordinates)) { console.warn('Lewati data jalan rusak tanpa geometry valid', item); return; }
|
||||
const cfg = WARNA_RUSAK[item.tingkat]||WARNA_RUSAK['Sedang'];
|
||||
const coord = gj.geometry.coordinates; // [lng, lat]
|
||||
const layer = L.circleMarker([coord[1],coord[0]], cfg).addTo(layerRusak);
|
||||
|
||||
Reference in New Issue
Block a user