You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tivi_kemana_saja_laravel/app/Models/VideoUpdate.php

173 lines
6.5 KiB
PHP

<?php
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\Builder;
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 VideoUpdate extends Model {
use HasFactory;
use CanMultiSearch;
use CanMultiOrderBy;
protected $table = 'video_updates';
protected $hidden = ['file'];
protected $appends = ['file_url'];
// ---------------------------------------------------------------------------------------
// -- RELATED TO SCOPE
public function scopeSelected(Builder $query){
return $query->where('is_selected', true);
}
// -- END RELATED TO SCOPE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO GET DATA
public static function getLatestSelected(){ return self::selected()->latest('updated_at')->first(); }
// -- END RELATED TO GET DATA
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO MODIFICATION DATA FROM REQUEST
public static function upsertFromRequest(Request $request) {
$request->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)
->when($request->id, function(Builder $query, $id) {
$query->where('id', '!=', $id);
})
->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;
}
}
// -- END RELATED MODIFICATION DATA FROM REQUEST
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- 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
// ---------------------------------------------------------------------------------------
}