1 <?php namespace BookStack\Http\Controllers;
4 use BookStack\Repos\UserRepo;
5 use BookStack\Services\ExportService;
6 use Illuminate\Http\Request;
7 use BookStack\Http\Requests;
8 use BookStack\Repos\BookRepo;
9 use BookStack\Repos\ChapterRepo;
10 use BookStack\Repos\PageRepo;
11 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14 class PageController extends Controller
19 protected $chapterRepo;
20 protected $exportService;
24 * PageController constructor.
25 * @param PageRepo $pageRepo
26 * @param BookRepo $bookRepo
27 * @param ChapterRepo $chapterRepo
28 * @param ExportService $exportService
29 * @param UserRepo $userRepo
31 public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService, UserRepo $userRepo)
33 $this->pageRepo = $pageRepo;
34 $this->bookRepo = $bookRepo;
35 $this->chapterRepo = $chapterRepo;
36 $this->exportService = $exportService;
37 $this->userRepo = $userRepo;
38 parent::__construct();
42 * Show the form for creating a new page.
44 * @param bool $chapterSlug
46 * @internal param bool $pageSlug
48 public function create($bookSlug, $chapterSlug = false)
50 $book = $this->bookRepo->getBySlug($bookSlug);
51 $chapter = $chapterSlug ? $this->chapterRepo->getBySlug($chapterSlug, $book->id) : false;
52 $parent = $chapter ? $chapter : $book;
53 $this->checkOwnablePermission('page-create', $parent);
54 $this->setPageTitle('Create New Page');
55 return view('pages/create', ['book' => $book, 'chapter' => $chapter]);
59 * Store a newly created page in storage.
60 * @param Request $request
64 public function store(Request $request, $bookSlug)
66 $this->validate($request, [
67 'name' => 'required|string|max:255'
70 $input = $request->all();
71 $book = $this->bookRepo->getBySlug($bookSlug);
72 $chapterId = ($request->has('chapter') && $this->chapterRepo->idExists($request->get('chapter'))) ? $request->get('chapter') : null;
73 $parent = $chapterId !== null ? $this->chapterRepo->getById($chapterId) : $book;
74 $this->checkOwnablePermission('page-create', $parent);
75 $input['priority'] = $this->bookRepo->getNewPriority($book);
77 $page = $this->pageRepo->saveNew($input, $book, $chapterId);
79 Activity::add($page, 'page_create', $book->id);
80 return redirect($page->getUrl());
84 * Display the specified page.
85 * If the page is not found via the slug the
86 * revisions are searched for a match.
91 public function show($bookSlug, $pageSlug)
93 $book = $this->bookRepo->getBySlug($bookSlug);
96 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
97 } catch (NotFoundHttpException $e) {
98 $page = $this->pageRepo->findPageUsingOldSlug($pageSlug, $bookSlug);
99 if ($page === null) abort(404);
100 return redirect($page->getUrl());
103 $sidebarTree = $this->bookRepo->getChildren($book);
105 $this->setPageTitle($page->getShortName());
106 return view('pages/show', ['page' => $page, 'book' => $book, 'current' => $page, 'sidebarTree' => $sidebarTree]);
110 * Show the form for editing the specified page.
115 public function edit($bookSlug, $pageSlug)
117 $book = $this->bookRepo->getBySlug($bookSlug);
118 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
119 $this->checkOwnablePermission('page-update', $page);
120 $this->setPageTitle('Editing Page ' . $page->getShortName());
121 return view('pages/edit', ['page' => $page, 'book' => $book, 'current' => $page]);
125 * Update the specified page in storage.
126 * @param Request $request
131 public function update(Request $request, $bookSlug, $pageSlug)
133 $this->validate($request, [
134 'name' => 'required|string|max:255'
136 $book = $this->bookRepo->getBySlug($bookSlug);
137 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
138 $this->checkOwnablePermission('page-update', $page);
139 $this->pageRepo->updatePage($page, $book->id, $request->all());
140 Activity::add($page, 'page_update', $book->id);
141 return redirect($page->getUrl());
145 * Redirect from a special link url which
146 * uses the page id rather than the name.
148 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
150 public function redirectFromLink($pageId)
152 $page = $this->pageRepo->getById($pageId);
153 return redirect($page->getUrl());
157 * Show the deletion page for the specified page.
160 * @return \Illuminate\View\View
162 public function showDelete($bookSlug, $pageSlug)
164 $book = $this->bookRepo->getBySlug($bookSlug);
165 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
166 $this->checkOwnablePermission('page-delete', $page);
167 $this->setPageTitle('Delete Page ' . $page->getShortName());
168 return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]);
172 * Remove the specified page from storage.
177 * @internal param int $id
179 public function destroy($bookSlug, $pageSlug)
181 $book = $this->bookRepo->getBySlug($bookSlug);
182 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
183 $this->checkOwnablePermission('page-delete', $page);
184 Activity::addMessage('page_delete', $book->id, $page->name);
185 $this->pageRepo->destroy($page);
186 return redirect($book->getUrl());
190 * Shows the last revisions for this page.
193 * @return \Illuminate\View\View
195 public function showRevisions($bookSlug, $pageSlug)
197 $book = $this->bookRepo->getBySlug($bookSlug);
198 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
199 $this->setPageTitle('Revisions For ' . $page->getShortName());
200 return view('pages/revisions', ['page' => $page, 'book' => $book, 'current' => $page]);
204 * Shows a preview of a single revision
208 * @return \Illuminate\View\View
210 public function showRevision($bookSlug, $pageSlug, $revisionId)
212 $book = $this->bookRepo->getBySlug($bookSlug);
213 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
214 $revision = $this->pageRepo->getRevisionById($revisionId);
215 $page->fill($revision->toArray());
216 $this->setPageTitle('Page Revision For ' . $page->getShortName());
217 return view('pages/revision', ['page' => $page, 'book' => $book]);
221 * Restores a page using the content of the specified revision.
225 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
227 public function restoreRevision($bookSlug, $pageSlug, $revisionId)
229 $book = $this->bookRepo->getBySlug($bookSlug);
230 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
231 $this->checkOwnablePermission('page-update', $page);
232 $page = $this->pageRepo->restoreRevision($page, $book, $revisionId);
233 Activity::add($page, 'page_restore', $book->id);
234 return redirect($page->getUrl());
238 * Exports a page to pdf format using barryvdh/laravel-dompdf wrapper.
239 * https://github.com/barryvdh/laravel-dompdf
242 * @return \Illuminate\Http\Response
244 public function exportPdf($bookSlug, $pageSlug)
246 $book = $this->bookRepo->getBySlug($bookSlug);
247 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
248 $pdfContent = $this->exportService->pageToPdf($page);
249 return response()->make($pdfContent, 200, [
250 'Content-Type' => 'application/octet-stream',
251 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.pdf'
256 * Export a page to a self-contained HTML file.
259 * @return \Illuminate\Http\Response
261 public function exportHtml($bookSlug, $pageSlug)
263 $book = $this->bookRepo->getBySlug($bookSlug);
264 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
265 $containedHtml = $this->exportService->pageToContainedHtml($page);
266 return response()->make($containedHtml, 200, [
267 'Content-Type' => 'application/octet-stream',
268 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html'
273 * Export a page to a simple plaintext .txt file.
276 * @return \Illuminate\Http\Response
278 public function exportPlainText($bookSlug, $pageSlug)
280 $book = $this->bookRepo->getBySlug($bookSlug);
281 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
282 $containedHtml = $this->exportService->pageToPlainText($page);
283 return response()->make($containedHtml, 200, [
284 'Content-Type' => 'application/octet-stream',
285 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.txt'
290 * Show a listing of recently created pages
291 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
293 public function showRecentlyCreated()
295 $pages = $this->pageRepo->getRecentlyCreatedPaginated(20);
296 return view('pages/detailed-listing', [
297 'title' => 'Recently Created Pages',
303 * Show a listing of recently created pages
304 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
306 public function showRecentlyUpdated()
308 $pages = $this->pageRepo->getRecentlyUpdatedPaginated(20);
309 return view('pages/detailed-listing', [
310 'title' => 'Recently Updated Pages',
316 * Show the Restrictions view.
319 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
321 public function showRestrict($bookSlug, $pageSlug)
323 $book = $this->bookRepo->getBySlug($bookSlug);
324 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
325 $this->checkOwnablePermission('restrictions-manage', $page);
326 $roles = $this->userRepo->getRestrictableRoles();
327 return view('pages/restrictions', [
334 * Set the restrictions for this page.
337 * @param Request $request
338 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
340 public function restrict($bookSlug, $pageSlug, Request $request)
342 $book = $this->bookRepo->getBySlug($bookSlug);
343 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
344 $this->checkOwnablePermission('restrictions-manage', $page);
345 $this->pageRepo->updateRestrictionsFromRequest($request, $page);
346 session()->flash('success', 'Page Restrictions Updated');
347 return redirect($page->getUrl());