laravel-vue-file-share/app/Models/File.php

141 lines
4.7 KiB
PHP

<?php
namespace App\Models;
use App\Traits\HasCreatorAndUpdater;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Kalnoy\Nestedset\NodeTrait;
use Illuminate\Support\Facades\Storage;
use Kalnoy\NestedSet\DescendantsRelation;
class File extends Model
{
use HasFactory, HasCreatorAndUpdater, NodeTrait, SoftDeletes; // adds node and recycle bin functionality to files
// returns the user this file or folder belongs to
public function user(): BelongsTo {
return $this->belongsTo(User::class, 'created_by');
}
// returns the parent file or folder for this file or folder
public function parent(): BelongsTo {
return $this->belongsTo(File::class, 'parent_id');
}
// returns whether or not the current folder is a root-level folder
public function isRoot() {
// is there a parent_id for this folder?
return $this->parent_id == null;
}
// returns simple boolean whether or not the passed userID is the creator of the file
public function isOwner($userID): bool
{
return $this->created_by = $userID;
}
// returns formatted size
public function formatSize($size) {
// maximum file size is in the GB range
$sizeUnits = ['B', 'KB', 'MB', 'GB'];
// floor() the size and get the amount of times 1024 fits into it
$power = $size > 0 ? floor(log($size, 1024)) : 0;
// calculate output by dividing total size by $power * 1024 then adding relevant $sizeUnit based on $power ($power can be no greater than 3 - no bigger than GB's)
$output = number_format(($size / pow(1024, $power)), 2, ".", ",") . " " . $sizeUnits[$power];
return $output;
}
// outputs correct sizes for folders
public function getFolderSize() {
$sum = [];
// call recursive function, then sum
$this->recurseChildren($this->children, $sum);
$sum = array_sum($sum);
// return $sum
return $sum;
}
// shred $this file
public function shred() {
// recursively shred all of $this
$this->recursiveShred([$this]);
// also call force delete
$this->forceDelete();
}
// additional bootstrapping on top of default Model model
protected static function boot()
{
// start with parent Model
parent::boot();
// define new bootstrapping
static::creating(function ($model) {
// check for parent - if one exists, exit function
if (!$model->parent) return;
// if file or folder is NOT a root-level folder
if (!$model->parent->isRoot()) {
// path is a node off the parent path
$model->path = $model->parent->path . '/';
}
// otherwise free-standing
else $model->path = '';
// append current file or folder name to path name
$model->path = $model->path . $model->name;
});
// define delete function
static::deleted(function (File $file) {
// if file is a regular file (not a folder)
if (!$file->is_folder) {
// delete file from file system
Storage::delete($file->stored_at);
}
});
}
// moves $this file to recycle bin
private function recycle() {
// set this file's deleted_at to now
$this->deleted_at = Carbon::now();
// save record
return $this->save();
}
// recursively shred $queued files
private function recursiveShred($queued) {
// get children of parent and determine whether recursive function needs to be called
foreach ($queued as $file) {
// if there are no children, delete file
if ($file->children->isEmpty()) {
Storage::delete($file->stored_at);
// continue loop
continue;
}
// else recurse
$this->recursiveShred($file->children);
}
}
// get all children and subchildren
private function recurseChildren ($files, &$total) {
// go through each file in queue
foreach($files as $file) {
// push to array since it is a child
array_push($total, $file->size);
// iterate to next file in $queue if no more children
if (!$file->children) {
continue;
}
// else recurse on $current file children
$this->recurseChildren($file->children, $total);
}
}
}