Files
Plataforma-de-Tutoriais/plataforma-tutorias/app/Http/Controllers/VideosController.php
2026-05-15 16:13:33 +01:00

268 lines
8.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Video;
use Illuminate\Http\Request;
use App\Http\Requests\CreateVideoRequest;
use App\Http\Requests\UpdateVideoRequest;
use Illuminate\Support\Facades\Storage;
class VideosController extends Controller
{
public function __construct()
{
// Aumentar limites temporariamente para uploads grandes
// Nota: Estas configurações devem ser feitas antes do PHP processar o POST
// Por isso também estão no public/index.php
@ini_set('upload_max_filesize', '200M');
@ini_set('post_max_size', '200M');
@ini_set('max_execution_time', '300'); // 5 minutos
@ini_set('max_input_time', '300');
@ini_set('memory_limit', '512M');
}
public function index(Request $request)
{
$user = auth()->user();
if (!$user) {
return response()->json([
'message' => 'Utilizador não autenticado',
'data' => null,
'errors' => null,
], 404);
}
$search = trim((string) $request->query('search', ''));
$videosQuery = Video::with('categories');
if ($search !== '') {
$videosQuery->where(function ($query) use ($search) {
$query->where('title', 'like', "%{$search}%")
->orWhere('tags', 'like', "%{$search}%");
});
}
if ($user->role_id !== 1) {
$videosQuery->where('is_active', true);
}
$videos = $videosQuery->get();
if ($videos->isEmpty()) {
return response()->json([
'message' => $search !== '' ? 'Sem resultados para a pesquisa' : 'Não foram encontrados vídeos',
'data' => [],
'errors' => null,
], $search !== '' ? 200 : 404); // 200 se for pesquisa, 404 se for listagem normal
}
return response()->json([
'message' => 'Vídeos obtidos com sucesso',
'data' => $videos,
'errors' => null,
], 200);
}
public function getVideo($id)
{
$user = auth()->user();
if (!$user) {
return response()->json([
'message' => 'Utilizador não autenticado',
'data' => null,
'errors' => null,
], 404);
}
if ($user->role_id !== 1) {
$video = Video::with('categories')->where('is_active', true)->find($id);
/* Para não mostrar vídeos inactivos para utilizadores não administradores */
if (!$video || $video->is_active === false) {
return response()->json([
'message' => 'Acesso negado',
'data' => null,
'errors' => null,
], 404);
}
}
$video = Video::with('categories')->find($id);
if ($video) {
$video->url = Storage::url($video->url);
$video->thumbnail = Storage::url($video->thumbnail);
return response()->json([
'message' => 'Vídeo obtido com sucesso',
'data' => [
'id' => $video->id,
'title' => $video->title,
'description' => $video->description,
'url' => $video->url,
'thumbnail' => $video->thumbnail,
'duration' => $video->duration,
'tags' => $video->tags,
'categories' => $video->categories->map(function ($category) {
return [
'id' => $category->id,
'name' => $category->name,
];
})->values(),
'is_active' => $video->is_active,
],
'errors' => null,
], 200);
} else {
return response()->json([
'message' => 'Vídeo não encontrado',
'data' => null,
'errors' => null,
], 404);
}
}
public function create(CreateVideoRequest $request)
{
$user = auth()->user();
if (!$user) {
return response()->json([
'message' => 'Utilizador não autenticado',
'data' => null,
'errors' => null,
], 404);
}
$validated = $request->validated();
$videoPath = $request->file('url')->store('videos', 'public');
$thumbnailPath = $request->file('thumbnail')->store('thumbnails', 'public');
$video = Video::create([
'title' => $validated['title'],
'description' => $validated['description'],
'url' => $videoPath,
'thumbnail' => $thumbnailPath,
'duration' => $validated['duration'] ?? '00:00',
'tags' => $validated['tags'],
]);
if ($request->filled('category_ids')) {
$video->categories()->sync($request->input('category_ids'));
}
$baseUrl = $request->getSchemeAndHttpHost();
return response()->json([
'message' => 'Vídeo criado com sucesso',
'data' => [
'id' => $video->id,
'title' => $video->title,
'description' => $video->description,
'url' => $baseUrl . Storage::url($video->url),
'thumbnail' => $baseUrl . Storage::url($video->thumbnail),
'duration' => $video->duration,
'tags' => $video->tags,
'categories' => $video->categories->pluck('name'),
'is_active' => $video->is_active,
],
'errors' => null,
], 201);
}
public function update(UpdateVideoRequest $request, $id)
{
$user = auth()->user();
if (!$user) {
return response()->json([
'message' => 'Utilizador não autenticado',
'data' => null,
'errors' => null,
], 404);
}
$videoToUpdate = Video::find($id);
if (!$videoToUpdate) {
return response()->json([
'message' => 'Vídeo não encontrado',
'data' => null,
'errors' => null,
], 404);
}
$validated = $request->validated();
if ($request->hasFile('thumbnail')) {
// Apagar thumbnail antiga
if ($videoToUpdate->thumbnail && Storage::disk('public')->exists($videoToUpdate->thumbnail)) {
Storage::disk('public')->delete($videoToUpdate->thumbnail);
}
$validated['thumbnail'] = $request->file('thumbnail')->store('thumbnails', 'public');
}
try {
$videoToUpdate->update([
'title' => $validated['title'] ?? $videoToUpdate->title,
'description' => $validated['description'] ?? $videoToUpdate->description,
'tags' => $validated['tags'] ?? $videoToUpdate->tags,
'thumbnail' => $validated['thumbnail'] ?? $videoToUpdate->thumbnail,
'is_active' => array_key_exists('is_active', $validated) ? $validated['is_active'] : $videoToUpdate->is_active,
]);
if ($request->has('category_ids')) {
$videoToUpdate->categories()->sync($request->input('category_ids'));
}
return response()->json([
'message' => 'Dados do vídeo atualizados com sucesso',
'data' => $videoToUpdate->load('categories'),
'errors' => null,
], 200);
} catch (\Throwable $th) {
return response()->json([
'message' => 'Não foi possível atualizar o vídeo',
'data' => null,
'errors' => null,
], 500);
}
}
public function destroy($id)
{
$user = auth()->user();
if (!$user) {
return response()->json([
'message' => 'Utilizador não autenticado',
'data' => null,
'errors' => null,
], 404);
}
$video = Video::find($id);
if (!$video) {
return response()->json([
'message' => 'Vídeo não encontrado',
'data' => null,
'errors' => null,
], 404);
}
$video->delete();
return response()->json([
'message' => 'Vídeo apagado com sucesso',
'data' => null,
'errors' => null,
], 200);
}
}