]> BookStack Code Mirror - bookstack/blob - app/Activity/Tools/UserEntityWatchOptions.php
Copying: Fixed issue with non-page links to page permalinks
[bookstack] / app / Activity / Tools / UserEntityWatchOptions.php
1 <?php
2
3 namespace BookStack\Activity\Tools;
4
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;
13
14 class UserEntityWatchOptions
15 {
16     protected ?array $watchMap = null;
17
18     public function __construct(
19         protected User $user,
20         protected Entity $entity,
21     ) {
22     }
23
24     public function canWatch(): bool
25     {
26         return $this->user->can(Permission::ReceiveNotifications) && !$this->user->isGuest();
27     }
28
29     public function getWatchLevel(): string
30     {
31         return WatchLevels::levelValueToName($this->getWatchLevelValue());
32     }
33
34     public function isWatching(): bool
35     {
36         return $this->getWatchLevelValue() !== WatchLevels::DEFAULT;
37     }
38
39     public function getWatchedParent(): ?WatchedParentDetails
40     {
41         $watchMap = $this->getWatchMap();
42         unset($watchMap[$this->entity->getMorphClass()]);
43
44         if (isset($watchMap['chapter'])) {
45             return new WatchedParentDetails('chapter', $watchMap['chapter']);
46         }
47
48         if (isset($watchMap['book'])) {
49             return new WatchedParentDetails('book', $watchMap['book']);
50         }
51
52         return null;
53     }
54
55     public function updateLevelByName(string $level): void
56     {
57         $levelValue = WatchLevels::levelNameToValue($level);
58         $this->updateLevelByValue($levelValue);
59     }
60
61     public function updateLevelByValue(int $level): void
62     {
63         if ($level < 0) {
64             $this->remove();
65             return;
66         }
67
68         $this->updateLevel($level);
69     }
70
71     public function getWatchMap(): array
72     {
73         if (!is_null($this->watchMap)) {
74             return $this->watchMap;
75         }
76
77         $entities = [$this->entity];
78         if ($this->entity instanceof BookChild) {
79             $entities[] = $this->entity->book;
80         }
81         if ($this->entity instanceof Page && $this->entity->chapter) {
82             $entities[] = $this->entity->chapter;
83         }
84
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);
92                     });
93                 }
94             });
95
96         $this->watchMap = $query->get(['watchable_type', 'level'])
97             ->pluck('level', 'watchable_type')
98             ->toArray();
99
100         return $this->watchMap;
101     }
102
103     protected function getWatchLevelValue()
104     {
105         return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT;
106     }
107
108     protected function updateLevel(int $levelValue): void
109     {
110         Watch::query()->updateOrCreate([
111             'watchable_id' => $this->entity->id,
112             'watchable_type' => $this->entity->getMorphClass(),
113             'user_id' => $this->user->id,
114         ], [
115             'level' => $levelValue,
116         ]);
117         $this->watchMap = null;
118     }
119
120     protected function remove(): void
121     {
122         $this->entityQuery()->delete();
123         $this->watchMap = null;
124     }
125
126     protected function entityQuery(): Builder
127     {
128         return Watch::query()->where('watchable_id', '=', $this->entity->id)
129             ->where('watchable_type', '=', $this->entity->getMorphClass())
130             ->where('user_id', '=', $this->user->id);
131     }
132 }