From e3458433f2f5a75cd3c8cd5e9e7036c4edac3409 Mon Sep 17 00:00:00 2001 From: Baghiz Zuhdi Adzin <74885652+baghizzhd@users.noreply.github.com> Date: Mon, 12 Jan 2026 08:05:36 +0700 Subject: [PATCH] pembenaran player course --- app/Helpers/Api_helper.php | 96 --------- app/Http/Controllers/CommonController.php | 33 +-- app/Http/Controllers/LiveClassController.php | 1 + app/Http/Controllers/PlayerController.php | 13 +- .../Controllers/student/MessageController.php | 10 +- .../Controllers/student/QuizController.php | 63 ++++-- .../views/admin/course/edit_media.blade.php | 27 +-- .../views/admin/course/lesson_add.blade.php | 27 +-- .../views/admin/course/lesson_type.blade.php | 60 +----- .../course_content_body.blade.php | 76 +++---- resources/views/course_player/init.blade.php | 37 ++++ .../course_player/player_config.blade.php | 7 +- .../views/course_player/player_page.blade.php | 190 ++++++++---------- .../views/course_player/quiz/index.blade.php | 33 ++- .../course_player/quiz/questions.blade.php | 24 +-- .../views/course_player/side_bar.blade.php | 27 ++- .../default/course/course_details.blade.php | 84 +++++--- .../default/student/message/index.blade.php | 45 ++++- .../instructor/course/edit_media.blade.php | 26 +-- .../instructor/course/lesson_type.blade.php | 53 +---- routes/player.php | 1 + 21 files changed, 388 insertions(+), 545 deletions(-) diff --git a/app/Helpers/Api_helper.php b/app/Helpers/Api_helper.php index 5aaab45..4ca55fd 100644 --- a/app/Helpers/Api_helper.php +++ b/app/Helpers/Api_helper.php @@ -213,32 +213,6 @@ function is_added_to_wishlist($user_id = 0, $course_id = "") } } -// function is_purchased($user_id = 0, $course_id = "") -// { -// // 0 represents Not purchased, 1 represents Purchased, 2 represents Pending -// if ($user_id > 0) { -// if (enroll_status($course_id, $user_id) == 'valid') { -// return true; -// } else { -// return false; -// } -// } else { -// return false; -// } -// } - -// function is_purchased($user_id = 0, $course_id = "") -// { -// // 0 represents not purchased, 1 represents purchased -// if ($user_id > 0) { -// $status = enroll_status($course_id, $user_id); -// return $status === 'valid'; // Return true only if status is 'valid' -// } else { -// return false; // User ID is not valid -// } -// } - - if (!function_exists('is_purchased')) { function is_purchased($user_id = 0, $course_id = "") { @@ -271,7 +245,6 @@ if (!function_exists('enroll_status_api')) { } } - function get_total_duration_of_lesson_by_course_id($course_id) { $total_duration = 0; @@ -433,75 +406,6 @@ if (!function_exists('update_watch_history_manually')) { } } -// if (!function_exists('update_watch_history_manually')) { -// // code of mark this lesson as completed -// function update_watch_history_manually($lesson_id = "", $course_id = "", $user_id = "") -// { -// $is_completed = 0; - -// $query = DB::table('watch_histories')->where('course_id', $course_id)->where('student_id', $user_id)->first(); - -// $course_progress = course_progress($course_id, $user_id); - -// if (!empty($query)) { -// $lesson_ids = json_decode($query->completed_lesson, true); -// if (!is_array($lesson_ids)) -// $lesson_ids = array(); -// if (!in_array($lesson_id, $lesson_ids)) { -// array_push($lesson_ids, $lesson_id); -// $total_lesson = DB::table('lessons')->where('course_id', $course_id)->get(); -// $course_progress = (100 / count($total_lesson)) * count($lesson_ids); - -// if ($course_progress >= 100 && $query->completed_date == null) { -// $completed_date = time(); -// } else { -// $completed_date = $query->completed_date; -// } - -// DB::table('watch_histories')->where('id', $query->id)->update([ -// 'completed_lesson' => json_encode($lesson_ids), -// 'completed_date' => $completed_date, -// ]); - -// $is_completed = 1; - -// } else { -// if (($key = array_search($lesson_id, $lesson_ids)) !== false) { -// unset($lesson_ids[$key]); -// } - -// $total_lesson = DB::table('lessons')->where('course_id', $course_id)->get(); -// $course_progress = (100 / count($total_lesson)) * count($lesson_ids); - -// if ($course_progress >= 100 && $query->completed_date == null) { -// $completed_date = time(); -// } else { -// $completed_date = $query->completed_date; -// } - -// DB::table('watch_histories')->where('id', $query->id)->update([ -// 'completed_lesson' => json_encode($lesson_ids), -// 'completed_date' => $completed_date, -// ]); - -// $is_completed = 0; -// } - -// } else { -// $total_lesson = DB::table('lessons')->where('course_id', $course_id)->get(); -// $course_progress = (100 / count($total_lesson)); - -// $insert_data['course_id'] = $course_id; -// $insert_data['student_id'] = $user_id; -// $insert_data['completed_lesson'] = json_encode(array($lesson_id)); -// $insert_data['watching_lesson_id'] = $lesson_id; -// DB::table('watch_histories')->create($insert_data); -// } - -// return json_encode(array('lesson_id' => $lesson_id, 'course_progress' => round($course_progress), 'is_completed' => $is_completed)); -// } -// } - function course_completion_data($course_id = "", $user_id = "") { $response = array(); diff --git a/app/Http/Controllers/CommonController.php b/app/Http/Controllers/CommonController.php index 33afad2..5d12251 100644 --- a/app/Http/Controllers/CommonController.php +++ b/app/Http/Controllers/CommonController.php @@ -7,7 +7,6 @@ use Illuminate\Http\Request; class CommonController extends Controller { - // Get video details new code function get_video_details(Request $request, $url = "") { if ($url == "") { @@ -17,36 +16,9 @@ class CommonController extends Controller $host = explode('.', str_replace('www.', '', strtolower(parse_url($url, PHP_URL_HOST)))); $host = isset($host[0]) ? $host[0] : $host; - $vimeo_api_key = get_settings('vimeo_api_key'); $youtube_api_key = get_settings('youtube_api_key'); - if ($host == 'vimeo') { - $video_id = substr(parse_url($url, PHP_URL_PATH), 1); - $options = array('http' => array( - 'method' => 'GET', - 'header' => 'Authorization: Bearer ' . $vimeo_api_key - )); - $context = stream_context_create($options); - - try { - $hash = json_decode(file_get_contents("https://api.vimeo.com/videos/{$video_id}", false, $context)); - } catch (\Throwable $th) { - $hash = ''; - } - - if ($hash == '') return; - - - return array( - 'provider' => 'Vimeo', - 'video_id' => $video_id, - 'title' => $hash->name, - 'thumbnail' => $hash->pictures->sizes[0]->link, - 'video' => $hash->link, - 'embed_video' => "https://player.vimeo.com/video/" . $video_id, - 'duration' => gmdate("H:i:s", $hash->duration) - ); - } elseif ($host == 'youtube' || $host == 'youtu') { + if ($host == 'youtube' || $host == 'youtu') { preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $match); $video_id = $match[1]; @@ -68,8 +40,7 @@ class CommonController extends Controller 'embed_video' => "http://www.youtube.com/embed/" . $hash->items[0]->id, 'duration' => $duration->format('%H:%I:%S'), ); - } elseif ($host == 'drive') { - } + } } public function rendered_view(Request $request, $path = "") diff --git a/app/Http/Controllers/LiveClassController.php b/app/Http/Controllers/LiveClassController.php index 00384df..a684a0b 100644 --- a/app/Http/Controllers/LiveClassController.php +++ b/app/Http/Controllers/LiveClassController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Http\Controllers\Controller; use App\Models\Course; use App\Models\Live_class; use App\Models\Setting; diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index 8b612b7..3faf860 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -13,6 +13,17 @@ use Illuminate\Support\Facades\Session; class PlayerController extends Controller { + public function reload_sidebar($course_id, $lesson_id) + { + $course_details = Course::findOrFail($course_id); + $lesson_details = Lesson::findOrFail($lesson_id); + + return view('course_player.side_bar', compact( + 'course_details', + 'lesson_details' + )); + } + public function course_player(Request $request, $slug, $id = '') { $course = Course::where('slug', $slug)->firstOrNew(); @@ -35,7 +46,7 @@ class PlayerController extends Controller } } } - + //cek histori tontonan $check_lesson_history = Watch_history::where('course_id', $course->id) ->where('student_id', auth()->user()->id)->first(); $first_lesson_of_course = Lesson::where('course_id', $course->id)->orderBy('sort', 'asc')->value('id'); diff --git a/app/Http/Controllers/student/MessageController.php b/app/Http/Controllers/student/MessageController.php index 512ca99..3459ef2 100644 --- a/app/Http/Controllers/student/MessageController.php +++ b/app/Http/Controllers/student/MessageController.php @@ -134,8 +134,14 @@ class MessageController extends Controller public function search_student(Request $request) { - $page_data['user_details'] = User::where('email', $request->search_mail)->first(); - $view_path = 'frontend.' . get_frontend_settings('theme') . '.student.message.search_result'; + $search = $request->search_mail; + + if (empty(trim($search))) { + $page_data['user_details'] = null; // or collect() for no results + } else { + $page_data['user_details'] = User::where('email', 'LIKE', '%' . $search . '%') ->first(); + } + $view_path = 'frontend.' . get_frontend_settings('theme') . '.student.message.search_result'; return view($view_path, $page_data); } diff --git a/app/Http/Controllers/student/QuizController.php b/app/Http/Controllers/student/QuizController.php index cffdf8f..da7fa74 100644 --- a/app/Http/Controllers/student/QuizController.php +++ b/app/Http/Controllers/student/QuizController.php @@ -14,9 +14,14 @@ class QuizController extends Controller { public function quiz_submit(Request $request) { - $retake = Lesson::where('id', $request->quiz_id)->value('retake'); - $submit = QuizSubmission::where('quiz_id', $request->quiz_id)->where('user_id', auth()->user()->id)->count(); - if ($submit > $retake) { + $quiz = Lesson::findOrFail($request->quiz_id); + + $retake = $quiz->retake; + $submit = QuizSubmission::where('quiz_id', $quiz->id) + ->where('user_id', auth()->user()->id) + ->count(); + + if ($submit >= $retake) { Session::flash('warning', get_phrase('Attempt has been over.')); return redirect()->back(); } @@ -37,41 +42,63 @@ class QuizController extends Controller $questions = Question::whereIn('id', $question_ids)->get(); $right_answers = $wrong_answers = []; + foreach ($questions as $key => $question) { $correct_answer = json_decode($question->answer, true); $submitted = $submitted_answers[$key]; if ($question->type == 'mcq') { - $isCorrect = empty(array_diff($correct_answer, $submitted)) && empty(array_diff($submitted, $correct_answer)); + $isCorrect = empty(array_diff($correct_answer, $submitted)) + && empty(array_diff($submitted, $correct_answer)); } elseif ($question->type == 'fill_blanks') { $isCorrect = count($correct_answer) === count($submitted); - if ($isCorrect) { - for ($i = 0; $i < count($correct_answer); $i++) { - if (strtolower($correct_answer[$i]) != strtolower($submitted[$i])) { + foreach ($correct_answer as $i => $answer) { + if (strtolower($answer) !== strtolower($submitted[$i])) { $isCorrect = false; break; } } - } else { - $isCorrect = false; } } elseif ($question->type == 'true_false') { - $isCorrect = strtolower(json_encode($correct_answer)) == strtolower($submitted); + $isCorrect = strtolower(json_encode($correct_answer)) === strtolower($submitted); } - $isCorrect ? $right_answers[] = $question->id : $wrong_answers[] = $question->id; + $isCorrect + ? $right_answers[] = $question->id + : $wrong_answers[] = $question->id; } - $data['quiz_id'] = $quiz_id; - $data['user_id'] = auth()->user()->id; - $data['correct_answer'] = $right_answers ? json_encode($right_answers) : null; - $data['wrong_answer'] = $wrong_answers ? json_encode($wrong_answers) : null; - $data['submits'] = $submits->count() > 0 ? json_encode($submits->toArray()) : null; + QuizSubmission::create([ + 'quiz_id' => $quiz->id, + 'user_id' => auth()->user()->id, + 'correct_answer' => $right_answers ? json_encode($right_answers) : null, + 'wrong_answer' => $wrong_answers ? json_encode($wrong_answers) : null, + 'submits' => $submits->count() ? json_encode($submits->toArray()) : null, + ]); + + // ✅ HITUNG NILAI + $total_questions = $questions->count(); + $mark_per_question = $total_questions > 0 + ? ($quiz->total_mark / $total_questions) + : 0; + + $obtained_mark = count($right_answers) * $mark_per_question; + + // ✅ JIKA LULUS → MARK LESSON COMPLETED + if ($obtained_mark >= $quiz->pass_mark) { + update_watch_history_manually( + $quiz->id, + $quiz->course_id, + auth()->user()->id + ); + + Session::flash('success', get_phrase('Congratulations, you passed the quiz.')); + } else { + Session::flash('warning', get_phrase('You did not reach the minimum score.')); + } - QuizSubmission::insert($data); - Session::flash('success', get_phrase('Your answers have been submitted.')); return redirect()->back(); } diff --git a/resources/views/admin/course/edit_media.blade.php b/resources/views/admin/course/edit_media.blade.php index 4ea77ec..d036401 100644 --- a/resources/views/admin/course/edit_media.blade.php +++ b/resources/views/admin/course/edit_media.blade.php @@ -14,37 +14,14 @@
-
- @php - $preview_video_type = str_contains($course_details->preview, 'youtu') ? 'youtube' : ''; - $preview_video_type = str_contains($course_details->preview, 'vimeo') && $preview_video_type == '' ? 'vimeo' : ''; - $preview_video_type = str_contains($course_details->preview, 'http') && $preview_video_type == '' ? 'html5' : ''; - @endphp - -
-   -    -  
-
- - - -
- -
- - -
- -
- - -
- -
- - -
+
-
- -
-
diff --git a/resources/views/course_player/course_content_body.blade.php b/resources/views/course_player/course_content_body.blade.php index aeec090..5024aa5 100644 --- a/resources/views/course_player/course_content_body.blade.php +++ b/resources/views/course_player/course_content_body.blade.php @@ -31,14 +31,6 @@
@include('frontend.course_player.player_config') -@elseif($lesson_details->lesson_type == 'system-video') -
- -
- @include('frontend.course_player.player_config') @elseif($lesson_details->lesson_type == 'image')
@php @@ -47,47 +39,41 @@ @endphp
-@elseif($lesson_details->lesson_type == 'vimeo-url' && $lesson_details->video_type == 'vimeo') - @php - $video_url = $lesson_details->lesson_src; - $video_id = explode('https://vimeo.com/', $video_url); - $video_id = str_replace('https://vimeo.com/', '', $video_url); - @endphp -
-
- - - - - -
-
-
-
- @include('frontend.course_player.player_config') @elseif($lesson_details->lesson_type == 'google_drive') @php - $video_url = $lesson_details->lesson_src; - $url_array_1 = explode('/', $video_url . '/'); - $url_array_2 = explode('=', $video_url); - $video_id = null; - if ($url_array_1[4] == 'd'): - $video_id = $url_array_1[5]; - else: - $video_id = $url_array_2[1]; - endif; + $video_url = trim($lesson_details->lesson_src); + + // Extract Google Drive file ID reliably from standard share links + preg_match('/\/d\/([a-zA-Z0-9_-]+)/', $video_url, $matches); + $video_id = $matches[1] ?? null; @endphp -
- -
- @include('frontend.course_player.player_config') + @if($video_id) +
+ +
+ +
+
+ @include('frontend.course_player.player_config') + @else +
+
+
Invalid Google Drive Link
+

