| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Entities\Controllers; | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  | use BookStack\Entities\Queries\EntityQueries; | 
					
						
							| 
									
										
										
										
											2024-02-06 01:35:49 +08:00
										 |  |  | use BookStack\Entities\Queries\PageQueries; | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  | use BookStack\Entities\Repos\PageRepo; | 
					
						
							|  |  |  | use BookStack\Exceptions\PermissionsException; | 
					
						
							| 
									
										
										
										
											2023-05-19 03:53:39 +08:00
										 |  |  | use BookStack\Http\ApiController; | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  | use Exception; | 
					
						
							|  |  |  | use Illuminate\Http\Request; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class PageApiController extends ApiController | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     protected $rules = [ | 
					
						
							|  |  |  |         'create' => [ | 
					
						
							| 
									
										
										
										
											2021-11-05 08:26:55 +08:00
										 |  |  |             'book_id'    => ['required_without:chapter_id', 'integer'], | 
					
						
							|  |  |  |             'chapter_id' => ['required_without:book_id', 'integer'], | 
					
						
							|  |  |  |             'name'       => ['required', 'string', 'max:255'], | 
					
						
							|  |  |  |             'html'       => ['required_without:markdown', 'string'], | 
					
						
							|  |  |  |             'markdown'   => ['required_without:html', 'string'], | 
					
						
							|  |  |  |             'tags'       => ['array'], | 
					
						
							| 
									
										
										
										
											2023-06-12 21:12:46 +08:00
										 |  |  |             'priority'   => ['integer'], | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         ], | 
					
						
							|  |  |  |         'update' => [ | 
					
						
							| 
									
										
										
										
											2022-04-05 00:24:05 +08:00
										 |  |  |             'book_id'    => ['integer'], | 
					
						
							|  |  |  |             'chapter_id' => ['integer'], | 
					
						
							| 
									
										
										
										
											2021-11-05 08:26:55 +08:00
										 |  |  |             'name'       => ['string', 'min:1', 'max:255'], | 
					
						
							|  |  |  |             'html'       => ['string'], | 
					
						
							|  |  |  |             'markdown'   => ['string'], | 
					
						
							|  |  |  |             'tags'       => ['array'], | 
					
						
							| 
									
										
										
										
											2023-06-12 21:12:46 +08:00
										 |  |  |             'priority'   => ['integer'], | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         ], | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 00:07:46 +08:00
										 |  |  |     public function __construct( | 
					
						
							| 
									
										
										
										
											2024-02-06 01:35:49 +08:00
										 |  |  |         protected PageRepo $pageRepo, | 
					
						
							|  |  |  |         protected PageQueries $queries, | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  |         protected EntityQueries $entityQueries, | 
					
						
							| 
									
										
										
										
											2023-06-21 00:07:46 +08:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a listing of pages visible to the user. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function list() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-02-11 23:42:37 +08:00
										 |  |  |         $pages = $this->queries->visibleForList() | 
					
						
							|  |  |  |             ->addSelect(['created_by', 'updated_by', 'revision_count', 'editor']); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         return $this->apiListingResponse($pages, [ | 
					
						
							|  |  |  |             'id', 'book_id', 'chapter_id', 'name', 'slug', 'priority', | 
					
						
							|  |  |  |             'draft', 'template', | 
					
						
							| 
									
										
										
										
											2021-01-04 06:29:58 +08:00
										 |  |  |             'created_at', 'updated_at', | 
					
						
							|  |  |  |             'created_by', 'updated_by', 'owned_by', | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a new page in the system. | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * The ID of a parent book or chapter is required to indicate | 
					
						
							|  |  |  |      * where this page should be located. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Any HTML content provided should be kept to a single-block depth of plain HTML | 
					
						
							|  |  |  |      * elements to remain compatible with the BookStack front-end and editors. | 
					
						
							| 
									
										
										
										
											2021-06-03 04:34:34 +08:00
										 |  |  |      * Any images included via base64 data URIs will be extracted and saved as gallery | 
					
						
							|  |  |  |      * images against the page during upload. | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function create(Request $request) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->validate($request, $this->rules['create']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($request->has('chapter_id')) { | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  |             $parent = $this->entityQueries->chapters->findVisibleByIdOrFail(intval($request->get('chapter_id'))); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  |             $parent = $this->entityQueries->books->findVisibleByIdOrFail(intval($request->get('book_id'))); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         $this->checkOwnablePermission('page-create', $parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $draft = $this->pageRepo->getNewDraftPage($parent); | 
					
						
							|  |  |  |         $this->pageRepo->publishDraft($draft, $request->only(array_keys($this->rules['create']))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |         return response()->json($draft->forJsonDisplay()); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * View the details of a single page. | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |      * Pages will always have HTML content. They may have markdown content | 
					
						
							|  |  |  |      * if the markdown editor was used to last update the page. | 
					
						
							| 
									
										
										
										
											2022-08-11 17:49:45 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 00:15:32 +08:00
										 |  |  |      * The 'html' property is the fully rendered & escaped HTML content that BookStack | 
					
						
							|  |  |  |      * would show on page view, with page includes handled. | 
					
						
							|  |  |  |      * The 'raw_html' property is the direct database stored HTML content, which would be | 
					
						
							|  |  |  |      * what BookStack shows on page edit. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-08-11 17:49:45 +08:00
										 |  |  |      * See the "Content Security" section of these docs for security considerations when using | 
					
						
							|  |  |  |      * the page content returned from this endpoint. | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function read(string $id) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-02-06 01:35:49 +08:00
										 |  |  |         $page = $this->queries->findVisibleByIdOrFail($id); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |         return response()->json($page->forJsonDisplay()); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Update the details of a single page. | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * See the 'create' action for details on the provided HTML/Markdown. | 
					
						
							|  |  |  |      * Providing a 'book_id' or 'chapter_id' property will essentially move | 
					
						
							|  |  |  |      * the page into that parent element if you have permissions to do so. | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function update(Request $request, string $id) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-04-05 00:24:05 +08:00
										 |  |  |         $requestData = $this->validate($request, $this->rules['update']); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 01:35:49 +08:00
										 |  |  |         $page = $this->queries->findVisibleByIdOrFail($id); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         $this->checkOwnablePermission('page-update', $page); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $parent = null; | 
					
						
							|  |  |  |         if ($request->has('chapter_id')) { | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  |             $parent = $this->entityQueries->chapters->findVisibleByIdOrFail(intval($request->get('chapter_id'))); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |         } elseif ($request->has('book_id')) { | 
					
						
							| 
									
										
										
										
											2024-02-08 00:37:36 +08:00
										 |  |  |             $parent = $this->entityQueries->books->findVisibleByIdOrFail(intval($request->get('book_id'))); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($parent && !$parent->matches($page->getParent())) { | 
					
						
							|  |  |  |             $this->checkOwnablePermission('page-delete', $page); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |             try { | 
					
						
							|  |  |  |                 $this->pageRepo->move($page, $parent->getType() . ':' . $parent->id); | 
					
						
							|  |  |  |             } catch (Exception $exception) { | 
					
						
							|  |  |  |                 if ($exception instanceof  PermissionsException) { | 
					
						
							|  |  |  |                     $this->showPermissionError(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return $this->jsonError(trans('errors.selected_book_chapter_not_found')); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-05 00:24:05 +08:00
										 |  |  |         $updatedPage = $this->pageRepo->update($page, $requestData); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |         return response()->json($updatedPage->forJsonDisplay()); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2020-11-28 23:21:54 +08:00
										 |  |  |      * Delete a page. | 
					
						
							|  |  |  |      * This will typically send the page to the recycle bin. | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function delete(string $id) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-02-06 01:35:49 +08:00
										 |  |  |         $page = $this->queries->findVisibleByIdOrFail($id); | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         $this->checkOwnablePermission('page-delete', $page); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->pageRepo->destroy($page); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 22:56:19 +08:00
										 |  |  |         return response('', 204); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |