1 <?php namespace BookStack\Http\Controllers;
3 use BookStack\Entities\Managers\PageContent;
4 use BookStack\Entities\Repos\PageRepo;
5 use BookStack\Exceptions\NotFoundException;
6 use BookStack\Facades\Activity;
7 use GatherContent\Htmldiff\Htmldiff;
9 class PageRevisionController extends Controller
15 * PageRevisionController constructor.
17 public function __construct(PageRepo $pageRepo)
19 $this->pageRepo = $pageRepo;
20 parent::__construct();
24 * Shows the last revisions for this page.
25 * @throws NotFoundException
27 public function index(string $bookSlug, string $pageSlug)
29 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
30 $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName'=>$page->getShortName()]));
31 return view('pages.revisions', [
38 * Shows a preview of a single revision.
39 * @throws NotFoundException
41 public function show(string $bookSlug, string $pageSlug, int $revisionId)
43 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
44 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
45 if ($revision === null) {
46 throw new NotFoundException();
49 $page->fill($revision->toArray());
50 // TODO - Refactor PageContent so we don't need to juggle this
51 $page->html = $revision->html;
52 $page->html = (new PageContent($page))->render();
54 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
55 return view('pages.revision', [
57 'book' => $page->book,
59 'revision' => $revision
64 * Shows the changes of a single revision.
65 * @throws NotFoundException
67 public function changes(string $bookSlug, string $pageSlug, int $revisionId)
69 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
70 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
71 if ($revision === null) {
72 throw new NotFoundException();
75 $prev = $revision->getPrevious();
76 $prevContent = $prev->html ?? '';
77 $diff = (new Htmldiff)->diff($prevContent, $revision->html);
79 $page->fill($revision->toArray());
80 // TODO - Refactor PageContent so we don't need to juggle this
81 $page->html = $revision->html;
82 $page->html = (new PageContent($page))->render();
83 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
85 return view('pages.revision', [
87 'book' => $page->book,
89 'revision' => $revision
94 * Restores a page using the content of the specified revision.
95 * @throws NotFoundException
97 public function restore(string $bookSlug, string $pageSlug, int $revisionId)
99 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
100 $this->checkOwnablePermission('page-update', $page);
102 $page = $this->pageRepo->restoreRevision($page, $revisionId);
104 Activity::add($page, 'page_restore', $page->book->id);
105 return redirect($page->getUrl());
109 * Deletes a revision using the id of the specified revision.
110 * @throws NotFoundException
112 public function destroy(string $bookSlug, string $pageSlug, int $revId)
114 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
115 $this->checkOwnablePermission('page-delete', $page);
117 $revision = $page->revisions()->where('id', '=', $revId)->first();
118 if ($revision === null) {
119 throw new NotFoundException("Revision #{$revId} not found");
122 // Get the current revision for the page
123 $currentRevision = $page->getCurrentRevision();
125 // Check if its the latest revision, cannot delete latest revision.
126 if (intval($currentRevision->id) === intval($revId)) {
127 $this->showErrorNotification(trans('entities.revision_cannot_delete_latest'));
128 return redirect($page->getUrl('/revisions'));
132 $this->showSuccessNotification(trans('entities.revision_delete_success'));
133 return redirect($page->getUrl('/revisions'));