1 <?php namespace BookStack\Actions;
3 use BookStack\Auth\Permissions\PermissionService;
4 use BookStack\Auth\User;
5 use BookStack\Entities\Entity;
6 use Illuminate\Support\Collection;
12 protected $permissionService;
15 * ActivityService constructor.
17 public function __construct(Activity $activity, PermissionService $permissionService)
19 $this->activity = $activity;
20 $this->permissionService = $permissionService;
25 * Add activity data to database.
27 public function add(Entity $entity, string $activityKey, ?int $bookId = null)
29 $activity = $this->newActivityForUser($activityKey, $bookId);
30 $entity->activity()->save($activity);
31 $this->setNotification($activityKey);
35 * Adds a activity history with a message, without binding to a entity.
37 public function addMessage(string $activityKey, string $message, ?int $bookId = null)
39 $this->newActivityForUser($activityKey, $bookId)->forceFill([
43 $this->setNotification($activityKey);
47 * Get a new activity instance for the current user.
49 protected function newActivityForUser(string $key, ?int $bookId = null): Activity
51 return $this->activity->newInstance()->forceFill([
52 'key' => strtolower($key),
53 'user_id' => $this->user->id,
54 'book_id' => $bookId ?? 0,
59 * Removes the entity attachment from each of its activities
60 * and instead uses the 'extra' field with the entities name.
61 * Used when an entity is deleted.
63 public function removeEntity(Entity $entity): Collection
65 $activities = $entity->activity()->get();
66 $entity->activity()->update([
67 'extra' => $entity->name,
75 * Gets the latest activity.
77 public function latest(int $count = 20, int $page = 0): array
79 $activityList = $this->permissionService
80 ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
81 ->orderBy('created_at', 'desc')
82 ->with(['user', 'entity'])
83 ->skip($count * $page)
87 return $this->filterSimilar($activityList);
91 * Gets the latest activity for an entity, Filtering out similar
92 * items to prevent a message activity list.
94 public function entityActivity(Entity $entity, int $count = 20, int $page = 1): array
96 if ($entity->isA('book')) {
97 $query = $this->activity->newQuery()->where('book_id', '=', $entity->id);
99 $query = $this->activity->newQuery()->where('entity_type', '=', $entity->getMorphClass())
100 ->where('entity_id', '=', $entity->id);
103 $activity = $this->permissionService
104 ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type')
105 ->orderBy('created_at', 'desc')
106 ->with(['entity', 'user.avatar'])
107 ->skip($count * ($page - 1))
111 return $this->filterSimilar($activity);
115 * Get latest activity for a user, Filtering out similar items.
117 public function userActivity(User $user, int $count = 20, int $page = 0): array
119 $activityList = $this->permissionService
120 ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
121 ->orderBy('created_at', 'desc')
122 ->where('user_id', '=', $user->id)
123 ->skip($count * $page)
127 return $this->filterSimilar($activityList);
131 * Filters out similar activity.
132 * @param Activity[] $activities
135 protected function filterSimilar(iterable $activities): array
138 $previousItem = null;
140 foreach ($activities as $activityItem) {
141 if (!$previousItem || !$activityItem->isSimilarTo($previousItem)) {
142 $newActivity[] = $activityItem;
145 $previousItem = $activityItem;
152 * Flashes a notification message to the session if an appropriate message is available.
154 protected function setNotification(string $activityKey)
156 $notificationTextKey = 'activities.' . $activityKey . '_notification';
157 if (trans()->has($notificationTextKey)) {
158 $message = trans($notificationTextKey);
159 session()->flash('success', $message);
164 * Log failed accesses, for further processing by tools like Fail2Ban
169 public function logFailedAccess($username)
171 $log_msg = config('logging.failed_access_message');
173 if (!is_string($username) || !is_string($log_msg) || strlen($log_msg)<1)
176 $log_msg = str_replace("%u", $username, $log_msg);
177 error_log($log_msg, 4);