|
|
<?php
namespace App\Http\Controllers;
use App\Models\File; use App\Models\Project; use App\Rules\MaxBound; use App\Models\Business; use Illuminate\Support\Str; use Illuminate\Http\Request; use Illuminate\Http\UploadedFile; use App\Http\Resources\FileResource; use Illuminate\Support\Facades\Auth; use Spatie\QueryBuilder\QueryBuilder; use Spatie\QueryBuilder\AllowedFilter; use Illuminate\Support\Facades\Storage;
class FileController extends Controller { public function index(int $business, Request $request) { permit('businessAccess');
$this->indexValidation($request);
$per_page = $request->limit > 100 ? 10 : $request->limit;
return $this->indexFiltering($business)->paginate($per_page); }
public function indexValidation($request) { $bound = 10; $this->validate($request, [ 'filter.project_id' => [new MaxBound($bound)] , 'filter.user_id' => [new MaxBound($bound)] , ]); }
public function indexFiltering($business) { $query = File::where('business_id', $business); $fileQ = QueryBuilder::for($query) ->allowedFilters([ AllowedFilter::exact('user_id'), AllowedFilter::exact('project_id'), AllowedFilter::exact('extension'), ]); if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) { $requested_projects = isset(\request('filter')['project_id']) ? array_unique(explode(',',\request('filter')['project_id'] ?? null )) : null; $requested_projects = collect($requested_projects)->keyBy(null)->toArray(); $project_ids = $this->myStateProjects($requested_projects); $fileQ->where(function ($q) use ($project_ids) { $q->whereIn('project_id', $project_ids['non_guest_ids']) ->orWhere(function ($q) use ($project_ids) { $q->whereIn('project_id', $project_ids['guest_ids']) ->where('user_id', auth()->id()); }); }); }
if (request()->filled('group')) { $fileQ->selectRaw("files.group, count(files.id) as file_count, sum(files.size) as file_size")->groupBy('group'); }
return $fileQ; }
public function myStateProjects($requested_projects) { $non_guest_ids = []; $guest_ids = []; $is_empty = empty($requested_projects);
foreach (\request('_business_info')['info']['projects'] as $p_id => $p) {
$level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level'];
if (( $is_empty || isset($requested_projects[$p_id])) && $level > enum('levels.guest.id')) { array_push($non_guest_ids, $p_id); } if (( $is_empty || isset($requested_projects[$p_id])) && $level == enum('levels.guest.id')) { array_push($guest_ids, $p_id); } }
return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids]; }
public function store(Request $request, int $business, int $project) { // different size and different validation
// validate
// validate the wallet is not so much in debt
// create record in the db
// put file in s3
// return file resource
$business = Business::findOrFail($business); $project = Project::findOrFail($project);
$this->validate($request, ['file' => 'required|file',]);
$file = $request->file('file'); $file_extension = $file->getClientOriginalExtension(); $file_name = Str::random(40).'.'.$file_extension; $file->storeAs( $business->id.\DIRECTORY_SEPARATOR.$project->id, $file_name, 's3' );
$file_record = File::create([ 'user_id' => Auth::id(), 'business_id' => $business->id, 'project_id' => $project->id, 'disk' => 's3', // default disk
'original_name' => $file->getClientOriginalName(), 'extension' => $file_extension, 'name' => $file_name, 'mime' => $file->getClientMimeType(), 'group' => $this->groupDetection($file), 'size' => $file->getSize(), 'description' => $request->description ]);
$business->update([ 'files_volume' => $business->files_volume + $file_record->size ]);
return new FileResource($file_record); }
public function groupDetection(UploadedFile $file) { // Media files like mp4, mp3, wma and png or jpeg
[$type, $subtype] = Str::of($file->getMimeType())->explode("/",2)->pad(2, null);
if (in_array($type, ['audio', 'video', 'image'])) { return $type; }
// Covert string to \Illuminate\Support\Stringable object
$subtype = Str::of($subtype);
// PDF files
if ($subtype->contains(["pdf"])) { return "pdf"; }
// Compressed files like zip, cab, rar, etc.
if ($subtype->contains(['compressed']) || in_array($file->getClientOriginalExtension(), ['zip', 'rar','7z','cab'])) { return "compressed"; }
// Office files like xls, xlsx, doc, docx, etc.
if ($subtype->contains(['vnd.ms', 'vnd.sealed', 'officedocument', 'opendocument'])) { return "office"; }
// Non of the above files
return "other"; }
public function download(int $business, int $project, int $file) { // requested file belongs to this project and this business
// check permisson
// create perma link or temp link
// return the file resource or stream it
return File::findOrFail($file)->getTemporaryLink(); }
public function rename(Request $request, int $business, int $project, int $file) { // requested file belongs to this project and this business
// check permisson
// update original name
// return the file resource
// sanitize the name for slashs and back slashes
$this->validate($request, [ 'name' => 'required|string' ]);
$file = File::findOrFail($file);
$file->update(['original_name' => $request->name.".".$file->extension]);
return new FileResource($file); }
public function delete(Request $request, int $business, int $project, int $file) { // requested file belongs to this project and this business
// check permisson
// check it's relations
// delete the file form File table
// delete file from s3
$file = File::findOrFail($file); Storage::disk('s3')->delete($file->getPath()); return $file->delete(); } }
|