You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
6.9 KiB
207 lines
6.9 KiB
<?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();
|
|
}
|
|
}
|