Could not extract video ID.

+ Use a link like:
+ https://drive.google.com/file/d/FILE_ID/view +
+
+
+ @endif @elseif($lesson_details->lesson_type == 'html5')
diff --git a/resources/views/course_player/init.blade.php b/resources/views/course_player/init.blade.php index f6b4e5c..2071d4e 100644 --- a/resources/views/course_player/init.blade.php +++ b/resources/views/course_player/init.blade.php @@ -1,3 +1,40 @@ + + \ No newline at end of file + + + diff --git a/resources/views/course_player/quiz/index.blade.php b/resources/views/course_player/quiz/index.blade.php index 11b0f34..81b323e 100644 --- a/resources/views/course_player/quiz/index.blade.php +++ b/resources/views/course_player/quiz/index.blade.php @@ -70,6 +70,28 @@ ->get(); @endphp +@php + $is_passed = false; + + if ($submits->count() > 0 && $questions->count() > 0) { + $mark_per_question = $quiz->total_mark / $questions->count(); + + foreach ($submits as $submit) { + $correct_answers = $submit->correct_answer + ? json_decode($submit->correct_answer, true) + : []; + + $obtained_mark = count($correct_answers) * $mark_per_question; + + if ($obtained_mark >= $quiz->pass_mark) { + $is_passed = true; + break; + } + } + } +@endphp + +

