1 <?php namespace BookStack\Http\Controllers;
4 use BookStack\Services\ExportService;
5 use Illuminate\Http\Request;
6 use BookStack\Http\Requests;
7 use BookStack\Repos\BookRepo;
8 use BookStack\Repos\ChapterRepo;
9 use BookStack\Repos\PageRepo;
10 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
13 class PageController extends Controller
18 protected $chapterRepo;
19 protected $exportService;
22 * PageController constructor.
23 * @param PageRepo $pageRepo
24 * @param BookRepo $bookRepo
25 * @param ChapterRepo $chapterRepo
26 * @param ExportService $exportService
28 public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService)
30 $this->pageRepo = $pageRepo;
31 $this->bookRepo = $bookRepo;
32 $this->chapterRepo = $chapterRepo;
33 $this->exportService = $exportService;
34 parent::__construct();
38 * Show the form for creating a new page.
40 * @param bool $chapterSlug
42 * @internal param bool $pageSlug
44 public function create($bookSlug, $chapterSlug = false)
46 $book = $this->bookRepo->getBySlug($bookSlug);
47 $chapter = $chapterSlug ? $this->chapterRepo->getBySlug($chapterSlug, $book->id) : false;
48 $parent = $chapter ? $chapter : $book;
49 $this->checkOwnablePermission('page-create', $parent);
50 $this->setPageTitle('Create New Page');
51 return view('pages/create', ['book' => $book, 'chapter' => $chapter]);
55 * Store a newly created page in storage.
56 * @param Request $request
60 public function store(Request $request, $bookSlug)
62 $this->validate($request, [
63 'name' => 'required|string|max:255'
66 $input = $request->all();
67 $book = $this->bookRepo->getBySlug($bookSlug);
68 $chapterId = ($request->has('chapter') && $this->chapterRepo->idExists($request->get('chapter'))) ? $request->get('chapter') : null;
69 $parent = $chapterId !== null ? $this->chapterRepo->getById($chapterId) : $book;
70 $this->checkOwnablePermission('page-create', $parent);
71 $input['priority'] = $this->bookRepo->getNewPriority($book);
73 $page = $this->pageRepo->saveNew($input, $book, $chapterId);
75 Activity::add($page, 'page_create', $book->id);
76 return redirect($page->getUrl());
80 * Display the specified page.
81 * If the page is not found via the slug the
82 * revisions are searched for a match.
87 public function show($bookSlug, $pageSlug)
89 $book = $this->bookRepo->getBySlug($bookSlug);
92 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
93 } catch (NotFoundHttpException $e) {
94 $page = $this->pageRepo->findPageUsingOldSlug($pageSlug, $bookSlug);
95 if ($page === null) abort(404);
96 return redirect($page->getUrl());
99 $sidebarTree = $this->bookRepo->getChildren($book);
101 $this->setPageTitle($page->getShortName());
102 return view('pages/show', ['page' => $page, 'book' => $book, 'current' => $page, 'sidebarTree' => $sidebarTree]);
106 * Show the form for editing the specified page.
111 public function edit($bookSlug, $pageSlug)
113 $book = $this->bookRepo->getBySlug($bookSlug);
114 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
115 $this->checkOwnablePermission('page-update', $page);
116 $this->setPageTitle('Editing Page ' . $page->getShortName());
117 return view('pages/edit', ['page' => $page, 'book' => $book, 'current' => $page]);
121 * Update the specified page in storage.
122 * @param Request $request
127 public function update(Request $request, $bookSlug, $pageSlug)
129 $this->validate($request, [
130 'name' => 'required|string|max:255'
132 $book = $this->bookRepo->getBySlug($bookSlug);
133 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
134 $this->checkOwnablePermission('page-update', $page);
135 $this->pageRepo->updatePage($page, $book->id, $request->all());
136 Activity::add($page, 'page_update', $book->id);
137 return redirect($page->getUrl());
141 * Redirect from a special link url which
142 * uses the page id rather than the name.
144 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
146 public function redirectFromLink($pageId)
148 $page = $this->pageRepo->getById($pageId);
149 return redirect($page->getUrl());
153 * Show the deletion page for the specified page.
156 * @return \Illuminate\View\View
158 public function showDelete($bookSlug, $pageSlug)
160 $book = $this->bookRepo->getBySlug($bookSlug);
161 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
162 $this->checkOwnablePermission('page-delete', $page);
163 $this->setPageTitle('Delete Page ' . $page->getShortName());
164 return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]);
168 * Remove the specified page from storage.
173 * @internal param int $id
175 public function destroy($bookSlug, $pageSlug)
177 $book = $this->bookRepo->getBySlug($bookSlug);
178 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
179 $this->checkOwnablePermission('page-delete', $page);
180 Activity::addMessage('page_delete', $book->id, $page->name);
181 $this->pageRepo->destroy($page);
182 return redirect($book->getUrl());
186 * Shows the last revisions for this page.
189 * @return \Illuminate\View\View
191 public function showRevisions($bookSlug, $pageSlug)
193 $book = $this->bookRepo->getBySlug($bookSlug);
194 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
195 $this->setPageTitle('Revisions For ' . $page->getShortName());
196 return view('pages/revisions', ['page' => $page, 'book' => $book, 'current' => $page]);
200 * Shows a preview of a single revision
204 * @return \Illuminate\View\View
206 public function showRevision($bookSlug, $pageSlug, $revisionId)
208 $book = $this->bookRepo->getBySlug($bookSlug);
209 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
210 $revision = $this->pageRepo->getRevisionById($revisionId);
211 $page->fill($revision->toArray());
212 $this->setPageTitle('Page Revision For ' . $page->getShortName());
213 return view('pages/revision', ['page' => $page, 'book' => $book]);
217 * Restores a page using the content of the specified revision.
221 * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
223 public function restoreRevision($bookSlug, $pageSlug, $revisionId)
225 $book = $this->bookRepo->getBySlug($bookSlug);
226 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
227 $this->checkOwnablePermission('page-update', $page);
228 $page = $this->pageRepo->restoreRevision($page, $book, $revisionId);
229 Activity::add($page, 'page_restore', $book->id);
230 return redirect($page->getUrl());
234 * Exports a page to pdf format using barryvdh/laravel-dompdf wrapper.
235 * https://github.com/barryvdh/laravel-dompdf
238 * @return \Illuminate\Http\Response
240 public function exportPdf($bookSlug, $pageSlug)
242 $book = $this->bookRepo->getBySlug($bookSlug);
243 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
244 $pdfContent = $this->exportService->pageToPdf($page);
245 return response()->make($pdfContent, 200, [
246 'Content-Type' => 'application/octet-stream',
247 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.pdf'
252 * Export a page to a self-contained HTML file.
255 * @return \Illuminate\Http\Response
257 public function exportHtml($bookSlug, $pageSlug)
259 $book = $this->bookRepo->getBySlug($bookSlug);
260 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
261 $containedHtml = $this->exportService->pageToContainedHtml($page);
262 return response()->make($containedHtml, 200, [
263 'Content-Type' => 'application/octet-stream',
264 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html'
269 * Export a page to a simple plaintext .txt file.
272 * @return \Illuminate\Http\Response
274 public function exportPlainText($bookSlug, $pageSlug)
276 $book = $this->bookRepo->getBySlug($bookSlug);
277 $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
278 $containedHtml = $this->exportService->pageToPlainText($page);
279 return response()->make($containedHtml, 200, [
280 'Content-Type' => 'application/octet-stream',
281 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.txt'
286 * Show a listing of recently created pages
287 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
289 public function showRecentlyCreated()
291 $pages = $this->pageRepo->getRecentlyCreatedPaginated(20);
292 return view('pages/detailed-listing', [
293 'title' => 'Recently Created Pages',
299 * Show a listing of recently created pages
300 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
302 public function showRecentlyUpdated()
304 $pages = $this->pageRepo->getRecentlyUpdatedPaginated(20);
305 return view('pages/detailed-listing', [
306 'title' => 'Recently Updated Pages',