PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.4.6
Fluent Support – Helpdesk & Customer Support Ticket System v1.4.6
2.4.0 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 All 68 releases
fluent-support / app / Http / Controllers / CustomerPortalController.php

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

426 lines 13.4 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\Customer;
7 use FluentSupport\App\Models\MailBox;
8 use FluentSupport\App\Models\Product;
9 use FluentSupport\App\Models\Conversation;
10 use FluentSupport\App\Models\Ticket;
11 use FluentSupport\App\Services\Helper;
12 use FluentSupport\App\Services\Includes\FileSystem;
13 use FluentSupport\App\Services\Tickets\ResponseService;
14 use FluentSupport\App\Services\Tickets\TicketService;
15 use FluentSupport\Framework\Request\Request;
16 use FluentSupport\Framework\Support\Arr;
17
18 class CustomerPortalController extends Controller
19 {
20 public function getTickets(Request $request)
21 {
22 $customer = $this->resolveCustomer($request);
23
24 if (!$customer) {
25 return $this->sendError([
26 'message' => __('No Customer Found', 'fluent-support'),
27 'error_type' => 'no_customer'
28 ]);
29 }
30
31 if($customer->status == 'inactive') {
32 return $this->sendError([
33 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
34 'error_type' => 'inactive_customer'
35 ]);
36 }
37
38 $statuses = Arr::get([
39 'open' => ['new', 'active', 'on-hold'],
40 'all' => [],
41 'closed' => ['closed']
42 ], $request->get('filter_type', ''));
43
44 $ticketsQuery = Ticket::with([
45 'customer' => function ($query) {
46 $query->select(['first_name', 'last_name', 'id']);
47 }, 'agent' => function ($query) {
48 $query->select(['first_name', 'last_name', 'id']);
49 }
50 ])
51 ->where('customer_id', $customer->id)
52 ->orderBy('id', 'DESC');
53
54 $ticketsQuery->where('customer_id', $customer->id);
55
56 if ($statuses) {
57 $ticketsQuery->whereIn('status', $statuses);
58 }
59
60 $tickets = $ticketsQuery->paginate();
61
62 foreach ($tickets as $ticket) {
63 $ticket->human_date = sprintf(__('%s ago', 'fluent-support'), human_time_diff(strtotime($ticket->created_at), current_time('timestamp')));
64 $ticket->preview_response = $ticket->getLastResponse();
65 }
66
67 return [
68 'tickets' => $tickets
69 ];
70 }
71
72 public function createTicket(Request $request)
73 {
74 $data = $request->all();
75
76 $this->validate($data, [
77 'title' => 'required',
78 'content' => 'required'
79 ]);
80
81 $data['title'] = sanitize_text_field(wp_unslash($data['title']));
82
83 $data['content'] = wp_unslash(wp_kses_post($data['content']));
84
85 $customer = $this->resolveCustomer($request, true);
86
87 if($customer->status == 'inactive') {
88 return $this->sendError([
89 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
90 'error_type' => 'inactive_customer'
91 ]);
92 }
93
94 if (!$customer) {
95 return $this->sendError([
96 'message' => __('No Customer Found', 'fluent-support'),
97 'error_type' => 'no_customer'
98 ]);
99 }
100
101 $data['customer_id'] = $customer->id;
102 $data['product_source'] = 'local';
103 $data['mailbox_id'] = $this->resolveMailboxId($request);
104
105 $disabledFields = apply_filters('fluent_support/disabled_ticket_fields', []);
106
107 if(!in_array('priority', $disabledFields)) {
108 $data['priority'] = sanitize_text_field($data['client_priority']);
109 $data['client_priority'] = sanitize_text_field($data['client_priority']);
110 }
111
112 if(!in_array('product_services', $disabledFields)) {
113 unset($data['product_id']);
114 }
115
116 $data['source'] = 'web';
117
118 $data = apply_filters('fluent_support/create_ticket_data', $data, $customer);
119 do_action('fluent_support/before_ticket_create', $data, $customer);
120 $ticket = Ticket::create($data);
121
122 if ($attachments = Arr::get($data, 'attachments') && !in_array('file_upload', $disabledFields)) {
123 Attachment::whereNull('ticket_id')
124 ->whereIn('file_hash', $attachments)
125 ->whereNull('ticket_id')
126 ->update([
127 'ticket_id' => $ticket->id,
128 'person_id' => $customer->id,
129 'status' => 'active'
130 ]);
131 $ticket->load('attachments');
132 }
133
134
135 if(defined('FLUENTSUPPORTPRO')) {
136 $customData = Arr::get($data, 'custom_data');
137 if($customData) {
138 $customData = wp_unslash($customData);
139 $ticket->syncCustomFields($customData);
140 }
141 }
142
143 do_action('fluent_support/ticket_created', $ticket, $customer);
144
145 return [
146 'message' => __('Ticket has been created successfully', 'fluent-support'),
147 'ticket' => $ticket
148 ];
149 }
150
151 public function getTicket(Request $request, $ticketId)
152 {
153 $ticket = Ticket::where('id', $ticketId)
154 ->with([
155 'customer' => function ($query) {
156 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id']);
157 }, 'agent' => function ($query) {
158 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id', 'title']);
159 },
160 'product',
161 'attachments'
162 ])
163 ->first();
164
165 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
166 $customer = $ticket->customer;
167 } else {
168 $customer = $this->resolveCustomer($request);
169 }
170
171 if (!$customer) {
172 return $this->sendError([
173 'message' => __('Sorry, You do not have permission to this support ticket', 'fluent-support'),
174 'error_type' => 'no_customer'
175 ]);
176 }
177
178 if($customer->status == 'inactive') {
179 return $this->sendError([
180 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
181 'error_type' => 'inactive_customer'
182 ]);
183 }
184
185
186 if ($ticket->privacy == 'private' && $customer->id != $ticket->customer_id) {
187 return $this->sendError([
188 'message' => __('You do not have permission to view this support ticket', 'fluent-support'),
189 'error_type' => 'permission_error'
190 ]);
191 }
192
193 $responses = Conversation::where('ticket_id', $ticketId)
194 ->with([
195 'person' => function ($query) {
196 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id', 'title']);
197 },
198 'attachments'
199 ])
200 ->filterByType('response')
201 ->orderBy('id', 'DESC')
202 ->get();
203
204 foreach ($responses as $response) {
205 $response->content = make_clickable($response->content);
206 if ($response->person) {
207 $response->person->setHidden(['email']);
208 }
209 }
210
211 $ticket->content = make_clickable($ticket->content);
212
213 if ($ticket->customer) {
214 $ticket->customer->setHidden(['email']);
215 }
216
217 if ($ticket->agent) {
218 $ticket->agent->setHidden(['email']);
219 }
220
221 if ($ticket->status == 'closed') {
222 $ticket->load('closed_by_person');
223 if ($ticket->closed_by_person) {
224 $ticket->closed_by_person->setVisible(['first_name', 'last_name', 'id', 'full_name', 'photo']);
225 }
226 }
227
228 if(defined('FLUENTSUPPORTPRO')) {
229 $ticket->custom_fields = $ticket->customData('public', true);
230 }
231
232 return [
233 'ticket' => $ticket,
234 'responses' => $responses,
235 'sign_on_id' => $ticket->customer_id
236 ];
237 }
238
239 public function createResponse(Request $request, $ticketId)
240 {
241 $data = $request->all();
242 $this->validate($data, [
243 'content' => 'required'
244 ]);
245
246 $data['content'] = wp_unslash(wp_kses_post($data['content']));
247
248
249 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
250
251 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
252 $customer = $ticket->customer;
253 } else {
254 $customer = $this->resolveCustomer($request);
255 }
256
257 if (!$customer) {
258 return $this->sendError([
259 'message' => __('Sorry! No customer found', 'fluent-support')
260 ]);
261 }
262
263 if($customer->status == 'inactive') {
264 return $this->sendError([
265 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
266 'error_type' => 'inactive_customer'
267 ]);
268 }
269
270
271 if ($ticket->privacy == 'private' && $customer->id != $ticket->customer_id) {
272 return $this->sendError([
273 'message' => __('Sorry! You can not reply to this ticket', 'fluent-support')
274 ]);
275 }
276
277 $data['conversation_type'] = 'response';
278 $responseData = (new ResponseService())->createResponse($data, $customer, $ticket);
279
280 return [
281 'message' => __('Reply has been added', 'fluent-support'),
282 'response' => $responseData['response'],
283 'ticket' => $responseData['ticket']
284 ];
285 }
286
287 public function closeTicket(Request $request, $ticketId)
288 {
289 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
290
291 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
292 $customer = $ticket->customer;
293 } else {
294 $customer = $this->resolveCustomer($request);
295 }
296
297 if (!$customer) {
298 return $this->sendError([
299 'message' => __('Sorry! No customer found', 'fluent-support')
300 ]);
301 }
302
303 if($customer->status == 'inactive') {
304 return $this->sendError([
305 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
306 'error_type' => 'inactive_customer'
307 ]);
308 }
309
310
311 if ($customer->id != $ticket->customer_id) {
312 return $this->sendError([
313 'message' => __('Sorry! You can not close this ticket', 'fluent-support')
314 ]);
315 }
316
317 return [
318 'message' => __('Ticket has been closed', 'fluent_support'),
319 'ticket' => (new TicketService())->close($ticket, $customer)
320 ];
321 }
322
323 public function reOpenTicket(Request $request, $ticketId)
324 {
325 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
326
327 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
328 $customer = $ticket->customer;
329 } else {
330 $customer = $this->resolveCustomer($request);
331 }
332
333 if($customer->status == 'inactive') {
334 return $this->sendError([
335 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
336 'error_type' => 'inactive_customer'
337 ]);
338 }
339
340
341 if (!$customer) {
342 return $this->sendError([
343 'message' => __('Sorry! No customer found', 'fluent-support')
344 ]);
345 }
346
347 if ($customer->id != $ticket->customer_id) {
348 return $this->sendError([
349 'message' => __('Sorry! You can not close this ticket', 'fluent-support')
350 ]);
351 }
352
353
354 return [
355 'message' => __('Ticket has been opened again', 'fluent_support'),
356 'ticket' => (new TicketService())->reopen($ticket, $customer)
357 ];
358
359
360 }
361
362 private function resolveCustomer($request, $forceCreate = false)
363 {
364 $onBehalf = $request->get('on_behalf');
365
366 if (!$onBehalf) {
367 $user = get_user_by('ID', get_current_user_id());
368 if (!$user) {
369 return false;
370 }
371 $onBehalf = [
372 'user_id' => $user->id,
373 'email' => $user->user_email,
374 'last_ip_address' => $request->getIp()
375 ];
376 }
377
378 if ($forceCreate) {
379 return Customer::maybeCreateCustomer($onBehalf);
380 }
381
382 return Customer::getCustomerFromData($onBehalf);
383 }
384
385 public function getPublicOptions()
386 {
387 $products = Product::select(['id', 'title'])->get();
388
389 return [
390 'support_products' => $products,
391 'customer_ticket_priorities' => Helper::customerTicketPriorities()
392 ];
393 }
394
395 public function getCustomFieldsRender()
396 {
397 if(!defined('FLUENTSUPPORTPRO')) {
398 return [
399 'custom_fields_rendered' => []
400 ];
401 }
402
403 return [
404 'custom_fields_rendered' => \FluentSupportPro\App\Services\CustomFieldsService::getRenderedPublicFields()
405 ];
406
407 }
408
409 private function resolveMailboxId($request)
410 {
411 if ($mailboxId = $request->get('mailbox_id')) {
412 $mailbox = MailBox::find($mailboxId);
413 if ($mailbox) {
414 return $mailbox->id;
415 }
416 }
417
418 $mailbox = Helper::getDefaultMailBox();
419
420 if ($mailbox) {
421 return $mailbox->id;
422 }
423 return null;
424 }
425 }
426