]> BookStack Code Mirror - bookstack/blob - app/Activity/Tools/UserEntityWatchOptions.php
08fbe2e8d94dab240186d2fc2c54c819bfa337c4
[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\Users\Models\User;
11 use Illuminate\Database\Eloquent\Builder;
12
13 class UserEntityWatchOptions
14 {
15     protected ?array $watchMap = null;
16
17     public function __construct(
18         protected User $user,
19         protected Entity $entity,
20     ) {
21     }
22
23     public function canWatch(): bool
24     {
25         return $this->user->can('receive-notifications') && !$this->user->isDefault();
26     }
27
28     public function getWatchLevel(): string
29     {
30         return WatchLevels::levelValueToName($this->getWatchLevelValue());
31     }
32
33     public function isWatching(): bool
34     {
35         return $this->getWatchLevelValue() !== WatchLevels::DEFAULT;
36     }
37
38     public function getWatchedParent(): ?WatchedParentDetails
39     {
40         $watchMap = $this->getWatchMap();
41         unset($watchMap[$this->entity->getMorphClass()]);
42
43         if (isset($watchMap['chapter'])) {
44             return new WatchedParentDetails('chapter', $watchMap['chapter']);
45         }
46
47         if (isset($watchMap['book'])) {
48             return new WatchedParentDetails('book', $watchMap['book']);
49         }
50
51         return null;
52     }
53
54     public function updateWatchLevel(string $level): void
55     {
56         $levelValue = WatchLevels::levelNameToValue($level);
57         if ($levelValue < 0) {
58             $this->remove();
59             return;
60         }
61
62         $this->updateLevel($levelValue);
63     }
64
65     public function getWatchMap(): array
66     {
67         if (!is_null($this->watchMap)) {
68             return $this->watchMap;
69         }
70
71         $entities = [$this->entity];
72         if ($this->entity instanceof BookChild) {
73             $entities[] = $this->entity->book;
74         }
75         if ($this->entity instanceof Page && $this->entity->chapter) {
76             $entities[] = $this->entity->chapter;
77         }
78
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);
86                     });
87                 }
88             });
89
90         $this->watchMap = $query->get(['watchable_type', 'level'])
91             ->pluck('level', 'watchable_type')
92             ->toArray();
93
94         return $this->watchMap;
95     }
96
97     protected function getWatchLevelValue()
98     {
99         return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT;
100     }
101
102     protected function updateLevel(int $levelValue): void
103     {
104         Watch::query()->updateOrCreate([
105             'watchable_id' => $this->entity->id,
106             'watchable_type' => $this->entity->getMorphClass(),
107             'user_id' => $this->user->id,
108         ], [
109             'level' => $levelValue,
110         ]);
111         $this->watchMap = null;
112     }
113
114     protected function remove(): void
115     {
116         $this->entityQuery()->delete();
117         $this->watchMap = null;
118     }
119
120     protected function entityQuery(): Builder
121     {
122         return Watch::query()->where('watchable_id', '=', $this->entity->id)
123             ->where('watchable_type', '=', $this->entity->getMorphClass())
124             ->where('user_id', '=', $this->user->id);
125     }
126 }