[(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;