]> BookStack Code Mirror - bookstack/blob - app/Actions/ActivityService.php
8511e4d6d730769caf3ef5654acaf567b9d9ea7f
[bookstack] / app / Actions / ActivityService.php
1 <?php namespace BookStack\Actions;
2
3 use BookStack\Auth\Permissions\PermissionService;
4 use BookStack\Entities\Entity;
5
6 class ActivityService
7 {
8     protected $activity;
9     protected $user;
10     protected $permissionService;
11
12     /**
13      * ActivityService constructor.
14      * @param Activity $activity
15      * @param PermissionService $permissionService
16      */
17     public function __construct(Activity $activity, PermissionService $permissionService)
18     {
19         $this->activity = $activity;
20         $this->permissionService = $permissionService;
21         $this->user = user();
22     }
23
24     /**
25      * Add activity data to database.
26      * @param \BookStack\Entities\Entity $entity
27      * @param string $activityKey
28      * @param int $bookId
29      */
30     public function add(Entity $entity, string $activityKey, int $bookId = null)
31     {
32         $activity = $this->newActivityForUser($activityKey, $bookId);
33         $entity->activity()->save($activity);
34         $this->setNotification($activityKey);
35     }
36
37     /**
38      * Adds a activity history with a message, without binding to a entity.
39      * @param string $activityKey
40      * @param string $message
41      * @param int $bookId
42      */
43     public function addMessage(string $activityKey, string $message, int $bookId = null)
44     {
45         $this->newActivityForUser($activityKey, $bookId)->forceFill([
46             'extra' => $message
47         ])->save();
48
49         $this->setNotification($activityKey);
50     }
51
52     /**
53      * Get a new activity instance for the current user.
54      * @param string $key
55      * @param int|null $bookId
56      * @return Activity
57      */
58     protected function newActivityForUser(string $key, int $bookId = null)
59     {
60         return $this->activity->newInstance()->forceFill([
61             'key' => strtolower($key),
62             'user_id' => $this->user->id,
63             'book_id' => $bookId ?? 0,
64         ]);
65     }
66
67     /**
68      * Removes the entity attachment from each of its activities
69      * and instead uses the 'extra' field with the entities name.
70      * Used when an entity is deleted.
71      * @param Entity $entity
72      * @return mixed
73      */
74     public function removeEntity(Entity $entity)
75     {
76         $activities = $entity->activity;
77         foreach ($activities as $activity) {
78             $activity->extra = $entity->name;
79             $activity->entity_id = 0;
80             $activity->entity_type = null;
81             $activity->save();
82         }
83         return $activities;
84     }
85
86     /**
87      * Gets the latest activity.
88      * @param int $count
89      * @param int $page
90      * @return array
91      */
92     public function latest($count = 20, $page = 0)
93     {
94         $activityList = $this->permissionService
95             ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
96             ->orderBy('created_at', 'desc')
97             ->with('user', 'entity')
98             ->skip($count * $page)
99             ->take($count)
100             ->get();
101
102         return $this->filterSimilar($activityList);
103     }
104
105     /**
106      * Gets the latest activity for an entity, Filtering out similar
107      * items to prevent a message activity list.
108      * @param Entity $entity
109      * @param int $count
110      * @param int $page
111      * @return array
112      */
113     public function entityActivity($entity, $count = 20, $page = 1)
114     {
115         if ($entity->isA('book')) {
116             $query = $this->activity->where('book_id', '=', $entity->id);
117         } else {
118             $query = $this->activity->where('entity_type', '=', $entity->getMorphClass())
119                 ->where('entity_id', '=', $entity->id);
120         }
121         
122         $activity = $this->permissionService
123             ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type')
124             ->orderBy('created_at', 'desc')
125             ->with(['entity', 'user.avatar'])
126             ->skip($count * ($page - 1))
127             ->take($count)
128             ->get();
129
130         return $this->filterSimilar($activity);
131     }
132
133     /**
134      * Get latest activity for a user, Filtering out similar
135      * items.
136      * @param $user
137      * @param int $count
138      * @param int $page
139      * @return array
140      */
141     public function userActivity($user, $count = 20, $page = 0)
142     {
143         $activityList = $this->permissionService
144             ->filterRestrictedEntityRelations($this->activity, 'activities', 'entity_id', 'entity_type')
145             ->orderBy('created_at', 'desc')->where('user_id', '=', $user->id)->skip($count * $page)->take($count)->get();
146         return $this->filterSimilar($activityList);
147     }
148
149     /**
150      * Filters out similar activity.
151      * @param Activity[] $activities
152      * @return array
153      */
154     protected function filterSimilar($activities)
155     {
156         $newActivity = [];
157         $previousItem = false;
158         foreach ($activities as $activityItem) {
159             if ($previousItem === false) {
160                 $previousItem = $activityItem;
161                 $newActivity[] = $activityItem;
162                 continue;
163             }
164             if (!$activityItem->isSimilarTo($previousItem)) {
165                 $newActivity[] = $activityItem;
166             }
167             $previousItem = $activityItem;
168         }
169         return $newActivity;
170     }
171
172     /**
173      * Flashes a notification message to the session if an appropriate message is available.
174      * @param $activityKey
175      */
176     protected function setNotification($activityKey)
177     {
178         $notificationTextKey = 'activities.' . $activityKey . '_notification';
179         if (trans()->has($notificationTextKey)) {
180             $message = trans($notificationTextKey);
181             session()->flash('success', $message);
182         }
183     }
184 }