UAS SIG Proyek WebGis
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
// api/foto.php v2.0
|
||||
// ============================================================
|
||||
// API Upload & Kelola Foto Rumah + GPS Geo-tagging
|
||||
// ============================================================
|
||||
require_once __DIR__ . '/../includes/config.php';
|
||||
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
header('Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') exit;
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$db = getDB();
|
||||
|
||||
// Pastikan folder upload ada
|
||||
if (!is_dir(UPLOAD_DIR)) mkdir(UPLOAD_DIR, 0755, true);
|
||||
|
||||
switch ($method) {
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
// GET – Ambil daftar foto per penduduk
|
||||
// ════════════════════════════════════════════════════════
|
||||
case 'GET':
|
||||
$pendudukId = $_GET['penduduk_id'] ?? null;
|
||||
if (!$pendudukId) {
|
||||
header('Content-Type: application/json');
|
||||
jsonResponse(['success' => false, 'error' => 'penduduk_id diperlukan'], 400);
|
||||
}
|
||||
$stmt = $db->prepare("
|
||||
SELECT f.*, u.nama AS nama_petugas
|
||||
FROM foto_rumah f
|
||||
LEFT JOIN users u ON u.id = f.diambil_oleh
|
||||
WHERE f.penduduk_id = ?
|
||||
ORDER BY f.is_primary DESC, f.created_at ASC
|
||||
");
|
||||
$stmt->execute([$pendudukId]);
|
||||
header('Content-Type: application/json');
|
||||
jsonResponse(['success' => true, 'data' => $stmt->fetchAll()]);
|
||||
break;
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
// POST – Upload foto baru
|
||||
// ════════════════════════════════════════════════════════
|
||||
case 'POST':
|
||||
header('Content-Type: application/json');
|
||||
$pendudukId = (int)($_POST['penduduk_id'] ?? 0);
|
||||
if (!$pendudukId) jsonResponse(['success' => false, 'error' => 'penduduk_id diperlukan'], 400);
|
||||
|
||||
// Cek penduduk ada
|
||||
$cek = $db->prepare("SELECT id FROM penduduk_miskin WHERE id = ?");
|
||||
$cek->execute([$pendudukId]);
|
||||
if (!$cek->fetch()) jsonResponse(['success' => false, 'error' => 'Data penduduk tidak ditemukan'], 404);
|
||||
|
||||
if (!isset($_FILES['foto']) || $_FILES['foto']['error'] !== UPLOAD_ERR_OK) {
|
||||
$errCode = $_FILES['foto']['error'] ?? 'no_file';
|
||||
jsonResponse(['success' => false, 'error' => "Upload gagal (kode: $errCode)"], 400);
|
||||
}
|
||||
|
||||
$file = $_FILES['foto'];
|
||||
$tmpPath = $file['tmp_name'];
|
||||
$origName = $file['name'];
|
||||
$fileSize = $file['size'];
|
||||
|
||||
// Validasi ukuran
|
||||
if ($fileSize > MAX_FOTO_SIZE) {
|
||||
jsonResponse(['success' => false, 'error' => 'Ukuran file maksimal 5 MB'], 413);
|
||||
}
|
||||
|
||||
// Validasi ekstensi & MIME type
|
||||
$ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime = finfo_file($finfo, $tmpPath);
|
||||
finfo_close($finfo);
|
||||
$allowedMime = ['image/jpeg','image/png','image/webp'];
|
||||
if (!in_array($ext, ALLOWED_EXT) || !in_array($mime, $allowedMime)) {
|
||||
jsonResponse(['success' => false, 'error' => 'Format file tidak didukung (jpg/png/webp)'], 415);
|
||||
}
|
||||
|
||||
// Generate nama file unik
|
||||
$newName = 'foto_' . $pendudukId . '_' . time() . '_' . bin2hex(random_bytes(4)) . '.' . $ext;
|
||||
$destPath = UPLOAD_DIR . $newName;
|
||||
$relPath = UPLOAD_URL . $newName;
|
||||
|
||||
if (!move_uploaded_file($tmpPath, $destPath)) {
|
||||
jsonResponse(['success' => false, 'error' => 'Gagal menyimpan file'], 500);
|
||||
}
|
||||
|
||||
// Cek apakah ini foto pertama → jadikan primary
|
||||
$countStmt = $db->prepare("SELECT COUNT(*) FROM foto_rumah WHERE penduduk_id = ?");
|
||||
$countStmt->execute([$pendudukId]);
|
||||
$isPrimary = ($countStmt->fetchColumn() == 0) ? 1 : 0;
|
||||
|
||||
// Koordinat GPS dari POST (dari browser Geolocation atau EXIF)
|
||||
$latFoto = isset($_POST['lat_foto']) && $_POST['lat_foto'] !== '' ? (float)$_POST['lat_foto'] : null;
|
||||
$lngFoto = isset($_POST['lng_foto']) && $_POST['lng_foto'] !== '' ? (float)$_POST['lng_foto'] : null;
|
||||
$accuracy = isset($_POST['accuracy_meter']) && $_POST['accuracy_meter'] !== '' ? (float)$_POST['accuracy_meter']
|
||||
: (isset($_POST['accuracy']) && $_POST['accuracy'] !== '' ? (float)$_POST['accuracy'] : null);
|
||||
|
||||
// Jika user set is_primary = 1, nonaktifkan primary lain dulu
|
||||
$isPrimaryReq = isset($_POST['is_primary']) && (int)$_POST['is_primary'] === 1;
|
||||
if ($isPrimaryReq) {
|
||||
$db->prepare("UPDATE foto_rumah SET is_primary = 0 WHERE penduduk_id = ?")
|
||||
->execute([$pendudukId]);
|
||||
$isPrimary = 1;
|
||||
}
|
||||
|
||||
// diambil_oleh: support field name lama (user_id) dan baru (diambil_oleh)
|
||||
$diambilOleh = $_POST['diambil_oleh'] ?? $_POST['user_id'] ?? null;
|
||||
|
||||
$db->prepare("
|
||||
INSERT INTO foto_rumah (penduduk_id, file_path, lat_foto, lng_foto, accuracy_meter, is_primary, ukuran_kb, keterangan, diambil_oleh)
|
||||
VALUES (?,?,?,?,?,?,?,?,?)
|
||||
")->execute([
|
||||
$pendudukId,
|
||||
$relPath,
|
||||
$latFoto,
|
||||
$lngFoto,
|
||||
$accuracy,
|
||||
$isPrimary,
|
||||
(int)round($fileSize / 1024),
|
||||
$_POST['keterangan'] ?? null,
|
||||
$diambilOleh ? (int)$diambilOleh : null,
|
||||
]);
|
||||
|
||||
$newId = (int)$db->lastInsertId();
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'id' => $newId,
|
||||
'file_path' => $relPath,
|
||||
'is_primary'=> $isPrimary,
|
||||
'message' => 'Foto berhasil diupload',
|
||||
]);
|
||||
break;
|
||||
|
||||
// ════════════════════════════════════════════════════════
|
||||
// DELETE – Hapus foto
|
||||
// ════════════════════════════════════════════════════════
|
||||
case 'DELETE':
|
||||
header('Content-Type: application/json');
|
||||
$id = (int)($_GET['id'] ?? 0);
|
||||
if (!$id) jsonResponse(['success' => false, 'error' => 'ID diperlukan'], 400);
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM foto_rumah WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$foto = $stmt->fetch();
|
||||
if (!$foto) jsonResponse(['success' => false, 'error' => 'Foto tidak ditemukan'], 404);
|
||||
|
||||
// Hapus file fisik
|
||||
$filePath = __DIR__ . '/../' . $foto['file_path'];
|
||||
if (file_exists($filePath)) @unlink($filePath);
|
||||
|
||||
$db->prepare("DELETE FROM foto_rumah WHERE id = ?")->execute([$id]);
|
||||
|
||||
// Jika foto yang dihapus adalah primary, set foto lain jadi primary
|
||||
if ($foto['is_primary']) {
|
||||
$next = $db->prepare("SELECT id FROM foto_rumah WHERE penduduk_id = ? ORDER BY created_at ASC LIMIT 1");
|
||||
$next->execute([$foto['penduduk_id']]);
|
||||
$nextFoto = $next->fetch();
|
||||
if ($nextFoto) {
|
||||
$db->prepare("UPDATE foto_rumah SET is_primary = 1 WHERE id = ?")->execute([$nextFoto['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
jsonResponse(['success' => true, 'message' => 'Foto berhasil dihapus']);
|
||||
break;
|
||||
|
||||
default:
|
||||
header('Content-Type: application/json');
|
||||
jsonResponse(['success' => false, 'error' => 'Method tidak diizinkan'], 405);
|
||||
}
|
||||
Reference in New Issue
Block a user