PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.4.5
Fluent Support – Helpdesk & Customer Support Ticket System v2.4.5
2.4.5 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 All 69 releases
fluent-support / app / Models / Traits / AgentTrait.php

AgentTrait.php in Fluent Support – Helpdesk & Customer Support Ticket System 2.4.5, at app/Models/Traits/AgentTrait.php

373 lines 12.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\Models\Traits;
4
5 use FluentSupport\App\Models\Attachment;
6 use FluentSupport\App\Models\Conversation;
7 use FluentSupport\App\Models\Meta;
8 use FluentSupport\App\Models\Product;
9 use FluentSupport\App\Models\AgentGroup;
10 use FluentSupport\App\Models\TagPivot;
11 use FluentSupport\App\Models\Ticket;
12 use FluentSupport\App\Modules\PermissionManager;
13 use FluentSupport\App\Models\Person;
14 use FluentSupport\App\Modules\Reporting\Reporting;
15 use FluentSupport\App\Modules\StatModule;
16 use FluentSupport\App\Services\Helper;
17 use FluentSupport\App\Services\TicketHelper;
18 use FluentSupport\App\Services\Tickets\AgentTicketAccess;
19 use FluentSupport\Framework\Support\Arr;
20 use Exception;
21
22 trait AgentTrait
23 {
24 public function getAgents($search)
25 {
26 $agents = static::latest()
27 ->searchBy($search)
28 ->with(['groups' => function ($query) {
29 $query->select(['fs_taggables.id', 'title']);
30 }])
31 ->paginate();
32
33 $agentIds = $agents->pluck('id')->map('intval')->all();
34
35 if (!$agentIds) {
36 return $agents;
37 }
38
39 // One query per kind of data for the whole page, not per agent.
40 $repliesCount = Conversation::whereIn('person_id', $agentIds)
41 ->groupBy('person_id')
42 ->selectRaw('person_id, COUNT(*) AS total')
43 ->pluck('total', 'person_id')
44 ->all();
45
46 $interactionsCount = Conversation::whereIn('person_id', $agentIds)
47 ->groupBy('person_id')
48 ->selectRaw('person_id, COUNT(DISTINCT ticket_id) AS total')
49 ->pluck('total', 'person_id')
50 ->all();
51
52 $metaDefaults = [
53 'telegram_chat_id' => '',
54 'slack_user_id' => '',
55 'whatsapp_number' => '',
56 'agent_restrictions' => [
57 'restrictedBusinessBoxes' => [],
58 'businessBoxRestrictions' => false
59 ],
60 'agent_signature' => '',
61 'agent_signature_enabled' => 'no',
62 ];
63
64 $metaRows = Meta::where('object_type', 'person_meta')
65 ->whereIn('object_id', $agentIds)
66 ->whereIn('key', array_keys($metaDefaults))
67 ->orderBy('id', 'ASC')
68 ->get(['object_id', 'key', 'value']);
69
70 // First row per agent and key wins, as getMeta()'s first() did.
71 $metaValues = [];
72 foreach ($metaRows as $row) {
73 if (!isset($metaValues[$row->object_id][$row->key])) {
74 $metaValues[$row->object_id][$row->key] = Helper::safeUnserialize($row->value);
75 }
76 }
77
78 // Prime WordPress's user and user meta caches for the permission lookups.
79 $userIds = array_filter(array_map('intval', $agents->pluck('user_id')->all()));
80 if ($userIds) {
81 cache_users($userIds);
82 }
83
84 foreach ($agents as $agent) {
85 $agent->permissions = PermissionManager::getUserPermissions($agent->user_id);
86
87 if ($agent->user_id) {
88 $agent->user_profile = admin_url('user-edit.php?user_id=' . $agent->user_id);
89 }
90
91 $agent->replies_count = (int) Arr::get($repliesCount, $agent->id, 0);
92 $agent->interactions_count = (int) Arr::get($interactionsCount, $agent->id, 0);
93
94 // Same rule as getMeta(): a missing or empty value falls back to the default.
95 $meta = function ($key) use ($metaValues, $metaDefaults, $agent) {
96 $value = $metaValues[$agent->id][$key] ?? null;
97 return $value ? $value : $metaDefaults[$key];
98 };
99
100 $agent->telegram_chat_id = $meta('telegram_chat_id');
101 $agent->slack_user_id = $meta('slack_user_id');
102 $agent->whatsapp_number = $meta('whatsapp_number');
103 $agent->restrictions = $meta('agent_restrictions');
104 $agent->agent_signature = $meta('agent_signature');
105 $agent->agent_signature_enabled = $meta('agent_signature_enabled');
106 }
107
108 return $agents;
109 }
110
111 public function createAgent(array $data)
112 {
113 if (!$user = get_user_by('email', $data['email'])) {
114 throw new \Exception('Sorry, Connected user could not be found with the provided email address');
115 }
116
117 $data = $this->setAgentInfo($data, $user);
118
119 $person = Person::where('email', $data['email'])->first();
120
121 if ($person) {
122 throw new \Exception('Sorry, Another agent/person exist with the same email address. Please use a different email address');
123 }
124
125
126 $agent = $this->setAgentMeta($user, $data, static::create($data));
127
128 $defaultGroup = AgentGroup::whereNotNull('settings')->get()->first(function ($group) {
129 return !empty($group->settings['is_default']);
130 });
131
132 if ($defaultGroup) {
133 TagPivot::create([
134 'tag_id' => $defaultGroup->id,
135 'source_id' => $agent->id,
136 'source_type' => 'agent_group',
137 ]);
138 }
139
140 return $agent;
141 }
142
143 /**
144 * @param array $data
145 * @param object $agent
146 * @return object
147 * @throws Exception
148 */
149 public function updateAgent(array $data, object $agent)
150 {
151 if (!$user = get_user_by('ID', $agent->user_id)) {
152 throw new \Exception('Sorry, Connected user could not be found with the provided email address');
153 }
154
155 PermissionManager::attachPermissions($user, Arr::get($data, 'permissions', []));
156
157 $updateData = Arr::only($data, ['first_name', 'last_name', 'title']);
158 $updateData['user_id'] = $user->ID;
159 $updateData['email'] = $user->user_email;
160
161 static::where('id', $agent->id)
162 ->update($updateData);
163
164 $agent = $this->setAgentMeta($user, $data, $agent);
165
166 return $agent;
167 }
168
169
170 /**
171 * Delete an agent and move their records to the fallback agent.
172 *
173 * @param int $fallBackAgentId
174 * @param int $agentId
175 * @return void
176 * @throws Exception
177 */
178 public function deleteAgent($fallBackAgentId, $agentId)
179 {
180 if ($fallBackAgentId == $agentId) {
181 throw new \Exception('Old Agent and New agent is same person');
182 }
183
184 $agent = static::findOrFail($agentId);
185
186 try {
187 $newAgent = static::findOrFail($fallBackAgentId);
188 } catch (\Exception $e) {
189 throw new \Exception('Fallback agent could not be found');
190 }
191
192 PermissionManager::detachPermissions($agent->user_id);
193
194 $this->assignDataToFallbackAgent($agent->id, $newAgent);
195
196 TagPivot::where('source_id', $agent->id)
197 ->where('source_type', 'agent_group')
198 ->delete();
199
200 $agent->deleteAllMeta();
201
202 static::where('id', $agentId)->delete();
203 }
204
205 /**
206 * @param int $agentId
207 * @param object $newAgent
208 * @return void
209 */
210 private function assignDataToFallbackAgent($agentId, $newAgent)
211 {
212 Attachment::where('person_id', $agentId)->update([
213 'person_id' => $newAgent->id
214 ]);
215
216 Conversation::where('person_id', $agentId)->update([
217 'person_id' => $newAgent->id
218 ]);
219
220 Product::where('created_by', $agentId)->update([
221 'created_by' => $newAgent->id
222 ]);
223
224 Ticket::where('agent_id', $agentId)->update([
225 'agent_id' => $newAgent->id
226 ]);
227 }
228
229 public function getAgentStat($stats, $with, $agentId)
230 {
231 if (PermissionManager::currentUserCan('fst_manage_unassigned_tickets')) {
232 $stats['unassigned_tickets'] = [
233 'title' => __('Unassigned Tickets', 'fluent-support'),
234 'count' => Ticket::whereNull('agent_id')->where('status', '!=', 'closed')->count()
235 ];
236 }
237
238 $data = [
239 'stats' => $stats
240 ];
241
242 return $this->agentDashboardWidgets($data, $with, $agentId);
243 }
244
245 private function agentDashboardWidgets($data, $with, $agentId)
246 {
247 if (in_array('suggested_tickets', $with)) {
248 $data['suggested_tickets'] = TicketHelper::getSuggestedTickets($agentId);
249 }
250
251 if (defined('FLUENTSUPPORTPRO') && in_array('ticket_to_watch', $with)) {
252 $data['ticket_to_watch'] = TicketHelper::getTicketsToWatch();
253 }
254
255 if (in_array('overall_stats', $with)) {
256 $data['overall_stats'] = (new Reporting())->getActiveStats();
257 }
258
259 if (in_array('individual_stat', $with)) {
260 $data['individual_stat'] = (new Reporting())->getActiveStatByAgent($agentId);
261 }
262 if (in_array('my_overall_stats', $with)) {
263 $data['my_overall_stats'] = StatModule::getAgentOverallStats($agentId);
264 }
265
266 if (in_array('tickets_by_products', $with)) {
267 $data['tickets_by_product'] = StatModule::getActiveTicketsByProductStats();
268 }
269
270 return $data;
271 }
272
273 /**
274 * @param array $data
275 * @param $user
276 * @return array
277 */
278 private function setAgentInfo(array $data, $user)
279 {
280 $data['user_id'] = $user->ID;
281
282 if (empty($data['first_name'])) {
283 $data['first_name'] = $user->first_name;
284 }
285
286 if (empty($data['last_name'])) {
287 $data['last_name'] = $user->last_name;
288 }
289
290 return $data;
291 }
292
293 /**
294 * Save permissions and agent settings meta.
295 *
296 * @param $user
297 * @param array $data
298 * @param object $agent
299 * @return object
300 */
301 private function setAgentMeta($user, $data, $agent)
302 {
303 PermissionManager::attachPermissions($user, Arr::get($data, 'permissions', []));
304
305 if (isset($data['telegram_chat_id'])) {
306 $chatId = sanitize_text_field($data['telegram_chat_id']);
307 $agent->updateMeta('telegram_chat_id', $chatId);
308 $agent->telegram_chat_id = $chatId;
309 }
310
311 if (isset($data['slack_user_id'])) {
312 $chatId = sanitize_text_field($data['slack_user_id']);
313 $agent->updateMeta('slack_user_id', $chatId);
314 $agent->slack_user_id = $chatId;
315 }
316
317 if (isset($data['whatsapp_number'])) {
318 $whatsappNumber = sanitize_text_field($data['whatsapp_number']);
319 $agent->updateMeta('whatsapp_number', $whatsappNumber);
320 $agent->whatsapp_number = $whatsappNumber;
321 }
322
323 if (isset($data['restrictions'])) {
324 $restrictedBusinessBoxes = $data['restrictions']['restrictedBusinessBoxes'] ?? [];
325 $businessBoxRestrictions = filter_var($data['restrictions']['businessBoxRestrictions'] ?? false, FILTER_VALIDATE_BOOLEAN);
326
327 $restrictions = [
328 'restrictedBusinessBoxes' => is_array($restrictedBusinessBoxes) ? array_map('intval', $restrictedBusinessBoxes) : [],
329 'businessBoxRestrictions' => $businessBoxRestrictions
330 ];
331
332 $agent->updateMeta('agent_restrictions', $restrictions);
333 AgentTicketAccess::resetCache();
334 $agent->restrictions = $restrictions;
335 }
336
337 if (isset($data['agent_signature'])) {
338 $agent->updateMeta('agent_signature', $data['agent_signature']);
339 $agent->agent_signature = $data['agent_signature'];
340 }
341
342 if (isset($data['agent_signature_enabled'])) {
343 $agent->updateMeta('agent_signature_enabled', $data['agent_signature_enabled']);
344 $agent->agent_signature_enabled = $data['agent_signature_enabled'];
345 }
346
347 return $agent;
348 }
349
350 public function agentInsights($search)
351 {
352 $agents = static::latest()
353 ->select('id', 'first_name', 'last_name', 'email', 'user_id')
354 ->searchBy($search)
355 ->get();
356
357 foreach ($agents as $agent) {
358 $agent->permissions = PermissionManager::getUserPermissions($agent->user_id);
359
360 if ($agent->user_id) {
361 $agent->user_profile = admin_url('user-edit.php?user_id=' . $agent->user_id);
362 }
363
364 $agent->restrictions = $agent->getMeta('agent_restrictions', [
365 'restrictedBusinessBoxes' => [],
366 'businessBoxRestrictions' => false
367 ]);
368 }
369
370 return $agents;
371 }
372 }
373