validate([ 'id' => 'nullable|integer|exists:App\Models\VideoUpdate,id', 'is_selected' => 'nullable|in:true,false', 'file' => 'required_without:id|file|' . FileHelper::convertToStrLaraValidation(FileHelper::$allowedVideoExtensions), 'file_name' => 'required|string', ], [ 'file' => ['required_without' => 'The file field is required.'] ]); $delOldDbFileLocation = ''; $newDbFileLocation = ''; try { // save photo if($request->file) $newDbFileLocation = self::saveFile($request->file)['db_url']; // try to upsert data DB::beginTransaction(); $videoUpdate = null; if(!$request->id) $videoUpdate = new VideoUpdate(); else $videoUpdate = VideoUpdate::findOrFail($request->id); // del old db file location if has old file if($newDbFileLocation) { if($videoUpdate->file) $delOldDbFileLocation = $videoUpdate->file; $videoUpdate->file = $newDbFileLocation; } $videoUpdate->file_name = $request->file_name; if($request->is_selected == 'true') { VideoUpdate::where('is_selected', true)->update(['is_selected' => false]); $videoUpdate->is_selected = true; } else $videoUpdate->is_selected = false; // renew data $videoUpdate->save(); // delete old file if exist if($delOldDbFileLocation) self::deleteFile($delOldDbFileLocation); DB::commit(); return JSONResponse::Success(); } catch (\Throwable $th) { DB::rollBack(); if($newDbFileLocation) self::deleteFile($newDbFileLocation); throw $th; } } public static function deleteFromRequest(Request $request) { $request->validate(['id' => 'required|integer|exists:App\Models\VideoUpdate,id']); try { DB::beginTransaction(); $videoUpdate = VideoUpdate::findOrFail($request->id); if($videoUpdate->is_selected) throw new \Exception("Cannot delete video when 'is Selected' is true"); $oldDbFile = $videoUpdate->file; $videoUpdate->delete(); if($oldDbFile) self::deleteFile($oldDbFile); DB::commit(); return JSONResponse::Success(); } catch (\Throwable $th) { DB::rollBack(); throw $th; } } public static function changeSelectedVideoFromRequest(Request $request) { $request->validate(['id' => 'required|integer|exists:App\Models\VideoUpdate,id']); try { DB::beginTransaction(); $videoUpdate = VideoUpdate::findOrFail($request->id); $videoUpdate->is_selected = !$videoUpdate->is_selected; $videoUpdate->save(); DB::commit(); if($videoUpdate->is_selected) { VideoUpdate::where([ ['id', '!=', $videoUpdate->id], ['is_selected', true] ])->update(['is_selected' => false]); } return JSONResponse::Success(); } catch (\Throwable $th) { DB::rollBack(); throw $th; } } // -- File UTILITIES protected function fileUrl(): Attribute { return Attribute::make( fn() => $this->file ? Storage::disk('s3')->url($this->file) : '' ); } private static function fileFolder() { return env('STORAGE_FOLDER', 'tivi') . '/video-upload'; } public static function saveFile($file) { if (!$file->isValid()) throw new \Exception('File is not valid'); //Save file to local data $fileName = self::getFileName($file); $path = self::fileFolder(); Storage::disk('s3')->put($path . '/' . $fileName, file_get_contents(new File($file)), 'public'); return ['db_url' => "$path/$fileName"]; } private static function getFileName($file) { $tz = Carbon::now()->timestamp; $extension = $file->getClientOriginalExtension(); $name = "$tz-" . Common::generateRandomString(); return "$name.$extension"; } public static function deleteFile($dbUrl) { Storage::disk('s3')->delete($dbUrl); } // -- END File UTILITIES }