139 lines
4.4 KiB
PHP
139 lines
4.4 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Api\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use Illuminate\Http\JsonResponse;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Str;
|
||
use OpenApi\Attributes as OA;
|
||
|
||
class UploadController extends Controller
|
||
{
|
||
#[OA\Post(
|
||
path: '/api/admin/upload',
|
||
summary: 'Dosya yükle',
|
||
description: 'Görsel veya video dosyası yükler. Görseller max 5MB, videolar max 100MB. Modül bazlı klasörleme destekler.',
|
||
security: [['sanctum' => []]],
|
||
tags: ['Upload'],
|
||
requestBody: new OA\RequestBody(
|
||
required: true,
|
||
content: new OA\MediaType(
|
||
mediaType: 'multipart/form-data',
|
||
schema: new OA\Schema(
|
||
required: ['file'],
|
||
properties: [
|
||
new OA\Property(property: 'file', type: 'string', format: 'binary', description: 'Görsel veya video dosyası'),
|
||
new OA\Property(property: 'type', type: 'string', enum: ['image', 'video'], description: 'Dosya tipi'),
|
||
new OA\Property(property: 'folder', type: 'string', description: 'Modül klasörü (hero-slides, courses, vb.)'),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
responses: [
|
||
new OA\Response(response: 201, description: 'Dosya yüklendi', content: new OA\JsonContent(
|
||
properties: [
|
||
new OA\Property(property: 'data', type: 'object', properties: [
|
||
new OA\Property(property: 'path', type: 'string'),
|
||
new OA\Property(property: 'url', type: 'string'),
|
||
]),
|
||
],
|
||
)),
|
||
new OA\Response(response: 422, description: 'Validasyon hatası'),
|
||
],
|
||
)]
|
||
public function store(Request $request): JsonResponse
|
||
{
|
||
$type = $request->input('type', 'image');
|
||
|
||
if ($type === 'video') {
|
||
return $this->storeVideo($request);
|
||
}
|
||
|
||
return $this->storeImage($request);
|
||
}
|
||
|
||
/**
|
||
* @var list<string>
|
||
*/
|
||
private const ALLOWED_FOLDERS = [
|
||
'images',
|
||
'videos',
|
||
'hero-slides',
|
||
'settings',
|
||
'pages',
|
||
'courses',
|
||
'announcements',
|
||
'categories',
|
||
];
|
||
|
||
private function resolveFolder(Request $request, string $default): string
|
||
{
|
||
$folder = $request->input('folder', $default);
|
||
|
||
if (! in_array($folder, self::ALLOWED_FOLDERS, true)) {
|
||
$folder = $default;
|
||
}
|
||
|
||
return $folder;
|
||
}
|
||
|
||
private function storeImage(Request $request): JsonResponse
|
||
{
|
||
$request->validate([
|
||
'file' => ['required', 'file', 'image', 'max:5120'],
|
||
'folder' => ['sometimes', 'string'],
|
||
], [
|
||
'file.required' => 'Dosya zorunludur.',
|
||
'file.image' => 'Dosya bir görsel (jpg, png, gif, svg, webp) olmalıdır.',
|
||
'file.max' => 'Dosya boyutu en fazla 5MB olabilir.',
|
||
]);
|
||
|
||
$folder = $this->resolveFolder($request, 'images');
|
||
|
||
$file = $request->file('file');
|
||
$filename = Str::uuid().'.'.$file->getClientOriginalExtension();
|
||
|
||
$directory = public_path('uploads/'.$folder);
|
||
$file->move($directory, $filename);
|
||
|
||
$relativePath = 'uploads/'.$folder.'/'.$filename;
|
||
|
||
return response()->json([
|
||
'data' => [
|
||
'path' => $relativePath,
|
||
'url' => url($relativePath),
|
||
],
|
||
], 201);
|
||
}
|
||
|
||
private function storeVideo(Request $request): JsonResponse
|
||
{
|
||
$request->validate([
|
||
'file' => ['required', 'file', 'mimes:mp4,webm,mov,avi,mkv', 'max:102400'],
|
||
'folder' => ['sometimes', 'string'],
|
||
], [
|
||
'file.required' => 'Dosya zorunludur.',
|
||
'file.mimes' => 'Dosya bir video (mp4, webm, mov, avi, mkv) olmalıdır.',
|
||
'file.max' => 'Video boyutu en fazla 100MB olabilir.',
|
||
]);
|
||
|
||
$folder = $this->resolveFolder($request, 'videos');
|
||
|
||
$file = $request->file('file');
|
||
$filename = Str::uuid().'.'.$file->getClientOriginalExtension();
|
||
|
||
$directory = public_path('uploads/'.$folder);
|
||
$file->move($directory, $filename);
|
||
|
||
$relativePath = 'uploads/'.$folder.'/'.$filename;
|
||
|
||
return response()->json([
|
||
'data' => [
|
||
'path' => $relativePath,
|
||
'url' => url($relativePath),
|
||
],
|
||
], 201);
|
||
}
|
||
}
|