PluginProbe
Fluent Support – Helpdesk & Customer Support Ticket System / 2.1.0
Fluent Support – Helpdesk & Customer Support Ticket System v2.1.0
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 2.1.0, at app/Services/Tickets/TicketService.php

250 lines 9.0 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');
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 do_action('fluent_support/agent_initiated_ticket_response', $agentResponse, $createdTicket, $agent);
219
220 $createdTicket->content = $initializedMessage;
221
222 }
223
224 $createdTicket->save();
225 }
226
227 do_action('fluent_support/ticket_created', $createdTicket, $customer);
228 do_action('fluent_support/ticket_created_behalf_of_customer', $createdTicket, $customer, $agent);
229
230 return $createdTicket;
231 }
232
233 public function deleteTicket($ticket, $agent = null)
234 {
235 if (!$agent) {
236 $agent = Helper::getAgentByUserId();
237 }
238
239 $ticketData = [
240 'id' => $ticket->id,
241 'title' => $ticket->title
242 ];
243
244 do_action('fluent_support/deleting_ticket', $ticket);
245 $ticket->delete();
246 do_action('fluent_support/ticket_deleted', $agent, $ticketData);
247 }
248
249 }
250