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

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