PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 1.10.1
Fluent Support – Helpdesk & Customer Support Ticket System v1.10.1
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 / TicketHelper.php

TicketHelper.php in Fluent Support – Helpdesk & Customer Support Ticket System 1.10.1, at app/Services/TicketHelper.php

378 lines 12.6 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;
4
5 use FluentSupport\App\Models\Agent;
6 use FluentSupport\App\Models\Conversation;
7 use FluentSupport\App\Models\MailBox;
8 use FluentSupport\App\Models\Meta;
9 use FluentSupport\App\Models\Product;
10 use FluentSupport\App\Models\TagPivot;
11 use FluentSupport\App\Models\Ticket;
12 use FluentSupport\App\Models\TicketTag;
13 use FluentSupport\App\Modules\PermissionManager;
14 use FluentSupport\App\Services\Helper;
15
16 class TicketHelper
17 {
18 /**
19 * getActivity method will return the activity in a ticket by agent
20 * @param $ticketId
21 * @param false $currentAgentId
22 * @return array
23 */
24 public static function getActivity($ticketId, $currentAgentId = false)
25 {
26 //Get the ticket meta information
27 $meta = Meta::where('object_type', 'ticket_meta')
28 ->where('key', '_live_activity')
29 ->where('object_id', $ticketId)
30 ->first();
31
32 $activities = [];
33 if ($meta) {
34 $activities = Helper::safeUnserialize($meta->value);
35 }
36
37 foreach ($activities as $index => $activity) {
38 if ((time() - $activity) > 60) {
39 unset($activities[$index]);
40 }
41 }
42
43 if (!$currentAgentId) {
44 return self::getAgentsInfoFromActivities($activities);
45 }
46
47 $activities[$currentAgentId] = time();
48
49 if ($meta) {
50 $meta->value = maybe_serialize($activities);
51 $meta->save();
52 } else {
53 Meta::insert([
54 'object_type' => 'ticket_meta',
55 'key' => '_live_activity',
56 'object_id' => $ticketId,
57 'value' => maybe_serialize($activities)
58 ]);
59 }
60
61 return self::getAgentsInfoFromActivities($activities);
62 }
63
64 public static function getAgentsInfoFromActivities($activities)
65 {
66 if (!$activities) {
67 return [];
68 }
69
70 return Agent::select(['email', 'first_name', 'last_name'])
71 ->whereIn('id', array_keys($activities))
72 ->get();
73 }
74
75 /**
76 * removeFromActivities method will remove the old live activity by agent and ticket id
77 * @param $ticketId
78 * @param $agentId
79 * @return bool
80 */
81 public static function removeFromActivities($ticketId, $agentId)
82 {
83 $meta = Meta::where('object_type', 'ticket_meta')
84 ->where('key', '_live_activity')
85 ->where('object_id', $ticketId)
86 ->first();
87
88 $activities = [];
89 if ($meta) {
90 $activities = Helper::safeUnserialize($meta->value);
91 }
92
93 if (!$activities) {
94 return false;
95 }
96
97 unset($activities[$agentId]);
98 foreach ($activities as $index => $activity) {
99 if ((time() - $activity) > 60) {
100 unset($activities[$index]);
101 }
102 }
103
104 $meta->value = maybe_serialize($activities);
105 $meta->save();
106
107 return true;
108 }
109
110 /**
111 * getSuggestedTickets method will return the list of Suggested tickets
112 * This method will get the agent id as parameter and fetch ticket information that are waiting to reply or unassigned
113 * @param $agentId
114 * @param int $limit
115 * @return mixed
116 */
117 public static function getSuggestedTickets($agentId, $limit = 5)
118 {
119 $restrictedBusinessBoxes = PermissionManager::currentUserRestrictedBusinessBoxes();
120
121 //Get lis of tickets which are waiting for reply
122 $tickets = Ticket::where('agent_id', $agentId)
123 ->whereNotIn('mailbox_id', $restrictedBusinessBoxes)
124 ->where('status', '!=', 'closed')
125 ->applyFilters([
126 'waiting_for_reply' => 'yes'
127 ])
128 ->oldest('last_customer_response')
129 ->limit($limit)
130 ->with('customer')
131 ->get();
132
133 //If no ticket is available for reply and logged-in user has permission to manage unassigned tickets
134 if($tickets->isEmpty() && PermissionManager::currentUserCan('fst_manage_unassigned_tickets')) {
135 //Get the ticket list which status is not closed and agent id is null or 0
136 $tickets = Ticket::where('status', '!=', 'closed')
137 ->oldest('id')
138 ->whereNotIn('mailbox_id', $restrictedBusinessBoxes)
139 ->where(function ($q) {
140 $q->whereNull('agent_id');
141 $q->orWhere('agent_id', '0');
142 })
143 ->with('customer')
144 ->limit($limit)
145 ->get();
146 }
147
148
149 return $tickets;
150
151 }
152
153 // This method will return all tagged/mentioned/watcher ticket's ids for filtering
154 public static function getWatcherTicketIds($agentId)
155 {
156 $mentioned = TagPivot::where('source_type', 'ticket_watcher')
157 ->where('tag_id', $agentId)
158 ->latest('id')
159 ->get(['source_id']);
160
161 $ticketIds = array_column($mentioned->toArray(), 'source_id');
162 return $ticketIds;
163 }
164
165 // This method will return all tagged/mentioned/watcher tickets of logged in agent
166 public static function getTicketsToWatch()
167 {
168 $agent = Helper::getCurrentAgent();
169 $restrictedBusinessBoxes = PermissionManager::currentUserRestrictedBusinessBoxes();
170
171 $tickets = Ticket::with('customer')
172 ->limit(5)
173 ->whereNotIn('mailbox_id', $restrictedBusinessBoxes)
174 ->join('fs_tag_pivot', 'fs_tag_pivot.source_id', '=', 'fs_tickets.id')
175 ->where('fs_tag_pivot.source_type', '=', 'ticket_watcher')
176 ->where('fs_tag_pivot.tag_id', '=', $agent->id)
177 ->select(['fs_tickets.*'])
178 ->get();
179
180 return $tickets;
181 }
182
183 // This method will return all ticket watcher inside a ticket
184 public static function getWatchers($watchers)
185 {
186 $watcherAgents = [];
187
188 foreach ($watchers as $watcher) {
189 $watcherAgents[] = Agent::where('id', absint($watcher->tag_id))->select(['id', 'first_name', 'last_name'])->first();
190 }
191
192 return $watcherAgents;
193 }
194
195 public static function getCarbonCopyCustomerInfo($ticketId){
196 $existing = Meta::where('object_type', 'beginning_cc_info')->where('object_id', $ticketId)->first();
197 if($existing){
198 return Helper::safeUnserialize($existing->value, []);
199 }
200
201 return [];
202 }
203
204 // This method will count total tickets
205 public static function countAllTickets()
206 {
207 return (new Ticket())->count();
208 }
209 // This method will count all un-assigned tickets
210 public static function countUnassignedTickets()
211 {
212 return Ticket::whereNull('agent_id')->count();
213 }
214 // This method will count all closed tickets
215 public static function countClosedTickets()
216 {
217 return Ticket::where('status', 'closed')->count();
218 }
219
220 // This method will count all New tickets
221 public static function countNewTickets()
222 {
223 return Ticket::where('status', 'new')->count();
224 }
225
226 // This method will count all Active tickets
227 public static function countActiveTickets()
228 {
229 return Ticket::where('status', 'active')->count();
230 }
231
232 public static function getTicketEssentials($type = '')
233 {
234 $agents = Agent::select(['id', 'first_name', 'last_name'])
235 ->where('person_type', 'agent')
236 ->get()->toArray();
237
238 $data = [
239 'client_priorities' => Helper::customerTicketPriorities(),
240 'ticket_statuses_group' => Helper::ticketStatusGroups(),
241 'agents' => $agents,
242 'changeable_ticket_statuses' => Helper::changeableTicketStatuses(),
243 'admin_priorities' => Helper::adminTicketPriorities(),
244 'enable_draft_mode' => Helper::getBusinessSettings('enable_draft_mode', 'no'),
245 'max_file_upload' => Helper::getBusinessSettings('max_file_upload', 3),
246 'support_products' => Product::select(['id', 'title'])->get(),
247 'ticket_tags' => TicketTag::select(['id', 'title'])->get()->toArray(),
248 'mailboxes' => MailBox::select(['id', 'name', 'settings'])->get(),
249 'ticket_statuses' => Helper::ticketStatuses(),
250 ];
251
252 return $type ? $data[$type] : $data;
253 }
254
255 public static function getLabelSearch($agentId)
256 {
257 $lists = Meta::where('object_id', $agentId)
258 ->where('object_type', 'search_meta')
259 ->where('key', 'label_search')
260 ->first();
261 $unserialize = [];
262 if ($lists) {
263 $unserialize = Helper::safeUnserialize($lists->value);
264 }
265
266 return $unserialize;
267 }
268
269 public static function saveSearchLabel($agent_id, $searchData, $filterType) {
270
271 $agent_id = get_current_user_id();
272 $existingRecord = Meta::where('object_id', $agent_id)
273 ->where('object_type', 'search_meta')
274 ->where('key', 'label_search')
275 ->first();
276
277 // If record exists, unserialize the data or initialize an empty array
278 $existingData = $existingRecord ? Helper::safeUnserialize($existingRecord->value) ?: [] : [];
279
280 // Check if it's an update or new entry
281 $isUpdate = isset($searchData['id']) && array_filter($existingData, function ($item) use ($searchData) {
282 return isset($item['id']) && $item['id'] == $searchData['id'];
283 });
284
285 // Handle adding or updating
286 $updatedData = self::addOrUpdateSearchData($existingData, $searchData);
287
288 // Save the updated data back to the database
289 if ($existingRecord) {
290 $existingRecord->update([
291 'value' => maybe_serialize($updatedData)
292 ]);
293 } else {
294 Meta::insert([
295 'object_type' => 'search_meta',
296 'key' => 'label_search',
297 'object_id' => $agent_id,
298 'value' => maybe_serialize($updatedData)
299 ]);
300 }
301
302 $message = $isUpdate
303 ? __('Your saved search has been updated successfully!', 'fluent-support')
304 : __('Your search has been saved successfully!', 'fluent-support');
305
306 return [
307 'message' => $message,
308 ];
309 }
310
311 private static function addOrUpdateSearchData(array $existingData, array $searchData): array
312 {
313 if (isset($searchData['id'])) {
314 $updated = false;
315
316 // Update the existing record with the matching ID
317 foreach ($existingData as &$record) {
318 if (isset($record['id']) && $record['id'] == $searchData['id']) {
319 $record = array_merge($record, $searchData);
320 $updated = true;
321 break;
322 }
323 }
324
325 // If no matching record found, append the new data
326 if (!$updated) {
327 $existingData[] = $searchData;
328 }
329 } else {
330 // If no ID provided, generate a new one and add the data
331 $newId = self::generateNewId($existingData);
332 $searchData['id'] = $newId;
333 $existingData[] = $searchData;
334 }
335
336 return $existingData;
337 }
338
339 public static function deleteSavedSearch($search_id) {
340 $agent_id = get_current_user_id();
341 $existingRecord = Meta::where('object_id', $agent_id)
342 ->where('object_type', 'search_meta')
343 ->where('key', 'label_search')
344 ->first();
345
346 if ($existingRecord) {
347 $existingData = Helper::safeUnserialize($existingRecord->value) ?: [];
348
349 $updatedData = array_filter($existingData, function ($item) use ($search_id) {
350 return isset($item['id']) && $item['id'] != $search_id;
351 });
352
353 if (count($existingData) !== count($updatedData)) {
354 $existingRecord->update([
355 'value' => maybe_serialize(array_values($updatedData))
356 ]);
357 return [
358 'message' => __('Search deleted successfully.', 'fluent-support'),
359 ];
360 }
361
362 return [
363 'message' => __('Search ID not found.', 'fluent-support'),
364 ];
365 }
366 }
367
368 private static function generateNewId(array $existingData): int
369 {
370 if (empty($existingData)) {
371 return 1;
372 }
373
374 $maxId = max(array_column($existingData, 'id'));
375 return $maxId + 1;
376 }
377 }
378