| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | namespace BookStack\Uploads\Controllers; | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use BookStack\Exceptions\ImageUploadException; | 
					
						
							| 
									
										
										
										
											2021-05-09 01:49:58 +08:00
										 |  |  | use BookStack\Exceptions\NotFoundException; | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  | use BookStack\Exceptions\NotifyException; | 
					
						
							| 
									
										
										
										
											2023-05-19 03:53:39 +08:00
										 |  |  | use BookStack\Http\Controller; | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  | use BookStack\Uploads\Image; | 
					
						
							|  |  |  | use BookStack\Uploads\ImageRepo; | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  | use BookStack\Uploads\ImageResizer; | 
					
						
							| 
									
										
										
										
											2021-11-01 07:53:17 +08:00
										 |  |  | use BookStack\Uploads\ImageService; | 
					
						
							| 
									
										
										
										
											2023-09-29 20:54:08 +08:00
										 |  |  | use BookStack\Util\OutOfMemoryHandler; | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  | use Exception; | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  | use Illuminate\Http\Request; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ImageController extends Controller | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-05-29 00:32:22 +08:00
										 |  |  |     public function __construct( | 
					
						
							|  |  |  |         protected ImageRepo $imageRepo, | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |         protected ImageService $imageService, | 
					
						
							|  |  |  |         protected ImageResizer $imageResizer, | 
					
						
							| 
									
										
										
										
											2023-05-29 00:32:22 +08:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Provide an image file from storage. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-05-09 01:49:58 +08:00
										 |  |  |      * @throws NotFoundException | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function showImage(string $path) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-09-01 23:17:14 +08:00
										 |  |  |         if (!$this->imageService->pathAccessibleInLocalSecure($path)) { | 
					
						
							| 
									
										
										
										
											2021-05-09 01:49:58 +08:00
										 |  |  |             throw (new NotFoundException(trans('errors.image_not_found'))) | 
					
						
							|  |  |  |                 ->setSubtitle(trans('errors.image_not_found_subtitle')) | 
					
						
							|  |  |  |                 ->setDetails(trans('errors.image_not_found_details')); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-01 07:53:17 +08:00
										 |  |  |         return $this->imageService->streamImageFromStorageResponse('gallery', $path); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * Update image details. | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |     public function update(Request $request, string $id) | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-09-29 18:45:31 +08:00
										 |  |  |         $data = $this->validate($request, [ | 
					
						
							| 
									
										
										
										
											2021-11-05 08:26:55 +08:00
										 |  |  |             'name' => ['required', 'min:2', 'string'], | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $image = $this->imageRepo->getById($id); | 
					
						
							|  |  |  |         $this->checkImagePermission($image); | 
					
						
							|  |  |  |         $this->checkOwnablePermission('image-update', $image); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 18:45:31 +08:00
										 |  |  |         $image = $this->imageRepo->updateImageDetails($image, $data); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-22 20:15:58 +08:00
										 |  |  |         return view('pages.parts.image-manager-form', [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'image'          => $image, | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |             'dependantPages' => null, | 
					
						
							|  |  |  |         ]); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-29 00:32:22 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Update the file for an existing image. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function updateFile(Request $request, string $id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->validate($request, [ | 
					
						
							|  |  |  |             'file' => ['required', 'file', ...$this->getImageValidationRules()], | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $image = $this->imageRepo->getById($id); | 
					
						
							|  |  |  |         $this->checkImagePermission($image); | 
					
						
							|  |  |  |         $this->checkOwnablePermission('image-update', $image); | 
					
						
							|  |  |  |         $file = $request->file('file'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 01:28:42 +08:00
										 |  |  |         new OutOfMemoryHandler(function () { | 
					
						
							|  |  |  |             return $this->jsonError(trans('errors.image_upload_memory_limit')); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-29 00:32:22 +08:00
										 |  |  |         try { | 
					
						
							|  |  |  |             $this->imageRepo->updateImageFile($image, $file); | 
					
						
							|  |  |  |         } catch (ImageUploadException $exception) { | 
					
						
							|  |  |  |             return $this->jsonError($exception->getMessage()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return response(''); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |      * Get the form for editing the given image. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |      * @throws Exception | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |     public function edit(Request $request, string $id) | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $image = $this->imageRepo->getById($id); | 
					
						
							|  |  |  |         $this->checkImagePermission($image); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |         if ($request->has('delete')) { | 
					
						
							|  |  |  |             $dependantPages = $this->imageRepo->getPagesUsingImage($image); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |         $viewData = [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'image'          => $image, | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |             'dependantPages' => $dependantPages ?? null, | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |             'warning'        => '', | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new OutOfMemoryHandler(function () use ($viewData) { | 
					
						
							|  |  |  |             $viewData['warning'] = trans('errors.image_thumbnail_memory_limit'); | 
					
						
							|  |  |  |             return response()->view('pages.parts.image-manager-form', $viewData); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->imageResizer->loadGalleryThumbnailsForImage($image, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return view('pages.parts.image-manager-form', $viewData); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * Deletes an image and all thumbnail/image files. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |      * @throws Exception | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |     public function destroy(string $id) | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $image = $this->imageRepo->getById($id); | 
					
						
							|  |  |  |         $this->checkOwnablePermission('image-delete', $image); | 
					
						
							|  |  |  |         $this->checkImagePermission($image); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->imageRepo->destroyImage($image); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-25 07:20:58 +08:00
										 |  |  |         return response(''); | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 20:54:08 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Rebuild the thumbnails for the given image. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function rebuildThumbnails(string $id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $image = $this->imageRepo->getById($id); | 
					
						
							|  |  |  |         $this->checkImagePermission($image); | 
					
						
							|  |  |  |         $this->checkOwnablePermission('image-update', $image); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new OutOfMemoryHandler(function () { | 
					
						
							|  |  |  |             return $this->jsonError(trans('errors.image_thumbnail_memory_limit')); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |         $this->imageResizer->loadGalleryThumbnailsForImage($image, true); | 
					
						
							| 
									
										
										
										
											2023-09-29 20:54:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return response(trans('components.image_rebuild_thumbs_success')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check related page permission and ensure type is drawio or gallery. | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |      * @throws NotifyException | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-10-01 20:05:18 +08:00
										 |  |  |     protected function checkImagePermission(Image $image): void | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-05-05 01:11:00 +08:00
										 |  |  |         if ($image->type !== 'drawio' && $image->type !== 'gallery') { | 
					
						
							| 
									
										
										
										
											2019-05-04 22:48:15 +08:00
										 |  |  |             $this->showPermissionError(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $relatedPage = $image->getPage(); | 
					
						
							|  |  |  |         if ($relatedPage) { | 
					
						
							|  |  |  |             $this->checkOwnablePermission('page-view', $relatedPage); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |