307
common/Files/FileEntry.php
Executable file
307
common/Files/FileEntry.php
Executable file
@@ -0,0 +1,307 @@
|
||||
<?php namespace Common\Files;
|
||||
|
||||
use App\Models\User;
|
||||
use Arr;
|
||||
use Auth;
|
||||
use Common\Core\BaseModel;
|
||||
use Common\Files\Traits\HandlesEntryPaths;
|
||||
use Common\Files\Traits\HashesId;
|
||||
use Common\Tags\HandlesTags;
|
||||
use Common\Tags\Tag;
|
||||
use Common\Workspaces\Traits\BelongsToWorkspace;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class FileEntry extends BaseModel
|
||||
{
|
||||
use SoftDeletes,
|
||||
HashesId,
|
||||
HandlesEntryPaths,
|
||||
HandlesTags,
|
||||
BelongsToWorkspace;
|
||||
|
||||
public const MODEL_TYPE = 'fileEntry';
|
||||
protected $guarded = ['id'];
|
||||
protected $hidden = ['pivot', 'preview_token'];
|
||||
protected $appends = ['hash', 'url'];
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'file_size' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'thumbnail' => 'boolean',
|
||||
'public' => 'boolean',
|
||||
'workspace_id' => 'integer',
|
||||
];
|
||||
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->morphedByMany(
|
||||
FileEntryUser::class,
|
||||
'model',
|
||||
'file_entry_models',
|
||||
'file_entry_id',
|
||||
'model_id',
|
||||
)
|
||||
->using(FileEntryPivot::class)
|
||||
->select(
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'users.id',
|
||||
'avatar',
|
||||
'model_type',
|
||||
)
|
||||
->withPivot('owner', 'permissions')
|
||||
->withTimestamps()
|
||||
->orderBy('file_entry_models.created_at');
|
||||
}
|
||||
|
||||
public function children(): HasMany
|
||||
{
|
||||
return $this->hasMany(static::class, 'parent_id')->withoutGlobalScope(
|
||||
'fsType',
|
||||
);
|
||||
}
|
||||
|
||||
public function parent(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(static::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function tags(): BelongsToMany
|
||||
{
|
||||
return $this->morphToMany(Tag::class, 'taggable')->wherePivot(
|
||||
'user_id',
|
||||
Auth::id() ?? null,
|
||||
);
|
||||
}
|
||||
|
||||
public function getUrlAttribute(string $value = null): ?string
|
||||
{
|
||||
if ($value) {
|
||||
return $value;
|
||||
}
|
||||
if (
|
||||
!isset($this->attributes['type']) ||
|
||||
$this->attributes['type'] === 'folder'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$endpoint = config('common.site.file_preview_endpoint');
|
||||
|
||||
if (Arr::get($this->attributes, 'public')) {
|
||||
$publicPath = "$this->disk_prefix/$this->file_name";
|
||||
if ($endpoint) {
|
||||
return "$endpoint/storage/$publicPath";
|
||||
}
|
||||
return Storage::disk('public')->url($publicPath);
|
||||
} elseif ($endpoint) {
|
||||
return "$endpoint/uploads/{$this->file_name}/{$this->file_name}";
|
||||
} else {
|
||||
return "api/v1/file-entries/{$this->attributes['id']}";
|
||||
}
|
||||
}
|
||||
|
||||
public function getStoragePath(bool $useThumbnail = false): string
|
||||
{
|
||||
$fileName = $useThumbnail ? 'thumbnail.jpg' : $this->file_name;
|
||||
if ($this->public) {
|
||||
return "$this->disk_prefix/$fileName";
|
||||
} else {
|
||||
return "$this->file_name/$fileName";
|
||||
}
|
||||
}
|
||||
|
||||
public function getDisk()
|
||||
{
|
||||
if ($this->public) {
|
||||
return Storage::drive('public');
|
||||
} else {
|
||||
return Storage::drive('uploads');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeWhereRootOrParentNotTrashed(Builder $query)
|
||||
{
|
||||
return $query
|
||||
->whereNull('parent_id')
|
||||
->orWhereHas('parent', function (Builder $query) {
|
||||
return $query->whereNull('deleted_at');
|
||||
});
|
||||
}
|
||||
|
||||
public function owner(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all entries user has access to.
|
||||
*/
|
||||
public function scopeWhereUser(
|
||||
Builder $builder,
|
||||
int $userId,
|
||||
bool|null $owner = null,
|
||||
): Builder {
|
||||
return $builder->whereIn($this->qualifyColumn('id'), function (
|
||||
$query,
|
||||
) use ($userId, $owner) {
|
||||
$query
|
||||
->select('file_entry_id')
|
||||
->from('file_entry_models')
|
||||
->where('model_id', $userId)
|
||||
->where('model_type', User::MODEL_TYPE);
|
||||
|
||||
// if $owner is not null, need to load either only
|
||||
// entries user owns or entries user does not own
|
||||
//if $owner is null, load all entries
|
||||
if (!is_null($owner)) {
|
||||
$query->where('owner', $owner);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeWhereOwner(Builder $builder, int $userId): Builder
|
||||
{
|
||||
return $builder->where('owner_id', $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select only entries that were not created by specified user.
|
||||
*/
|
||||
public function scopeWhereNotOwner(Builder $builder, int $userId): Builder
|
||||
{
|
||||
return $this->scopeWhereUser($builder, $userId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path of specified entry.
|
||||
*
|
||||
* @param int $id
|
||||
* @return string
|
||||
*/
|
||||
public function findPath($id)
|
||||
{
|
||||
$entry = $this->find($id, ['path']);
|
||||
return $entry ? $entry->getRawOriginal('path') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return file entry name with extension.
|
||||
* @return string
|
||||
*/
|
||||
public function getNameWithExtension()
|
||||
{
|
||||
if (!$this->exists) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$extension = pathinfo($this->name, PATHINFO_EXTENSION);
|
||||
|
||||
if (!$extension && $this->extension) {
|
||||
return $this->name . '.' . $this->extension;
|
||||
}
|
||||
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getTotalSize(): int
|
||||
{
|
||||
if ($this->type === 'folder') {
|
||||
return $this->allChildren()->sum('file_size');
|
||||
} else {
|
||||
return $this->file_size;
|
||||
}
|
||||
}
|
||||
|
||||
public function resolveRouteBinding($value, $field = null): ?self
|
||||
{
|
||||
return $this->byIdOrHash($value)
|
||||
->withTrashed()
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* $value might be ID with extension: "4546.mp4" or hash: "ja4d5ad4" or ID int: 4546 or filename
|
||||
*/
|
||||
public function scopeByIdOrHash(Builder $builder, $value): Builder
|
||||
{
|
||||
if (str_contains($value, '.') && str_contains($value, '-')) {
|
||||
return $builder->where('file_name', $value);
|
||||
}
|
||||
|
||||
$id = (int) $value;
|
||||
if ($id === 0) {
|
||||
$id = $this->decodeHash($value);
|
||||
}
|
||||
return $builder->where('id', $id);
|
||||
}
|
||||
|
||||
protected function makeAllSearchableUsing($query)
|
||||
{
|
||||
return $query->with(['tags']);
|
||||
}
|
||||
|
||||
public function toSearchableArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'file_size' => $this->file_size,
|
||||
'mime' => $this->mime,
|
||||
'extension' => $this->extension,
|
||||
'owner_id' => $this->owner_id,
|
||||
'created_at' => $this->created_at->timestamp ?? '_null',
|
||||
'updated_at' => $this->updated_at->timestamp ?? '_null',
|
||||
'deleted_at' => $this->deleted_at->timestamp ?? '_null',
|
||||
'public' => $this->public,
|
||||
'description' => $this->description,
|
||||
'password' => $this->password,
|
||||
'type' => $this->type,
|
||||
'workspace_id' => $this->workspace_id ?? '_null',
|
||||
'tags' => $this->tags->pluck('name'),
|
||||
];
|
||||
}
|
||||
|
||||
public function toNormalizedArray(): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'description' => $this->type,
|
||||
'image' => null,
|
||||
'model_type' => self::MODEL_TYPE,
|
||||
];
|
||||
}
|
||||
|
||||
public static function filterableFields(): array
|
||||
{
|
||||
return [
|
||||
'id',
|
||||
'owner_id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
'file_size',
|
||||
'public',
|
||||
'password',
|
||||
'type',
|
||||
'workspace_id',
|
||||
];
|
||||
}
|
||||
|
||||
public static function getModelTypeAttribute(): string
|
||||
{
|
||||
return static::MODEL_TYPE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user