PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.1.2
Fluent Support – Helpdesk & Customer Support Ticket System v2.1.2
2.3.2 2.3.1 2.3.0 2.2.1 2.2.0 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.4.0 1.4.1 1.4.2 1.4.5 1.4.6 1.4.7 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 All 67 releases
fluent-support / app / Http / Controllers / UploaderController.php

UploaderController.php in Fluent Support – Helpdesk & Customer Support Ticket System 2.1.2, at app/Http/Controllers/UploaderController.php

236 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentSupport\App\Http\Controllers;
4
5 use FluentSupport\App\Models\Attachment;
6 use FluentSupport\App\Models\Ticket;
7 use FluentSupport\App\Services\EmailNotification\Settings;
8 use FluentSupport\App\Services\Helper;
9 use FluentSupport\Framework\Http\Request\Request;
10 use FluentSupport\App\Services\Includes\UploadService;
11
12 /**
13 * UploaderController class is responsible for uploading file
14 * @package FluentSupport\App\Http\Controllers
15 *
16 * @version 1.0.0
17 */
18 class UploaderController extends Controller
19 {
20 /**
21 * uploadTicketFiles method will upload all the attached file in a ticket
22 * @param Request $request
23 * @return array[]
24 * @throws \FluentSupport\Framework\Validator\ValidationException
25 */
26 public function uploadTicketFiles(Request $request)
27 {
28 $settings = (new Settings())->globalBusinessSettings();
29 $maxFileSize = floatval($settings['max_file_size']);
30 $mimeHeadings = Helper::getAcceptedMimeHeadings();
31 $maxSizeBytes = $maxFileSize * 1024;
32 $imageType = $request->type ? $request->type : null;
33
34 $this->validateUploadedFiles($request->files(), $maxSizeBytes, $mimeHeadings, $maxFileSize);
35 $ticketId = $this->resolveTicketId($request);
36 $person = $this->resolvePerson($ticketId, $request);
37
38 $this->checkPermissionToUploadFile($person);
39
40 try {
41 $uploadedFiles = UploadService::handleTempFileUpload($request->files());
42 } catch (\Exception $e) {
43 return $this->sendError([
44 'message' => Helper::getSafeErrorMessage($e),
45 ]);
46 }
47
48 if (is_wp_error($uploadedFiles)) {
49 return $this->sendError([
50 'message' => $uploadedFiles->get_error_message(),
51 ]);
52 }
53
54 $attachmentHashes = $this->createAttachmentRecords($uploadedFiles, $ticketId, $person, $imageType);
55
56 return [
57 'attachments' => $attachmentHashes,
58 ];
59 }
60
61 private function validateUploadedFiles($files, $maxSizeBytes, $mimeHeadings, $maxFileSize)
62 {
63 $validationRules = [
64 'file' => 'max:' . $maxSizeBytes . '|mimetypes:' . implode(',', Helper::ticketAcceptedFileMiles()),
65 ];
66
67 $validationMessages = [
68 // translators: %s is a comma-separated list of allowed file types (e.g., "jpg, png, pdf")
69 'file.mimetypes' => sprintf(__('Only %s files are allowed.', 'fluent-support'), implode(', ', $mimeHeadings)),
70 // translators: %.01f is the maximum file size in megabytes
71 'file.max' => sprintf(__('The file cannot be more than %.01fMB. Please upload somewhere like Dropbox/Google Drive and paste the link in the response', 'fluent-support'), $maxFileSize),
72 ];
73
74 $this->validate($files, $validationRules, $validationMessages);
75 }
76
77 private function resolveTicketId($request)
78 {
79 $ticketId = $request->getSafe('ticket_id', 'intval');
80 return $ticketId == 'undefined' ? null : $ticketId;
81 }
82
83 private function resolvePerson($ticketId, Request $request)
84 {
85 if ($request->getSafe('is_agent', 'sanitize_text_field') == 'yes') {
86 return Helper::getCurrentAgent();
87 }
88
89 if ($ticketId && Helper::isPublicSignedTicketEnabled()) {
90 $intendedTicketHash = $request->getSafe('intended_ticket_hash', 'sanitize_text_field');
91 if ($intendedTicketHash && $intendedTicketHash != 'undefined') {
92 $ticket = Ticket::with(['customer'])
93 ->where('hash', $intendedTicketHash)
94 ->find($ticketId);
95
96 if ($ticket && $ticket->customer) {
97 return $ticket->customer;
98 }
99 }
100 }
101
102 return Helper::getCurrentPerson();
103 }
104
105 private function checkPermissionToUploadFile($person)
106 {
107 if (!$person) {
108 return $this->sendError([
109 'message' => __('You do not have permission to upload a file', 'fluent-support'),
110 ]);
111 }
112
113 if ($person->person_type === 'customer') {
114 $disabledFields = apply_filters('fluent_support/disabled_ticket_fields', []);
115 if (in_array('file_upload', $disabledFields)) {
116 return $this->sendError([
117 'message' => __('You do not have permission to upload a file', 'fluent-support'),
118 ]);
119 }
120 }
121 }
122
123 private function createAttachmentRecords($uploadedFiles, $ticketId, $person, $imageType)
124 {
125 $attachments = [];
126 $full_path = null;
127
128 foreach ($uploadedFiles as $file) {
129 if (empty($file['file_path'])) continue;
130
131 $fileData = [
132 'ticket_id' => intval($ticketId) ?: NULL,
133 'person_id' => intval($person->id),
134 'file_type' => $file['type'],
135 'file_path' => $file['file_path'],
136 'full_url' => esc_url($file['url']),
137 'title' => sanitize_file_name($file['name']),
138 'driver' => 'local',
139 'status' => 'in-active',
140 'settings' => [
141 'local_temp_path' => $file['file_path'],
142 ]
143 ];
144
145 if($imageType == 'direct_paste'){
146 $full_path = esc_url($file['url']);
147 }
148
149 try {
150 $attachment = Attachment::create($fileData);
151 $attachments[] = $attachment->file_hash;
152 do_action('fluent_support/attachment_uploaded_as_temp', $attachment, $ticketId);
153 $driver = Helper::getUploadDriverKey();
154
155 do_action_ref_array('fluent_support/attachment_uploaded_as_temp_' . $driver, [&$attachment, $ticketId]);
156 } catch (\Exception $exception) {
157 continue;
158 }
159 }
160
161 return $imageType == 'direct_paste' ? $full_path : $attachments;
162 }
163
164 public function uploadImage(Request $request)
165 {
166 $images = $request->files();
167 $ticketId = $this->resolveTicketId($request);
168
169 $validationError = $this->isValidImageType($images);
170 if ($validationError) {
171 return $validationError;
172 }
173
174 try {
175 $uploadedFiles = UploadService::handleUploadToLocal($ticketId, $images);
176 } catch (\Exception $e) {
177 return $this->sendError([
178 'message' => Helper::getSafeErrorMessage($e),
179 ]);
180 }
181
182 return [
183 'images' => $uploadedFiles,
184 ];
185 }
186
187 private function isValidImageType($images)
188 {
189 if (empty($images['image'])) {
190 return $this->sendError([
191 'message' => __('No image file provided.', 'fluent-support'),
192 ]);
193 }
194
195 $file = $images['image'];
196 $tempPath = $file->getPathname();
197 $extension = strtolower($file->getClientOriginalExtension());
198 $allowedExtensions = ['gif', 'ief', 'jpeg', 'jpg', 'webp', 'pjpeg', 'ktx', 'png'];
199
200 if (!in_array($extension, $allowedExtensions)) {
201 return $this->sendError([
202 'message' => __('Invalid image file type.', 'fluent-support'),
203 ]);
204 }
205
206 $allowedMimes = Helper::getMimeGroups()['images']['mimes'];
207 $realMime = $this->detectMimeType($tempPath);
208
209 if (!$realMime || !in_array($realMime, $allowedMimes)) {
210 return $this->sendError([
211 'message' => __('File content does not match the image type.', 'fluent-support'),
212 ]);
213 }
214
215 return null;
216 }
217
218 private function detectMimeType($filePath)
219 {
220 if (function_exists('finfo_open')) {
221 $finfo = finfo_open(FILEINFO_MIME_TYPE);
222 $mime = finfo_file($finfo, $filePath);
223 finfo_close($finfo);
224 return $mime;
225 }
226
227 if (function_exists('mime_content_type')) {
228 return mime_content_type($filePath);
229 }
230
231 // getimagesize works for standard image formats as last resort
232 $imageInfo = @getimagesize($filePath);
233 return $imageInfo ? $imageInfo['mime'] : false;
234 }
235 }
236