class EntityWatchers
{
+ /**
+ * @var int[]
+ */
protected array $watchers = [];
+
+ /**
+ * @var int[]
+ */
protected array $ignorers = [];
public function __construct(
$this->build();
}
+ public function getWatcherUserIds(): array
+ {
+ return $this->watchers;
+ }
+
+ public function isUserIgnoring(int $userId): bool
+ {
+ return in_array($userId, $this->ignorers);
+ }
+
protected function build(): void
{
$watches = $this->getRelevantWatches();
- // TODO - De-dupe down watches per-user across entity types
- // so we end up with [user_id => status] values
- // then filter to current watch level, considering ignores,
- // then populate the class watchers/ignores with ids.
+ // Sort before de-duping, so that the order looped below follows book -> chapter -> page ordering
+ usort($watches, function (Watch $watchA, Watch $watchB) {
+ $entityTypeDiff = $watchA->watchable_type <=> $watchB->watchable_type;
+ return $entityTypeDiff === 0 ? ($watchA->user_id <=> $watchB->user_id) : $entityTypeDiff;
+ });
+
+ // De-dupe by user id to get their most relevant level
+ $levelByUserId = [];
+ foreach ($watches as $watch) {
+ $levelByUserId[$watch->user_id] = $watch->level;
+ }
+
+ // Populate the class arrays
+ $this->watchers = array_keys(array_filter($levelByUserId, fn(int $level) => $level >= $this->watchLevel));
+ $this->ignorers = array_keys(array_filter($levelByUserId, fn(int $level) => $level === 0));
}
+ /**
+ * @return Watch[]
+ */
protected function getRelevantWatches(): array
{
/** @var Entity[] $entitiesInvolved */
});
return $query->get([
- 'level', 'watchable_id', 'watchable_type', 'user_id'
+ 'level', 'watchable_id', 'watchable_type', 'user_id'
])->all();
}
}