X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/a6633642232efd164d4708967ab59e498fbff896..refs/pull/3918/head:/app/Http/Controllers/PageController.php diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 7d8e54382..8b131c4f3 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -1,35 +1,43 @@ -pageRepo = $pageRepo; + $this->referenceFetcher = $referenceFetcher; } /** * Show the form for creating a new page. + * * @throws Throwable */ public function create(string $bookSlug, string $chapterSlug = null) @@ -40,22 +48,25 @@ class PageController extends Controller // Redirect to draft edit screen if signed in if ($this->isSignedIn()) { $draft = $this->pageRepo->getNewDraftPage($parent); + return redirect($draft->getUrl()); } // Otherwise show the edit view if they're a guest $this->setPageTitle(trans('entities.pages_new')); + return view('pages.guest-create', ['parent' => $parent]); } /** * Create a new page as a guest user. + * * @throws ValidationException */ public function createAsGuest(Request $request, string $bookSlug, string $chapterSlug = null) { $this->validate($request, [ - 'name' => 'required|string|max:255' + 'name' => ['required', 'string', 'max:255'], ]); $parent = $this->pageRepo->getParentFromSlugs($bookSlug, $chapterSlug); @@ -64,7 +75,6 @@ class PageController extends Controller $page = $this->pageRepo->getNewDraftPage($parent); $this->pageRepo->publishDraft($page, [ 'name' => $request->get('name'), - 'html' => '' ]); return redirect($page->getUrl('/edit')); @@ -72,35 +82,30 @@ class PageController extends Controller /** * Show form to continue editing a draft page. + * * @throws NotFoundException */ - public function editDraft(string $bookSlug, int $pageId) + public function editDraft(Request $request, string $bookSlug, int $pageId) { $draft = $this->pageRepo->getById($pageId); $this->checkOwnablePermission('page-create', $draft->getParent()); - $this->setPageTitle(trans('entities.pages_edit_draft')); - $draftsEnabled = $this->isSignedIn(); - $templates = $this->pageRepo->getTemplates(10); + $editorData = new PageEditorData($draft, $this->pageRepo, $request->query('editor', '')); + $this->setPageTitle(trans('entities.pages_edit_draft')); - return view('pages.edit', [ - 'page' => $draft, - 'book' => $draft->book, - 'isDraft' => true, - 'draftsEnabled' => $draftsEnabled, - 'templates' => $templates, - ]); + return view('pages.edit', $editorData->getViewData()); } /** * Store a new page by changing a draft into a page. + * * @throws NotFoundException * @throws ValidationException */ public function store(Request $request, string $bookSlug, int $pageId) { $this->validate($request, [ - 'name' => 'required|string|max:255' + 'name' => ['required', 'string', 'max:255'], ]); $draftPage = $this->pageRepo->getById($pageId); $this->checkOwnablePermission('page-create', $draftPage->getParent()); @@ -113,6 +118,7 @@ class PageController extends Controller /** * Display the specified page. * If the page is not found via the slug the revisions are searched for a match. + * * @throws NotFoundException */ public function show(string $bookSlug, string $pageSlug) @@ -142,81 +148,68 @@ class PageController extends Controller $page->load(['comments.createdBy']); } - Views::add($page); + $nextPreviousLocator = new NextPreviousContentLocator($page, $sidebarTree); + + View::incrementFor($page); $this->setPageTitle($page->getShortName()); + return view('pages.show', [ - 'page' => $page, - 'book' => $page->book, - 'current' => $page, - 'sidebarTree' => $sidebarTree, + 'page' => $page, + 'book' => $page->book, + 'current' => $page, + 'sidebarTree' => $sidebarTree, 'commentsEnabled' => $commentsEnabled, - 'pageNav' => $pageNav + 'pageNav' => $pageNav, + 'next' => $nextPreviousLocator->getNext(), + 'previous' => $nextPreviousLocator->getPrevious(), + 'referenceCount' => $this->referenceFetcher->getPageReferenceCountToEntity($page), ]); } /** * Get page from an ajax request. + * * @throws NotFoundException */ public function getPageAjax(int $pageId) { $page = $this->pageRepo->getById($pageId); $page->setHidden(array_diff($page->getHidden(), ['html', 'markdown'])); - $page->addHidden(['book']); + $page->makeHidden(['book']); + return response()->json($page); } /** * Show the form for editing the specified page. + * * @throws NotFoundException */ - public function edit(string $bookSlug, string $pageSlug) + public function edit(Request $request, string $bookSlug, string $pageSlug) { $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); - $page->isDraft = false; - $editActivity = new PageEditActivity($page); - - // Check for active editing - $warnings = []; - if ($editActivity->hasActiveEditing()) { - $warnings[] = $editActivity->activeEditingMessage(); + $editorData = new PageEditorData($page, $this->pageRepo, $request->query('editor', '')); + if ($editorData->getWarnings()) { + $this->showWarningNotification(implode("\n", $editorData->getWarnings())); } - // Check for a current draft version for this user - $userDraft = $this->pageRepo->getUserDraft($page); - if ($userDraft !== null) { - $page->forceFill($userDraft->only(['name', 'html', 'markdown'])); - $page->isDraft = true; - $warnings[] = $editActivity->getEditingActiveDraftMessage($userDraft); - } - - if (count($warnings) > 0) { - $this->showWarningNotification(implode("\n", $warnings)); - } - - $templates = $this->pageRepo->getTemplates(10); - $draftsEnabled = $this->isSignedIn(); $this->setPageTitle(trans('entities.pages_editing_named', ['pageName' => $page->getShortName()])); - return view('pages.edit', [ - 'page' => $page, - 'book' => $page->book, - 'current' => $page, - 'draftsEnabled' => $draftsEnabled, - 'templates' => $templates, - ]); + + return view('pages.edit', $editorData->getViewData()); } /** * Update the specified page in storage. + * * @throws ValidationException * @throws NotFoundException */ public function update(Request $request, string $bookSlug, string $pageSlug) { $this->validate($request, [ - 'name' => 'required|string|max:255' + 'name' => ['required', 'string', 'max:255'], ]); $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); @@ -228,6 +221,7 @@ class PageController extends Controller /** * Save a draft update as a revision. + * * @throws NotFoundException */ public function saveDraft(Request $request, int $pageId) @@ -240,62 +234,71 @@ class PageController extends Controller } $draft = $this->pageRepo->updatePageDraft($page, $request->only(['name', 'html', 'markdown'])); + $warnings = (new PageEditActivity($page))->getWarningMessagesForDraft($draft); - $updateTime = $draft->updated_at->timestamp; return response()->json([ 'status' => 'success', 'message' => trans('entities.pages_edit_draft_save_at'), - 'timestamp' => $updateTime + 'warning' => implode("\n", $warnings), + 'timestamp' => $draft->updated_at->timestamp, ]); } /** * Redirect from a special link url which uses the page id rather than the name. + * * @throws NotFoundException */ public function redirectFromLink(int $pageId) { $page = $this->pageRepo->getById($pageId); + return redirect($page->getUrl()); } /** * Show the deletion page for the specified page. + * * @throws NotFoundException */ public function showDelete(string $bookSlug, string $pageSlug) { $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-delete', $page); - $this->setPageTitle(trans('entities.pages_delete_named', ['pageName'=>$page->getShortName()])); + $this->setPageTitle(trans('entities.pages_delete_named', ['pageName' => $page->getShortName()])); + $times_used_as_template = Book::where('default_template', '=', $page->id)->count(); + return view('pages.delete', [ - 'book' => $page->book, - 'page' => $page, - 'current' => $page + 'book' => $page->book, + 'page' => $page, + 'current' => $page, + 'times_used_as_template' => $times_used_as_template, ]); } /** * Show the deletion page for the specified page. + * * @throws NotFoundException */ public function showDeleteDraft(string $bookSlug, int $pageId) { $page = $this->pageRepo->getById($pageId); $this->checkOwnablePermission('page-update', $page); - $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName'=>$page->getShortName()])); + $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()])); + return view('pages.delete', [ - 'book' => $page->book, - 'page' => $page, - 'current' => $page + 'book' => $page->book, + 'page' => $page, + 'current' => $page, ]); } /** * Remove the specified page from storage. + * * @throws NotFoundException * @throws Throwable - * @throws NotifyException */ public function destroy(string $bookSlug, string $pageSlug) { @@ -310,8 +313,8 @@ class PageController extends Controller /** * Remove the specified draft page from storage. + * * @throws NotFoundException - * @throws NotifyException * @throws Throwable */ public function destroyDraft(string $bookSlug, int $pageId) @@ -328,6 +331,7 @@ class PageController extends Controller if ($chapter && userCan('view', $chapter)) { return redirect($chapter->getUrl()); } + return redirect($book->getUrl()); } @@ -336,18 +340,28 @@ class PageController extends Controller */ public function showRecentlyUpdated() { - $pages = Page::visible()->orderBy('updated_at', 'desc') + $visibleBelongsScope = function (BelongsTo $query) { + $query->scopes('visible'); + }; + + $pages = Page::visible()->with(['updatedBy', 'book' => $visibleBelongsScope, 'chapter' => $visibleBelongsScope]) + ->orderBy('updated_at', 'desc') ->paginate(20) ->setPath(url('/pages/recently-updated')); - return view('pages.detailed-listing', [ - 'title' => trans('entities.recently_updated_pages'), - 'pages' => $pages + $this->setPageTitle(trans('entities.recently_updated_pages')); + + return view('common.detailed-listing-paginated', [ + 'title' => trans('entities.recently_updated_pages'), + 'entities' => $pages, + 'showUpdatedBy' => true, + 'showPath' => true, ]); } /** * Show the view to choose a new parent to move a page into. + * * @throws NotFoundException */ public function showMove(string $bookSlug, string $pageSlug) @@ -355,14 +369,16 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); $this->checkOwnablePermission('page-delete', $page); + return view('pages.move', [ 'book' => $page->book, - 'page' => $page + 'page' => $page, ]); } /** * Does the action of moving the location of a page. + * * @throws NotFoundException * @throws Throwable */ @@ -379,21 +395,22 @@ class PageController extends Controller try { $parent = $this->pageRepo->move($page, $entitySelection); + } catch (PermissionsException $exception) { + $this->showPermissionError(); } catch (Exception $exception) { - if ($exception instanceof PermissionsException) { - $this->showPermissionError(); - } - $this->showErrorNotification(trans('errors.selected_book_chapter_not_found')); + return redirect()->back(); } $this->showSuccessNotification(trans('entities.pages_move_success', ['parentName' => $parent->name])); + return redirect($page->getUrl()); } /** * Show the view to copy a page. + * * @throws NotFoundException */ public function showCopy(string $bookSlug, string $pageSlug) @@ -401,67 +418,39 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-view', $page); session()->flashInput(['name' => $page->name]); + return view('pages.copy', [ 'book' => $page->book, - 'page' => $page + 'page' => $page, ]); } - /** * Create a copy of a page within the requested target destination. + * * @throws NotFoundException * @throws Throwable */ - public function copy(Request $request, string $bookSlug, string $pageSlug) + public function copy(Request $request, Cloner $cloner, string $bookSlug, string $pageSlug) { $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); $this->checkOwnablePermission('page-view', $page); - $entitySelection = $request->get('entity_selection', null) ?? null; - $newName = $request->get('name', null); - - try { - $pageCopy = $this->pageRepo->copy($page, $entitySelection, $newName); - } catch (Exception $exception) { - if ($exception instanceof PermissionsException) { - $this->showPermissionError(); - } + $entitySelection = $request->get('entity_selection') ?: null; + $newParent = $entitySelection ? $this->pageRepo->findParentByIdentifier($entitySelection) : $page->getParent(); + if (is_null($newParent)) { $this->showErrorNotification(trans('errors.selected_book_chapter_not_found')); + return redirect()->back(); } - $this->showSuccessNotification(trans('entities.pages_copy_success')); - return redirect($pageCopy->getUrl()); - } + $this->checkOwnablePermission('page-create', $newParent); - /** - * Show the Permissions view. - * @throws NotFoundException - */ - public function showPermissions(string $bookSlug, string $pageSlug) - { - $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); - $this->checkOwnablePermission('restrictions-manage', $page); - return view('pages.permissions', [ - 'page' => $page, - ]); - } - - /** - * Set the permissions for this page. - * @throws NotFoundException - * @throws Throwable - */ - public function permissions(Request $request, PermissionsUpdater $permissionsUpdater, string $bookSlug, string $pageSlug) - { - $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); - $this->checkOwnablePermission('restrictions-manage', $page); - - $permissionsUpdater->updateFromPermissionsForm($page, $request); + $newName = $request->get('name') ?: $page->name; + $pageCopy = $cloner->clonePage($page, $newParent, $newName); + $this->showSuccessNotification(trans('entities.pages_copy_success')); - $this->showSuccessNotification(trans('entities.pages_permissions_success')); - return redirect($page->getUrl()); + return redirect($pageCopy->getUrl()); } }