PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.10.2
Fluent Support – Helpdesk & Customer Support Ticket System v1.10.2
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 / Services / Tickets / TicketService.php

TicketService.php in Fluent Support – Helpdesk & Customer Support Ticket System 1.10.2, at app/Services/Tickets/TicketService.php

270 lines 9.3 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\Services\Tickets;
4
5 use FluentSupport\App\Models\Attachment;
6 use FluentSupport\App\Models\Conversation;
7 use FluentSupport\App\Modules\PermissionManager;
8 use FluentSupport\App\Services\Helper;
9 use FluentSupport\App\Services\Includes\UploadService;
10 use FluentSupport\App\Services\TicketHelper;
11 use FluentSupport\App\Services\TicketQueryService;
12 use FluentSupport\Framework\Support\Arr;
13
14 class TicketService
15 {
16 /**
17 * this function will set the ticket status as closed
18 * @param $ticket
19 * @param $person
20 * @param string $internalNote
21 * @param bool $silently
22 * @return mixed
23 */
24
25 public function close($ticket, $person, $internalNote = '', $silently = 'no')
26 {
27 if ($ticket->status != 'closed') {
28 $ticket->status = 'closed';
29 $ticket->resolved_at = current_time('mysql');
30 $ticket->closed_by = $person->id;
31 $ticket->total_close_time = current_time('timestamp') - strtotime($ticket->created_at);
32 $ticket->save();
33
34 if ('no' == $silently) {
35 do_action('fluent_support/ticket_closed', $ticket, $person);
36 do_action('fluent_support/ticket_closed_by_' . $person->person_type, $ticket, $person);
37 }
38
39 if (!$internalNote) {
40 $internalNote = __('Ticket has been closed', 'fluent-support');
41 }
42
43 //Keep track in conversation
44 Conversation::create([
45 'ticket_id' => $ticket->id,
46 'person_id' => $person->id,
47 'conversation_type' => 'internal_info',
48 'content' => $internalNote
49 ]);
50 }
51
52 return $ticket;
53 }
54
55 public function reopen($ticket, $person)
56 {
57 if ($ticket->status == 'closed') {
58 $ticket->status = 'active';
59 $ticket->waiting_since = current_time('mysql');
60 $ticket->save();
61
62 /*
63 * Action on ticket reopen
64 *
65 * @since v1.0.0
66 * @param object $ticket
67 * @param object $person
68 */
69 do_action('fluent_support/ticket_reopen', $ticket, $person);
70 do_action('fluent_support/ticket_reopen_by_' . $person->person_type, $ticket, $person);
71 Conversation::create([
72 'ticket_id' => $ticket->id,
73 'person_id' => $person->id,
74 'conversation_type' => 'internal_info',
75 'content' => __('Ticket has been reopened', 'fluent-support')
76 ]);
77 }
78
79 return $person;
80 }
81
82 public function onAgentChange($ticket, $person)
83 {
84 do_action('fluent_support/ticket_agent_change', $ticket, $person);
85 Conversation::create([
86 'ticket_id' => $ticket->id,
87 'person_id' => $person->id,
88 'conversation_type' => 'internal_info',
89 'content' => $ticket->agent->user_id !== $person->user_id ?
90 $person->full_name . __(' assigned ', 'fluent-support') . $ticket->agent->full_name . __(' in this ticket', 'fluent-support') :
91 $person->full_name .__( ' assign this ticket to self', 'fluent-support')
92 ]);
93
94 return $person;
95 }
96
97 /**
98 * This `getTickets` method will return the all tickets
99 * @param array $data This is the data that will be used to filter the tickets
100 * @param string $filterType This is the type of filter that will be used to filter the tickets
101 * @return array $tickets
102 */
103 public function getTickets($data, $filterType)
104 {
105 $queryArgs = $this->prepareQuery($data, $filterType);
106 $tickets = $this->getTicketsByQuery($queryArgs);
107
108 foreach ($tickets as $ticket) {
109 if (Arr::get($data, 'per_page') < 15) {
110 if ($ticket->status != 'closed') {
111 $ticket->live_activity = TicketHelper::getActivity($ticket->id);
112 } else {
113 $ticket->live_activity = [];
114 }
115 }
116 }
117
118 return [
119 'tickets' => $tickets
120 ];
121 }
122
123 /**
124 * This is a supporting method for getTickets method
125 * it prepares the query arguments for tickets filtering
126 * @param array $data
127 * @param string $filterType
128 * @return array
129 */
130 private function prepareQuery($data, $filterType)
131 {
132 $queryArgs = [
133 'with' => [],
134 'filter_type' => $filterType,
135 'sort_by' => sanitize_sql_orderby(Arr::get($data, 'order_by', 'id')),
136 'sort_type' => Arr::get($data, 'order_type', 'DESC') == 'DESC' ? 'DESC' : 'ASC',
137 ];
138
139 if ($filterType == 'advanced') {
140 //Get the selected query params for advanced filter
141 $queryArgs['filters_groups_raw'] = json_decode(Arr::get($data, 'advanced_filters', '[]'), true);
142 } else {
143 //Selected filter type is simple
144 $queryArgs['simple_filters'] = Arr::get($data, 'filters', []);
145 $queryArgs['search'] = trim(Arr::get($data, 'search', ''));
146 if ($customerId = Arr::get($data, 'customer_id')) {
147 $queryArgs['customer_id'] = $customerId;
148 }
149 }
150
151 return $queryArgs;
152 }
153
154 // This is a supporting method for getTickets method
155 // it returns the tickets by query arguments
156 private function getTicketsByQuery($queryArgs)
157 {
158 $ticketsModel = (new TicketQueryService($queryArgs))->getModel();
159
160 $ticketsModel = $ticketsModel->with([
161 'customer' => function ($query) {
162 $query->select(['first_name', 'last_name', 'email', 'id', 'avatar']);
163 }, 'agent' => function ($query) {
164 $query->select(['first_name', 'last_name', 'id']);
165 },
166 'mailbox',
167 'product',
168 'tags',
169 'preview_response' => function ($query) {
170 $query->latest('id');
171 }
172 ]);
173
174
175 // apply filters by access level
176 do_action_ref_array('fluent_support/tickets_query_by_permission_ref', [&$ticketsModel, false]);
177
178 return $ticketsModel->paginate();
179 }
180
181 /**
182 * This `addTicketAttachments` method is responsible for adding attachments to ticket
183 * @param array $data
184 * @param array $disabledFields
185 * @param \FluentSupport\App\Models\Ticket $ticket
186 * @param object $customer
187 * @return \FluentSupport\App\Models\Ticket $ticket
188 * @since 1.5.7
189 */
190 public static function addTicketAttachments($data, $disabledFields, $ticket, $customer)
191 {
192 Helper::tempImageMoveUploadDir($ticket->id, 'ticket-create');
193
194 if (($attachmentsHashes = Arr::get($data, 'attachments')) && !in_array('file_upload', $disabledFields)) {
195 $attachments = Attachment::whereIn('file_hash', $attachmentsHashes)
196 ->where('status', 'in-active')
197 ->get();
198
199 if ($attachments->isEmpty()) {
200 return $ticket;
201 }
202
203 $storageDriver = Helper::getUploadDriverKey();
204
205 if ($storageDriver != 'local') {
206 foreach ($attachments as $attachment) {
207 do_action_ref_array('fluent_support/finalize_file_upload_' . $storageDriver, [&$attachment, $ticket->id]);
208 }
209 }
210
211 foreach ($attachments as $attachment) {
212 if ($attachment->driver == 'local') {
213 $newFileInfo = UploadService::copyFileTicketFolder($attachment->file_path, $ticket->id);
214 if ($newFileInfo) {
215 $attachment->file_path = $newFileInfo['file_path'];
216 $attachment->full_url = $newFileInfo['url'];
217 }
218 }
219
220 $attachment->ticket_id = $ticket->id;
221 $attachment->person_id = $customer->id;
222 $attachment->status = 'active';
223 $attachment->save();
224 }
225
226 $ticket->load('attachments');
227 }
228
229 return $ticket;
230 }
231
232 /**
233 * This `delete` method is responsible for deleting the ticket by ticket id
234 * @param int $id
235 * @return array
236 */
237 public function delete($ticket)
238 {
239 $deletePermission = PermissionManager::currentUserCan('fst_delete_tickets');
240 $agent = Helper::getAgentByUserId();
241 if (!$deletePermission && $ticket->agent_id != $agent->id) {
242 throw new \Exception(esc_html__('You are not allowed to delete this ticket', 'fluent-support'));
243 }
244
245 $ticketData = [
246 'id' => $ticket->id,
247 'title' => $ticket->title
248 ];
249 do_action('fluent_support/deleting_ticket', $ticket);
250 $ticket->delete();
251 do_action('fluent_support/ticket_deleted', $agent, $ticketData);
252
253 return [
254 'message' => __('Ticket has been deleted successfully', 'fluent-support')
255 ];
256 }
257
258 public function deleteTickets($tickets)
259 {
260 $tickets->each(function ($ticket) {
261 $this->delete($ticket);
262 });
263
264 return [
265 // translators: %d is the number of tickets that were deleted
266 'message' => sprintf(__('%d tickets have been deleted', 'fluent-support'), count($tickets))
267 ];
268 }
269 }
270