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 / Integrations / FluentForm / FeedIntegration.php

FeedIntegration.php in Fluent Support – Helpdesk & Customer Support Ticket System 2.1.0, at app/Services/Integrations/FluentForm/FeedIntegration.php

492 lines 19.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\Integrations\FluentForm;
4
5 use FluentForm\App\Http\Controllers\IntegrationManagerController;
6 use FluentSupport\App\App;
7 use FluentSupport\App\Models\Attachment;
8 use FluentSupport\App\Models\Customer;
9 use FluentSupport\App\Models\MailBox;
10 use FluentSupport\App\Models\Product;
11 use FluentSupport\App\Models\Ticket;
12 use FluentSupport\Framework\Support\Arr;
13
14 class FeedIntegration extends IntegrationManagerController
15 {
16
17 public $hasGlobalMenu = false;
18
19 public $disableGlobalSettings = 'yes';
20
21 public function __construct($app = null)
22 {
23 parent::__construct(
24 $app,
25 'FluentSupport',
26 'fluent_support',
27 '_fluentsupport_settings',
28 'fluentform_fluentsupport_feed',
29 16
30 );
31
32 $app = App::getInstance();
33
34 $assets = $app['url.assets'];
35
36 $this->logo = $assets.'/images/fluent-support-color-logo.png';
37
38 $this->description = __('Create Support Ticket From Your Form Submission in FluentSupport', 'fluent-support');
39
40 $this->registerAdminHooks();
41
42 add_filter('fluentform/notifying_async_fluent_support', '__return_false');
43
44 }
45
46 public function pushIntegration($integrations, $formId)
47 {
48 $integrations[$this->integrationKey] = [
49 'title' => $this->title . ' Integration',
50 'logo' => $this->logo,
51 'is_active' => $this->isConfigured(),
52 'configure_title' => __('Configuration required!', 'fluent-support'),
53 'global_configure_url' => '#',
54 'configure_message' => __('FluentSupport is not configured yet! Please configure your FluentSupport api first', 'fluent-support'),
55 'configure_button_text' => __('Set FluentSupport', 'fluent-support')
56 ];
57 return $integrations;
58 }
59
60 public function getIntegrationDefaults($settings, $formId)
61 {
62 return [
63 'name' => '',
64 'first_name' => '',
65 'last_name' => '',
66 'email' => '',
67 'list_id' => '', // this is the business ID
68 'ticket_title' => '',
69 'ticket_body' => '',
70 'client_priority' => '',
71 'attachments' => '',
72 'product_id' => '',
73 'product_id_selection_type' => 'simple',
74 'product_routers' => [],
75 'customer_other_fields' => [
76 [
77 'item_value' => '',
78 'label' => ''
79 ]
80 ],
81 'conditionals' => [
82 'conditions' => [],
83 'status' => false,
84 'type' => 'all'
85 ],
86 'enabled' => true
87 ];
88 }
89
90 public function getSettingsFields($settings, $formId)
91 {
92 $fieldOptions = [];
93 foreach (Customer::mappables() as $key => $column) {
94 $fieldOptions[$key] = $column;
95 }
96 return [
97 'fields' => [
98 [
99 'key' => 'name',
100 'label' => __('Feed Name', 'fluent-support'),
101 'required' => true,
102 'placeholder' => __('Your Feed Name', 'fluent-support'),
103 'component' => 'text'
104 ],
105 [
106 'key' => 'list_id',
107 'label' => __('Business', 'fluent-support'),
108 'placeholder' => __('Select Business', 'fluent-support'),
109 'tips' => __('Select the Business you would like to add your Support Ticket to.', 'fluent-support'),
110 'component' => 'select',
111 'required' => true,
112 'options' => $this->geMailBoxes(),
113 ],
114 [
115 'key' => 'product_id',
116 'require_list' => false,
117 'label' => __('Product', 'fluent-support'),
118 'placeholder' => __('Select Support Product', 'fluent-support'),
119 'component' => 'selection_routing',
120 'simple_component' => 'select',
121 'routing_input_type' => 'select',
122 'routing_key' => 'product_id_selection_type',
123 'settings_key' => 'product_routers',
124 'is_multiple' => false,
125 'labels' => [
126 'choice_label' => __('Enable Dynamic Product Selection', 'fluent-support'),
127 'input_label' => '',
128 'input_placeholder' => __('Set Product', 'fluent-support')
129 ],
130 'options' => $this->getProducts()
131 ],
132 [
133 'key' => 'ticket_title',
134 'require_list' => false,
135 'label' => __('Ticket Title', 'fluent-support'),
136 'placeholder' => __('Ticket Title', 'fluent-support'),
137 'component' => 'value_text'
138 ],
139 [
140 'key' => 'ticket_content',
141 'require_list' => false,
142 'label' => __('Ticket Content', 'fluent-support'),
143 'placeholder' => __('Ticket Content', 'fluent-support'),
144 'component' => 'value_textarea'
145 ],
146 [
147 'key' => 'ticket_attachments',
148 'require_list' => false,
149 'label' => __('Ticket Attachments', 'fluent-support'),
150 'Placeholder' => __('Ticket Attachments', 'fluent-support'),
151 'tips' => __('Please input your file upload or image upload field shortcode here', 'fluent-support'),
152 'component' => 'value_text'
153 ],
154 [
155 'key' => 'client_priority',
156 'require_list' => false,
157 'label' => __('Ticket Priority', 'fluent-support'),
158 'Placeholder' => __('Ticket Priority', 'fluent-support'),
159 'tips' => __('Make sure form field values match with Fluent Support priorities', 'fluent-support'),
160 'component' => 'value_text'
161 ],
162 $this->getCustomField(), //Getting Fluent Support Custom Field To Map
163 [
164 'component' => 'html_info',
165 'html_info' => '<h4>' . __('Please provide the ticket provider info. If user is logged in then it will use that info. For Public users you can set your customer info', 'fluent-support') . '</h4>'
166 ],
167 [
168 'key' => 'CustomerFields',
169 'require_list' => false,
170 'label' => __('Customer Data', 'fluent-support'),
171 'tips' => __('Please Map Your Customer Data for this form. If your customer already logged in you can leave this', 'fluent-support'),
172 'component' => 'map_fields',
173 'field_label_remote' => __('Support Customer Field', 'fluent-support'),
174 'field_label_local' => __('Form Field', 'fluent-support'),
175 'primary_fileds' => [
176 [
177 'key' => 'email',
178 'label' => __('Email Address', 'fluent-support'),
179 'required' => true,
180 'input_options' => 'emails'
181 ],
182 [
183 'key' => 'first_name',
184 'label' => __('First Name', 'fluent-support')
185 ],
186 [
187 'key' => 'last_name',
188 'label' => __('Last Name', 'fluent-support')
189 ]
190 ]
191 ],
192 [
193 'key' => 'customer_other_fields',
194 'require_list' => false,
195 'label' => __('Customer Other Fields', 'fluent-support'),
196 'tips' => __('Select which Fluent Forms fields pair with their<br /> respective Fluent Support fields.', 'fluent-support'),
197 'field_label_remote' => __('Fluent Support Field', 'fluent-support'),
198 'field_label_local' => __('Form Field', 'fluent-support'),
199 'component' => 'dropdown_many_fields',
200 'options' => $fieldOptions
201 ],
202 ],
203 'button_require_list' => false,
204 'integration_title' => $this->title
205 ];
206 }
207
208 private function geMailBoxes()
209 {
210 $items = MailBox::all();
211 $formattedItems = [];
212 foreach ($items as $item) {
213 $formattedItems[strval($item->id)] = $item->name;
214 }
215 return $formattedItems;
216 }
217
218 private function getProducts()
219 {
220 $products = Product::all();
221 $formattedProducts = [];
222 foreach ($products as $product) {
223 $formattedProducts[strval($product->id)] = $product->title;
224 }
225 return $formattedProducts;
226 }
227
228 private function getCustomField()
229 {
230 $customFields = apply_filters('fluent_support/ticket_custom_fields', []);
231 $fieldToExclude = apply_filters('fluent_support/custom_field_types', []);
232
233 if(empty($customFields)){
234 return[
235 'component' => 'html_info',
236 'html_info' => ''
237 ];
238 }
239
240 $fields = [];
241 foreach ($customFields as $customFieldKey=>$customFieldValue) {
242
243 if(in_array($customFieldValue['type'], array_keys($fieldToExclude))){
244 unset($customFieldValue);
245 }
246
247 $fields[] = [
248 'key' => $customFieldValue['slug'],
249 'label' => $customFieldValue['label']
250 ];
251 }
252
253 $fields = array_map('array_filter', $fields);
254 $fields = array_filter( $fields );
255
256 return [
257 'key' => 'TicketCustomFields',
258 'require_list' => false,
259 'label' => __('Ticket Custom Fields', 'fluent-support'),
260 'tips' => __('Please Map Your Ticket Custom Field Data for this form.', 'fluent-support'),
261 'component' => 'map_fields',
262 'field_label_remote' => __('Fluent Support Custom Field', 'fluent-support'),
263 'field_label_local' => __('Form Field', 'fluent-support'),
264 'primary_fileds' => $fields
265 ];
266 }
267
268 public function getMergeFields($list, $listId, $formId)
269 {
270 return [];
271 }
272
273 public function notify($feed, $formData, $entry, $form)
274 {
275 $data = $feed['processedValues'];
276
277 if (!empty($data['email']) && !is_email($data['email'])) {
278 $data['email'] = Arr::get($formData, $data['email']);
279 }
280
281 $ticketCustomField = array_filter($data, function($key) {
282 return strpos($key, 'cf_') === 0;
283 }, ARRAY_FILTER_USE_KEY);
284
285
286 $customFields = apply_filters('fluent_support/ticket_custom_fields', []);
287
288 foreach($customFields as $key => $field){
289 $type = $field['type'];
290 $slug = $field['slug'];
291 if(!isset($ticketCustomField[$slug])) {
292 continue;
293 }
294
295 if( $type=='checkbox' && array_key_exists($slug, $ticketCustomField)) {
296 $value = Arr::get($ticketCustomField, $slug, '');
297 $ticketCustomField[$slug] = $value ? explode(',', (string)$value) : [];
298 } else {
299 $ticketCustomField[$slug] = Arr::get($ticketCustomField, $slug);
300 }
301 }
302
303 $ticketData = [
304 'product_source' => 'local',
305 'mailbox_id' => Arr::get($data, 'list_id'),
306 'title' => sanitize_text_field(wp_unslash(Arr::get($data, 'ticket_title'))),
307 'content' => wp_unslash(wp_kses_post(Arr::get($data, 'ticket_content'))),
308 'attachments' => sanitize_text_field(Arr::get($data, 'ticket_attachments')),
309 'client_priority' => strtolower(sanitize_text_field(Arr::get($data, 'client_priority', ''))),
310 'priority' => strtolower(sanitize_text_field(Arr::get($data, 'client_priority', ''))),
311 'custom_fields' => $ticketCustomField,
312 'source' => 'web'
313 ];
314
315 $selectedProductArray = (array) $this->getSelectedTagIds($data, $formData, 'product_id', 'product_id_selection_type', 'product_routers');
316
317 if($selectedProductArray) {
318 $selectedProduct = $selectedProductArray[0];
319 $ticketData['product_id'] = $selectedProduct;
320 }
321
322 $customerData = Arr::only($data, ['first_name', 'last_name', 'email']);
323
324 foreach (Arr::get($data, 'customer_other_fields') as $field) {
325 if ($field['item_value']) {
326 $customerData[$field['label']] = $field['item_value'];
327 }
328 }
329
330
331 $user = get_user_by('ID', get_current_user_id());
332
333 if(!$user) {
334 $user = get_user_by('email', $customerData['email']);
335 }
336
337 if($user) {
338 $customerData['email'] = $user->user_email;
339 $customerData['user_id'] = $user->ID;
340 }
341
342 if(empty($customerData['email'])) {
343 do_action('fluentform/log_data', [
344 'title' => $feed['settings']['name'],
345 'status' => 'failed',
346 'description' => __('Support ticket creation failed, because no valid customer email found', 'fluent-support'),
347 'parent_source_id' => $form->id,
348 'source_id' => $entry->id,
349 'component' => $this->integrationKey,
350 'source_type' => 'submission_item'
351 ]);
352 return false;
353 }
354
355 $customerData['last_ip_address'] = $entry->ip;
356
357 $customer = Customer::maybeCreateCustomer($customerData);
358
359 // Don't create a ticket if customer is blocked
360 if($this->isBlockedCustomer($customerData['email'])) {
361 do_action('fluentform/log_data', [
362 'title' => $feed['settings']['name'],
363 'status' => 'failed',
364 'description' => __('Support ticket creation failed, because customer email is blocked', 'fluent-support'),
365 'parent_source_id' => $form->id,
366 'source_id' => $entry->id,
367 'component' => $this->integrationKey,
368 'source_type' => 'submission_item'
369 ]);
370 return false;
371 }
372
373 $ticketData['customer_id'] = $customer->id;
374
375 $ticketData = apply_filters('fluent_support/create_ticket_data', $ticketData, $customer);
376 do_action('fluent_support/before_ticket_create', $ticketData, $customer);
377
378 $ticket = Ticket::create($ticketData);
379
380 if(defined('FLUENTSUPPORTPRO') && !empty($ticketData['custom_fields'])) {
381 $ticket->syncCustomFields($ticketData['custom_fields']);
382 /*
383 * This custom_fields is causing issues in all webhook to where we called $ticket->save()
384 * As we are calling $ticket->syncCustomFields() above, we don't need this anymore
385 * TODO: need to remove this line in future
386 */
387 //$ticket->custom_fields = $ticket->customData();
388 }
389
390 do_action('fluent_support/ticket_created', $ticket, $customer);
391
392 do_action('fluentform/log_data', [
393 'title' => $feed['settings']['name'],
394 'status' => 'success',
395 // translators: %d is the ticket ID number
396 'description' => sprintf(__('Support ticket has been created at Fluent Support. Ticket ID: %d', 'fluent-support'), $ticket->id),
397 'parent_source_id' => $form->id,
398 'source_id' => $entry->id,
399 'component' => $this->integrationKey,
400 'source_type' => 'submission_item'
401 ]);
402
403 if ($ticketData['attachments']) {
404 $attachments = is_array($ticketData['attachments'])
405 ? $ticketData['attachments']
406 : explode(',', $ticketData['attachments']);
407
408 $uploadDir = wp_upload_dir();
409
410 foreach ($attachments as $attachment) {
411 $attachment = trim($attachment);
412 if (empty($attachment)) {
413 continue;
414 }
415
416 $isMediaLibrary = false;
417 $attachmentId = null;
418
419 // Try to get attachment ID if it's a media library URL
420 $attachmentId = attachment_url_to_postid($attachment);
421 if ($attachmentId) {
422 $isMediaLibrary = true;
423 }
424
425 try {
426 if ($isMediaLibrary) {
427 $filePath = get_attached_file($attachmentId);
428 if (!$filePath) {
429 continue;
430 }
431 $fileName = basename($filePath);
432 $fileType = get_post_mime_type($attachmentId);
433 $fullUrl = wp_get_attachment_url($attachmentId);
434 } else {
435 $fileName = basename($attachment);
436 $filePath = $uploadDir['basedir'] . FLUENTFORM_UPLOAD_DIR . '/' . $fileName;
437 $fileInfo = wp_check_filetype($filePath);
438 $fileType = (!empty($fileInfo['type'])) ? $fileInfo['type'] : '';
439 $fullUrl = $attachment;
440 }
441
442 if (file_exists($filePath)) {
443 try {
444 Attachment::create([
445 'ticket_id' => $ticket->id,
446 'file_path' => sanitize_text_field($filePath),
447 'full_url' => sanitize_url($fullUrl),
448 'title' => sanitize_text_field($fileName),
449 'person_id' => $customer->id,
450 'file_type' => sanitize_text_field($fileType),
451 'is_media_library' => $isMediaLibrary,
452 'attachment_id' => $attachmentId
453 ]);
454 } catch (\Exception $e) {
455
456 }
457 }
458 } catch (\Exception $e) {
459 continue;
460 }
461 }
462
463 $ticket->load('attachments');
464 }
465
466 return true;
467 }
468
469 public function isConfigured()
470 {
471 return true;
472 }
473
474 public function isEnabled()
475 {
476 return true;
477 }
478
479 // check if customer is blocked or not
480 private function isBlockedCustomer($customerEmail)
481 {
482 $customer = Customer::where('email', $customerEmail)->first();
483
484 if('inactive' == $customer->status || !$customer->status) {
485 return true;
486 }
487
488 return false;
489 }
490
491 }
492