You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.1 KiB

1 month ago
<?php
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Models\Competition;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
class CompetitionLogoController extends Controller
{
public function store(Request $request, Competition $competition): JsonResponse
{
$request->validate([
'file' => ['required', 'file', 'max:2048', 'mimes:png,jpg,jpeg,webp,gif,svg'],
]);
$uploaded = $request->file('file');
$ext = strtolower((string) ($uploaded->getClientOriginalExtension() ?: $uploaded->extension() ?: 'png'));
$dir = 'competitions/'.$competition->id;
$filename = 'logo-'.bin2hex(random_bytes(4)).'.'.$ext;
$this->deleteStoredLogos($competition);
try {
$path = $uploaded->storeAs($dir, $filename, 'public');
} catch (\Throwable $e) {
Log::error('competition.logo.store_exception', [
'competition_id' => $competition->id,
'error' => $e->getMessage(),
]);
throw ValidationException::withMessages([
'file' => ['Logo 保存失败,请稍后重试'],
]);
}
if (! is_string($path) || $path === '' || $path === '0' || ! Storage::disk('public')->exists($path)) {
throw ValidationException::withMessages([
'file' => ['Logo 保存失败,请稍后重试'],
]);
}
$url = '/storage/'.$path.'?t='.time();
$this->writeLogoUrl($competition, $url);
return response()->json([
'url' => $url,
'logoUrl' => $url,
]);
}
public function destroy(Competition $competition): JsonResponse
{
$this->deleteStoredLogos($competition);
$this->writeLogoUrl($competition, '');
return response()->json([
'url' => '',
'logoUrl' => '',
]);
}
private function writeLogoUrl(Competition $competition, string $url): void
{
$branding = is_array($competition->branding_json) ? $competition->branding_json : [];
$login = is_array($branding['login'] ?? null) ? $branding['login'] : [];
if ($url === '') {
unset($login['logoUrl']);
} else {
$login['logoUrl'] = $url;
}
if ($login === []) {
unset($branding['login']);
} else {
$branding['login'] = $login;
}
$competition->branding_json = $branding === [] ? null : $branding;
$competition->save();
}
private function deleteStoredLogos(Competition $competition): void
{
$dir = 'competitions/'.$competition->id;
$disk = Storage::disk('public');
if (! $disk->exists($dir)) {
return;
}
foreach ($disk->files($dir) as $file) {
if (str_starts_with(basename($file), 'logo')) {
$disk->delete($file);
}
}
}
}