125 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
		
		
			
		
	
	
			125 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace BookStack\Activity\Tools;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use BookStack\Activity\Models\Watch;
							 | 
						||
| 
								 | 
							
								use BookStack\Activity\WatchLevels;
							 | 
						||
| 
								 | 
							
								use BookStack\Entities\Models\BookChild;
							 | 
						||
| 
								 | 
							
								use BookStack\Entities\Models\Entity;
							 | 
						||
| 
								 | 
							
								use BookStack\Entities\Models\Page;
							 | 
						||
| 
								 | 
							
								use BookStack\Users\Models\User;
							 | 
						||
| 
								 | 
							
								use Illuminate\Database\Eloquent\Builder;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class UserEntityWatchOptions
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    protected ?array $watchMap = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function __construct(
							 | 
						||
| 
								 | 
							
								        protected User $user,
							 | 
						||
| 
								 | 
							
								        protected Entity $entity,
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function canWatch(): bool
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->user->can('receive-notifications') && !$this->user->isDefault();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getWatchLevel(): string
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return WatchLevels::levelValueToName($this->getWatchLevelValue());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function isWatching(): bool
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->getWatchLevelValue() !== WatchLevels::DEFAULT;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getWatchedParent(): ?WatchedParentDetails
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $watchMap = $this->getWatchMap();
							 | 
						||
| 
								 | 
							
								        unset($watchMap[$this->entity->getMorphClass()]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($watchMap['chapter'])) {
							 | 
						||
| 
								 | 
							
								            return new WatchedParentDetails('chapter', $watchMap['chapter']);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($watchMap['book'])) {
							 | 
						||
| 
								 | 
							
								            return new WatchedParentDetails('book', $watchMap['book']);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function updateWatchLevel(string $level): void
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $levelValue = WatchLevels::levelNameToValue($level);
							 | 
						||
| 
								 | 
							
								        if ($levelValue < 0) {
							 | 
						||
| 
								 | 
							
								            $this->remove();
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->updateLevel($levelValue);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public function getWatchMap(): array
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!is_null($this->watchMap)) {
							 | 
						||
| 
								 | 
							
								            return $this->watchMap;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $entities = [$this->entity];
							 | 
						||
| 
								 | 
							
								        if ($this->entity instanceof BookChild) {
							 | 
						||
| 
								 | 
							
								            $entities[] = $this->entity->book;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if ($this->entity instanceof Page && $this->entity->chapter) {
							 | 
						||
| 
								 | 
							
								            $entities[] = $this->entity->chapter;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $query = Watch::query()->where(function (Builder $subQuery) use ($entities) {
							 | 
						||
| 
								 | 
							
								            foreach ($entities as $entity) {
							 | 
						||
| 
								 | 
							
								                $subQuery->orWhere(function (Builder $whereQuery) use ($entity) {
							 | 
						||
| 
								 | 
							
								                    $whereQuery->where('watchable_type', '=', $entity->getMorphClass())
							 | 
						||
| 
								 | 
							
								                        ->where('watchable_id', '=', $entity->id);
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $this->watchMap = $query->get(['watchable_type', 'level'])
							 | 
						||
| 
								 | 
							
								            ->pluck('level', 'watchable_type')
							 | 
						||
| 
								 | 
							
								            ->toArray();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $this->watchMap;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected function getWatchLevelValue()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->getWatchMap()[$this->entity->getMorphClass()] ?? WatchLevels::DEFAULT;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected function updateLevel(int $levelValue): void
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        Watch::query()->updateOrCreate([
							 | 
						||
| 
								 | 
							
								            'watchable_id' => $this->entity->id,
							 | 
						||
| 
								 | 
							
								            'watchable_type' => $this->entity->getMorphClass(),
							 | 
						||
| 
								 | 
							
								            'user_id' => $this->user->id,
							 | 
						||
| 
								 | 
							
								        ], [
							 | 
						||
| 
								 | 
							
								            'level' => $levelValue,
							 | 
						||
| 
								 | 
							
								        ]);
							 | 
						||
| 
								 | 
							
								        $this->watchMap = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected function remove(): void
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->entityQuery()->delete();
							 | 
						||
| 
								 | 
							
								        $this->watchMap = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    protected function entityQuery(): Builder
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return Watch::query()->where('watchable_id', '=', $this->entity->id)
							 | 
						||
| 
								 | 
							
								            ->where('watchable_type', '=', $this->entity->getMorphClass())
							 | 
						||
| 
								 | 
							
								            ->where('user_id', '=', $this->user->id);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |