X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/295cd0160525125bbd7756d7ad07392ae7201cb8..06901b878f2c8057a6f9b7d2e0adfda425c68dee:/app/Entities/Controllers/ChapterApiController.php diff --git a/app/Entities/Controllers/ChapterApiController.php b/app/Entities/Controllers/ChapterApiController.php index 3f860ba64..85c81c248 100644 --- a/app/Entities/Controllers/ChapterApiController.php +++ b/app/Entities/Controllers/ChapterApiController.php @@ -5,35 +5,36 @@ namespace BookStack\Entities\Controllers; use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Repos\ChapterRepo; -use BookStack\Http\Controllers\ApiController; +use BookStack\Exceptions\PermissionsException; +use BookStack\Http\ApiController; +use Exception; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Http\Request; class ChapterApiController extends ApiController { - protected $chapterRepo; - protected $rules = [ 'create' => [ - 'book_id' => ['required', 'integer'], - 'name' => ['required', 'string', 'max:255'], - 'description' => ['string', 'max:1000'], - 'tags' => ['array'], + 'book_id' => ['required', 'integer'], + 'name' => ['required', 'string', 'max:255'], + 'description' => ['string', 'max:1900'], + 'description_html' => ['string', 'max:2000'], + 'tags' => ['array'], + 'priority' => ['integer'], ], 'update' => [ - 'book_id' => ['integer'], - 'name' => ['string', 'min:1', 'max:255'], - 'description' => ['string', 'max:1000'], - 'tags' => ['array'], + 'book_id' => ['integer'], + 'name' => ['string', 'min:1', 'max:255'], + 'description' => ['string', 'max:1900'], + 'description_html' => ['string', 'max:2000'], + 'tags' => ['array'], + 'priority' => ['integer'], ], ]; - /** - * ChapterController constructor. - */ - public function __construct(ChapterRepo $chapterRepo) - { - $this->chapterRepo = $chapterRepo; + public function __construct( + protected ChapterRepo $chapterRepo + ) { } /** @@ -54,15 +55,15 @@ class ChapterApiController extends ApiController */ public function create(Request $request) { - $this->validate($request, $this->rules['create']); + $requestData = $this->validate($request, $this->rules['create']); $bookId = $request->get('book_id'); $book = Book::visible()->findOrFail($bookId); $this->checkOwnablePermission('chapter-create', $book); - $chapter = $this->chapterRepo->create($request->all(), $book); + $chapter = $this->chapterRepo->create($requestData, $book); - return response()->json($chapter->load(['tags'])); + return response()->json($this->forJsonDisplay($chapter)); } /** @@ -70,24 +71,47 @@ class ChapterApiController extends ApiController */ public function read(string $id) { - $chapter = Chapter::visible()->with(['tags', 'createdBy', 'updatedBy', 'ownedBy', 'pages' => function (HasMany $query) { - $query->scopes('visible')->get(['id', 'name', 'slug']); - }])->findOrFail($id); + $chapter = Chapter::visible()->findOrFail($id); + $chapter = $this->forJsonDisplay($chapter); + + $chapter->load([ + 'createdBy', 'updatedBy', 'ownedBy', + 'pages' => function (HasMany $query) { + $query->scopes('visible')->get(['id', 'name', 'slug']); + } + ]); return response()->json($chapter); } /** * Update the details of a single chapter. + * Providing a 'book_id' property will essentially move the chapter + * into that parent element if you have permissions to do so. */ public function update(Request $request, string $id) { + $requestData = $this->validate($request, $this->rules()['update']); $chapter = Chapter::visible()->findOrFail($id); $this->checkOwnablePermission('chapter-update', $chapter); - $updatedChapter = $this->chapterRepo->update($chapter, $request->all()); + if ($request->has('book_id') && $chapter->book_id !== intval($requestData['book_id'])) { + $this->checkOwnablePermission('chapter-delete', $chapter); + + try { + $this->chapterRepo->move($chapter, "book:{$requestData['book_id']}"); + } catch (Exception $exception) { + if ($exception instanceof PermissionsException) { + $this->showPermissionError(); + } - return response()->json($updatedChapter->load(['tags'])); + return $this->jsonError(trans('errors.selected_book_not_found')); + } + } + + $updatedChapter = $this->chapterRepo->update($chapter, $requestData); + + return response()->json($this->forJsonDisplay($updatedChapter)); } /** @@ -103,4 +127,17 @@ class ChapterApiController extends ApiController return response('', 204); } + + protected function forJsonDisplay(Chapter $chapter): Chapter + { + $chapter = clone $chapter; + $chapter->unsetRelations()->refresh(); + + $chapter->load(['tags']); + $chapter->makeVisible('description_html'); + $chapter->setAttribute('description_html', $chapter->descriptionHtml()); + $chapter->setAttribute('book_slug', $chapter->book()->first()->slug); + + return $chapter; + } }