1 <?php namespace BookStack\Http\Controllers;
3 use BookStack\Actions\ActivityType;
4 use BookStack\Entities\Managers\PageContent;
5 use BookStack\Entities\Repos\PageRepo;
6 use BookStack\Exceptions\NotFoundException;
7 use BookStack\Facades\Activity;
8 use GatherContent\Htmldiff\Htmldiff;
10 class PageRevisionController extends Controller
16 * PageRevisionController constructor.
18 public function __construct(PageRepo $pageRepo)
20 $this->pageRepo = $pageRepo;
21 parent::__construct();
25 * Shows the last revisions for this page.
26 * @throws NotFoundException
28 public function index(string $bookSlug, string $pageSlug)
30 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
31 $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName'=>$page->getShortName()]));
32 return view('pages.revisions', [
39 * Shows a preview of a single revision.
40 * @throws NotFoundException
42 public function show(string $bookSlug, string $pageSlug, int $revisionId)
44 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
45 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
46 if ($revision === null) {
47 throw new NotFoundException();
50 $page->fill($revision->toArray());
51 // TODO - Refactor PageContent so we don't need to juggle this
52 $page->html = $revision->html;
53 $page->html = (new PageContent($page))->render();
55 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
56 return view('pages.revision', [
58 'book' => $page->book,
60 'revision' => $revision
65 * Shows the changes of a single revision.
66 * @throws NotFoundException
68 public function changes(string $bookSlug, string $pageSlug, int $revisionId)
70 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
71 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
72 if ($revision === null) {
73 throw new NotFoundException();
76 $prev = $revision->getPrevious();
77 $prevContent = $prev->html ?? '';
78 $diff = (new Htmldiff)->diff($prevContent, $revision->html);
80 $page->fill($revision->toArray());
81 // TODO - Refactor PageContent so we don't need to juggle this
82 $page->html = $revision->html;
83 $page->html = (new PageContent($page))->render();
84 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()]));
86 return view('pages.revision', [
88 'book' => $page->book,
90 'revision' => $revision
95 * Restores a page using the content of the specified revision.
96 * @throws NotFoundException
98 public function restore(string $bookSlug, string $pageSlug, int $revisionId)
100 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
101 $this->checkOwnablePermission('page-update', $page);
103 $page = $this->pageRepo->restoreRevision($page, $revisionId);
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'));