111 lines
4.1 KiB
PHP
111 lines
4.1 KiB
PHP
<?php
|
||
/**
|
||
* api/foto.php — Upload & kelola foto kondisi rumah (KF-13).
|
||
*
|
||
* GET ?warga_id=ID → daftar foto {id, url}
|
||
* POST multipart: warga_id + foto[] (1–5) → kompres & simpan
|
||
* DELETE ?id=ID → hapus foto
|
||
*
|
||
* Foto dikompres (maks lebar 1024px, JPEG q75) memakai GD.
|
||
*/
|
||
require_once __DIR__ . '/../config/db.php';
|
||
require_once __DIR__ . '/helpers.php';
|
||
require_once __DIR__ . '/../config/app.php';
|
||
require_once __DIR__ . '/../config/activity.php';
|
||
|
||
$pdo = Database::getConnection();
|
||
$method = $_SERVER['REQUEST_METHOD'];
|
||
|
||
// GET: cukup login. Mutasi: operator atau enumerator.
|
||
if ($method !== 'GET') requireApiAnyRole(['operator', 'enumerator']);
|
||
|
||
const MAX_FOTO = 5;
|
||
const UPLOAD_DIR = __DIR__ . '/../uploads/rumah/';
|
||
|
||
function compressImage(string $src, string $dst, int $maxW = 1024, int $quality = 75): bool {
|
||
$info = @getimagesize($src);
|
||
if (!$info) return false;
|
||
[$w, $h] = $info;
|
||
switch ($info['mime']) {
|
||
case 'image/jpeg': $img = imagecreatefromjpeg($src); break;
|
||
case 'image/png': $img = imagecreatefrompng($src); break;
|
||
case 'image/webp': $img = imagecreatefromwebp($src); break;
|
||
default: return false;
|
||
}
|
||
if (!$img) return false;
|
||
$nw = $w > $maxW ? $maxW : $w;
|
||
$nh = (int)round($h * ($nw / $w));
|
||
$canvas = imagecreatetruecolor($nw, $nh);
|
||
// latar putih untuk PNG transparan
|
||
imagefill($canvas, 0, 0, imagecolorallocate($canvas, 255, 255, 255));
|
||
imagecopyresampled($canvas, $img, 0, 0, 0, 0, $nw, $nh, $w, $h);
|
||
$ok = imagejpeg($canvas, $dst, $quality);
|
||
imagedestroy($img);
|
||
imagedestroy($canvas);
|
||
return $ok;
|
||
}
|
||
|
||
switch ($method) {
|
||
case 'GET':
|
||
$wargaId = $_GET['warga_id'] ?? null;
|
||
if (!$wargaId) sendError('warga_id wajib');
|
||
$stmt = $pdo->prepare("SELECT id, file_path FROM foto_rumah WHERE warga_id=? ORDER BY id");
|
||
$stmt->execute([$wargaId]);
|
||
$out = [];
|
||
while ($r = $stmt->fetch()) {
|
||
$out[] = ['id' => (int)$r['id'], 'url' => app_url($r['file_path'])];
|
||
}
|
||
sendSuccess($out, 'Foto rumah');
|
||
break;
|
||
|
||
case 'POST':
|
||
$wargaId = $_POST['warga_id'] ?? null;
|
||
if (!$wargaId) sendError('warga_id wajib');
|
||
if (empty($_FILES['foto'])) sendError('Tidak ada file diunggah');
|
||
|
||
$existing = (int)$pdo->query("SELECT COUNT(*) FROM foto_rumah WHERE warga_id=" . (int)$wargaId)->fetchColumn();
|
||
|
||
// Normalisasi $_FILES['foto'] ke array
|
||
$files = $_FILES['foto'];
|
||
$names = is_array($files['name']) ? $files['name'] : [$files['name']];
|
||
$tmps = is_array($files['tmp_name']) ? $files['tmp_name'] : [$files['tmp_name']];
|
||
|
||
if (!is_dir(UPLOAD_DIR)) mkdir(UPLOAD_DIR, 0775, true);
|
||
|
||
$saved = 0;
|
||
foreach ($tmps as $i => $tmp) {
|
||
if ($existing + $saved >= MAX_FOTO) break;
|
||
if (!is_uploaded_file($tmp)) continue;
|
||
$fname = 'w' . (int)$wargaId . '_' . uniqid() . '.jpg';
|
||
$dst = UPLOAD_DIR . $fname;
|
||
if (compressImage($tmp, $dst)) {
|
||
$rel = 'uploads/rumah/' . $fname;
|
||
$pdo->prepare("INSERT INTO foto_rumah (warga_id, file_path) VALUES (?,?)")
|
||
->execute([$wargaId, $rel]);
|
||
$saved++;
|
||
}
|
||
}
|
||
if ($saved === 0) sendError('Gagal memproses foto (format harus JPG/PNG/WEBP)');
|
||
logActivity($pdo, 'create', 'foto_rumah', (int)$wargaId, "Upload {$saved} foto");
|
||
sendSuccess(['uploaded' => $saved], "{$saved} foto diunggah", 201);
|
||
break;
|
||
|
||
case 'DELETE':
|
||
$id = $_GET['id'] ?? null;
|
||
if (!$id) sendError('ID wajib');
|
||
$row = $pdo->prepare("SELECT file_path FROM foto_rumah WHERE id=?");
|
||
$row->execute([$id]);
|
||
$fp = $row->fetchColumn();
|
||
if ($fp) {
|
||
$abs = __DIR__ . '/../' . $fp;
|
||
if (is_file($abs)) @unlink($abs);
|
||
$pdo->prepare("DELETE FROM foto_rumah WHERE id=?")->execute([$id]);
|
||
logActivity($pdo, 'delete', 'foto_rumah', (int)$id, 'Hapus foto');
|
||
}
|
||
sendSuccess(null, 'Foto dihapus');
|
||
break;
|
||
|
||
default:
|
||
sendError('Method not allowed', 405);
|
||
}
|