user->can('receive-notifications') && !$this->user->isGuest(); } public function getWatchLevel(): string { return WatchLevels::levelValueToName($this->getWatchLevelValue()); } public function isWatching(): bool { return $this->getWatchLevelValue() !== WatchLevels::DEFAULT; } public function getWatchedParent(): ?WatchedParentDetails { $watchMap = $this->getWatchMap(); unset($watchMap[$this->entity->getMorphClass()]); if (isset($watchMap['chapter'])) { return new WatchedParentDetails('chapter', $watchMap['chapter']); } if (isset($watchMap['book'])) { return new WatchedParentDetails('book', $watchMap['book']); } return null; } public function updateLevelByName(string $level): void { $levelValue = WatchLevels::levelNameToValue($level); $this->updateLevelByValue($levelValue); } public function updateLevelByValue(int $level): void { if ($level < 0) { $this->remove(); return; } $this->updateLevel($level); } public function getWatchMap(): array { if (!is_null($this->watchMap)) { return $this->watchMap; } $entities = [$this->entity]; if ($this->entity instanceof BookChild) { $entities[] = $this->entity->book; } if ($this->entity instanceof Page && $this->entity->chapter) { $entities[] = $this->entity->chapter; } $query = Watch::query() ->where('user_id', '=', $this->user->id) ->where(function (Builder $subQuery) use ($entities) { foreach ($entities as $entity) { $subQuery->orWhere(function (Builder $whereQuery) use ($entity) { $whereQuery->where('watchable_type', '=', $entity->getMorphClass()) ->where('watchable_id', '=', $entity->id); }); } }); $this->watchMap = $query->get(['watchable_type', 'level']) ->pluck('level', 'watchable_type') ->toArray(); return $this->watchMap; } protected function getWatchLevelValue() { return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT; } protected function updateLevel(int $levelValue): void { Watch::query()->updateOrCreate([ 'watchable_id' => $this->entity->id, 'watchable_type' => $this->entity->getMorphClass(), 'user_id' => $this->user->id, ], [ 'level' => $levelValue, ]); $this->watchMap = null; } protected function remove(): void { $this->entityQuery()->delete(); $this->watchMap = null; } protected function entityQuery(): Builder { return Watch::query()->where('watchable_id', '=', $this->entity->id) ->where('watchable_type', '=', $this->entity->getMorphClass()) ->where('user_id', '=', $this->user->id); } }