3 namespace BookStack\Activity\Tools;
5 use BookStack\Activity\Models\Watch;
6 use BookStack\Activity\WatchLevels;
7 use BookStack\Entities\Models\BookChild;
8 use BookStack\Entities\Models\Entity;
9 use BookStack\Entities\Models\Page;
10 use BookStack\Permissions\Permission;
11 use BookStack\Users\Models\User;
12 use Illuminate\Database\Eloquent\Builder;
14 class UserEntityWatchOptions
16 protected ?array $watchMap = null;
18 public function __construct(
20 protected Entity $entity,
24 public function canWatch(): bool
26 return $this->user->can(Permission::ReceiveNotifications) && !$this->user->isGuest();
29 public function getWatchLevel(): string
31 return WatchLevels::levelValueToName($this->getWatchLevelValue());
34 public function isWatching(): bool
36 return $this->getWatchLevelValue() !== WatchLevels::DEFAULT;
39 public function getWatchedParent(): ?WatchedParentDetails
41 $watchMap = $this->getWatchMap();
42 unset($watchMap[$this->entity->getMorphClass()]);
44 if (isset($watchMap['chapter'])) {
45 return new WatchedParentDetails('chapter', $watchMap['chapter']);
48 if (isset($watchMap['book'])) {
49 return new WatchedParentDetails('book', $watchMap['book']);
55 public function updateLevelByName(string $level): void
57 $levelValue = WatchLevels::levelNameToValue($level);
58 $this->updateLevelByValue($levelValue);
61 public function updateLevelByValue(int $level): void
68 $this->updateLevel($level);
71 public function getWatchMap(): array
73 if (!is_null($this->watchMap)) {
74 return $this->watchMap;
77 $entities = [$this->entity];
78 if ($this->entity instanceof BookChild) {
79 $entities[] = $this->entity->book;
81 if ($this->entity instanceof Page && $this->entity->chapter) {
82 $entities[] = $this->entity->chapter;
85 $query = Watch::query()
86 ->where('user_id', '=', $this->user->id)
87 ->where(function (Builder $subQuery) use ($entities) {
88 foreach ($entities as $entity) {
89 $subQuery->orWhere(function (Builder $whereQuery) use ($entity) {
90 $whereQuery->where('watchable_type', '=', $entity->getMorphClass())
91 ->where('watchable_id', '=', $entity->id);
96 $this->watchMap = $query->get(['watchable_type', 'level'])
97 ->pluck('level', 'watchable_type')
100 return $this->watchMap;
103 protected function getWatchLevelValue()
105 return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT;
108 protected function updateLevel(int $levelValue): void
110 Watch::query()->updateOrCreate([
111 'watchable_id' => $this->entity->id,
112 'watchable_type' => $this->entity->getMorphClass(),
113 'user_id' => $this->user->id,
115 'level' => $levelValue,
117 $this->watchMap = null;
120 protected function remove(): void
122 $this->entityQuery()->delete();
123 $this->watchMap = null;
126 protected function entityQuery(): Builder
128 return Watch::query()->where('watchable_id', '=', $this->entity->id)
129 ->where('watchable_type', '=', $this->entity->getMorphClass())
130 ->where('user_id', '=', $this->user->id);