Got chapter conversion to books working

- Added required UI within edit view.
- Added required routes and controller actions.
This commit is contained in:
Dan Brown 2022-06-14 16:42:29 +01:00
parent 90ec40691a
commit 8da856bac3
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
7 changed files with 69 additions and 6 deletions

View File

@ -16,6 +16,7 @@ class ActivityType
const CHAPTER_MOVE = 'chapter_move';
const BOOK_CREATE = 'book_create';
const BOOK_CREATE_FROM_CHAPTER = 'book_create_from_chapter';
const BOOK_UPDATE = 'book_update';
const BOOK_DELETE = 'book_delete';
const BOOK_SORT = 'book_sort';

View File

@ -91,7 +91,7 @@ class BookRepo
{
$book = new Book();
$this->baseRepo->create($book, $input);
$this->baseRepo->updateCoverImage($book, $input['image']);
$this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
Activity::add(ActivityType::BOOK_CREATE, $book);
return $book;
@ -104,7 +104,7 @@ class BookRepo
{
$this->baseRepo->update($book, $input);
if (isset($input['image'])) {
if (array_key_exists('image', $input)) {
$this->baseRepo->updateCoverImage($book, $input['image'], $input['image'] === null);
}

View File

@ -2,12 +2,14 @@
namespace BookStack\Entities\Tools;
use BookStack\Actions\ActivityType;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Repos\BookshelfRepo;
use BookStack\Facades\Activity;
class HierarchyTransformer
{
@ -16,10 +18,20 @@ class HierarchyTransformer
protected Cloner $cloner;
protected TrashCan $trashCan;
public function __construct(BookRepo $bookRepo, BookshelfRepo $shelfRepo, Cloner $cloner, TrashCan $trashCan)
{
$this->bookRepo = $bookRepo;
$this->shelfRepo = $shelfRepo;
$this->cloner = $cloner;
$this->trashCan = $trashCan;
}
/**
* Transform a chapter into a book.
* Does not check permissions, check before calling.
*/
public function transformChapterToBook(Chapter $chapter): Book
{
// TODO - Check permissions before call
// Permissions: edit-chapter, delete-chapter, create-book
$inputData = $this->cloner->entityToInputData($chapter);
$book = $this->bookRepo->create($inputData);
$this->cloner->copyEntityPermissions($chapter, $book);
@ -32,7 +44,7 @@ class HierarchyTransformer
$this->trashCan->destroyEntity($chapter);
// TODO - Log activity for change
Activity::add(ActivityType::BOOK_CREATE_FROM_CHAPTER);
return $book;
}

View File

@ -7,6 +7,7 @@ use BookStack\Entities\Models\Book;
use BookStack\Entities\Repos\ChapterRepo;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Tools\Cloner;
use BookStack\Entities\Tools\HierarchyTransformer;
use BookStack\Entities\Tools\NextPreviousContentLocator;
use BookStack\Entities\Tools\PermissionsUpdater;
use BookStack\Exceptions\MoveOperationException;
@ -272,4 +273,20 @@ class ChapterController extends Controller
return redirect($chapter->getUrl());
}
/**
* Convert the chapter to a book.
*/
public function convertToBook(HierarchyTransformer $transformer, string $bookSlug, string $chapterSlug)
{
$chapter = $this->chapterRepo->getBySlug($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-update', $chapter);
$this->checkOwnablePermission('chapter-delete', $chapter);
$this->checkPermission('book-create-all');
$book = $transformer->transformChapterToBook($chapter);
return redirect($book->getUrl());
}
}

View File

@ -28,6 +28,8 @@ return [
// Books
'book_create' => 'created book',
'book_create_notification' => 'Book successfully created',
'book_create_from_chapter' => 'converted chapter to book',
'book_create_from_chapter_notification' => 'Chapter successfully converted to a book',
'book_update' => 'updated book',
'book_update_notification' => 'Book successfully updated',
'book_delete' => 'deleted book',

View File

@ -15,7 +15,7 @@
]])
</div>
<main class="content-wrap card">
<main class="content-wrap card auto-height">
<h1 class="list-heading">{{ trans('entities.chapters_edit') }}</h1>
<form action="{{ $chapter->getUrl() }}" method="POST">
<input type="hidden" name="_method" value="PUT">
@ -23,6 +23,36 @@
</form>
</main>
{{-- TODO - Permissions--}}
<div class="content-wrap card auto-height">
<h2 class="list-heading">Convert to Book</h2>
<div class="grid half left-focus no-row-gap">
<p>
You can convert this chapter to a new book with the same contents.
Any permissions set on this chapter will be copied to the new book but any inherited permissions,
from the parent book, will not be copied which could lead to a change of access control.
</p>
<div class="text-m-right">
<div component="dropdown" class="dropdown-container">
<button refs="dropdown@toggle" class="button outline" aria-haspopup="true" aria-expanded="false">Convert Chapter</button>
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
<li class="px-m py-s text-small text-muted">
Are you sure you want to convert this chapter?
<br>
This cannot be as easily undone.
</li>
<li>
<form action="{{ $chapter->getUrl('/convert-to-book') }}" method="POST">
{!! csrf_field() !!}
<button type="submit" class="text-primary text-item">{{ trans('common.confirm') }}</button>
</form>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
@stop

View File

@ -132,6 +132,7 @@ Route::middleware('auth')->group(function () {
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/copy', [ChapterController::class, 'showCopy']);
Route::post('/books/{bookSlug}/chapter/{chapterSlug}/copy', [ChapterController::class, 'copy']);
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/edit', [ChapterController::class, 'edit']);
Route::post('/books/{bookSlug}/chapter/{chapterSlug}/convert-to-book', [ChapterController::class, 'convertToBook']);
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [ChapterController::class, 'showPermissions']);
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ChapterExportController::class, 'pdf']);
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/html', [ChapterExportController::class, 'html']);