lms/app/Http/Controllers/Course/PlayerController.php
Ahmed Darrazi 3d67eedf0c
All checks were successful
Build & Push Docker Image / docker (push) Successful in 2m10s
bugfix
2025-12-19 01:37:38 +01:00

177 lines
6.8 KiB
PHP

<?php
namespace App\Http\Controllers\Course;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Course\WatchHistory;
use App\Services\Course\CoursePlayerService;
use App\Services\Course\CourseReviewService;
use App\Services\Course\CourseService;
use App\Services\Course\CourseSectionService;
use App\Services\LiveClass\ZoomLiveService;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class PlayerController extends Controller
{
public function __construct(
protected CourseService $courseService,
protected CoursePlayerService $coursePlay,
protected CourseSectionService $sectionService,
protected CourseReviewService $reviewService,
protected ZoomLiveService $zoomLiveService,
// protected AssignmentSubmissionService $submissionService,
) {}
public function index(Request $request)
{
$courses = $this->courseService->getCourses($request->all(), null, true);
return Inertia::render('courses/index', compact('courses'));
}
public function intWatchHistory(Request $request)
{
$user = Auth::user();
$watchHistory = $this->sectionService->initWatchHistory($request->course_id, 'lesson', $user->id);
return redirect()->route('course.player', [
'type' => $watchHistory->current_watching_type,
'watch_history' => $watchHistory->id,
'lesson_id' => $watchHistory->current_watching_id,
]);
}
public function course_player(Request $request, string $type, WatchHistory $watch_history, string $lesson_id)
{
try {
$user = Auth::user();
$watching_id = $lesson_id ?: $watch_history->current_watching_id;
$watching_type = in_array($type, ['lesson', 'quiz'], true) ? $type : ($watch_history->current_watching_type ?? 'lesson');
$course = $this->courseService->getUserCourseById($watch_history->course_id, $user);
$watching = $this->coursePlay->getWatchingLesson($watching_id, $watching_type);
$reviews = $this->reviewService->getReviews(['course_id' => $course->id, ...$request->all()], true);
$userReview = $this->reviewService->userReview($course->id, $user->id);
$totalReviews = $this->reviewService->totalReviews($course->id);
$zoomConfig = $this->zoomLiveService->zoomConfig;
$totalContent = 0;
foreach ($course->sections as $courseSection) {
$totalContent += count($courseSection->section_lessons) + count($courseSection->section_quizzes);
}
$watchHistory = $this->coursePlay->watchHistory($course, $watching_id, $watching_type, $user->id);
$section = $course->sections->firstWhere('id', $watchHistory->current_section_id);
// $submissions = null;
// if ($assignment) {
// $submissions = $this->submissionService->getSubmissions($assignment, $request->all());
// }
return Inertia::render('course-player/index', [
'type' => $type,
'course' => $course,
'section' => $section,
'reviews' => $reviews,
'watching' => $watching,
'totalContent' => $totalContent,
'watchHistory' => $watchHistory,
'userReview' => $userReview,
'totalReviews' => $totalReviews,
'zoomConfig' => $zoomConfig,
]);
} catch (ModelNotFoundException $th) {
$fallbackId = $watch_history->current_watching_id;
$fallbackType = $watch_history->current_watching_type;
$requestedType = $watching_type ?? $type;
if ($fallbackId && in_array($fallbackType, ['lesson', 'quiz'], true)) {
$isDifferentFromRequested = ((string) $fallbackId !== (string) $lesson_id) || ($fallbackType !== $requestedType);
if ($isDifferentFromRequested) {
try {
$this->coursePlay->getWatchingLesson((string) $fallbackId, $fallbackType);
return redirect()->route('course.player', [
'type' => $fallbackType,
'watch_history' => $watch_history->id,
'lesson_id' => $fallbackId,
]);
} catch (ModelNotFoundException $fallbackException) {
// Fall through to generic error below.
}
}
}
return redirect()->route('category.courses', ['category' => 'all'])->with('error', 'The requested content could not be found.');
} catch (\Throwable $th) {
return redirect()->route('category.courses', ['category' => 'all'])->with('error', $th->getMessage());
}
}
public function finish_course(WatchHistory $watch_history)
{
$completedItems = json_decode($watch_history->completed_watching, true) ?: [];
$lastItem = [
'id' => $watch_history->current_watching_id,
'type' => $watch_history->current_watching_type,
];
// Check if lastItem already exists in completedItems
$itemExists = false;
foreach ($completedItems as $item) {
if ((string)$item['id'] === (string)$lastItem['id'] && $item['type'] === $lastItem['type']) {
$itemExists = true;
break;
}
}
// Add lastItem to completedItems if it doesn't exist
if (!$itemExists) {
$completedItems[] = $lastItem;
}
// Clean up duplicates and ensure consistent data types
$completedItems = $this->cleanupCompletedItems($completedItems);
$watch_history->completed_watching = json_encode($completedItems);
$watch_history->completion_date = now();
$watch_history->save();
return back()->with('success', 'Kurs erfolgreich abgeschlossen.');
}
/**
* Clean up completed items to remove duplicates and ensure consistent data types
*/
private function cleanupCompletedItems(array $completedItems): array
{
$cleaned = [];
$seen = [];
foreach ($completedItems as $item) {
// Ensure consistent data types (string for ID)
$normalizedItem = [
'id' => (string)$item['id'],
'type' => $item['type']
];
// Create unique key for duplicate checking
$key = $normalizedItem['id'] . '|' . $normalizedItem['type'];
// Only add if not already seen
if (!isset($seen[$key])) {
$seen[$key] = true;
$cleaned[] = $normalizedItem;
}
}
return $cleaned;
}
}