BookStackApp / BookStack

A platform to create documentation/wiki content built with PHP & Laravel
https://www.bookstackapp.com/
MIT License
15.49k stars 1.95k forks source link

show-or-create for pages #5115

Closed cod3monk closed 4 months ago

cod3monk commented 4 months ago

This PR adds two new routes: /books/{bookSlug}/show-or-create?name={pageSlug} and /books/{bookSlug}/chapter/{chapterSlug}/show-or-create?name={pageSlug}

The concept is, that with these URL a user will either drop into the edit view of a new Page, or -if the page already exists- be redirected to the page itself.

This solves the feature request mentioned in #5099.

ssddanbrown commented 4 months ago

Thanks for offering this @cod3monk, but I'm really not keen on maintaining & supporting new endpoints that are built/intended for specific external business processes.

These kinds of additions would be a good use case of using the logical theme system to add your own endpoints as somewhat reflected here, which would allow you to add these custom endpoints to your own instance without altering core app code.

cod3monk commented 4 months ago

Would you be willing to include a ?createIfNotFound property in the show endpoints to redirect to an edit view on NotFoundException?

I am working on porting the endpoint to the logical theme system, which turns out to be rather tedious. Due to a lack of understanding of the Facades and thus how to port my original showOrCreate PageController. Documentation seems to be very sparse or too abstract on bookstack and laravel side.

ssddanbrown commented 4 months ago

Would you be willing to include a ?createIfNotFound property in the show endpoints to redirect to an edit view on NotFoundException?

No.

Here's my take on a port of your changes to a logical theme function.php file (tested on my dev instance which is pretty much matching the current release in terms of back-end logic):

functions.php

```php validate($request, [ 'name' => ['required', 'string', 'max:255'], ]); $pageName = $data['name']; try { // Redirect to the page if an existing page is found $page = $this->entityQueries->pages->findVisibleBySlugsOrFail($bookSlug, $pageName); return redirect($page->getUrl()); } catch (NotFoundException $e) { // Otherwise create a new page and start editing it if ($chapterSlug) { $parent = $this->entityQueries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); } else { $parent = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug); } $this->checkOwnablePermission('page-create', $parent); $page = $this->pageRepo->getNewDraftPage($parent); $this->pageRepo->publishDraft($page, [ 'name' => $pageName, ]); return redirect($page->getUrl('/edit')); } } } // Register the routes for our custom controller & action Theme::listen(ThemeEvents::ROUTES_REGISTER_WEB_AUTH, function (Router $router) { $router->get('/books/{bookSlug}/show-or-create', [CustomPageActionsController::class, 'showOrCreate']); $router->get('/books/{bookSlug}/chapter/{chapterSlug}/show-or-create', [CustomPageActionsController::class, 'showOrCreate']); }); ```

I've made changes to the method code but the general logic/routes/endpoints/request-data should be the same with the desired overall output.

cod3monk commented 4 months ago

Thanks! Code-wise I had almost the same, but it was missing some of the use imports, thus running into using Facade versions of the same objects and not catching the correct NotFoundException.