Files
2026-06-15 21:53:17 +07:00

227 lines
12 KiB
PHP

<?php
include 'db2.php';
require_once __DIR__ . '/includes/stats.php';
function toGeoJsonLine($pts) {
$coords = array_map(fn($p) => [(float)$p[1], (float)$p[0]], $pts);
return json_encode(['type' => 'LineString', 'coordinates' => $coords]);
}
function toGeoJsonPoly($pts) {
$coords = array_map(fn($p) => [(float)$p[1], (float)$p[0]], $pts);
if (count($coords) && $coords[0] !== $coords[count($coords)-1]) $coords[] = $coords[0];
return json_encode(['type' => 'Polygon', 'coordinates' => [$coords]]);
}
function toGeoJsonPoint($lat, $lng) {
return json_encode(['type' => 'Point', 'coordinates' => [(float)$lng, (float)$lat]]);
}
// Deteksi POST yang melebihi post_max_size: PHP mengosongkan $_POST/$_FILES
// padahal CONTENT_LENGTH > 0. Tanpa ini respons jadi kosong -> "Koneksi gagal!".
if ($_SERVER['REQUEST_METHOD'] === 'POST'
&& empty($_POST) && empty($_FILES)
&& (int)($_SERVER['CONTENT_LENGTH'] ?? 0) > 0) {
header('Content-Type: application/json; charset=utf-8');
http_response_code(413);
echo json_encode([
'ok' => false,
'msg' => 'Data terlalu besar (melebihi post_max_size=' . ini_get('post_max_size')
. '). Kecilkan ukuran foto atau naikkan post_max_size.'
]);
exit;
}
$action = $_GET['action'] ?? $_POST['action'] ?? null;
if (!$action) return;
header('Content-Type: application/json; charset=utf-8');
$a = $action;
if ($a === 'reverse') {
$lat = (float)($_GET['lat'] ?? 0);
$lon = (float)($_GET['lon'] ?? $_GET['lng'] ?? 0);
if ($lat == 0 && $lon == 0) { echo json_encode(['error' => 'koordinat kosong']); exit; }
$url = 'https://nominatim.openstreetmap.org/reverse?format=jsonv2&zoom=17&accept-language=id'
. '&lat=' . urlencode($lat) . '&lon=' . urlencode($lon);
// Nominatim mewajibkan User-Agent yang valid; browser tak bisa set ini, jadi diproxy dari server
$ua = 'SIG2-JalanTanah/1.0 (kontak: webmaster@webgis-untan.xyz)';
$body = false;
if (function_exists('curl_init')) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => $ua,
CURLOPT_TIMEOUT => 8,
CURLOPT_FOLLOWLOCATION => true,
]);
$body = curl_exec($ch);
curl_close($ch);
}
if ($body === false) {
$ctx = stream_context_create(['http' => [
'header' => "User-Agent: $ua\r\n",
'timeout' => 8,
]]);
$body = @file_get_contents($url, false, $ctx);
}
if ($body === false) { echo json_encode(['error' => 'gagal hubungi nominatim']); exit; }
echo $body; exit;
}
if ($a === 'search') {
$q = '%' . $conn->real_escape_string($_GET['q'] ?? '') . '%';
$tipe = $_GET['tipe'] ?? 'semua';
$sf = $_GET['status_filter'] ?? '';
$pmin = (float)($_GET['panjang_min'] ?? 0);
$pmax = (float)($_GET['panjang_max'] ?? 0);
$rusak_periode = $_GET['rusak_periode'] ?? 'semua';
$out = [];
if ($tipe === 'semua' || $tipe === 'jalan') {
$w = "nama_jalan LIKE '$q'";
if ($sf) $w .= " AND status_jalan='" . $conn->real_escape_string($sf) . "'";
if ($pmin > 0) $w .= " AND panjang_meter>=$pmin";
if ($pmax > 0) $w .= " AND panjang_meter<=$pmax";
$rj = $conn->query("SELECT id,nama_jalan,status_jalan,panjang_meter,koordinat FROM jalan WHERE $w LIMIT 20");
while ($row = $rj->fetch_assoc()) { $row['type'] = 'jalan'; $out[] = $row; }
}
if ($tipe === 'semua' || $tipe === 'parsil') {
$w = "(nama_parsil LIKE '$q' OR nama_pemilik LIKE '$q')";
if ($sf) $w .= " AND status_kepemilikan='" . $conn->real_escape_string($sf) . "'";
$rp = $conn->query("SELECT id,nama_parsil,nama_pemilik,nomor_sertifikat,status_kepemilikan,luas_m2,koordinat FROM parsil WHERE $w LIMIT 20");
while ($row = $rp->fetch_assoc()) { $row['type'] = 'parsil'; $out[] = $row; }
}
if ($tipe === 'semua' || $tipe === 'rusak') {
$wR = "nama LIKE '$q'";
if ($rusak_periode === '1bulan') $wR .= " AND tanggal >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)";
elseif ($rusak_periode === '3tahun') $wR .= " AND tanggal >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR)";
$rr = $conn->query("SELECT id,nama,tanggal,latitude,longitude,keterangan,koordinat FROM jalan_rusak WHERE $wR ORDER BY tanggal DESC LIMIT 20");
while ($row = $rr->fetch_assoc()) { $row['type'] = 'rusak'; $out[] = $row; }
}
echo json_encode($out); exit;
}
if ($a === 'save_jalan' && isset($_GET['nama'], $_GET['status'], $_GET['ukuran'], $_GET['koordinat'])) {
$nama = $conn->real_escape_string($_GET['nama']);
$status = $conn->real_escape_string($_GET['status']);
$panjang = (float)$_GET['ukuran'];
$raw = json_decode($_GET['koordinat'], true);
$geojson = $conn->real_escape_string(toGeoJsonLine($raw));
$r = $conn->query("INSERT INTO jalan(nama_jalan,status_jalan,panjang_meter,koordinat) VALUES('$nama','$status','$panjang','$geojson')");
echo json_encode(array_merge(['ok' => (bool)$r, 'id' => $conn->insert_id, 'msg' => $conn->error], getStats($conn))); exit;
}
if ($a === 'save_parsil' && isset($_GET['nama'], $_GET['status'], $_GET['ukuran'], $_GET['koordinat'])) {
$nama = $conn->real_escape_string($_GET['nama']);
$pemilik = $conn->real_escape_string($_GET['pemilik'] ?? '');
$nosert = $conn->real_escape_string($_GET['nosert'] ?? '');
$ket = $conn->real_escape_string($_GET['keterangan'] ?? '');
$status = $conn->real_escape_string($_GET['status']);
$luas = (float)$_GET['ukuran'];
$raw = json_decode($_GET['koordinat'], true);
$geojson = $conn->real_escape_string(toGeoJsonPoly($raw));
$r = $conn->query("INSERT INTO parsil(nama_parsil,nama_pemilik,nomor_sertifikat,keterangan,status_kepemilikan,luas_m2,koordinat) VALUES('$nama','$pemilik','$nosert','$ket','$status','$luas','$geojson')");
echo json_encode(array_merge(['ok' => (bool)$r, 'id' => $conn->insert_id, 'msg' => $conn->error], getStats($conn))); exit;
}
if ($a === 'save_rusak') {
$pelapor = $conn->real_escape_string($_POST['pelapor'] ?? $_GET['pelapor'] ?? '') ?: 'Anonym';
$nama_jalan = $conn->real_escape_string($_POST['nama_jalan'] ?? $_GET['nama_jalan'] ?? '');
$tanggal = $conn->real_escape_string($_POST['tanggal'] ?? $_GET['tanggal'] ?? date('Y-m-d'));
$lat = (float)($_POST['lat'] ?? $_GET['lat'] ?? 0);
$lng = (float)($_POST['lng'] ?? $_GET['lng'] ?? 0);
$ket = $conn->real_escape_string($_POST['keterangan'] ?? $_GET['keterangan'] ?? '');
$foto = $conn->real_escape_string($_POST['foto'] ?? $_GET['foto'] ?? '');
$namaFull = $conn->real_escape_string($pelapor . ($nama_jalan ? ' | Jalan: ' . $nama_jalan : ''));
$geojson = $conn->real_escape_string(toGeoJsonPoint($lat, $lng));
$r = $conn->query("INSERT INTO jalan_rusak(nama,tanggal,latitude,longitude,keterangan,foto,koordinat) VALUES('$namaFull','$tanggal','$lat','$lng','$ket','$foto','$geojson')");
echo json_encode(array_merge(['ok' => (bool)$r, 'id' => $conn->insert_id, 'msg' => $conn->error, 'nama' => $namaFull], getStats($conn))); exit;
}
if ($a === 'delete_jalan' && isset($_GET['id'])) {
$conn->query("DELETE FROM jalan WHERE id=" . (int)$_GET['id']);
echo json_encode(getStats($conn)); exit;
}
if ($a === 'delete_parsil' && isset($_GET['id'])) {
$conn->query("DELETE FROM parsil WHERE id=" . (int)$_GET['id']);
echo json_encode(getStats($conn)); exit;
}
if ($a === 'delete_rusak' && isset($_GET['id'])) {
$conn->query("DELETE FROM jalan_rusak WHERE id=" . (int)$_GET['id']);
echo json_encode(getStats($conn)); exit;
}
if ($a === 'edit_jalan' && isset($_GET['id'], $_GET['nama'], $_GET['status'])) {
$id = (int)$_GET['id'];
$n = $conn->real_escape_string($_GET['nama']);
$s = $conn->real_escape_string($_GET['status']);
$coords = $_GET['koordinat'] ?? '';
$pjg = 0;
if ($coords) {
$g = json_decode($coords, true);
$pts = [];
if (isset($g['type']) && $g['type'] === 'LineString') foreach ($g['coordinates'] as $c) $pts[] = ['lat' => $c[1], 'lng' => $c[0]];
else foreach (json_decode($coords, true) as $p) $pts[] = ['lat' => $p[0], 'lng' => $p[1]];
for ($i = 0; $i < count($pts) - 1; $i++) {
$la1 = deg2rad($pts[$i]['lat']); $lo1 = deg2rad($pts[$i]['lng']);
$la2 = deg2rad($pts[$i+1]['lat']); $lo2 = deg2rad($pts[$i+1]['lng']);
$d = 2 * 6371000 * asin(sqrt(sin(($la2-$la1)/2)**2 + cos($la1)*cos($la2)*sin(($lo2-$lo1)/2)**2));
$pjg += $d;
}
$ce = $conn->real_escape_string($coords);
$conn->query("UPDATE jalan SET nama_jalan='$n',status_jalan='$s',panjang_meter='$pjg',koordinat='$ce' WHERE id=$id");
} else {
$conn->query("UPDATE jalan SET nama_jalan='$n',status_jalan='$s' WHERE id=$id");
$pjg = $conn->query("SELECT panjang_meter FROM jalan WHERE id=$id")->fetch_assoc()['panjang_meter'];
}
echo json_encode(array_merge(getStats($conn), ['panjang' => round($pjg, 1)])); exit;
}
if ($a === 'edit_parsil' && isset($_GET['id'], $_GET['nama'], $_GET['status'])) {
$id = (int)$_GET['id'];
$n = $conn->real_escape_string($_GET['nama']);
$s = $conn->real_escape_string($_GET['status']);
$pemilik = $conn->real_escape_string($_GET['pemilik'] ?? '');
$nosert = $conn->real_escape_string($_GET['nosert'] ?? '');
$ket = $conn->real_escape_string($_GET['keterangan'] ?? '');
$coords = $_GET['koordinat'] ?? '';
$luas = 0;
if ($coords) {
$g = json_decode($coords, true);
$pts = isset($g['type']) && $g['type'] === 'Polygon'
? array_map(fn($c) => ['lat' => $c[1], 'lng' => $c[0]], $g['coordinates'][0])
: array_map(fn($p) => ['lat' => $p[0], 'lng' => $p[1]], json_decode($coords, true));
$R = 6371000; $n2 = count($pts); $area = 0;
for ($i = 0; $i < $n2; $i++) {
$j = ($i + 1) % $n2;
$xi = $pts[$i]['lng'] * M_PI/180 * $R * cos($pts[$i]['lat'] * M_PI/180);
$yi = $pts[$i]['lat'] * M_PI/180 * $R;
$xj = $pts[$j]['lng'] * M_PI/180 * $R * cos($pts[$j]['lat'] * M_PI/180);
$yj = $pts[$j]['lat'] * M_PI/180 * $R;
$area += ($xi * $yj - $xj * $yi);
}
$luas = abs($area / 2);
$ce = $conn->real_escape_string($coords);
$conn->query("UPDATE parsil SET nama_parsil='$n',status_kepemilikan='$s',nama_pemilik='$pemilik',nomor_sertifikat='$nosert',keterangan='$ket',luas_m2='$luas',koordinat='$ce' WHERE id=$id");
} else {
$conn->query("UPDATE parsil SET nama_parsil='$n',status_kepemilikan='$s',nama_pemilik='$pemilik',nomor_sertifikat='$nosert',keterangan='$ket' WHERE id=$id");
$luas = $conn->query("SELECT luas_m2 FROM parsil WHERE id=$id")->fetch_assoc()['luas_m2'];
}
echo json_encode(array_merge(getStats($conn), ['luas' => round($luas, 1)])); exit;
}
if ($a === 'edit_rusak' && isset($_GET['id'])) {
$id = (int)$_GET['id'];
$n = $conn->real_escape_string($_POST['nama'] ?? $_GET['nama'] ?? '');
$tgl = $conn->real_escape_string($_POST['tanggal'] ?? $_GET['tanggal'] ?? '');
$ket = $conn->real_escape_string($_POST['keterangan'] ?? $_GET['keterangan'] ?? '');
$foto = $conn->real_escape_string($_POST['foto'] ?? $_GET['foto'] ?? '');
$lat = isset($_POST['latitude']) ? (float)$_POST['latitude'] : (isset($_GET['latitude']) ? (float)$_GET['latitude'] : null);
$lng = isset($_POST['longitude']) ? (float)$_POST['longitude'] : (isset($_GET['longitude']) ? (float)$_GET['longitude'] : null);
if ($lat !== null && $lng !== null) {
$geojson = $conn->real_escape_string(toGeoJsonPoint($lat, $lng));
$conn->query("UPDATE jalan_rusak SET nama='$n',tanggal='$tgl',keterangan='$ket',foto='$foto',latitude='$lat',longitude='$lng',koordinat='$geojson' WHERE id=$id");
} else {
$conn->query("UPDATE jalan_rusak SET nama='$n',tanggal='$tgl',keterangan='$ket',foto='$foto' WHERE id=$id");
}
echo json_encode(array_merge(getStats($conn), ['ok' => true])); exit;
}
echo json_encode(['error' => 'unknown']); exit;