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\Users\Models\User;
11 use Illuminate\Database\Eloquent\Builder;
13 class UserEntityWatchOptions
15 protected ?array $watchMap = null;
17 public function __construct(
19 protected Entity $entity,
23 public function canWatch(): bool
25 return $this->user->can('receive-notifications') && !$this->user->isDefault();
28 public function getWatchLevel(): string
30 return WatchLevels::levelValueToName($this->getWatchLevelValue());
33 public function isWatching(): bool
35 return $this->getWatchLevelValue() !== WatchLevels::DEFAULT;
38 public function getWatchedParent(): ?WatchedParentDetails
40 $watchMap = $this->getWatchMap();
41 unset($watchMap[$this->entity->getMorphClass()]);
43 if (isset($watchMap['chapter'])) {
44 return new WatchedParentDetails('chapter', $watchMap['chapter']);
47 if (isset($watchMap['book'])) {
48 return new WatchedParentDetails('book', $watchMap['book']);
54 public function updateWatchLevel(string $level): void
56 $levelValue = WatchLevels::levelNameToValue($level);
57 if ($levelValue < 0) {
62 $this->updateLevel($levelValue);
65 public function getWatchMap(): array
67 if (!is_null($this->watchMap)) {
68 return $this->watchMap;
71 $entities = [$this->entity];
72 if ($this->entity instanceof BookChild) {
73 $entities[] = $this->entity->book;
75 if ($this->entity instanceof Page && $this->entity->chapter) {
76 $entities[] = $this->entity->chapter;
79 $query = Watch::query()
80 ->where('user_id', '=', $this->user->id)
81 ->where(function (Builder $subQuery) use ($entities) {
82 foreach ($entities as $entity) {
83 $subQuery->orWhere(function (Builder $whereQuery) use ($entity) {
84 $whereQuery->where('watchable_type', '=', $entity->getMorphClass())
85 ->where('watchable_id', '=', $entity->id);
90 $this->watchMap = $query->get(['watchable_type', 'level'])
91 ->pluck('level', 'watchable_type')
94 return $this->watchMap;
97 protected function getWatchLevelValue()
99 return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT;
102 protected function updateLevel(int $levelValue): void
104 Watch::query()->updateOrCreate([
105 'watchable_id' => $this->entity->id,
106 'watchable_type' => $this->entity->getMorphClass(),
107 'user_id' => $this->user->id,
109 'level' => $levelValue,
111 $this->watchMap = null;
114 protected function remove(): void
116 $this->entityQuery()->delete();
117 $this->watchMap = null;
120 protected function entityQuery(): Builder
122 return Watch::query()->where('watchable_id', '=', $this->entity->id)
123 ->where('watchable_type', '=', $this->entity->getMorphClass())
124 ->where('user_id', '=', $this->user->id);