use BookStack\Auth\Permissions\PermissionService;
use BookStack\Auth\User;
+use BookStack\Entities\Chapter;
use BookStack\Entities\Entity;
+use BookStack\Entities\Page;
+use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
-use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
class ActivityService
}
/**
- * Add activity data to database.
+ * Add activity data to database for an entity.
*/
- public function add(Entity $entity, string $type, ?int $bookId = null)
+ public function addForEntity(Entity $entity, string $type)
{
- $activity = $this->newActivityForUser($type, $bookId);
+ $activity = $this->newActivityForUser($type);
$entity->activity()->save($activity);
$this->setNotification($type);
}
/**
* Get a new activity instance for the current user.
*/
- protected function newActivityForUser(string $key, ?int $bookId = null): Activity
+ protected function newActivityForUser(string $type): Activity
{
return $this->activity->newInstance()->forceFill([
- 'key' => strtolower($key),
+ 'key' => strtolower($type),
'user_id' => $this->user->id,
- 'book_id' => $bookId ?? 0,
]);
}
* and instead uses the 'extra' field with the entities name.
* Used when an entity is deleted.
*/
- public function removeEntity(Entity $entity): Collection
+ public function removeEntity(Entity $entity)
{
- $activities = $entity->activity()->get();
$entity->activity()->update([
'extra' => $entity->name,
'entity_id' => 0,
'entity_type' => '',
]);
- return $activities;
}
/**
*/
public function entityActivity(Entity $entity, int $count = 20, int $page = 1): array
{
+ /** @var [string => int[]] $queryIds */
+ $queryIds = [$entity->getMorphClass() => [$entity->id]];
+
if ($entity->isA('book')) {
- $query = $this->activity->newQuery()->where('book_id', '=', $entity->id);
- } else {
- $query = $this->activity->newQuery()->where('entity_type', '=', $entity->getMorphClass())
- ->where('entity_id', '=', $entity->id);
+ $queryIds[(new Chapter)->getMorphClass()] = $entity->chapters()->visible()->pluck('id');
+ }
+ if ($entity->isA('book') || $entity->isA('chapter')) {
+ $queryIds[(new Page)->getMorphClass()] = $entity->pages()->visible()->pluck('id');
}
- $activity = $this->permissionService
- ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type')
- ->orderBy('created_at', 'desc')
+ $query = $this->activity->newQuery();
+ $query->where(function (Builder $query) use ($queryIds) {
+ foreach ($queryIds as $morphClass => $idArr) {
+ $query->orWhere(function (Builder $innerQuery) use ($morphClass, $idArr) {
+ $innerQuery->where('entity_type', '=', $morphClass)
+ ->whereIn('entity_id', $idArr);
+ });
+ }
+ });
+
+ $activity = $query->orderBy('created_at', 'desc')
->with(['entity' => function (Relation $query) {
$query->withTrashed();
}, 'user.avatar'])
use BookStack\Entities\Entity;
use League\CommonMark\CommonMarkConverter;
+use BookStack\Facades\Activity as ActivityService;
/**
* Class CommentRepo
$comment->parent_id = $parent_id;
$entity->comments()->save($comment);
- Activity::add($entity, ActivityType::COMMENTED_ON, $entity->book->id);
+ ActivityService::addForEntity($entity, ActivityType::COMMENTED_ON);
return $comment;
}
{
$book = new Book();
$this->baseRepo->create($book, $input);
- Activity::add($book, ActivityType::BOOK_CREATE, $book->id);
+ Activity::addForEntity($book, ActivityType::BOOK_CREATE);
return $book;
}
public function update(Book $book, array $input): Book
{
$this->baseRepo->update($book, $input);
- Activity::add($book, ActivityType::BOOK_UPDATE, $book->id);
+ Activity::addForEntity($book, ActivityType::BOOK_UPDATE);
return $book;
}
{
$trashCan = new TrashCan();
$trashCan->softDestroyBook($book);
- Activity::add($book, ActivityType::BOOK_DELETE, $book->id);
+ Activity::addForEntity($book, ActivityType::BOOK_DELETE);
$trashCan->autoClearOld();
}
$shelf = new Bookshelf();
$this->baseRepo->create($shelf, $input);
$this->updateBooks($shelf, $bookIds);
- Activity::add($shelf, ActivityType::BOOKSHELF_CREATE);
+ Activity::addForEntity($shelf, ActivityType::BOOKSHELF_CREATE);
return $shelf;
}
$this->updateBooks($shelf, $bookIds);
}
- Activity::add($shelf, ActivityType::BOOKSHELF_UPDATE);
+ Activity::addForEntity($shelf, ActivityType::BOOKSHELF_UPDATE);
return $shelf;
}
{
$trashCan = new TrashCan();
$trashCan->softDestroyShelf($shelf);
- Activity::add($shelf, ActivityType::BOOKSHELF_DELETE);
+ Activity::addForEntity($shelf, ActivityType::BOOKSHELF_DELETE);
$trashCan->autoClearOld();
}
}
$chapter->book_id = $parentBook->id;
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
$this->baseRepo->create($chapter, $input);
- Activity::add($chapter, ActivityType::CHAPTER_CREATE, $parentBook->id);
+ Activity::addForEntity($chapter, ActivityType::CHAPTER_CREATE);
return $chapter;
}
public function update(Chapter $chapter, array $input): Chapter
{
$this->baseRepo->update($chapter, $input);
- Activity::add($chapter, ActivityType::CHAPTER_UPDATE, $chapter->book->id);
+ Activity::addForEntity($chapter, ActivityType::CHAPTER_UPDATE);
return $chapter;
}
{
$trashCan = new TrashCan();
$trashCan->softDestroyChapter($chapter);
- Activity::add($chapter, ActivityType::CHAPTER_DELETE, $chapter->book->id);
+ Activity::addForEntity($chapter, ActivityType::CHAPTER_DELETE);
$trashCan->autoClearOld();
}
$chapter->changeBook($parent->id);
$chapter->rebuildPermissions();
- Activity::add($chapter, ActivityType::CHAPTER_MOVE, $parent->id);
+ Activity::addForEntity($chapter, ActivityType::CHAPTER_MOVE);
return $parent;
}
$draft->indexForSearch();
$draft->refresh();
- Activity::add($draft, ActivityType::PAGE_CREATE, $draft->book->id);
+ Activity::addForEntity($draft, ActivityType::PAGE_CREATE);
return $draft;
}
$this->savePageRevision($page, $summary);
}
- Activity::add($page, ActivityType::PAGE_UPDATE, $page->book->id);
+ Activity::addForEntity($page, ActivityType::PAGE_UPDATE);
return $page;
}
{
$trashCan = new TrashCan();
$trashCan->softDestroyPage($page);
- Activity::add($page, ActivityType::PAGE_DELETE, $page->book_id);
+ Activity::addForEntity($page, ActivityType::PAGE_DELETE);
$trashCan->autoClearOld();
}
$page->save();
$page->indexForSearch();
- Activity::add($page, ActivityType::PAGE_RESTORE, $page->book->id);
+ Activity::addForEntity($page, ActivityType::PAGE_RESTORE);
return $page;
}
$page->changeBook($parent instanceof Book ? $parent->id : $parent->book->id);
$page->rebuildPermissions();
- Activity::add($page, ActivityType::PAGE_MOVE, $page->book->id);
+ Activity::addForEntity($page, ActivityType::PAGE_MOVE);
return $parent;
}
if ($bookshelf) {
$bookshelf->appendBook($book);
- Activity::add($bookshelf, ActivityType::BOOKSHELF_UPDATE);
+ Activity::addForEntity($bookshelf, ActivityType::BOOKSHELF_UPDATE);
}
return redirect($book->getUrl());
// Rebuild permissions and add activity for involved books.
$booksInvolved->each(function (Book $book) {
- Activity::add($book, ActivityType::BOOK_SORT, $book->id);
+ Activity::addForEntity($book, ActivityType::BOOK_SORT);
});
return redirect($book->getUrl());
{
$this->asEditor();
$page = Page::first();
- \Activity::add($page, ActivityType::PAGE_UPDATE, $page->book->id);
+ \Activity::addForEntity($page, ActivityType::PAGE_UPDATE);
$this->assertDatabaseHas('activities', [
'key' => 'page_update',
$newUser = $this->getNewBlankUser();
$this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
- Activity::add($entities['book'], ActivityType::BOOK_UPDATE, $entities['book']->id);
- Activity::add($entities['page'], ActivityType::PAGE_CREATE, $entities['book']->id);
+ Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE);
+ Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE);
$this->asAdmin()->visit('/user/' . $newUser->id)
->seeInElement('#recent-user-activity', 'updated book')
$newUser = $this->getNewBlankUser();
$this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
- Activity::add($entities['book'], ActivityType::BOOK_UPDATE, $entities['book']->id);
- Activity::add($entities['page'], ActivityType::PAGE_CREATE, $entities['book']->id);
+ Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE);
+ Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE);
$this->asAdmin()->visit('/')->clickInElement('#recent-activity', $newUser->name)
->seePageIs('/user/' . $newUser->id)