PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.5.4
Fluent Support – Helpdesk & Customer Support Ticket System v1.5.4
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.5.4, at app/Http/Controllers/CustomerPortalController.php

428 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
124 Attachment::whereNull('ticket_id')
125 ->whereIn('file_hash', $attachments)
126 ->whereNull('ticket_id')
127 ->update([
128 'ticket_id' => $ticket->id,
129 'person_id' => $customer->id,
130 'status' => 'active'
131 ]);
132
133 $ticket->load('attachments');
134 }
135
136
137 if(defined('FLUENTSUPPORTPRO')) {
138 $customData = Arr::get($data, 'custom_data');
139 if($customData) {
140 $customData = wp_unslash($customData);
141 $ticket->syncCustomFields($customData);
142 }
143 }
144
145 do_action('fluent_support/ticket_created', $ticket, $customer);
146
147 return [
148 'message' => __('Ticket has been created successfully', 'fluent-support'),
149 'ticket' => $ticket
150 ];
151 }
152
153 public function getTicket(Request $request, $ticketId)
154 {
155 $ticket = Ticket::where('id', $ticketId)
156 ->with([
157 'customer' => function ($query) {
158 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id']);
159 }, 'agent' => function ($query) {
160 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id', 'title']);
161 },
162 'product',
163 'attachments'
164 ])
165 ->first();
166
167 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
168 $customer = $ticket->customer;
169 } else {
170 $customer = $this->resolveCustomer($request);
171 }
172
173 if (!$customer) {
174 return $this->sendError([
175 'message' => __('Sorry, You do not have permission to this support ticket', 'fluent-support'),
176 'error_type' => 'no_customer'
177 ]);
178 }
179
180 if($customer->status == 'inactive') {
181 return $this->sendError([
182 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
183 'error_type' => 'inactive_customer'
184 ]);
185 }
186
187
188 if ($ticket->privacy == 'private' && $customer->id != $ticket->customer_id) {
189 return $this->sendError([
190 'message' => __('You do not have permission to view this support ticket', 'fluent-support'),
191 'error_type' => 'permission_error'
192 ]);
193 }
194
195 $responses = Conversation::where('ticket_id', $ticketId)
196 ->with([
197 'person' => function ($query) {
198 $query->select(['first_name', 'email', 'person_type', 'last_name', 'id', 'title']);
199 },
200 'attachments'
201 ])
202 ->filterByType('response')
203 ->orderBy('id', 'DESC')
204 ->get();
205
206 foreach ($responses as $response) {
207 $response->content = make_clickable($response->content);
208 if ($response->person) {
209 $response->person->setHidden(['email']);
210 }
211 }
212
213 $ticket->content = make_clickable($ticket->content);
214
215 if ($ticket->customer) {
216 $ticket->customer->setHidden(['email']);
217 }
218
219 if ($ticket->agent) {
220 $ticket->agent->setHidden(['email']);
221 }
222
223 if ($ticket->status == 'closed') {
224 $ticket->load('closed_by_person');
225 if ($ticket->closed_by_person) {
226 $ticket->closed_by_person->setVisible(['first_name', 'last_name', 'id', 'full_name', 'photo']);
227 }
228 }
229
230 if(defined('FLUENTSUPPORTPRO')) {
231 $ticket->custom_fields = $ticket->customData('public', true);
232 }
233
234 return [
235 'ticket' => $ticket,
236 'responses' => $responses,
237 'sign_on_id' => $ticket->customer_id
238 ];
239 }
240
241 public function createResponse(Request $request, $ticketId)
242 {
243 $data = $request->all();
244 $this->validate($data, [
245 'content' => 'required'
246 ]);
247
248 $data['content'] = wp_unslash(wp_kses_post($data['content']));
249
250
251 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
252
253 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
254 $customer = $ticket->customer;
255 } else {
256 $customer = $this->resolveCustomer($request);
257 }
258
259 if (!$customer) {
260 return $this->sendError([
261 'message' => __('Sorry! No customer found', 'fluent-support')
262 ]);
263 }
264
265 if($customer->status == 'inactive') {
266 return $this->sendError([
267 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
268 'error_type' => 'inactive_customer'
269 ]);
270 }
271
272
273 if ($ticket->privacy == 'private' && $customer->id != $ticket->customer_id) {
274 return $this->sendError([
275 'message' => __('Sorry! You can not reply to this ticket', 'fluent-support')
276 ]);
277 }
278
279 $data['conversation_type'] = 'response';
280 $responseData = (new ResponseService())->createResponse($data, $customer, $ticket);
281
282 return [
283 'message' => __('Reply has been added', 'fluent-support'),
284 'response' => $responseData['response'],
285 'ticket' => $responseData['ticket']
286 ];
287 }
288
289 public function closeTicket(Request $request, $ticketId)
290 {
291 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
292
293 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
294 $customer = $ticket->customer;
295 } else {
296 $customer = $this->resolveCustomer($request);
297 }
298
299 if (!$customer) {
300 return $this->sendError([
301 'message' => __('Sorry! No customer found', 'fluent-support')
302 ]);
303 }
304
305 if($customer->status == 'inactive') {
306 return $this->sendError([
307 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
308 'error_type' => 'inactive_customer'
309 ]);
310 }
311
312
313 if ($customer->id != $ticket->customer_id) {
314 return $this->sendError([
315 'message' => __('Sorry! You can not close this ticket', 'fluent-support')
316 ]);
317 }
318
319 return [
320 'message' => __('Ticket has been closed', 'fluent_support'),
321 'ticket' => (new TicketService())->close($ticket, $customer)
322 ];
323 }
324
325 public function reOpenTicket(Request $request, $ticketId)
326 {
327 $ticket = Ticket::with(['customer'])->findOrFail($ticketId);
328
329 if ($request->get('intended_ticket_hash') && Helper::isPublicSignedTicketEnabled()) {
330 $customer = $ticket->customer;
331 } else {
332 $customer = $this->resolveCustomer($request);
333 }
334
335 if($customer->status == 'inactive') {
336 return $this->sendError([
337 'message' => __('Sorry, You do not have access to customer portal', 'fluent-support'),
338 'error_type' => 'inactive_customer'
339 ]);
340 }
341
342
343 if (!$customer) {
344 return $this->sendError([
345 'message' => __('Sorry! No customer found', 'fluent-support')
346 ]);
347 }
348
349 if ($customer->id != $ticket->customer_id) {
350 return $this->sendError([
351 'message' => __('Sorry! You can not close this ticket', 'fluent-support')
352 ]);
353 }
354
355
356 return [
357 'message' => __('Ticket has been opened again', 'fluent_support'),
358 'ticket' => (new TicketService())->reopen($ticket, $customer)
359 ];
360
361
362 }
363
364 private function resolveCustomer($request, $forceCreate = false)
365 {
366 $onBehalf = $request->get('on_behalf');
367
368 if (!$onBehalf) {
369 $user = get_user_by('ID', get_current_user_id());
370 if (!$user) {
371 return false;
372 }
373 $onBehalf = [
374 'user_id' => $user->id,
375 'email' => $user->user_email,
376 'last_ip_address' => $request->getIp()
377 ];
378 }
379
380 if ($forceCreate) {
381 return Customer::maybeCreateCustomer($onBehalf);
382 }
383
384 return Customer::getCustomerFromData($onBehalf);
385 }
386
387 public function getPublicOptions()
388 {
389 $products = Product::select(['id', 'title'])->get();
390
391 return [
392 'support_products' => $products,
393 'customer_ticket_priorities' => Helper::customerTicketPriorities()
394 ];
395 }
396
397 public function getCustomFieldsRender()
398 {
399 if(!defined('FLUENTSUPPORTPRO')) {
400 return [
401 'custom_fields_rendered' => []
402 ];
403 }
404
405 return [
406 'custom_fields_rendered' => \FluentSupportPro\App\Services\CustomFieldsService::getRenderedPublicFields()
407 ];
408
409 }
410
411 private function resolveMailboxId($request)
412 {
413 if ($mailboxId = $request->get('mailbox_id')) {
414 $mailbox = MailBox::find($mailboxId);
415 if ($mailbox) {
416 return $mailbox->id;
417 }
418 }
419
420 $mailbox = Helper::getDefaultMailBox();
421
422 if ($mailbox) {
423 return $mailbox->id;
424 }
425 return null;
426 }
427 }
428