140 lines
4.1 KiB
PHP
140 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Event;
|
|
use App\Services\Photobooth\Exceptions\SparkboothUploadException;
|
|
use App\Services\Photobooth\SparkboothUploadService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\Support\Str;
|
|
|
|
class SparkboothUploadController extends Controller
|
|
{
|
|
public function __construct(private readonly SparkboothUploadService $service) {}
|
|
|
|
public function store(Request $request): Response
|
|
{
|
|
$media = $this->resolveMedia($request);
|
|
|
|
if (! $media) {
|
|
return $this->respond(null, false, 'Media is required', null, 400, $request);
|
|
}
|
|
|
|
try {
|
|
$result = $this->service->handleUpload(
|
|
$media,
|
|
$request->input('username'),
|
|
$request->input('password')
|
|
);
|
|
|
|
/** @var Event $event */
|
|
$event = $result['event'];
|
|
|
|
return $this->respond($event, true, null, null, 200, $request);
|
|
} catch (SparkboothUploadException $exception) {
|
|
return $this->respond(null, false, $exception->getMessage(), null, $exception->statusCode ?? 400, $request);
|
|
} catch (\Throwable) {
|
|
return $this->respond(null, false, 'Upload failed, please retry.', null, 500, $request);
|
|
}
|
|
}
|
|
|
|
protected function respond(?Event $event, bool $ok, ?string $message, ?string $url, int $status, Request $request): Response
|
|
{
|
|
$format = $this->resolveFormat($event, $request);
|
|
|
|
if ($format === 'xml') {
|
|
$payload = $ok
|
|
? $this->buildSuccessXml($url)
|
|
: $this->buildFailureXml($message);
|
|
|
|
return response($payload, $status, ['Content-Type' => 'application/xml']);
|
|
}
|
|
|
|
return response()->json([
|
|
'status' => $ok,
|
|
'error' => $ok ? null : $message,
|
|
'url' => $url,
|
|
], $status);
|
|
}
|
|
|
|
protected function resolveFormat(?Event $event, Request $request): string
|
|
{
|
|
$preferred = $request->input('format');
|
|
|
|
if ($preferred && in_array($preferred, ['json', 'xml'], true)) {
|
|
return $preferred;
|
|
}
|
|
|
|
$configured = $event?->photobooth_metadata['sparkbooth_response_format'] ?? null;
|
|
|
|
if ($configured && in_array($configured, ['json', 'xml'], true)) {
|
|
return $configured;
|
|
}
|
|
|
|
return config('photobooth.sparkbooth.response_format', 'json') === 'xml' ? 'xml' : 'json';
|
|
}
|
|
|
|
protected function buildSuccessXml(?string $url): string
|
|
{
|
|
$urlAttribute = $url ? ' url="'.htmlspecialchars($url, ENT_QUOTES).'"' : '';
|
|
|
|
return sprintf('<?xml version="1.0" encoding="UTF-8"?>'."\n".'<rsp status="ok"%s />', $urlAttribute);
|
|
}
|
|
|
|
protected function buildFailureXml(?string $message): string
|
|
{
|
|
$escaped = htmlspecialchars($message ?? 'Upload failed', ENT_QUOTES);
|
|
|
|
return sprintf(
|
|
'<?xml version="1.0" encoding="UTF-8"?>'."\n".'<rsp status="fail"><err msg="%s" /></rsp>',
|
|
$escaped
|
|
);
|
|
}
|
|
|
|
protected function resolveMedia(Request $request): ?UploadedFile
|
|
{
|
|
$file = $request->file('media');
|
|
|
|
if ($file instanceof UploadedFile) {
|
|
return $file;
|
|
}
|
|
|
|
$raw = $request->input('media');
|
|
|
|
if (is_string($raw) && $raw !== '') {
|
|
return $this->createUploadedFileFromBase64($raw);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function createUploadedFileFromBase64(string $raw): ?UploadedFile
|
|
{
|
|
$payload = $raw;
|
|
|
|
if (Str::startsWith($raw, 'data:')) {
|
|
$segments = explode(',', $raw, 2);
|
|
$payload = $segments[1] ?? '';
|
|
}
|
|
|
|
$decoded = base64_decode($payload, true);
|
|
|
|
if ($decoded === false) {
|
|
return null;
|
|
}
|
|
|
|
$tmpPath = tempnam(sys_get_temp_dir(), 'sparkbooth-');
|
|
|
|
if (! $tmpPath) {
|
|
return null;
|
|
}
|
|
|
|
file_put_contents($tmpPath, $decoded);
|
|
|
|
return new UploadedFile($tmpPath, 'upload.jpg', null, null, true);
|
|
}
|
|
}
|