]> BookStack Code Mirror - bookstack/blob - app/Services/FileService.php
Added view, deletion and permissions for files
[bookstack] / app / Services / FileService.php
1 <?php namespace BookStack\Services;
2
3
4 use BookStack\Exceptions\FileUploadException;
5 use BookStack\File;
6 use Exception;
7 use Illuminate\Contracts\Filesystem\FileNotFoundException;
8 use Illuminate\Support\Collection;
9 use Symfony\Component\HttpFoundation\File\UploadedFile;
10
11 class FileService extends UploadService
12 {
13
14     /**
15      * Get a file from storage.
16      * @param File $file
17      * @return string
18      */
19     public function getFile(File $file)
20     {
21         $filePath = $this->getStorageBasePath() . $file->path;
22         return $this->getStorage()->get($filePath);
23     }
24
25     /**
26      * Store a new file upon user upload.
27      * @param UploadedFile $uploadedFile
28      * @param int $page_id
29      * @return File
30      * @throws FileUploadException
31      */
32     public function saveNewUpload(UploadedFile $uploadedFile, $page_id)
33     {
34         $fileName = $uploadedFile->getClientOriginalName();
35         $fileData = file_get_contents($uploadedFile->getRealPath());
36
37         $storage = $this->getStorage();
38         $fileBasePath = 'uploads/files/' . Date('Y-m-M') . '/';
39         $storageBasePath = $this->getStorageBasePath() . $fileBasePath;
40
41         $uploadFileName = $fileName;
42         while ($storage->exists($storageBasePath . $uploadFileName)) {
43             $uploadFileName = str_random(3) . $uploadFileName;
44         }
45
46         $filePath = $fileBasePath . $uploadFileName;
47         $fileStoragePath = $this->getStorageBasePath() . $filePath;
48
49         try {
50             $storage->put($fileStoragePath, $fileData);
51         } catch (Exception $e) {
52             throw new FileUploadException('File path ' . $fileStoragePath . ' could not be uploaded to. Ensure it is writable to the server.');
53         }
54
55         $largestExistingOrder = File::where('uploaded_to', '=', $page_id)->max('order');
56
57         $file = File::forceCreate([
58             'name' => $fileName,
59             'path' => $filePath,
60             'uploaded_to' => $page_id,
61             'created_by' => user()->id,
62             'updated_by' => user()->id,
63             'order' => $largestExistingOrder + 1
64         ]);
65
66         return $file;
67     }
68
69     /**
70      * Get the file storage base path, amended for storage type.
71      * This allows us to keep a generic path in the database.
72      * @return string
73      */
74     private function getStorageBasePath()
75     {
76         return $this->isLocal() ? 'storage/' : '';
77     }
78
79     /**
80      * Updates the file ordering for a listing of attached files.
81      * @param array $fileList
82      * @param $pageId
83      */
84     public function updateFileOrderWithinPage($fileList, $pageId)
85     {
86         foreach ($fileList as $index => $file) {
87             File::where('uploaded_to', '=', $pageId)->where('id', '=', $file['id'])->update(['order' => $index]);
88         }
89     }
90
91     /**
92      * Delete a file and any empty folders the deletion leaves.
93      * @param File $file
94      */
95     public function deleteFile(File $file)
96     {
97         $storedFilePath = $this->getStorageBasePath() . $file->path;
98         $storage = $this->getStorage();
99         $dirPath = dirname($storedFilePath);
100
101         $storage->delete($storedFilePath);
102         if (count($storage->allFiles($dirPath)) === 0) {
103             $storage->deleteDirectory($dirPath);
104         }
105
106         $file->delete();
107     }
108
109 }