Complete port of all 163 API endpoints from Lucee/CFML to PHP 8.3. Shared helpers in api/helpers.php (DB, auth, request/response, security). PDO prepared statements throughout. Same JSON response shapes as CFML.
110 lines
3.4 KiB
PHP
110 lines
3.4 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../helpers.php';
|
|
runAuth();
|
|
|
|
/*
|
|
Avatar Upload/Get API
|
|
GET: Returns avatar URL for authenticated user
|
|
POST: Uploads new avatar image (multipart form data)
|
|
Stores images as: /uploads/users/{UserID}.jpg
|
|
*/
|
|
|
|
global $userId;
|
|
|
|
if ($userId <= 0) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'not_logged_in', 'MESSAGE' => 'Authentication required']);
|
|
}
|
|
|
|
$uploadsDir = dirname(__DIR__, 2) . '/uploads/users';
|
|
$avatarUrl = baseUrl() . '/uploads/users/';
|
|
|
|
// Find existing avatar (check multiple extensions)
|
|
function findAvatarFile(string $dir, int $uid): ?string {
|
|
foreach (['jpg', 'jpeg', 'png', 'gif', 'webp'] as $ext) {
|
|
$path = "$dir/$uid.$ext";
|
|
if (file_exists($path)) return $path;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
$existingAvatar = findAvatarFile($uploadsDir, $userId);
|
|
|
|
// GET — return current avatar URL
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
$hasAvatar = $existingAvatar !== null;
|
|
$filename = $hasAvatar ? basename($existingAvatar) : '';
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'HAS_AVATAR' => $hasAvatar,
|
|
'AVATAR_URL' => $hasAvatar ? $avatarUrl . $filename . '?t=' . time() : '',
|
|
]);
|
|
}
|
|
|
|
// POST — upload new avatar
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
if (!isset($_FILES['avatar']) || $_FILES['avatar']['error'] !== UPLOAD_ERR_OK) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'missing_file', 'MESSAGE' => 'No avatar file provided']);
|
|
}
|
|
|
|
$file = $_FILES['avatar'];
|
|
$allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mime = finfo_file($finfo, $file['tmp_name']);
|
|
finfo_close($finfo);
|
|
|
|
if (!in_array($mime, $allowed, true)) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'invalid_type', 'MESSAGE' => 'Only JPEG, PNG, GIF, or WebP images are accepted']);
|
|
}
|
|
|
|
if (!is_dir($uploadsDir)) {
|
|
mkdir($uploadsDir, 0755, true);
|
|
}
|
|
|
|
$destPath = "$uploadsDir/$userId.jpg";
|
|
|
|
// Load, resize, and save as JPEG
|
|
$img = match ($mime) {
|
|
'image/jpeg' => imagecreatefromjpeg($file['tmp_name']),
|
|
'image/png' => imagecreatefrompng($file['tmp_name']),
|
|
'image/gif' => imagecreatefromgif($file['tmp_name']),
|
|
'image/webp' => imagecreatefromwebp($file['tmp_name']),
|
|
};
|
|
|
|
if ($img) {
|
|
$w = imagesx($img);
|
|
$h = imagesy($img);
|
|
|
|
if ($w > 500 || $h > 500) {
|
|
$ratio = min(500 / $w, 500 / $h);
|
|
$newW = (int) ($w * $ratio);
|
|
$newH = (int) ($h * $ratio);
|
|
$resized = imagecreatetruecolor($newW, $newH);
|
|
imagecopyresampled($resized, $img, 0, 0, 0, 0, $newW, $newH, $w, $h);
|
|
imagedestroy($img);
|
|
$img = $resized;
|
|
}
|
|
|
|
imagejpeg($img, $destPath, 85);
|
|
imagedestroy($img);
|
|
} else {
|
|
// Fallback: just move the file
|
|
move_uploaded_file($file['tmp_name'], $destPath);
|
|
}
|
|
|
|
// Delete old avatar with different extension
|
|
if ($existingAvatar && $existingAvatar !== $destPath && file_exists($existingAvatar)) {
|
|
unlink($existingAvatar);
|
|
}
|
|
|
|
// Update DB
|
|
queryTimed("UPDATE Users SET ImageExtension = 'jpg' WHERE ID = ?", [$userId]);
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'MESSAGE' => 'Avatar uploaded successfully',
|
|
'AVATAR_URL' => $avatarUrl . $userId . '.jpg?t=' . time(),
|
|
]);
|
|
}
|
|
|
|
apiAbort(['OK' => false, 'ERROR' => 'bad_method', 'MESSAGE' => 'Use GET or POST']);
|