mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-08-29 21:52:35 +00:00
![Dan Brown](/assets/img/avatar_default.png)
Added additional exceptions to prevent such cases in the future, so that they are caught in dev ideally. Added test case specifically for reported favourite scenario.
175 lines
5.0 KiB
PHP
175 lines
5.0 KiB
PHP
<?php
|
|
|
|
namespace BookStack\Entities\Repos;
|
|
|
|
use BookStack\Actions\ActivityType;
|
|
use BookStack\Entities\Models\Book;
|
|
use BookStack\Entities\Models\Bookshelf;
|
|
use BookStack\Entities\Tools\TrashCan;
|
|
use BookStack\Exceptions\NotFoundException;
|
|
use BookStack\Facades\Activity;
|
|
use Exception;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class BookshelfRepo
|
|
{
|
|
protected $baseRepo;
|
|
|
|
/**
|
|
* BookshelfRepo constructor.
|
|
*/
|
|
public function __construct(BaseRepo $baseRepo)
|
|
{
|
|
$this->baseRepo = $baseRepo;
|
|
}
|
|
|
|
/**
|
|
* Get all bookshelves in a paginated format.
|
|
*/
|
|
public function getAllPaginated(int $count = 20, string $sort = 'name', string $order = 'asc'): LengthAwarePaginator
|
|
{
|
|
return Bookshelf::visible()
|
|
->with(['visibleBooks', 'cover'])
|
|
->orderBy($sort, $order)
|
|
->paginate($count);
|
|
}
|
|
|
|
/**
|
|
* Get the bookshelves that were most recently viewed by this user.
|
|
*/
|
|
public function getRecentlyViewed(int $count = 20): Collection
|
|
{
|
|
return Bookshelf::visible()->withLastView()
|
|
->having('last_viewed_at', '>', 0)
|
|
->orderBy('last_viewed_at', 'desc')
|
|
->take($count)->get();
|
|
}
|
|
|
|
/**
|
|
* Get the most popular bookshelves in the system.
|
|
*/
|
|
public function getPopular(int $count = 20): Collection
|
|
{
|
|
return Bookshelf::visible()->withViewCount()
|
|
->having('view_count', '>', 0)
|
|
->orderBy('view_count', 'desc')
|
|
->take($count)->get();
|
|
}
|
|
|
|
/**
|
|
* Get the most recently created bookshelves from the system.
|
|
*/
|
|
public function getRecentlyCreated(int $count = 20): Collection
|
|
{
|
|
return Bookshelf::visible()->orderBy('created_at', 'desc')
|
|
->take($count)->get();
|
|
}
|
|
|
|
/**
|
|
* Get a shelf by its slug.
|
|
*/
|
|
public function getBySlug(string $slug): Bookshelf
|
|
{
|
|
$shelf = Bookshelf::visible()->where('slug', '=', $slug)->first();
|
|
|
|
if ($shelf === null) {
|
|
throw new NotFoundException(trans('errors.bookshelf_not_found'));
|
|
}
|
|
|
|
return $shelf;
|
|
}
|
|
|
|
/**
|
|
* Create a new shelf in the system.
|
|
*/
|
|
public function create(array $input, array $bookIds): Bookshelf
|
|
{
|
|
$shelf = new Bookshelf();
|
|
$this->baseRepo->create($shelf, $input);
|
|
$this->baseRepo->updateCoverImage($shelf, $input['image'] ?? null);
|
|
$this->updateBooks($shelf, $bookIds);
|
|
Activity::add(ActivityType::BOOKSHELF_CREATE, $shelf);
|
|
|
|
return $shelf;
|
|
}
|
|
|
|
/**
|
|
* Update an existing shelf in the system using the given input.
|
|
*/
|
|
public function update(Bookshelf $shelf, array $input, ?array $bookIds): Bookshelf
|
|
{
|
|
$this->baseRepo->update($shelf, $input);
|
|
|
|
if (!is_null($bookIds)) {
|
|
$this->updateBooks($shelf, $bookIds);
|
|
}
|
|
|
|
if (array_key_exists('image', $input)) {
|
|
$this->baseRepo->updateCoverImage($shelf, $input['image'], $input['image'] === null);
|
|
}
|
|
|
|
Activity::add(ActivityType::BOOKSHELF_UPDATE, $shelf);
|
|
|
|
return $shelf;
|
|
}
|
|
|
|
/**
|
|
* Update which books are assigned to this shelf by syncing the given book ids.
|
|
* Function ensures the books are visible to the current user and existing.
|
|
*/
|
|
protected function updateBooks(Bookshelf $shelf, array $bookIds)
|
|
{
|
|
$numericIDs = collect($bookIds)->map(function ($id) {
|
|
return intval($id);
|
|
});
|
|
|
|
$syncData = Book::visible()
|
|
->whereIn('id', $bookIds)
|
|
->pluck('id')
|
|
->mapWithKeys(function ($bookId) use ($numericIDs) {
|
|
return [$bookId => ['order' => $numericIDs->search($bookId)]];
|
|
});
|
|
|
|
$shelf->books()->sync($syncData);
|
|
}
|
|
|
|
/**
|
|
* Copy down the permissions of the given shelf to all child books.
|
|
*/
|
|
public function copyDownPermissions(Bookshelf $shelf, $checkUserPermissions = true): int
|
|
{
|
|
$shelfPermissions = $shelf->permissions()->get(['role_id', 'action'])->toArray();
|
|
$shelfBooks = $shelf->books()->get(['id', 'restricted', 'owned_by']);
|
|
$updatedBookCount = 0;
|
|
|
|
/** @var Book $book */
|
|
foreach ($shelfBooks as $book) {
|
|
if ($checkUserPermissions && !userCan('restrictions-manage', $book)) {
|
|
continue;
|
|
}
|
|
$book->permissions()->delete();
|
|
$book->restricted = $shelf->restricted;
|
|
$book->permissions()->createMany($shelfPermissions);
|
|
$book->save();
|
|
$book->rebuildPermissions();
|
|
$updatedBookCount++;
|
|
}
|
|
|
|
return $updatedBookCount;
|
|
}
|
|
|
|
/**
|
|
* Remove a bookshelf from the system.
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
public function destroy(Bookshelf $shelf)
|
|
{
|
|
$trashCan = new TrashCan();
|
|
$trashCan->softDestroyShelf($shelf);
|
|
Activity::add(ActivityType::BOOKSHELF_DELETE, $shelf);
|
|
$trashCan->autoClearOld();
|
|
}
|
|
}
|