{{ $quiz->title }}

@@ -135,10 +157,13 @@ id="{{ $submit->id }}">{{ get_phrase('View Result') }} {{ ++$key }} @endforeach - @if ($submits->count() < $quiz->retake) - - @endif + @if (!$is_passed && $submits->count() < $quiz->retake) + + @endif +
diff --git a/resources/views/course_player/quiz/questions.blade.php b/resources/views/course_player/quiz/questions.blade.php index 1146b9e..3d3034c 100644 --- a/resources/views/course_player/quiz/questions.blade.php +++ b/resources/views/course_player/quiz/questions.blade.php @@ -138,29 +138,7 @@ // Submit quiz function submitQuiz() { - - var quizId = "{{ $quiz->id }}"; - var completed_lesson_arr = @json($completed_lesson_arr); // Convert the PHP array to a JavaScript array - - // Check if quizId is in the completed_lesson_arr array using JavaScript's `includes()` method - if (!completed_lesson_arr.includes(quizId)) { - $.ajax({ - url: "{{ route('set.watch.history') }}", // Your route - type: "post", - data: { - lesson_id: "{{ $quiz->id }}", - course_id: "{{ $course_details->id }}" - }, - success: function(response) { - submitForm.submit(); - }, - error: function(xhr, status, error) { - console.error("Error updating watch history:", xhr.responseText); - } - }); - } else { - submitForm.submit(); - } + submitForm.submit(); } diff --git a/resources/views/course_player/side_bar.blade.php b/resources/views/course_player/side_bar.blade.php index b2f4300..7d25c4d 100644 --- a/resources/views/course_player/side_bar.blade.php +++ b/resources/views/course_player/side_bar.blade.php @@ -63,23 +63,30 @@ @php $type = $lesson->lesson_type; @endphp
  • + @if($course_details->enable_drip_content) @if($is_locked) @else @if(in_array($lesson->id, $completed_lesson_arr)) - @elseif(in_array($type, ['video-url', 'system-video', 'vimeo-url', 'google_drive'])) + @elseif(in_array($type, ['video-url', 'google_drive'])) @else - id, $completed_lesson)) checked @endif type="checkbox" id="{{ $lesson->id }}"> + id, $completed_lesson)) checked @endif + disabled + > @endif @endif
    @if (in_array($type, ['text', 'document_type', 'iframe'])) - @elseif (in_array($type, ['video-url', 'system-video', 'vimeo-url'])) + @elseif (in_array($type, ['video-url'])) @elseif ($type == 'image') @@ -91,7 +98,19 @@

    {{ $lesson->lesson_type }}

    - {{ $lesson->title }} + @if (in_array($type, ['google_drive', 'video-url', 'quiz'])) + + {{ $lesson->title }} + + @else + + {{ $lesson->title }} + + @endif @else id, $completed_lesson)) checked @endif type="checkbox" id="{{ $lesson->id }}">
    diff --git a/resources/views/frontend/default/course/course_details.blade.php b/resources/views/frontend/default/course/course_details.blade.php index fab6f85..951e73b 100644 --- a/resources/views/frontend/default/course/course_details.blade.php +++ b/resources/views/frontend/default/course/course_details.blade.php @@ -20,7 +20,6 @@ $average_rating = $rating / $total; } @endphp -
    @@ -34,14 +33,11 @@
    -
    -

    {{ $course_details->title }}

    {{ ellipsis($course_details->short_description, 160) }}

    - - - -
    -
    -
    -
    - - - -