diff --git a/app/Helper/FileHelper.php b/app/Helper/FileHelper.php index 69059a0..b5f33a5 100644 --- a/app/Helper/FileHelper.php +++ b/app/Helper/FileHelper.php @@ -1,6 +1,8 @@ \ No newline at end of file diff --git a/app/Http/Controllers/api/superadmin/ApkUploadController.php b/app/Http/Controllers/api/superadmin/ApkUploadController.php new file mode 100644 index 0000000..5d74ef8 --- /dev/null +++ b/app/Http/Controllers/api/superadmin/ApkUploadController.php @@ -0,0 +1,28 @@ +validate([ + 'perPage' => 'nullable|integer|min:1', + ...DatabaseHelper::getOrderBysValidations(), + 'search' => DatabaseHelper::getSearchValidation() + ]); + + $data = ApkUpdate::multiSearch($request->search, ['name']) + ->multiOrderBy($request->orderBys, 'version_code desc') + ->paginate($request->perPage ?? 10 ); + return JSONResponse::Success(['data' => $data]); + } + + public function save(Request $request) { return ApkUpdate::upsertFromRequest($request); } + public function update(Request $request) { return ApkUpdate::upsertFromRequest($request); } + public function delete(Request $request) { return ApkUpdate::deleteFromRequest($request); } +} diff --git a/app/Models/ApkUpdate.php b/app/Models/ApkUpdate.php index 0fbe11b..0168308 100644 --- a/app/Models/ApkUpdate.php +++ b/app/Models/ApkUpdate.php @@ -2,11 +2,117 @@ namespace App\Models; +use App\Helper\Common; +use App\Helper\FileHelper; +use App\Helper\JSONResponse; +use App\Helper\Traits\Models\CanMultiOrderBy; +use App\Helper\Traits\Models\CanMultiSearch; +use Carbon\Carbon; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Http\File; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Storage; class ApkUpdate extends Model { use HasFactory; + use CanMultiSearch; + use CanMultiOrderBy; protected $table = 'apk_updates'; + protected $hidden = ['file']; + protected $appends = ['file_url']; + + public static function upsertFromRequest(Request $request) { + $request->validate([ + 'id' => 'nullable|integer|exists:App\Models\ApkUpdate,id', + 'name' => 'required|string', + 'file' => 'required_without:id|file|' . FileHelper::convertToStrLaraValidation(FileHelper::$allowedApkExtensions), + 'version_code' => 'required|integer|min:1', + 'change_note' => 'nullable|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(); + $apkUpdate = null; + if(!$request->id) $apkUpdate = new ApkUpdate(); + else $apkUpdate = ApkUpdate::findOrFail($request->id); + + // del old db file location if has old file + if($newDbFileLocation) { + if($apkUpdate->file) $delOldDbFileLocation = $apkUpdate->file; + $apkUpdate->file = $newDbFileLocation; + } + $apkUpdate->name = $request->name; + $apkUpdate->version_code = $request->version_code; + $apkUpdate->change_note = $request->change_note; + $apkUpdate->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\ApkUpdate,id']); + try { + DB::beginTransaction(); + $apkUpdate = ApkUpdate::findOrFail($request->id); + + $oldDbFile = $apkUpdate->file; + $apkUpdate->delete(); + + if($oldDbFile) self::deleteFile($oldDbFile); + DB::commit(); + 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') . '/apk-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 } diff --git a/app/Models/User.php b/app/Models/User.php index 9dd72bf..9a2df29 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -70,7 +70,7 @@ class User extends Authenticatable 'token' => $currentAccessToken, 'allowedFileExtension' => [ 'video' => FileHelper::convertToStrJsValidation(FileHelper::$allowedVideoExtensions), - 'apk' => FileHelper::convertToStrJsValidation(FileHelper::$allowedVideoExtensions) + 'apk' => FileHelper::convertToStrJsValidation(FileHelper::$allowedApkExtensions) ] ]; } diff --git a/routes/api.php b/routes/api.php index 884c484..bcb0e71 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,6 +1,7 @@ prefix('superadmin')->group(function() { Route::post('/video-upload/delete', 'delete'); Route::post('/video-upload/change-selected-video', 'changeSelectedVideo'); }); + + Route::controller(ApkUploadController::class)->group(function() { + Route::post('/apk-upload', 'init'); + Route::post('/apk-upload/save', 'save'); + Route::post('/apk-upload/update', 'update'); + Route::post('/apk-upload/delete', 'delete'); + }); }); // tmux session, tmux attach session -t \ No newline at end of file