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

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