Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
forbidals
/
admin_panel
/
app
/
Http
/
Controllers
:
LessonController.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php namespace App\Http\Controllers; use App\Models\ClassSubject; use App\Models\LessonCommon; use App\Models\LessonTopic; use App\Models\Syllabus; use App\Repositories\ClassSection\ClassSectionInterface; use App\Repositories\ClassSubject\ClassSubjectInterface; use App\Repositories\Files\FilesInterface; use App\Repositories\Lessons\LessonsInterface; use App\Repositories\LessonsCommon\LessonsCommonInterface; use App\Repositories\Semester\SemesterInterface; use App\Repositories\Student\StudentInterface; use App\Repositories\Subject\SubjectInterface; use App\Repositories\SubjectTeacher\SubjectTeacherInterface; use App\Repositories\StudentSubject\StudentSubjectInterface; use App\Rules\DynamicMimes; use App\Rules\MaxFileSize; use App\Rules\uniqueLessonInClass; use App\Rules\YouTubeUrl; use App\Services\BootstrapTableService; use App\Services\CachingService; use App\Services\LessonNotificationService; use App\Services\ResponseService; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; use App\Repositories\SessionYear\SessionYearInterface; use Illuminate\Support\Str; use Throwable; class LessonController extends Controller { private SubjectTeacherInterface $subjectTeacher; private ClassSectionInterface $classSection; private LessonsInterface $lesson; private FilesInterface $files; private CachingService $cache; private LessonsCommonInterface $lessonCommon; private StudentInterface $student; private SubjectInterface $subject; private ClassSubjectInterface $class_subjects; private SemesterInterface $semester; private SessionYearInterface $sessionYear; private StudentSubjectInterface $studentSubject; private LessonNotificationService $lessonNotificationService; public function __construct(ClassSectionInterface $classSection, LessonsInterface $lesson, FilesInterface $files, SubjectTeacherInterface $subjectTeacher, CachingService $cache, LessonsCommonInterface $lessonCommon, StudentInterface $student, SubjectInterface $subject, ClassSubjectInterface $class_subjects, SemesterInterface $semester, SessionYearInterface $sessionYear, StudentSubjectInterface $studentSubject, LessonNotificationService $lessonNotificationService) { $this->subjectTeacher = $subjectTeacher; $this->classSection = $classSection; $this->lesson = $lesson; $this->files = $files; $this->cache = $cache; $this->lessonCommon = $lessonCommon; $this->student = $student; $this->subject = $subject; $this->class_subjects = $class_subjects; $this->semester = $semester; $this->sessionYear = $sessionYear; $this->studentSubject = $studentSubject; $this->lessonNotificationService = $lessonNotificationService; } public function index() { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenRedirect('lesson-list'); $class_section = $this->classSection->builder()->with('class.stream', 'class.shift', 'section', 'medium')->get(); $subjectTeachers = $this->subjectTeacher->builder()->with('subject:id,name,type')->get(); $lessons = $this->lesson->builder()->get(); $semesters = $this->semester->builder()->get(); return response(view('lessons.index', compact('class_section', 'subjectTeachers', 'lessons', 'semesters'))); } public function store(Request $request) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenRedirect('lesson-create'); $file_upload_size_limit = $this->cache->getSystemSettings('file_upload_size_limit'); $validator = Validator::make($request->all(), [ 'name' => 'required', 'description' => 'required', 'class_section_id' => 'required|array', 'class_section_id.*' => 'numeric', 'subject_id' => 'required|numeric', 'file_data' => 'nullable|array', 'file_data.*.type' => 'required|in:file_upload,youtube_link,video_upload,other_link', 'file_data.*.name' => 'required_with:file_data.*.type', 'file_data.*.thumbnail' => 'required_if:file_data.*.type,youtube_link,video_upload,other_link', 'file_data.*.link' => ['nullable', 'required_if:file_data.*.type,youtube_link,other_link', new YouTubeUrl], 'file_data.*.file' => [ 'nullable', 'required_if:file_data.*.type,file_upload,video_upload', new DynamicMimes(), new MaxFileSize($file_upload_size_limit), ], ]); if ($validator->fails()) { return ResponseService::errorResponse($validator->errors()->first()); } try { DB::beginTransaction(); /* -------------------- Lesson -------------------- */ $lesson = $this->lesson->create([ 'name' => $request->name, 'description' => $request->description, ]); $sessionYear = $this->cache->getSessionYear(); $sectionIds = $request->class_section_id; $lessonCommonData = []; foreach ($sectionIds as $sectionId) { $classSection = $this->classSection ->builder() ->where('id', $sectionId) ->first(); // $syllabus = Syllabus::where('class_id', $classSection->class->id) // ->where('subject_id', $request->subject_id) // ->where('status', 'active') // ->first(); $classSubject = ClassSubject::where('class_id', $classSection->class_id) ->where('subject_id', $request->subject_id) ->where('session_year_id', $sessionYear->id) ->first(); if ($classSubject && $classSubject->syllabus_id) { $lessonCommonData[] = [ 'lesson_id' => $lesson->id, 'class_section_id' => $sectionId, 'syllabus_id' => $classSubject->syllabus_id, ]; } else { ResponseService::errorResponse('Syllabus not found for class and subject'); } } LessonCommon::insert($lessonCommonData); /* -------------------- Files -------------------- */ if (!empty($request->file_data)) { $lessonFileData = []; foreach ($request->file_data as $file) { if (!empty($file['type'])) { $lessonFileData[] = $this->prepareFileData($file); } } if (!empty($lessonFileData)) { $lessonFile = $this->files->model()->modal()->associate($lesson); foreach ($lessonFileData as &$fileData) { $fileData['modal_type'] = $lessonFile->modal_type; $fileData['modal_id'] = $lessonFile->modal_id; } $this->files->createBulk($lessonFileData); } } /* ================== PUSH NOTIFICATIONS ================== */ $this->lessonNotificationService->send($lesson, $sectionIds, (int)$request->subject_id, 'created'); DB::commit(); ResponseService::successResponse('Data Stored Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e, 'Lesson Controller -> Store'); ResponseService::errorResponse(); } } private function prepareFileData($file) { if ($file['type']) { $tempFileData = [ 'file_name' => $file['name'] ]; // If File Upload if ($file['type'] == "file_upload") { // Add Type And File Url to TempDataArray and make Thumbnail data null $tempFileData['type'] = 1; $tempFileData['file_thumbnail'] = null; $tempFileData['file_url'] = $file['file']; } elseif ($file['type'] == "youtube_link") { // Add Type , Thumbnail and Link to TempDataArray $tempFileData['type'] = 2; $tempFileData['file_thumbnail'] = $file['thumbnail']; $tempFileData['file_url'] = $file['link']; } elseif ($file['type'] == "video_upload") { // Add Type , File Thumbnail and File URL to TempDataArray $tempFileData['type'] = 3; $tempFileData['file_thumbnail'] = $file['thumbnail']; $tempFileData['file_url'] = $file['file']; } elseif ($file['type'] == "other_link") { // Add Type , File Thumbnail and File URL to TempDataArray $tempFileData['type'] = 4; $tempFileData['file_thumbnail'] = $file['thumbnail']; $tempFileData['file_url'] = $file['link']; } } return $tempFileData; } public function show() { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenRedirect('lesson-list'); $offset = request('offset', 0); $limit = request('limit', 10); $sort = request('sort', 'id'); $order = request('order', 'DESC'); $search = request('search'); $semester_id = request('semester_id'); $sql = $this->lesson->builder() ->with([ 'topic', 'file', 'lesson_commons' => function ($q) { $q->whereHas('syllabus.class_subject', fn($q) => $q->whereNull('deleted_at')); }, 'lesson_commons.syllabus.class_subject.subject' => fn($q) => $q->whereNull('deleted_at'), 'lesson_commons.class_section.class.stream', 'lesson_commons.class_section.class.shift', 'lesson_commons.class_section.section' ]) ->when($search, function ($query) use ($search) { $query->where(function ($query) use ($search) { $query->where('name', 'LIKE', "%$search%") ->orWhere('description', 'LIKE', "%$search%") ->orWhereHas( 'lesson_commons.class_section.section', fn($q) => $q->where('name', 'LIKE', "%$search%") ) ->orWhereHas( 'lesson_commons.class_section.class', fn($q) => $q->where('name', 'LIKE', "%$search%") ) ->orWhereHas( 'lesson_commons.syllabus.class_subject.subject', fn($q) => $q->where('name', 'LIKE', "%$search%") ); }); }); if (request('class_id')) { $class_id = request('class_id'); $sql = $sql->whereHas('lesson_commons', function ($q) use ($class_id) { $q->where('class_section_id', $class_id); }); } if (request('class_subject_id')) { $subject_id = request('class_subject_id'); $sql = $sql->whereHas('lesson_commons.syllabus.class_subject', function ($q) use ($subject_id) { $q->where('id', $subject_id); }); } $total = $sql->count(); if ($offset >= $total && $total > 0) { $lastPage = floor(($total - 1) / $limit) * $limit; // calculate last page offset $offset = $lastPage; } $sql->orderBy($sort, $order)->skip($offset)->take($limit); $res = $sql->get(); $bulkData = array(); $bulkData['total'] = $total; $rows = array(); $no = 1; foreach ($res as $key => $row) { $row = (object) $row; // lesson commons with class section details $lessonCommons = $row->lesson_commons->map(function ($common) { return $common->class_section ? $common->class_section->full_name : null; }); // Get Subject Name $subject = $row->lesson_commons->first()?->syllabus?->subject; $subjectName = $subject ? $subject->name . ' - ' . $subject->type : null; $lessonCommons->filter()->map(function ($name) { return "{$name},"; })->toArray(); // dd( $lessonCommons); // $operate = BootstrapTableService::button(route('lesson.edit', $row->id), ['btn-gradient-primary'], ['title' => 'Edit'], ['fa fa-edit']); $operate = BootstrapTableService::button('fa fa-edit', route('lesson.edit', $row->id), ['btn-gradient-primary'], ['title' => 'Edit']); $operate .= BootstrapTableService::deleteButton(route('lesson.destroy', $row->id)); $tempRow = $row->toArray(); $tempRow['no'] = $no++; $tempRow['class_section_with_medium'] = $lessonCommons; $tempRow['subject_with_name'] = $subjectName; $tempRow['operate'] = $operate; $rows[] = $tempRow; } $bulkData['rows'] = $rows; return response()->json($bulkData); } public function edit($id) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenRedirect('lesson-edit'); $class_section = $this->classSection->builder()->with('class', 'class.stream', 'class.shift', 'section', 'medium')->get(); $subjectTeachers = $this->subjectTeacher->builder()->with('subject:id,name,type')->get(); $lesson = $this->lesson->builder()->with('file', 'lesson_commons.syllabus.class_subject')->where('id', $id)->first(); $lessonCommonClassSections = $lesson->lesson_commons->pluck('class_section_id'); $subjectId = $lesson->lesson_commons->first()->syllabus?->subject_id; return response(view('lessons.edit_lesson', compact('class_section', 'lessonCommonClassSections', 'subjectTeachers', 'lesson', 'subjectId'))); } public function update(Request $request, $id) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenSendJson('lesson-edit'); $file_upload_size_limit = $this->cache->getSystemSettings('file_upload_size_limit'); $validator = Validator::make( $request->all(), [ 'name' => 'required', 'description' => 'required', 'class_section_id' => 'required|array', 'class_section_id.*' => 'numeric', 'class_subject_id' => 'required|numeric', 'file_data' => 'nullable|array', 'file_data.*.type' => 'required|in:file_upload,youtube_link,video_upload,other_link', 'file_data.*.name' => 'required_with:file_data.*.type', 'file_data.*.link' => ['nullable', 'required_if:file_data.*.type,youtube_link', new YouTubeUrl], 'file_data.*.link' => ['nullable', 'required_if:file_data.*.type,other_link', 'url'], 'file_data.*.file' => [ 'nullable', new DynamicMimes, new MaxFileSize($file_upload_size_limit) ], ] ); if ($validator->fails()) { return ResponseService::errorResponse($validator->errors()->first()); } $classSectionIds = $request->class_section_id; try { DB::beginTransaction(); /* -------------------- Update lesson -------------------- */ $lesson = $this->lesson->update($id, [ 'name' => $request->name, 'description' => $request->description, ]); $sessionYear = $this->cache->getSessionYear(); /* -------------------- Rebuild lesson_common -------------------- */ LessonCommon::where('lesson_id', $id)->delete(); $lessonCommonData = []; foreach ($classSectionIds as $sectionId) { $classSection = $this->classSection ->builder() ->where('id', $sectionId) ->with('class') ->first(); $classSubject = ClassSubject::where('class_id', $classSection->class_id) ->where('subject_id', $request->subject_id) ->where('session_year_id', $sessionYear->id) ->first(); if (!$classSubject->syllabus_id) { ResponseService::errorResponse('Syllabus not found for class ' . $classSection->class->name . ' and subject ' . $request->subject_id); } $lessonCommonData[] = [ 'lesson_id' => $lesson->id, 'class_section_id' => $sectionId, 'syllabus_id' => $classSubject->syllabus_id, ]; // $classSubject = $this->class_subjects // ->builder() // ->where('class_id', $classSection->class->id) // ->where('subject_id', $request->class_subject_id) // ->first(); // $lessonCommonData[] = [ // 'lesson_id' => $id, // 'class_section_id' => $sectionId, // 'class_subject_id' => $classSubject->id, // ]; } LessonCommon::insert($lessonCommonData); /* -------------------- Files -------------------- */ if (!empty($request->file_data)) { foreach ($request->file_data as $key => $file) { if (empty($file['type'])) { continue; } $lessonFile = $this->files->model(); $lessonModelAssociate = $lessonFile->modal()->associate($lesson); // Base data (SAFE — no file fields here) $tempFileData = [ 'id' => $file['id'] ?? null, 'modal_type' => $lessonModelAssociate->modal_type, 'modal_id' => $lessonModelAssociate->modal_id, 'file_name' => $file['name'], 'updated_at' => now(), ]; // Only set created_at for new records if (empty($file['id'])) { $tempFileData['created_at'] = now(); } switch ($file['type']) { case 'file_upload': $tempFileData['type'] = 1; // ✅ only update if a NEW file is uploaded if ($request->hasFile("file_data.$key.file")) { $tempFileData['file_url'] = $file['file']; } break; case 'youtube_link': $tempFileData['type'] = 2; // ✅ link change only if provided if (!empty($file['link'])) { $tempFileData['file_url'] = $file['link']; } if ($request->hasFile("file_data.$key.thumbnail")) { $tempFileData['file_thumbnail'] = $file['thumbnail']; } break; case 'video_upload': $tempFileData['type'] = 3; if ($request->hasFile("file_data.$key.file")) { $tempFileData['file_url'] = $file['file']; } if ($request->hasFile("file_data.$key.thumbnail")) { $tempFileData['file_thumbnail'] = $file['thumbnail']; } break; case 'other_link': $tempFileData['type'] = 4; if (!empty($file['link'])) { $tempFileData['file_url'] = $file['link']; } if ($request->hasFile("file_data.$key.thumbnail")) { $tempFileData['file_thumbnail'] = $file['thumbnail']; } break; } // ✅ SAFE now — no null overwrites $this->files->updateOrCreate( ['id' => $file['id'] ?? null], $tempFileData ); } } /* ================== PUSH NOTIFICATIONS ================== */ $this->lessonNotificationService->send($lesson, $classSectionIds, (int)$request->class_subject_id, 'updated'); DB::commit(); return ResponseService::successResponse('Data Updated Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e, 'Lesson Controller -> update'); return ResponseService::errorResponse(); } } public function destroy($id) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenSendJson('lesson-delete'); try { $lesson_topics = LessonTopic::where('lesson_id', $id)->count(); if ($lesson_topics) { $response = array('error' => true, 'message' => trans('cannot_delete_because_data_is_associated_with_other_data')); } else { // Find the Data By ID $lesson = $this->lesson->findById($id); // If File exists if ($lesson->file) { // Loop on the Files foreach ($lesson->file as $file) { // Remove the Files From the Local if (Storage::disk('public')->exists($file->file_url)) { Storage::disk('public')->delete($file->file_url); } } } // Delete File Data $lesson->file()->delete(); // Delete Lesson Data $lesson->delete(); ResponseService::successResponse('Data Deleted Successfully'); } } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e, "Lesson Controller -> Destroy method"); ResponseService::errorResponse(); } return response()->json($response); } public function search(Request $request) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noPermissionThenRedirect('lesson-list'); try { // Get the new Instance of Lesson Model $lesson = $this->lesson->model(); if (isset($request->subject_id)) { $lesson = $lesson->where('subject_id', $request->subject_id); } if (isset($request->class_section_id)) { $lesson = $lesson->where('class_section_id', $request->class_section_id); } $lesson = $lesson->get(); $response = array( 'error' => false, 'data' => $lesson, 'message' => 'Lesson fetched successfully' ); } catch (Throwable $e) { ResponseService::logErrorResponse($e, "Lesson Controller -> Search Method"); ResponseService::errorResponse(); } return response()->json($response); } public function deleteFile($id) { ResponseService::noFeatureThenRedirect('Lesson Management'); ResponseService::noAnyPermissionThenRedirect(['lesson-delete', 'topic-delete']); try { DB::beginTransaction(); // Find the Data by FindByID $file = $this->files->findById($id); // Delete the file data $file->delete(); DB::commit(); ResponseService::successResponse('Data Deleted Successfully'); } catch (Throwable $e) { DB::rollBack(); ResponseService::logErrorResponse($e, "Lesson Controller -> deleteFile Method"); ResponseService::errorResponse(); } } }