PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.3.1
Fluent Support – Helpdesk & Customer Support Ticket System v2.3.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 / Tickets / ResponseService.php

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

255 lines 9.2 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\Services\Helper;
8 use FluentSupport\App\Services\Includes\UploadService;
9 use FluentSupport\Framework\Support\Arr;
10
11 class ResponseService
12 {
13 /**
14 * createResponse method is responsible for create responses to ticket by agent or customer
15 * @param $data
16 * @param $person
17 * @param $ticket
18 * @return array|false
19 */
20 public function createResponse($data, $person, $ticket, $silently = false)
21 {
22 if (empty($data['content'])) {
23 return false;
24 }
25
26 $cc_emails = Arr::get($data, 'cc_emails', []);
27
28 $informationalReply = Arr::get($data, 'informational_reply', false);
29 // Adding support for shortcode in agent response
30 if ($person->person_type == 'agent') {
31 $data['content'] = apply_filters('fluent_support/parse_smartcode_data', $data['content'], [
32 'customer' => $ticket->customer,
33 'agent' => $person
34 ]);
35 }
36
37 if ($person->person_type == 'agent' && Arr::get($data, 'conversation_type', 'response') == 'response') {
38 $data['content'] = $this->maybeAppendSignature($data['content'], $person);
39 }
40
41 $convoType = Arr::get($data, 'conversation_type', 'response');
42
43 $content = wp_unslash(wp_kses_post($data['content']));
44 $resetWaitingSince = apply_filters('fluent_support/reset_waiting_since', true, $content);
45 $content = apply_filters('fluent_support/response_content_before_use_anywhere', $content);
46 $response = [
47 'person_id' => $person->id,
48 'ticket_id' => $ticket->id,
49 'conversation_type' => $convoType,
50 'content' => $content,
51 'source' => Arr::get($data, 'source', 'web'),
52 'content_hash' => md5($content)
53 ];
54
55 if (!empty($data['message_id'])) {
56 $response['message_id'] = sanitize_text_field($data['message_id']);
57 }
58
59 $response = apply_filters('fluent_support/new_' . $person->person_type . '_' . $convoType, $response, $ticket, $person);
60
61 $createdResponse = \FluentSupport\App\Models\Conversation::create($response);
62
63 if (!empty($cc_emails)) {
64 //Store cc emails in meta settings for the response
65 $createdResponse->updateSettingsValue('cc_email', $cc_emails);
66
67 //Store all the carbon copy customers under the ticket
68 $existingCcEmails = $ticket->getSettingsValue('all_cc_email', []);
69 $newData = array_merge($existingCcEmails, $cc_emails);
70 $ticket->updateSettingsValue('all_cc_email', array_unique($newData));
71 }
72
73 $createdResponse->load('person');
74
75 if ($person->person_type == 'agent' && $ticket->status == 'new' && $convoType == 'response') {
76 $ticket->status = 'active';
77 if ($ticket->created_at) {
78 $ticket->first_response_time = strtotime(current_time('mysql')) - strtotime($ticket->created_at);
79 } else {
80 $ticket->first_response_time = 300;
81 }
82 }
83
84 $agentAdded = false;
85 $previousAgentId = (int) $ticket->agent_id;
86 $updateData = [];
87
88 if ($person->person_type == 'agent') {
89 if (!$ticket->agent_id && $convoType == 'response') {
90 $ticket->agent_id = $person->id;
91 $agentAdded = true;
92 $updateData = [
93 'agent_id' => $person->id
94 ];
95 }
96
97 if ($convoType == 'response') {
98 if ($resetWaitingSince && !$informationalReply) {
99 $ticket->last_agent_response = current_time('mysql');
100 $ticket->waiting_since = current_time('mysql');
101 }
102 }
103 } else {
104
105 if ($ticket->last_agent_response && strtotime($ticket->last_agent_response) > strtotime($ticket->last_customer_response)) {
106 $ticket->waiting_since = current_time('mysql');
107 }
108
109 $ticket->last_customer_response = current_time('mysql');
110 }
111
112 if ($convoType == 'response') {
113 $ticket->response_count += 1;
114 }
115
116 $closed = false;
117 if (Arr::get($data, 'close_ticket') == 'yes' && $ticket->status != 'closed') {
118 $ticket->status = 'closed';
119 $ticket->resolved_at = current_time('mysql');
120 $ticket->closed_by = $person->id;
121 $ticket->total_close_time = current_time('timestamp') - strtotime($ticket->created_at);
122 $closed = true;
123
124 $internalNote = __('Ticket has been closed', 'fluent-support');
125
126 $internalNote = apply_filters('fluent_support/ticket_close_internal_note', $internalNote, $ticket);
127
128 if ($internalNote) {
129 Conversation::create([
130 'ticket_id' => $ticket->id,
131 'person_id' => $person->id,
132 'conversation_type' => 'internal_info',
133 'content' => $internalNote
134 ]);
135 }
136 }
137
138 $ticket->save();
139
140 Helper::tempImageMoveUploadDir($ticket->id, 'conversation', $createdResponse->id, $person->id);
141
142 //If file upload failed to local during create response
143 if ($attachmentHashes = Arr::get($data, 'attachments', [])) {
144 $attachments = Attachment::where('ticket_id', $ticket->id)
145 ->whereIn('file_hash', $attachmentHashes)
146 ->where('status', 'in-active')
147 ->get();
148
149 if (!$attachments->isEmpty()) {
150 $storageDriver = Helper::getUploadDriverKey();
151 foreach ($attachments as $attachment) {
152 if ($storageDriver != 'local') {
153 do_action_ref_array('fluent_support/finalize_file_upload_' . $storageDriver, [&$attachment, $ticket->id]);
154 }
155
156 if ($attachment->driver == 'local') {
157 $newFileInfo = UploadService::copyFileTicketFolder($attachment->file_path, $ticket->id);
158 if ($newFileInfo && !empty($newFileInfo['file_path'])) {
159 $attachment->file_path = $newFileInfo['file_path'];
160 $attachment->full_url = $newFileInfo['url'];
161 }
162 }
163
164 $attachment->ticket_id = $ticket->id;
165 $attachment->person_id = $createdResponse->person_id;
166 $attachment->conversation_id = $createdResponse->id;
167 $attachment->status = 'active';
168 $attachment->save();
169 }
170 $createdResponse->load('attachments');
171 }
172 }
173
174 if ($silently) {
175 return [
176 'response' => $createdResponse,
177 'ticket' => $ticket,
178 'update_data' => $updateData
179 ];
180 }
181
182 if ($agentAdded) {
183 $assigner = Helper::getCurrentAgent();
184 $ticket->load('agent');
185
186 /*
187 * Action on ticket assign to an agent
188 *
189 * @since v1.0.0
190 * @param object $person
191 * @param object $ticket
192 * @param object $assigner
193 */
194 do_action('fluent_support/agent_assigned_to_ticket', $person, $ticket, $assigner, $previousAgentId);
195 $updateData['agent'] = $ticket->agent;
196 }
197
198 /*
199 * Action on conversation
200 *
201 * @since v1.0.0
202 * @param string $convoType
203 * @param string $personType
204 * @param object $createdResponse
205 * @param object $ticket
206 * @param object $person
207 */
208 do_action('fluent_support/' . $convoType . '_added_by_' . $person->person_type, $createdResponse, $ticket, $person);
209
210
211 if ($closed) {
212 /*
213 * Action on ticket close
214 *
215 * @since v1.0.0
216 * @param object $ticket
217 * @param object $person
218 */
219 do_action('fluent_support/ticket_closed', $ticket, $person);
220
221 /*
222 * Action on ticket close
223 *
224 * @since v1.0.0
225 * @param string $personType
226 * @param object $ticket
227 * @param object $person
228 */
229 do_action('fluent_support/ticket_closed_by_' . $person->person_type, $ticket, $person);
230 }
231
232 return [
233 'response' => $createdResponse,
234 'ticket' => $ticket,
235 'update_data' => $updateData
236 ];
237 }
238
239 public function maybeAppendSignature($content, $person)
240 {
241 if ($person->getMeta('agent_signature_enabled', 'no') !== 'yes') {
242 return $content;
243 }
244
245 $signature = $person->getMeta('agent_signature', '');
246 $hasText = !empty(trim(strip_tags($signature)));
247 $hasImage = (bool) preg_match('/<img[\s>]/i', $signature);
248 if (!$hasText && !$hasImage) {
249 return $content;
250 }
251
252 return $content . '<div class="fs_agent_signature">' . $signature . '</div>';
253 }
254 }
255