]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/ImageController.php
Change application namespace to BookStack
[bookstack] / app / Http / Controllers / ImageController.php
1 <?php
2
3 namespace BookStack\Http\Controllers;
4
5 use Illuminate\Filesystem\Filesystem as File;
6 use Illuminate\Http\Request;
7 use Illuminate\Support\Facades\Auth;
8 use Intervention\Image\Facades\Image as ImageTool;
9 use Illuminate\Support\Facades\DB;
10 use BookStack\Http\Requests;
11 use BookStack\Image;
12 use BookStack\Repos\PageRepo;
13
14 class ImageController extends Controller
15 {
16     protected $image;
17     protected $file;
18
19     /**
20      * ImageController constructor.
21      * @param Image $image
22      * @param File  $file
23      */
24     public function __construct(Image $image, File $file)
25     {
26         $this->image = $image;
27         $this->file = $file;
28         parent::__construct();
29     }
30
31
32     /**
33      * Get all images, Paginated
34      * @param int $page
35      * @return \Illuminate\Http\JsonResponse
36      */
37     public function getAll($page = 0)
38     {
39         $pageSize = 30;
40         $images = DB::table('images')->orderBy('created_at', 'desc')
41             ->skip($page * $pageSize)->take($pageSize)->get();
42         foreach ($images as $image) {
43             $image->thumbnail = $this->getThumbnail($image, 150, 150);
44         }
45         $hasMore = count(DB::table('images')->orderBy('created_at', 'desc')
46                 ->skip(($page + 1) * $pageSize)->take($pageSize)->get()) > 0;
47         return response()->json([
48             'images'  => $images,
49             'hasMore' => $hasMore
50         ]);
51     }
52
53     /**
54      * Get the thumbnail for an image.
55      * @param     $image
56      * @param int $width
57      * @param int $height
58      * @return string
59      */
60     public function getThumbnail($image, $width = 220, $height = 220)
61     {
62         $explodedPath = explode('/', $image->url);
63         array_splice($explodedPath, 4, 0, ['thumbs-' . $width . '-' . $height]);
64         $thumbPath = implode('/', $explodedPath);
65         $thumbFilePath = public_path() . $thumbPath;
66
67         // Return the thumbnail url path if already exists
68         if (file_exists($thumbFilePath)) {
69             return $thumbPath;
70         }
71
72         // Otherwise create the thumbnail
73         $thumb = ImageTool::make(public_path() . $image->url);
74         $thumb->fit($width, $height);
75
76         // Create thumbnail folder if it does not exist
77         if (!file_exists(dirname($thumbFilePath))) {
78             mkdir(dirname($thumbFilePath), 0775, true);
79         }
80
81         //Save Thumbnail
82         $thumb->save($thumbFilePath);
83         return $thumbPath;
84     }
85
86     /**
87      * Handles image uploads for use on pages.
88      * @param Request $request
89      * @return \Illuminate\Http\JsonResponse
90      */
91     public function upload(Request $request)
92     {
93         $this->checkPermission('image-create');
94         $imageUpload = $request->file('file');
95         $name = str_replace(' ', '-', $imageUpload->getClientOriginalName());
96         $storageName = substr(sha1(time()), 0, 10) . '-' . $name;
97         $imagePath = '/uploads/images/' . Date('Y-m-M') . '/';
98         $storagePath = public_path() . $imagePath;
99         $fullPath = $storagePath . $storageName;
100         while (file_exists($fullPath)) {
101             $storageName = substr(sha1(rand()), 0, 3) . $storageName;
102             $fullPath = $storagePath . $storageName;
103         }
104         $imageUpload->move($storagePath, $storageName);
105         // Create and save image object
106         $this->image->name = $name;
107         $this->image->url = $imagePath . $storageName;
108         $this->image->created_by = Auth::user()->id;
109         $this->image->updated_by = Auth::user()->id;
110         $this->image->save();
111         $this->image->thumbnail = $this->getThumbnail($this->image, 150, 150);
112         return response()->json($this->image);
113     }
114
115     /**
116      * Update image details
117      * @param         $imageId
118      * @param Request $request
119      * @return \Illuminate\Http\JsonResponse
120      */
121     public function update($imageId, Request $request)
122     {
123         $this->checkPermission('image-update');
124         $this->validate($request, [
125             'name' => 'required|min:2|string'
126         ]);
127         $image = $this->image->findOrFail($imageId);
128         $image->fill($request->all());
129         $image->save();
130         return response()->json($this->image);
131     }
132
133     /**
134      * Deletes an image and all thumbnail/image files
135      * @param PageRepo $pageRepo
136      * @param Request  $request
137      * @param int      $id
138      * @return \Illuminate\Http\JsonResponse
139      */
140     public function destroy(PageRepo $pageRepo, Request $request, $id)
141     {
142         $this->checkPermission('image-delete');
143         $image = $this->image->findOrFail($id);
144
145         // Check if this image is used on any pages
146         $pageSearch = $pageRepo->searchForImage($image->url);
147         $isForced = ($request->has('force') && ($request->get('force') === 'true') || $request->get('force') === true);
148         if ($pageSearch !== false && !$isForced) {
149             return response()->json($pageSearch, 400);
150         }
151
152         // Delete files
153         $folder = public_path() . dirname($image->url);
154         $fileName = basename($image->url);
155
156         // Delete thumbnails
157         foreach (glob($folder . '/*') as $file) {
158             if (is_dir($file)) {
159                 $thumbName = $file . '/' . $fileName;
160                 if (file_exists($file)) {
161                     unlink($thumbName);
162                 }
163                 // Remove thumb folder if empty
164                 if (count(glob($file . '/*')) === 0) {
165                     rmdir($file);
166                 }
167             }
168         }
169
170         // Delete file and database entry
171         unlink($folder . '/' . $fileName);
172         $image->delete();
173
174         // Delete parent folder if empty
175         if (count(glob($folder . '/*')) === 0) {
176             rmdir($folder);
177         }
178         return response()->json('Image Deleted');
179     }
180
181
182 }