]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/BookController.php
Started work on hierachy conversion actions
[bookstack] / app / Http / Controllers / BookController.php
1 <?php
2
3 namespace BookStack\Http\Controllers;
4
5 use BookStack\Actions\ActivityQueries;
6 use BookStack\Actions\ActivityType;
7 use BookStack\Actions\View;
8 use BookStack\Entities\Models\Bookshelf;
9 use BookStack\Entities\Repos\BookRepo;
10 use BookStack\Entities\Tools\BookContents;
11 use BookStack\Entities\Tools\Cloner;
12 use BookStack\Entities\Tools\PermissionsUpdater;
13 use BookStack\Entities\Tools\ShelfContext;
14 use BookStack\Exceptions\ImageUploadException;
15 use BookStack\Exceptions\NotFoundException;
16 use BookStack\Facades\Activity;
17 use Illuminate\Http\Request;
18 use Illuminate\Validation\ValidationException;
19 use Throwable;
20
21 class BookController extends Controller
22 {
23     protected $bookRepo;
24     protected $entityContextManager;
25
26     public function __construct(ShelfContext $entityContextManager, BookRepo $bookRepo)
27     {
28         $this->bookRepo = $bookRepo;
29         $this->entityContextManager = $entityContextManager;
30     }
31
32     /**
33      * Display a listing of the book.
34      */
35     public function index()
36     {
37         $view = setting()->getForCurrentUser('books_view_type');
38         $sort = setting()->getForCurrentUser('books_sort', 'name');
39         $order = setting()->getForCurrentUser('books_sort_order', 'asc');
40
41         $books = $this->bookRepo->getAllPaginated(18, $sort, $order);
42         $recents = $this->isSignedIn() ? $this->bookRepo->getRecentlyViewed(4) : false;
43         $popular = $this->bookRepo->getPopular(4);
44         $new = $this->bookRepo->getRecentlyCreated(4);
45
46         $this->entityContextManager->clearShelfContext();
47
48         $this->setPageTitle(trans('entities.books'));
49
50         return view('books.index', [
51             'books'   => $books,
52             'recents' => $recents,
53             'popular' => $popular,
54             'new'     => $new,
55             'view'    => $view,
56             'sort'    => $sort,
57             'order'   => $order,
58         ]);
59     }
60
61     /**
62      * Show the form for creating a new book.
63      */
64     public function create(string $shelfSlug = null)
65     {
66         $this->checkPermission('book-create-all');
67
68         $bookshelf = null;
69         if ($shelfSlug !== null) {
70             $bookshelf = Bookshelf::visible()->where('slug', '=', $shelfSlug)->firstOrFail();
71             $this->checkOwnablePermission('bookshelf-update', $bookshelf);
72         }
73
74         $this->setPageTitle(trans('entities.books_create'));
75
76         return view('books.create', [
77             'bookshelf' => $bookshelf,
78         ]);
79     }
80
81     /**
82      * Store a newly created book in storage.
83      *
84      * @throws ImageUploadException
85      * @throws ValidationException
86      */
87     public function store(Request $request, string $shelfSlug = null)
88     {
89         $this->checkPermission('book-create-all');
90         $this->validate($request, [
91             'name'        => ['required', 'string', 'max:255'],
92             'description' => ['string', 'max:1000'],
93             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
94         ]);
95
96         $bookshelf = null;
97         if ($shelfSlug !== null) {
98             $bookshelf = Bookshelf::visible()->where('slug', '=', $shelfSlug)->firstOrFail();
99             $this->checkOwnablePermission('bookshelf-update', $bookshelf);
100         }
101
102         $book = $this->bookRepo->create($request->all());
103
104         if ($bookshelf) {
105             $bookshelf->appendBook($book);
106             Activity::add(ActivityType::BOOKSHELF_UPDATE, $bookshelf);
107         }
108
109         return redirect($book->getUrl());
110     }
111
112     /**
113      * Display the specified book.
114      */
115     public function show(Request $request, ActivityQueries $activities, string $slug)
116     {
117         $book = $this->bookRepo->getBySlug($slug);
118         $bookChildren = (new BookContents($book))->getTree(true);
119         $bookParentShelves = $book->shelves()->scopes('visible')->get();
120
121         View::incrementFor($book);
122         if ($request->has('shelf')) {
123             $this->entityContextManager->setShelfContext(intval($request->get('shelf')));
124         }
125
126         $this->setPageTitle($book->getShortName());
127
128         return view('books.show', [
129             'book'              => $book,
130             'current'           => $book,
131             'bookChildren'      => $bookChildren,
132             'bookParentShelves' => $bookParentShelves,
133             'activity'          => $activities->entityActivity($book, 20, 1),
134         ]);
135     }
136
137     /**
138      * Show the form for editing the specified book.
139      */
140     public function edit(string $slug)
141     {
142         $book = $this->bookRepo->getBySlug($slug);
143         $this->checkOwnablePermission('book-update', $book);
144         $this->setPageTitle(trans('entities.books_edit_named', ['bookName'=>$book->getShortName()]));
145
146         return view('books.edit', ['book' => $book, 'current' => $book]);
147     }
148
149     /**
150      * Update the specified book in storage.
151      *
152      * @throws ImageUploadException
153      * @throws ValidationException
154      * @throws Throwable
155      */
156     public function update(Request $request, string $slug)
157     {
158         $book = $this->bookRepo->getBySlug($slug);
159         $this->checkOwnablePermission('book-update', $book);
160
161         $validated = $this->validate($request, [
162             'name'        => ['required', 'string', 'max:255'],
163             'description' => ['string', 'max:1000'],
164             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
165         ]);
166
167         if ($request->has('image_reset')) {
168             $validated['image'] = null;
169         } else if (is_null($validated['image'])) {
170             unset($validated['image']);
171         }
172
173         $book = $this->bookRepo->update($book, $validated);
174
175         return redirect($book->getUrl());
176     }
177
178     /**
179      * Shows the page to confirm deletion.
180      */
181     public function showDelete(string $bookSlug)
182     {
183         $book = $this->bookRepo->getBySlug($bookSlug);
184         $this->checkOwnablePermission('book-delete', $book);
185         $this->setPageTitle(trans('entities.books_delete_named', ['bookName' => $book->getShortName()]));
186
187         return view('books.delete', ['book' => $book, 'current' => $book]);
188     }
189
190     /**
191      * Remove the specified book from the system.
192      *
193      * @throws Throwable
194      */
195     public function destroy(string $bookSlug)
196     {
197         $book = $this->bookRepo->getBySlug($bookSlug);
198         $this->checkOwnablePermission('book-delete', $book);
199
200         $this->bookRepo->destroy($book);
201
202         return redirect('/books');
203     }
204
205     /**
206      * Show the permissions view.
207      */
208     public function showPermissions(string $bookSlug)
209     {
210         $book = $this->bookRepo->getBySlug($bookSlug);
211         $this->checkOwnablePermission('restrictions-manage', $book);
212
213         return view('books.permissions', [
214             'book' => $book,
215         ]);
216     }
217
218     /**
219      * Set the restrictions for this book.
220      *
221      * @throws Throwable
222      */
223     public function permissions(Request $request, PermissionsUpdater $permissionsUpdater, string $bookSlug)
224     {
225         $book = $this->bookRepo->getBySlug($bookSlug);
226         $this->checkOwnablePermission('restrictions-manage', $book);
227
228         $permissionsUpdater->updateFromPermissionsForm($book, $request);
229
230         $this->showSuccessNotification(trans('entities.books_permissions_updated'));
231
232         return redirect($book->getUrl());
233     }
234
235     /**
236      * Show the view to copy a book.
237      *
238      * @throws NotFoundException
239      */
240     public function showCopy(string $bookSlug)
241     {
242         $book = $this->bookRepo->getBySlug($bookSlug);
243         $this->checkOwnablePermission('book-view', $book);
244
245         session()->flashInput(['name' => $book->name]);
246
247         return view('books.copy', [
248             'book' => $book,
249         ]);
250     }
251
252     /**
253      * Create a copy of a book within the requested target destination.
254      *
255      * @throws NotFoundException
256      */
257     public function copy(Request $request, Cloner $cloner, string $bookSlug)
258     {
259         $book = $this->bookRepo->getBySlug($bookSlug);
260         $this->checkOwnablePermission('book-view', $book);
261         $this->checkPermission('book-create-all');
262
263         $newName = $request->get('name') ?: $book->name;
264         $bookCopy = $cloner->cloneBook($book, $newName);
265         $this->showSuccessNotification(trans('entities.books_copy_success'));
266
267         return redirect($bookCopy->getUrl());
268     }
269 }