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