PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.2.1
Fluent Support – Helpdesk & Customer Support Ticket System v2.2.1
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 / Services / Tickets / TicketService.php

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

262 lines 9.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\Tickets;
4
5 use FluentSupport\App\Models\Attachment;
6 use FluentSupport\App\Models\Conversation;
7 use FluentSupport\App\Models\MailBox;
8 use FluentSupport\App\Models\Ticket;
9 use FluentSupport\App\Services\Helper;
10 use FluentSupport\App\Services\Includes\UploadService;
11 use FluentSupport\Framework\Support\Arr;
12
13 class TicketService
14 {
15 /**
16 * this function will set the ticket status as closed
17 * @param $ticket
18 * @param $person
19 * @param string $internalNote
20 * @param bool $silently
21 * @return mixed
22 */
23
24 public function close($ticket, $person, $internalNote = '', $silently = 'no')
25 {
26 if ($ticket->status != 'closed') {
27 $ticket->status = 'closed';
28 $ticket->resolved_at = current_time('mysql');
29 $ticket->closed_by = $person->id;
30 $ticket->total_close_time = current_time('timestamp') - strtotime($ticket->created_at);
31 $ticket->save();
32
33 if ('no' == $silently) {
34 do_action('fluent_support/ticket_closed', $ticket, $person);
35 do_action('fluent_support/ticket_closed_by_' . $person->person_type, $ticket, $person);
36 }
37
38 if (!$internalNote) {
39 $internalNote = __('Ticket has been closed', 'fluent-support');
40 }
41
42 //Keep track in conversation
43 Conversation::create([
44 'ticket_id' => $ticket->id,
45 'person_id' => $person->id,
46 'conversation_type' => 'internal_info',
47 'content' => $internalNote
48 ]);
49 }
50
51 return $ticket;
52 }
53
54 public function reopen($ticket, $person)
55 {
56 if ($ticket->status == 'closed') {
57 $ticket->status = 'active';
58 $ticket->waiting_since = current_time('mysql');
59 $ticket->save();
60
61 /*
62 * Action on ticket reopen
63 *
64 * @since v1.0.0
65 * @param object $ticket
66 * @param object $person
67 */
68 do_action('fluent_support/ticket_reopen', $ticket, $person);
69 do_action('fluent_support/ticket_reopen_by_' . $person->person_type, $ticket, $person);
70 Conversation::create([
71 'ticket_id' => $ticket->id,
72 'person_id' => $person->id,
73 'conversation_type' => 'internal_info',
74 'content' => __('Ticket has been reopened', 'fluent-support')
75 ]);
76 }
77
78 return $ticket;
79 }
80
81 public function onAgentChange($ticket, $person)
82 {
83 do_action('fluent_support/ticket_agent_change', $ticket, $person);
84 Conversation::create([
85 'ticket_id' => $ticket->id,
86 'person_id' => $person->id,
87 'conversation_type' => 'internal_info',
88 'content' => $ticket->agent->user_id !== $person->user_id ?
89 $person->full_name . __(' assigned ', 'fluent-support') . $ticket->agent->full_name . __(' in this ticket', 'fluent-support') :
90 $person->full_name .__( ' assign this ticket to self', 'fluent-support')
91 ]);
92
93 return $person;
94 }
95
96 /**
97 * This `addTicketAttachments` method is responsible for adding attachments to ticket
98 * @param array $data
99 * @param array $disabledFields
100 * @param \FluentSupport\App\Models\Ticket $ticket
101 * @param object $customer
102 * @return \FluentSupport\App\Models\Ticket $ticket
103 * @since 1.5.7
104 */
105 public static function addTicketAttachments($data, $disabledFields, $ticket, $customer)
106 {
107 Helper::tempImageMoveUploadDir($ticket->id, 'ticket-create', null, $customer->id);
108
109 if (($attachmentsHashes = Arr::get($data, 'attachments')) && !in_array('file_upload', $disabledFields)) {
110 $attachments = Attachment::whereIn('file_hash', $attachmentsHashes)
111 ->where('status', 'in-active')
112 ->get();
113
114 if ($attachments->isEmpty()) {
115 return $ticket;
116 }
117
118 $storageDriver = Helper::getUploadDriverKey();
119
120 if ($storageDriver != 'local') {
121 foreach ($attachments as $attachment) {
122 do_action_ref_array('fluent_support/finalize_file_upload_' . $storageDriver, [&$attachment, $ticket->id]);
123 }
124 }
125
126 foreach ($attachments as $attachment) {
127 if ($attachment->driver == 'local') {
128 $newFileInfo = UploadService::copyFileTicketFolder($attachment->file_path, $ticket->id);
129 if ($newFileInfo) {
130 $attachment->file_path = $newFileInfo['file_path'];
131 $attachment->full_url = $newFileInfo['url'];
132 }
133 }
134
135 $attachment->ticket_id = $ticket->id;
136 $attachment->person_id = $customer->id;
137 $attachment->status = 'active';
138 $attachment->save();
139 }
140
141 $ticket->load('attachments');
142 }
143
144 return $ticket;
145 }
146
147 /**
148 * Sanitize ticket data, create the ticket, handle attachments & custom fields, fire hooks.
149 * Shared by TicketController::createTicket and ProTicketService::handleSplitTicket.
150 *
151 * @param array $ticketData
152 * @param \FluentSupport\App\Models\Customer $customer
153 * @return \FluentSupport\App\Models\Ticket
154 */
155 public function storeTicket($ticketData, $customer)
156 {
157 if (empty($ticketData['mailbox_id'])) {
158 $mailbox = Helper::getDefaultMailBox();
159 if ($mailbox) {
160 $ticketData['mailbox_id'] = $mailbox->id;
161 }
162 } else {
163 $mailbox = MailBox::findOrFail($ticketData['mailbox_id']);
164 }
165
166 if (!empty($ticketData['product_id'])) {
167 $ticketData['product_source'] = 'local';
168 }
169
170 $ticketData['title'] = sanitize_text_field(wp_unslash($ticketData['title']));
171 $ticketData['content'] = wp_specialchars_decode(wp_unslash(wp_kses_post($ticketData['content'])));
172
173 if (!empty($ticketData['priority'])) {
174 $ticketData['priority'] = sanitize_text_field($ticketData['priority']);
175 }
176
177 if (!empty($ticketData['client_priority'])) {
178 $ticketData['client_priority'] = sanitize_text_field($ticketData['client_priority']);
179 }
180
181 $ticketData = apply_filters('fluent_support/create_ticket_data', $ticketData, $customer);
182
183 do_action('fluent_support/before_ticket_create', $ticketData, $customer);
184
185 $createdTicket = Ticket::create($ticketData);
186
187 $disabledFields = apply_filters('fluent_support/disabled_ticket_fields', []);
188 self::addTicketAttachments($ticketData, $disabledFields, $createdTicket, $customer);
189
190 if (defined('FLUENTSUPPORTPRO') && !empty($ticketData['custom_fields'])) {
191 $createdTicket->syncCustomFields($ticketData['custom_fields']);
192 }
193
194 $agent = Helper::getAgentByUserId();
195 if ($agent) {
196 $isAgentInitiated = Arr::get($ticketData, 'agent_initiated') === 'yes';
197 $createdTicket->created_by = $agent->id;
198
199 if ($isAgentInitiated) {
200 // Skip all ticket creation emails for agent-initiated tickets
201 add_filter('fluent_support/should_send_notification', function ($shouldSend, $channel, $type) {
202 if ($channel === 'email' && in_array($type, ['ticket_created_email_to_customer', 'ticket_created_email_to_admin', 'ticket_created_by_agent_email_to_customer'])) {
203 return false;
204 }
205 return $shouldSend;
206 }, 10, 3);
207
208 $initializedMessage = $agent->full_name . __(' initialized this ticket', 'fluent-support');
209
210 // Agent response: actual ticket content — sends reply email to customer
211 $agentResponse = Conversation::create([
212 'ticket_id' => $createdTicket->id,
213 'person_id' => $agent->id,
214 'conversation_type' => 'response',
215 'content' => $createdTicket->content
216 ]);
217
218 if ($attachmentHashes = Arr::get($ticketData, 'attachments', [])) {
219 Attachment::where('ticket_id', $createdTicket->id)
220 ->whereIn('file_hash', $attachmentHashes)
221 ->where('status', 'active')
222 ->update([
223 'person_id' => $agentResponse->person_id,
224 'conversation_id' => $agentResponse->id
225 ]);
226
227 $agentResponse->load('attachments');
228 }
229
230 do_action('fluent_support/agent_initiated_ticket_response', $agentResponse, $createdTicket, $agent);
231
232 $createdTicket->content = $initializedMessage;
233
234 }
235
236 $createdTicket->save();
237 }
238
239 do_action('fluent_support/ticket_created', $createdTicket, $customer);
240 do_action('fluent_support/ticket_created_behalf_of_customer', $createdTicket, $customer, $agent);
241
242 return $createdTicket;
243 }
244
245 public function deleteTicket($ticket, $agent = null)
246 {
247 if (!$agent) {
248 $agent = Helper::getAgentByUserId();
249 }
250
251 $ticketData = [
252 'id' => $ticket->id,
253 'title' => $ticket->title
254 ];
255
256 do_action('fluent_support/deleting_ticket', $ticket);
257 $ticket->delete();
258 do_action('fluent_support/ticket_deleted', $agent, $ticketData);
259 }
260
261 }
262