X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/c7a2d568bf693add30c8402d68d1f46f09a44c5b..refs/pull/3693/head:/app/Entities/Models/Entity.php diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index 29853fe30..26a52073e 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -1,13 +1,28 @@ -scopeHasPermission($query, 'view'); - } - - /** - * Scope the query to those entities that the current user has the given permission for. - */ - public function scopeHasPermission(Builder $query, string $permission) + public function scopeVisible(Builder $query): Builder { - return Permissions::restrictEntityQuery($query, $permission); + return app()->make(PermissionApplicator::class)->restrictEntityQuery($query); } /** @@ -92,32 +102,26 @@ class Entity extends Ownable /** * Compares this entity to another given entity. * Matches by comparing class and id. - * @param $entity - * @return bool */ - public function matches($entity) + public function matches(self $entity): bool { return [get_class($this), $this->id] === [get_class($entity), $entity->id]; } /** - * Checks if an entity matches or contains another given entity. - * @param Entity $entity - * @return bool + * Checks if the current entity matches or contains the given. */ - public function matchesOrContains(Entity $entity) + public function matchesOrContains(self $entity): bool { - $matches = [get_class($this), $this->id] === [get_class($entity), $entity->id]; - - if ($matches) { + if ($this->matches($entity)) { return true; } - if (($entity->isA('chapter') || $entity->isA('page')) && $this->isA('book')) { + if (($entity instanceof BookChild) && $this instanceof Book) { return $entity->book_id === $this->id; } - if ($entity->isA('page') && $this->isA('chapter')) { + if ($entity instanceof Page && $this instanceof Chapter) { return $entity->chapter_id === $this->id; } @@ -126,9 +130,8 @@ class Entity extends Ownable /** * Gets the activity objects for this entity. - * @return MorphMany */ - public function activity() + public function activity(): MorphMany { return $this->morphMany(Activity::class, 'entity') ->orderBy('created_at', 'desc'); @@ -137,36 +140,33 @@ class Entity extends Ownable /** * Get View objects for this entity. */ - public function views() + public function views(): MorphMany { return $this->morphMany(View::class, 'viewable'); } /** * Get the Tag models that have been user assigned to this entity. - * @return MorphMany */ - public function tags() + public function tags(): MorphMany { return $this->morphMany(Tag::class, 'entity')->orderBy('order', 'asc'); } /** - * Get the comments for an entity - * @param bool $orderByCreated - * @return MorphMany + * Get the comments for an entity. */ - public function comments($orderByCreated = true) + public function comments(bool $orderByCreated = true): MorphMany { $query = $this->morphMany(Comment::class, 'entity'); + return $orderByCreated ? $query->orderBy('created_at', 'asc') : $query; } /** * Get the related search terms. - * @return MorphMany */ - public function searchTerms() + public function searchTerms(): MorphMany { return $this->morphMany(SearchTerm::class, 'entity'); } @@ -174,18 +174,15 @@ class Entity extends Ownable /** * Get this entities restrictions. */ - public function permissions() + public function permissions(): MorphMany { return $this->morphMany(EntityPermission::class, 'restrictable'); } /** * Check if this entity has a specific restriction set against it. - * @param $role_id - * @param $action - * @return bool */ - public function hasRestriction($role_id, $action) + public function hasRestriction(int $role_id, string $action): bool { return $this->permissions()->where('role_id', '=', $role_id) ->where('action', '=', $action)->count() > 0; @@ -208,37 +205,40 @@ class Entity extends Ownable } /** - * Check if this instance or class is a certain type of entity. - * Examples of $type are 'page', 'book', 'chapter' + * Get the references pointing from this entity to other items. */ - public static function isA(string $type): bool + public function referencesFrom(): MorphMany { - return static::getType() === strtolower($type); + return $this->morphMany(Reference::class, 'from'); } /** - * Get entity type. - * @return mixed + * Get the references pointing to this entity from other items. */ - public static function getType() + public function referencesTo(): MorphMany { - return strtolower(static::getClassName()); + return $this->morphMany(Reference::class, 'to'); } /** - * Get an instance of an entity of the given type. - * @param $type - * @return Entity + * Check if this instance or class is a certain type of entity. + * Examples of $type are 'page', 'book', 'chapter'. + * + * @deprecated Use instanceof instead. */ - public static function getEntityInstance($type) + public static function isA(string $type): bool { - $types = ['Page', 'Book', 'Chapter', 'Bookshelf']; - $className = str_replace([' ', '-', '_'], '', ucwords($type)); - if (!in_array($className, $types)) { - return null; - } + return static::getType() === strtolower($type); + } + + /** + * Get the entity type as a simple lowercase word. + */ + public static function getType(): string + { + $className = array_slice(explode('\\', static::class), -1, 1)[0]; - return app('BookStack\\Entities\\' . $className); + return strtolower($className); } /** @@ -249,55 +249,43 @@ class Entity extends Ownable if (mb_strlen($this->name) <= $length) { return $this->name; } - return mb_substr($this->name, 0, $length - 3) . '...'; - } - /** - * Get the body text of this entity. - * @return mixed - */ - public function getText() - { - return $this->{$this->textField}; + return mb_substr($this->name, 0, $length - 3) . '...'; } /** * Get an excerpt of this entity's descriptive content to the specified length. - * @param int $length - * @return mixed */ - public function getExcerpt(int $length = 100) + public function getExcerpt(int $length = 100): string { - $text = $this->getText(); + $text = $this->{$this->textField} ?? ''; + if (mb_strlen($text) > $length) { - $text = mb_substr($text, 0, $length-3) . '...'; + $text = mb_substr($text, 0, $length - 3) . '...'; } + return trim($text); } /** - * Get the url of this entity - * @param $path - * @return string + * Get the url of this entity. */ - public function getUrl($path = '/') - { - return $path; - } + abstract public function getUrl(string $path = '/'): string; /** * Get the parent entity if existing. * This is the "static" parent and does not include dynamic * relations such as shelves to books. */ - public function getParent(): ?Entity + public function getParent(): ?self { - if ($this->isA('page')) { + if ($this instanceof Page) { return $this->chapter_id ? $this->chapter()->withTrashed()->first() : $this->book()->withTrashed()->first(); } - if ($this->isA('chapter')) { + if ($this instanceof Chapter) { return $this->book()->withTrashed()->first(); } + return null; } @@ -306,25 +294,50 @@ class Entity extends Ownable */ public function rebuildPermissions() { - /** @noinspection PhpUnhandledExceptionInspection */ - Permissions::buildJointPermissionsForEntity(clone $this); + app()->make(JointPermissionBuilder::class)->rebuildForEntity(clone $this); } /** - * Index the current entity for search + * Index the current entity for search. */ public function indexForSearch() { - $searchService = app()->make(SearchService::class); - $searchService->indexEntity(clone $this); + app()->make(SearchIndex::class)->indexEntity(clone $this); } /** - * Generate and set a new URL slug for this model. + * {@inheritdoc} */ public function refreshSlug(): string { - $this->slug = (new SlugGenerator)->generate($this); + $this->slug = app()->make(SlugGenerator::class)->generate($this); + return $this->slug; } + + /** + * {@inheritdoc} + */ + public function favourites(): MorphMany + { + return $this->morphMany(Favourite::class, 'favouritable'); + } + + /** + * Check if the entity is a favourite of the current user. + */ + public function isFavourite(): bool + { + return $this->favourites() + ->where('user_id', '=', user()->id) + ->exists(); + } + + /** + * {@inheritdoc} + */ + public function logDescriptor(): string + { + return "({$this->id}) {$this->name}"; + } }