richard
/
cyca
Archived
1
0
Fork 0
This repository has been archived on 2024-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
cyca/app/Models/Folder.php

404 lines
12 KiB
PHP
Executable File

<?php
namespace App\Models;
use App\Models\Traits\Folder\BuildsTree;
use App\Models\Traits\Folder\CreatesDefaultFolders;
use Illuminate\Database\Eloquent\Model;
class Folder extends Model
{
use BuildsTree;
use CreatesDefaultFolders;
// -------------------------------------------------------------------------
// ----| Properties |-------------------------------------------------------
// -------------------------------------------------------------------------
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'type',
'title',
'parent_id',
'position',
'user_id',
'group_id',
];
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'icon',
'iconColor',
'is_selected',
'is_expanded',
];
// -------------------------------------------------------------------------
// ----| Attributes |-------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Return folder's title.
*
* If it's a special folder, ie not created by user, we will automatically
* translate its original title.
*
* @return string
*/
public function getTitleAttribute()
{
switch ($this->type) {
// Unspecified type of folder
default:
return $this->attributes['title'];
// Unread items
case 'unread_items':
return __('Unread items');
// Root folder
case 'root':
return __('Root');
}
}
/**
* Return folder's icon as a fragment identifier for a SVG sprite.
*
* @return string
*/
public function getIconAttribute()
{
switch ($this->type) {
// Unspecified type of folder
default:
return 'folder';
// Unread items
case 'unread_items':
return 'unread_items';
// Root folder
case 'root':
return 'house';
}
}
/**
* Return icon's color as a CSS class.
*
* @return string
*/
public function getIconColorAttribute()
{
switch ($this->type) {
// Unspecified type of folder
default:
return 'folder-common';
// Unread items
case 'unread_items':
if ($this->feed_item_states_count > 0) {
return 'folder-unread-not-empty';
}
return 'folder-unread';
// Root folder
case 'root':
return 'folder-root';
}
}
/**
* Return a formatted path to the folder, using every ascendant's title.
*
* @return string
*/
public function getBreadcrumbsAttribute()
{
$parts = [
(string) view('partials.folder', ['folder' => $this]),
];
$parent = $this->parent;
while ($parent !== null) {
$parts[] = (string) view('partials.folder', ['folder' => $parent]);
$parent = $parent->parent;
}
$parts[] = (string) view('partials.group', ['group' => $this->group]);
return implode(' ', array_reverse($parts));
}
/**
* Return a boolean value indicating if this folder is selected by current
* user.
*
* @return bool
*/
public function getIsSelectedAttribute()
{
if (!auth()->check()) {
return false;
}
return auth()->user()->selectedFolder()->id === $this->id;
}
/**
* Return a boolean value indicating if folder is expanded for specified
* user.
*
* @return bool
*/
public function getIsExpandedAttribute()
{
if (!auth()->check()) {
return false;
}
return auth()->user()->getFolderExpandedState($this);
}
// -------------------------------------------------------------------------
// ----| Relations |--------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Parent folder.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function parent()
{
return $this->belongsTo(Folder::class, 'parent_id');
}
/**
* Children folders.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function children()
{
return $this->hasMany(Folder::class, 'parent_id');
}
/**
* Creator of this folder.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Group this folder belongs to.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function group()
{
return $this->belongsTo(Group::class);
}
/**
* Documents in this folder.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function documents()
{
return $this->belongsToMany(Document::class, 'bookmarks')->using(Bookmark::class)->as('bookmark')->withPivot(['initial_url', 'created_at', 'updated_at', 'visits']);
}
/**
* Associated unread feed items.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function feedItemStates()
{
return $this->hasManyThrough(FeedItemState::class, Bookmark::class, 'folder_id', 'document_id', 'id', 'document_id');
}
/**
* Folder's permissions.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function permissions()
{
return $this->hasMany(Permission::class);
}
// -------------------------------------------------------------------------
// ----| Scopes |-----------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Scope a query to only include folders of a given type.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param mixed $type
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
// -------------------------------------------------------------------------
// ----| Methods |----------------------------------------------------------
// -------------------------------------------------------------------------
public static function listDocumentIds($folders, $group)
{
$unreadItemsFolder = $group->folders()->ofType('unread_items')->first();
$query = $group->folders()->with('documents:id');
if (!in_array($unreadItemsFolder->id, $folders)) {
$query = $query->whereIn('id', $folders);
}
return $query->get()->pluck('documents')->flatten()->pluck('id')->unique();
}
/**
* Return a list of ids of documents present in this folder.
*
* @return array
*/
public function getDocumentIds()
{
return $this->documents()->select('documents.id')->pluck('documents.id');
}
/**
* Return a list of documents built for front-end for specified user.
*
* @param \App\Models\User $user
*
* @return \Illuminate\Support\Collection
*/
public function listDocuments(User $user)
{
$columns = [
'documents.id',
'documents.url',
'documents.http_status_code',
'documents.http_status_text',
'documents.mimetype',
'documents.title',
'documents.favicon_path',
'documents.checked_at',
];
if ($this->type === 'unread_items') {
$documents = $this->group->documents()->pluck('document_id');
return Document::select($columns)->with('feeds:feeds.id', 'feeds.ignored', 'bookmark')->withCount(['feedItemStates' => function ($query) use ($user) {
$query->where('is_read', false)->where('user_id', $user->id);
}])->whereHas('feedItemStates', function ($query) use ($user) {
$query->where('is_read', false)->where('user_id', $user->id);
})->whereIn('documents.id', $documents)
->get();
} else {
$documentIds = $this->getDocumentIds();
return Document::select($columns)->with('feeds:feeds.id', 'feeds.ignored', 'bookmark')->withCount(['feedItemStates' => function ($query) use ($user) {
$query->where('is_read', false)->where('user_id', $user->id);
}])->whereIn('documents.id', $documentIds)
->get();
}
}
/**
* Return folder's permissions that applies to any user without explicit
* permissions.
*
* @return array
*/
public function getDefaultPermissions()
{
$defaultPermissions = $this->permissions()->whereNull('user_id')->first();
if (empty($defaultPermissions)) {
return [
'can_create_folder' => false,
'can_update_folder' => false,
'can_delete_folder' => false,
'can_create_document' => false,
'can_delete_document' => false,
];
}
return [
'can_create_folder' => $defaultPermissions->can_create_folder,
'can_update_folder' => $defaultPermissions->can_update_folder,
'can_delete_folder' => $defaultPermissions->can_delete_folder,
'can_create_document' => $defaultPermissions->can_create_document,
'can_delete_document' => $defaultPermissions->can_delete_document,
];
}
/**
* Return user's permission specific to this folder.
*
* @return array
*/
public function getUserPermissions(User $user = null)
{
if (empty($user)) {
if (!auth()->check()) {
return null;
}
$user = auth()->user();
}
return [
'can_change_permissions' => $this->group->user_id === $user->id,
'can_create_folder' => $user->can('createIn', $this),
'can_update_folder' => $user->can('update', $this),
'can_delete_folder' => $user->can('delete', $this),
'can_create_document' => $user->can('createBookmarkIn', $this),
'can_delete_document' => $user->can('deleteBookmarkFrom', $this),
];
}
public function setDefaultPermission($ability = null, $granted = false)
{
$permissions = $this->permissions()->whereNull('user_id')->first();
if (!$permissions) {
$permissions = new Permission();
$permissions->folder()->associate($this);
$permissions->can_create_folder = false;
$permissions->can_update_folder = false;
$permissions->can_delete_folder = false;
$permissions->can_create_document = false;
$permissions->can_delete_document = false;
}
if ($ability) {
$permissions->{$ability} = $granted;
}
$permissions->save();
return $permissions;
}
}