]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/ImageController.php
a61f447eb5ea883749c81ca541a6e34018441971
[bookstack] / app / Http / Controllers / ImageController.php
1 <?php namespace BookStack\Http\Controllers;
2
3 use BookStack\Exceptions\ImageUploadException;
4 use BookStack\Exceptions\NotFoundException;
5 use BookStack\Repos\EntityRepo;
6 use BookStack\Repos\ImageRepo;
7 use Illuminate\Filesystem\Filesystem as File;
8 use Illuminate\Http\Request;
9 use BookStack\Image;
10 use BookStack\Repos\PageRepo;
11
12 class ImageController extends Controller
13 {
14     protected $image;
15     protected $file;
16     protected $imageRepo;
17
18     /**
19      * ImageController constructor.
20      * @param Image $image
21      * @param File $file
22      * @param ImageRepo $imageRepo
23      */
24     public function __construct(Image $image, File $file, ImageRepo $imageRepo)
25     {
26         $this->image = $image;
27         $this->file = $file;
28         $this->imageRepo = $imageRepo;
29         parent::__construct();
30     }
31
32     /**
33      * Provide an image file from storage.
34      * @param string $path
35      * @return mixed
36      */
37     public function showImage(string $path)
38     {
39         $path = storage_path('uploads/images/' . $path);
40         if (!file_exists($path)) {
41             abort(404);
42         }
43
44         return response()->file($path);
45     }
46
47     /**
48      * Get all images for a specific type, Paginated
49      * @param string $type
50      * @param int $page
51      * @return \Illuminate\Http\JsonResponse
52      */
53     public function getAllByType($type, $page = 0)
54     {
55         $imgData = $this->imageRepo->getPaginatedByType($type, $page);
56         return response()->json($imgData);
57     }
58
59     /**
60      * Search through images within a particular type.
61      * @param $type
62      * @param int $page
63      * @param Request $request
64      * @return mixed
65      */
66     public function searchByType(Request $request, $type, $page = 0)
67     {
68         $this->validate($request, [
69             'term' => 'required|string'
70         ]);
71
72         $searchTerm = $request->get('term');
73         $imgData = $this->imageRepo->searchPaginatedByType($type, $searchTerm, $page, 24);
74         return response()->json($imgData);
75     }
76
77     /**
78      * Get all images for a user.
79      * @param int $page
80      * @return \Illuminate\Http\JsonResponse
81      */
82     public function getAllForUserType($page = 0)
83     {
84         $imgData = $this->imageRepo->getPaginatedByType('user', $page, 24, $this->currentUser->id);
85         return response()->json($imgData);
86     }
87
88     /**
89      * Get gallery images with a specific filter such as book or page
90      * @param $filter
91      * @param int $page
92      * @param Request $request
93      * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
94      */
95     public function getGalleryFiltered(Request $request, $filter, $page = 0)
96     {
97         $this->validate($request, [
98             'page_id' => 'required|integer'
99         ]);
100
101         $validFilters = collect(['page', 'book']);
102         if (!$validFilters->contains($filter)) {
103             return response('Invalid filter', 500);
104         }
105
106         $pageId = $request->get('page_id');
107         $imgData = $this->imageRepo->getGalleryFiltered(strtolower($filter), $pageId, $page, 24);
108
109         return response()->json($imgData);
110     }
111
112     /**
113      * Handles image uploads for use on pages.
114      * @param string $type
115      * @param Request $request
116      * @return \Illuminate\Http\JsonResponse
117      * @throws \Exception
118      */
119     public function uploadByType($type, Request $request)
120     {
121         $this->checkPermission('image-create-all');
122         $this->validate($request, [
123             'file' => 'is_image'
124         ]);
125
126         if (!$this->imageRepo->isValidType($type)) {
127             return $this->jsonError(trans('errors.image_upload_type_error'));
128         }
129
130         $imageUpload = $request->file('file');
131
132         try {
133             $uploadedTo = $request->get('uploaded_to', 0);
134             $image = $this->imageRepo->saveNew($imageUpload, $type, $uploadedTo);
135         } catch (ImageUploadException $e) {
136             return response($e->getMessage(), 500);
137         }
138
139         return response()->json($image);
140     }
141
142     /**
143      * Upload a drawing to the system.
144      * @param Request $request
145      * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
146      */
147     public function uploadDrawing(Request $request)
148     {
149         $this->validate($request, [
150             'image' => 'required|string',
151             'uploaded_to' => 'required|integer'
152         ]);
153         $this->checkPermission('image-create-all');
154         $imageBase64Data = $request->get('image');
155
156         try {
157             $uploadedTo = $request->get('uploaded_to', 0);
158             $image = $this->imageRepo->saveDrawing($imageBase64Data, $uploadedTo);
159         } catch (ImageUploadException $e) {
160             return response($e->getMessage(), 500);
161         }
162
163         return response()->json($image);
164     }
165
166     /**
167      * Replace the data content of a drawing.
168      * @param string $id
169      * @param Request $request
170      * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\Response
171      */
172     public function replaceDrawing(string $id, Request $request)
173     {
174         $this->validate($request, [
175             'image' => 'required|string'
176         ]);
177         $this->checkPermission('image-create-all');
178
179         $imageBase64Data = $request->get('image');
180         $image = $this->imageRepo->getById($id);
181         $this->checkOwnablePermission('image-update', $image);
182
183         try {
184             $image = $this->imageRepo->replaceDrawingContent($image, $imageBase64Data);
185         } catch (ImageUploadException $e) {
186             return response($e->getMessage(), 500);
187         }
188
189         return response()->json($image);
190     }
191
192     /**
193      * Get the content of an image based64 encoded.
194      * @param $id
195      * @return \Illuminate\Http\JsonResponse|mixed
196      */
197     public function getBase64Image($id)
198     {
199         $image = $this->imageRepo->getById($id);
200         $imageData = $this->imageRepo->getImageData($image);
201         if ($imageData === null) {
202             return $this->jsonError("Image data could not be found");
203         }
204         return response()->json([
205             'content' => base64_encode($imageData)
206         ]);
207     }
208
209     /**
210      * Generate a sized thumbnail for an image.
211      * @param $id
212      * @param $width
213      * @param $height
214      * @param $crop
215      * @return \Illuminate\Http\JsonResponse
216      * @throws ImageUploadException
217      * @throws \Exception
218      */
219     public function getThumbnail($id, $width, $height, $crop)
220     {
221         $this->checkPermission('image-create-all');
222         $image = $this->imageRepo->getById($id);
223         $thumbnailUrl = $this->imageRepo->getThumbnail($image, $width, $height, $crop == 'false');
224         return response()->json(['url' => $thumbnailUrl]);
225     }
226
227     /**
228      * Update image details
229      * @param integer $imageId
230      * @param Request $request
231      * @return \Illuminate\Http\JsonResponse
232      * @throws ImageUploadException
233      * @throws \Exception
234      */
235     public function update($imageId, Request $request)
236     {
237         $this->validate($request, [
238             'name' => 'required|min:2|string'
239         ]);
240         $image = $this->imageRepo->getById($imageId);
241         $this->checkOwnablePermission('image-update', $image);
242         $image = $this->imageRepo->updateImageDetails($image, $request->all());
243         return response()->json($image);
244     }
245
246     /**
247      * Deletes an image and all thumbnail/image files
248      * @param EntityRepo $entityRepo
249      * @param Request $request
250      * @param int $id
251      * @return \Illuminate\Http\JsonResponse
252      */
253     public function destroy(EntityRepo $entityRepo, Request $request, $id)
254     {
255         $image = $this->imageRepo->getById($id);
256         $this->checkOwnablePermission('image-delete', $image);
257
258         // Check if this image is used on any pages
259         $isForced = in_array($request->get('force', ''), [true, 'true']);
260         if (!$isForced) {
261             $pageSearch = $entityRepo->searchForImage($image->url);
262             if ($pageSearch !== false) {
263                 return response()->json($pageSearch, 400);
264             }
265         }
266
267         $this->imageRepo->destroyImage($image);
268         return response()->json(trans('components.images_deleted'));
269     }
270 }