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.
105 lines
3.3 KiB
PHP
105 lines
3.3 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../helpers.php';
|
|
runAuth();
|
|
|
|
/**
|
|
* Upload Business Header Image
|
|
*
|
|
* Multipart form: BusinessID (int), header (file)
|
|
* Or X-Business-ID header for BusinessID.
|
|
*/
|
|
|
|
// Get BusinessID from form, then header
|
|
$bizId = (int) ($_POST['BusinessID'] ?? 0);
|
|
if ($bizId <= 0) {
|
|
$bizId = (int) headerValue('X-Business-ID');
|
|
}
|
|
if ($bizId <= 0) {
|
|
apiAbort(['OK' => false, 'ERROR' => 'missing_businessid', 'MESSAGE' => 'BusinessID is required']);
|
|
}
|
|
|
|
if (!isset($_FILES['header']) || $_FILES['header']['error'] !== UPLOAD_ERR_OK) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'no_file', 'MESSAGE' => 'No file was uploaded']);
|
|
}
|
|
|
|
$headersDir = $_SERVER['DOCUMENT_ROOT'] . '/uploads/headers';
|
|
if (!is_dir($headersDir)) {
|
|
mkdir($headersDir, 0755, true);
|
|
}
|
|
|
|
try {
|
|
$tmpFile = $_FILES['header']['tmp_name'];
|
|
|
|
// Detect actual format from file contents (magic bytes)
|
|
$actualExt = '';
|
|
$fh = fopen($tmpFile, 'rb');
|
|
$header = fread($fh, 8);
|
|
fclose($fh);
|
|
$hex = strtoupper(bin2hex($header));
|
|
|
|
if (str_starts_with($hex, 'FFD8')) {
|
|
$actualExt = 'jpg';
|
|
} elseif (str_starts_with($hex, '89504E470D0A1A0A')) {
|
|
$actualExt = 'png';
|
|
} elseif (str_starts_with($hex, '474946')) {
|
|
$actualExt = 'gif';
|
|
} elseif (str_starts_with($hex, '52494646')) {
|
|
// RIFF container — could be WEBP
|
|
$actualExt = 'webp';
|
|
}
|
|
|
|
// Fallback to client extension
|
|
if ($actualExt === '') {
|
|
$actualExt = strtolower(pathinfo($_FILES['header']['name'], PATHINFO_EXTENSION));
|
|
}
|
|
|
|
$allowed = ['jpg', 'jpeg', 'gif', 'png', 'webp', 'heic', 'heif'];
|
|
if (!in_array($actualExt, $allowed)) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invalid_type', 'MESSAGE' => 'Only image files are accepted (jpg, jpeg, gif, png, webp, heic)']);
|
|
}
|
|
|
|
// Convert HEIC/HEIF extension to jpg for consistency
|
|
if ($actualExt === 'heic' || $actualExt === 'heif') {
|
|
$actualExt = 'jpg';
|
|
}
|
|
|
|
// Delete old header if exists
|
|
$old = queryOne("SELECT HeaderImageExtension FROM Businesses WHERE ID = ?", [$bizId]);
|
|
if ($old && !empty($old['HeaderImageExtension'])) {
|
|
$oldFile = "$headersDir/{$bizId}.{$old['HeaderImageExtension']}";
|
|
if (file_exists($oldFile)) {
|
|
@unlink($oldFile);
|
|
}
|
|
}
|
|
|
|
// Delete destination file if it already exists (same extension re-upload)
|
|
$destFile = "$headersDir/{$bizId}.{$actualExt}";
|
|
if (file_exists($destFile)) {
|
|
@unlink($destFile);
|
|
}
|
|
|
|
// Move uploaded file
|
|
if (!move_uploaded_file($tmpFile, $destFile)) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'upload_failed', 'MESSAGE' => 'Failed to save uploaded file']);
|
|
}
|
|
|
|
// Update database
|
|
queryTimed("UPDATE Businesses SET HeaderImageExtension = ? WHERE ID = ?", [$actualExt, $bizId]);
|
|
|
|
// Get image dimensions
|
|
$imgSize = @getimagesize($destFile);
|
|
$width = $imgSize[0] ?? 0;
|
|
$height = $imgSize[1] ?? 0;
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'ERROR' => '',
|
|
'MESSAGE' => 'Header uploaded successfully',
|
|
'HEADERURL' => "/uploads/headers/{$bizId}.{$actualExt}",
|
|
'WIDTH' => $width,
|
|
'HEIGHT' => $height,
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'server_error', 'MESSAGE' => $e->getMessage(), 'DETAIL' => '']);
|
|
}
|