3 namespace BookStack\Entities\Controllers;
5 use BookStack\Activity\ActivityQueries;
6 use BookStack\Activity\Models\View;
7 use BookStack\Entities\Queries\BookQueries;
8 use BookStack\Entities\Queries\BookshelfQueries;
9 use BookStack\Entities\Repos\BookshelfRepo;
10 use BookStack\Entities\Tools\ShelfContext;
11 use BookStack\Exceptions\ImageUploadException;
12 use BookStack\Exceptions\NotFoundException;
13 use BookStack\Http\Controller;
14 use BookStack\Permissions\Permission;
15 use BookStack\References\ReferenceFetcher;
16 use BookStack\Util\SimpleListOptions;
18 use Illuminate\Http\Request;
19 use Illuminate\Validation\ValidationException;
21 class BookshelfController extends Controller
23 public function __construct(
24 protected BookshelfRepo $shelfRepo,
25 protected BookshelfQueries $queries,
26 protected BookQueries $bookQueries,
27 protected ShelfContext $shelfContext,
28 protected ReferenceFetcher $referenceFetcher,
33 * Display a listing of bookshelves.
35 public function index(Request $request)
37 $view = setting()->getForCurrentUser('bookshelves_view_type');
38 $listOptions = SimpleListOptions::fromRequest($request, 'bookshelves')->withSortOptions([
39 'name' => trans('common.sort_name'),
40 'created_at' => trans('common.sort_created_at'),
41 'updated_at' => trans('common.sort_updated_at'),
44 $shelves = $this->queries->visibleForListWithCover()
45 ->orderBy($listOptions->getSort(), $listOptions->getOrder())
47 $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->get() : false;
48 $popular = $this->queries->popularForList()->get();
49 $new = $this->queries->visibleForList()
50 ->orderBy('created_at', 'desc')
54 $this->shelfContext->clearShelfContext();
55 $this->setPageTitle(trans('entities.shelves'));
57 return view('shelves.index', [
58 'shelves' => $shelves,
59 'recents' => $recents,
60 'popular' => $popular,
63 'listOptions' => $listOptions,
68 * Show the form for creating a new bookshelf.
70 public function create()
72 $this->checkPermission(Permission::BookshelfCreateAll);
73 $books = $this->bookQueries->visibleForList()->orderBy('name')->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
74 $this->setPageTitle(trans('entities.shelves_create'));
76 return view('shelves.create', ['books' => $books]);
80 * Store a newly created bookshelf in storage.
82 * @throws ValidationException
83 * @throws ImageUploadException
85 public function store(Request $request)
87 $this->checkPermission(Permission::BookshelfCreateAll);
88 $validated = $this->validate($request, [
89 'name' => ['required', 'string', 'max:255'],
90 'description_html' => ['string', 'max:2000'],
91 'image' => array_merge(['nullable'], $this->getImageValidationRules()),
95 $bookIds = explode(',', $request->get('books', ''));
96 $shelf = $this->shelfRepo->create($validated, $bookIds);
98 return redirect($shelf->getUrl());
102 * Display the bookshelf of the given slug.
104 * @throws NotFoundException
106 public function show(Request $request, ActivityQueries $activities, string $slug)
108 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
109 $this->checkOwnablePermission(Permission::BookshelfView, $shelf);
111 $listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([
112 'default' => trans('common.sort_default'),
113 'name' => trans('common.sort_name'),
114 'created_at' => trans('common.sort_created_at'),
115 'updated_at' => trans('common.sort_updated_at'),
118 $sort = $listOptions->getSort();
120 $sortedVisibleShelfBooks = $shelf->visibleBooks()
121 ->reorder($sort === 'default' ? 'order' : $sort, $listOptions->getOrder())
126 View::incrementFor($shelf);
127 $this->shelfContext->setShelfContext($shelf->id);
128 $view = setting()->getForCurrentUser('bookshelf_view_type');
130 $this->setPageTitle($shelf->getShortName());
132 return view('shelves.show', [
134 'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
136 'activity' => $activities->entityActivity($shelf, 20, 1),
137 'listOptions' => $listOptions,
138 'referenceCount' => $this->referenceFetcher->getReferenceCountToEntity($shelf),
143 * Show the form for editing the specified bookshelf.
145 public function edit(string $slug)
147 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
148 $this->checkOwnablePermission(Permission::BookshelfUpdate, $shelf);
150 $shelfBookIds = $shelf->books()->get(['id'])->pluck('id');
151 $books = $this->bookQueries->visibleForList()
152 ->whereNotIn('id', $shelfBookIds)
154 ->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
156 $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $shelf->getShortName()]));
158 return view('shelves.edit', [
165 * Update the specified bookshelf in storage.
167 * @throws ValidationException
168 * @throws ImageUploadException
169 * @throws NotFoundException
171 public function update(Request $request, string $slug)
173 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
174 $this->checkOwnablePermission(Permission::BookshelfUpdate, $shelf);
175 $validated = $this->validate($request, [
176 'name' => ['required', 'string', 'max:255'],
177 'description_html' => ['string', 'max:2000'],
178 'image' => array_merge(['nullable'], $this->getImageValidationRules()),
182 if ($request->has('image_reset')) {
183 $validated['image'] = null;
184 } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
185 unset($validated['image']);
188 $bookIds = explode(',', $request->get('books', ''));
189 $shelf = $this->shelfRepo->update($shelf, $validated, $bookIds);
191 return redirect($shelf->getUrl());
195 * Shows the page to confirm deletion.
197 public function showDelete(string $slug)
199 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
200 $this->checkOwnablePermission(Permission::BookshelfDelete, $shelf);
202 $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()]));
204 return view('shelves.delete', ['shelf' => $shelf]);
208 * Remove the specified bookshelf from storage.
212 public function destroy(string $slug)
214 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
215 $this->checkOwnablePermission(Permission::BookshelfDelete, $shelf);
217 $this->shelfRepo->destroy($shelf);
219 return redirect('/shelves');