PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 5.2.9
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v5.2.9
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Modules / Form / Form.php

Form.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 5.2.9, at app/Modules/Form/Form.php

869 lines 28.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentForm\App\Modules\Form;
4
5 use FluentForm\App\Helpers\Helper;
6 use FluentForm\App\Modules\Acl\Acl;
7 use FluentForm\Framework\Foundation\Application;
8 use FluentForm\Framework\Helpers\ArrayHelper;
9
10 class Form
11 {
12 /**
13 * Request object
14 *
15 * @var \FluentForm\Framework\Request\Request $request
16 */
17 protected $request;
18
19 /**
20 * Set this value when we need predefined default settings.
21 *
22 * @var array $defaultSettings
23 */
24 protected $defaultSettings;
25
26 /**
27 * Set this value when we need predefined default notifications.
28 *
29 * @var array $defaultNotifications
30 */
31 protected $defaultNotifications;
32
33 /**
34 * Set this value when we need predefined form fields.
35 *
36 * @var array $formFields
37 */
38 protected $formFields;
39
40 protected $metas = [];
41
42 protected $formType = 'form';
43
44 protected $hasPayment = 0;
45 /**
46 * @var \FluentForm\Framework\Database\Query\Builder
47 */
48 protected $model = null;
49
50 /**
51 * Form constructor.
52 *
53 * @param \FluentForm\Framework\Foundation\Application $application
54 */
55 public function __construct(Application $application)
56 {
57 $this->request = $application->request;
58 $this->model = wpFluent()->table('fluentform_forms');
59 }
60
61 /**
62 * Get all forms from database
63 */
64 public function index()
65 {
66 $forms = fluentFormApi('forms')->forms([
67 'search' => $this->request->get('search'),
68 'status' => $this->request->get('status'),
69 'filter_by' => $this->request->get('filter_by', 'all'),
70 'date_range' => $this->request->get('date_range', []),
71 'sort_column' => $this->request->get('sort_column', 'id'),
72 'sort_by' => $this->request->get('sort_by', 'DESC'),
73 'per_page' => $this->request->get('per_page', 10),
74 'page' => $this->request->get('page', 1),
75 ]);
76
77 wp_send_json($forms, 200);
78 }
79
80 /**
81 * Create a form from backend/editor
82 *
83 * @return void|array
84 */
85 public function store($returnJSON = true)
86 {
87 $type = $this->request->get('type', $this->formType);
88 $title = $this->request->get('title', 'My New Form');
89 $status = $this->request->get('status', 'published');
90 $createdBy = get_current_user_id();
91
92 $now = current_time('mysql');
93
94 $insertData = [
95 'title' => $title,
96 'type' => $type,
97 'status' => $status,
98 'created_by' => $createdBy,
99 'created_at' => $now,
100 'updated_at' => $now,
101 ];
102
103 if ($this->formFields) {
104 $insertData['form_fields'] = $this->formFields;
105 }
106
107 if ($this->hasPayment) {
108 $insertData['has_payment'] = $this->hasPayment;
109 }
110
111 $formId = $this->model->insertGetId($insertData);
112
113 // Rename the form name here
114 wpFluent()->table('fluentform_forms')->where('id', $formId)->update([
115 'title' => $title . ' (#' . $formId . ')',
116 ]);
117
118 if ($this->metas && is_array($this->metas)) {
119 foreach ($this->metas as $meta) {
120 $meta['value'] = trim(preg_replace('/\s+/', ' ', $meta['value']));
121
122 wpFluent()->table('fluentform_form_meta')
123 ->insert([
124 'form_id' => $formId,
125 'meta_key' => $meta['meta_key'],
126 'value' => $meta['value'],
127 ]);
128 }
129 } else {
130 // add default form settings now
131 $defaultSettings = $this->defaultSettings ?: $this->getFormsDefaultSettings($formId);
132
133 $defaultSettings = apply_filters_deprecated(
134 'fluentform_create_default_settings',
135 [
136 $defaultSettings
137 ],
138 FLUENTFORM_FRAMEWORK_UPGRADE,
139 'fluentform/create_default_settings',
140 'Use fluentform/create_default_settings instead of fluentform_create_default_settings.'
141 );
142
143 $defaultSettings = apply_filters('fluentform/create_default_settings', $defaultSettings);
144
145 wpFluent()->table('fluentform_form_meta')
146 ->insert([
147 'form_id' => $formId,
148 'meta_key' => 'formSettings',
149 'value' => json_encode($defaultSettings),
150 ]);
151
152 if ($this->defaultNotifications) {
153 wpFluent()->table('fluentform_form_meta')
154 ->insert([
155 'form_id' => $formId,
156 'meta_key' => 'notifications',
157 'value' => json_encode($this->defaultNotifications),
158 ]);
159 }
160 }
161
162 do_action_deprecated(
163 'fluentform_inserted_new_form',
164 [
165 $formId,
166 $insertData
167 ],
168 FLUENTFORM_FRAMEWORK_UPGRADE,
169 'fluentform/inserted_new_form',
170 'Use fluentform/inserted_new_form instead of fluentform_inserted_new_form.'
171 );
172
173 do_action('fluentform/inserted_new_form', $formId, $insertData);
174
175 $data = [
176 'formId' => $formId,
177 'redirect_url' => admin_url('admin.php?page=fluent_forms&form_id=' . $formId . '&route=editor'),
178 'message' => __('Successfully created a form.', 'fluentform'),
179 ];
180
181 if ($returnJSON) {
182 wp_send_json_success($data, 200);
183 }
184
185 return $data;
186 }
187
188 public function getFormsDefaultSettings($formId = false)
189 {
190 $defaultSettings = [
191 'confirmation' => [
192 'redirectTo' => 'samePage',
193 'messageToShow' => __('Thank you for your message. We will get in touch with you shortly.', 'fluentform'),
194 'customPage' => null,
195 'samePageFormBehavior' => 'hide_form',
196 'customUrl' => null,
197 ],
198 'restrictions' => [
199 'limitNumberOfEntries' => [
200 'enabled' => false,
201 'numberOfEntries' => null,
202 'period' => 'total',
203 'limitReachedMsg' => 'Maximum number of entries exceeded.',
204 ],
205 'scheduleForm' => [
206 'enabled' => false,
207 'start' => null,
208 'end' => null,
209 'selectedDays' => null,
210 'pendingMsg' => __('Form submission is not started yet.', 'fluentform'),
211 'expiredMsg' => __('Form submission is now closed.', 'fluentform'),
212 ],
213 'requireLogin' => [
214 'enabled' => false,
215 'requireLoginMsg' => 'You must be logged in to submit the form.',
216 ],
217 'denyEmptySubmission' => [
218 'enabled' => false,
219 'message' => __('Sorry, you cannot submit an empty form. Let\'s hear what you wanna say.', 'fluentform'),
220 ],
221 ],
222 'layout' => [
223 'labelPlacement' => 'top',
224 'helpMessagePlacement' => 'with_label',
225 'errorMessagePlacement' => 'inline',
226 'cssClassName' => '',
227 'asteriskPlacement' => 'asterisk-right'
228 ],
229 'delete_entry_on_submission' => 'no',
230 ];
231
232 if ($formId) {
233 $value = $this->getMeta($formId, 'formSettings', true);
234 if ($value) {
235 $defaultSettings = wp_parse_args($value, $defaultSettings);
236 }
237 } else {
238 $globalSettings = get_option('_fluentform_global_form_settings');
239 if (isset($globalSettings['layout'])) {
240 $defaultSettings['layout'] = $globalSettings['layout'];
241 }
242 }
243
244 return $defaultSettings;
245 }
246
247 public function getAdvancedValidationSettings($formId)
248 {
249 $settings = [
250 'status' => false,
251 'type' => 'all',
252 'conditions' => [
253 [
254 'field' => '',
255 'operator' => '=',
256 'value' => '',
257 ],
258 ],
259 'error_message' => '',
260 'validation_type' => 'fail_on_condition_met',
261 ];
262
263 $metaSettings = $this->getMeta($formId, 'advancedValidationSettings', true);
264
265 if ($metaSettings && is_array($metaSettings)) {
266 $settings = wp_parse_args($metaSettings, $settings);
267 }
268
269 return $settings;
270 }
271
272 public function getMeta($formId, $metaKey, $isJson = true)
273 {
274 $settingsMeta = wpFluent()->table('fluentform_form_meta')
275 ->where('form_id', $formId)
276 ->where('meta_key', $metaKey)
277 ->first();
278 if ($settingsMeta) {
279 if ($isJson) {
280 return \json_decode($settingsMeta->value, true);
281 } else {
282 return $settingsMeta->value;
283 }
284 }
285 return false;
286 }
287
288 public function updateMeta($formId, $metaKey, $metaValue)
289 {
290 $exist = wpFluent()->table('fluentform_form_meta')
291 ->where('form_id', $formId)
292 ->where('meta_key', $metaKey)
293 ->first();
294
295 if (is_array($metaValue) || is_object($metaValue)) {
296 $metaValue = \json_encode($metaValue);
297 }
298
299 if ($exist) {
300 return wpFluent()->table('fluentform_form_meta')
301 ->where('id', $exist->id)
302 ->update([
303 'value' => $metaValue,
304 ]);
305 }
306
307 return wpFluent()->table('fluentform_form_meta')->insertGetId([
308 'form_id' => $formId,
309 'meta_key' => $metaKey,
310 'value' => $metaValue,
311 ]);
312 }
313
314 public function deleteMeta($formId, $metaKey)
315 {
316 return wpFluent()->table('fluentform_form_meta')
317 ->where('form_id', $formId)
318 ->where('meta_key', $metaKey)
319 ->delete();
320 }
321
322 /**
323 * Find/Read a from from the database
324 */
325 public function find()
326 {
327 $form = $this->fetchForm($this->request->get('formId'));
328 wp_send_json(['form' => $form, 'metas' => []], 200);
329 }
330
331 /**
332 * Fetch a from from the database
333 * Note: required for ninja-tables
334 *
335 * @return mixed
336 */
337 public function fetchForm($formId)
338 {
339 return $this->model->find($formId);
340 }
341
342 /**
343 * Save/update a form from backend/editor
344 */
345 public function update()
346 {
347 $formId = $this->request->get('formId');
348 $title = sanitize_text_field($this->request->get('title'));
349 $status = $this->request->get('status', 'published');
350
351 $this->validate();
352
353 $data = [
354 'title' => $title,
355 'status' => $status,
356 'updated_at' => current_time('mysql'),
357 ];
358
359 if ($formFields = $this->request->get('formFields')) {
360 $formFields = apply_filters_deprecated(
361 'fluentform_form_fields_update',
362 [
363 $formFields,
364 $formId
365 ],
366 FLUENTFORM_FRAMEWORK_UPGRADE,
367 'fluentform/form_fields_update',
368 'Use fluentform/form_fields_update instead of fluentform_form_fields_update.'
369 );
370 $formFields = apply_filters('fluentform/form_fields_update', $formFields, $formId);
371 $formFields = $this->sanitizeFields($formFields);
372 $data['form_fields'] = $formFields;
373 }
374
375 $this->model->where('id', $formId)->update($data);
376
377 $form = $this->fetchForm($formId);
378
379 if (FormFieldsParser::hasPaymentFields($form)) {
380 $this->model->where('id', $formId)->update([
381 'has_payment' => 1,
382 ]);
383 } elseif ($form->has_payment) {
384 $this->model->where('id', $formId)->update([
385 'has_payment' => 0,
386 ]);
387 }
388
389 $emailInputs = FormFieldsParser::getElement($form, ['input_email'], ['element', 'attributes']);
390 if ($emailInputs) {
391 $emailInput = array_shift($emailInputs);
392 $emailInputName = ArrayHelper::get($emailInput, 'attributes.name');
393 $this->updateMeta($formId, '_primary_email_field', $emailInputName);
394 } else {
395 $this->updateMeta($formId, '_primary_email_field', '');
396 }
397
398 wp_send_json([
399 'message' => __('The form is successfully updated.', 'fluentform'),
400 ], 200);
401 }
402
403 private function sanitizeFields($formFields)
404 {
405 if (fluentformCanUnfilteredHTML()) {
406 return $formFields;
407 }
408
409 $fieldsArray = json_decode($formFields, true);
410
411 if (isset($fieldsArray['submitButton'])) {
412 $fieldsArray['submitButton']['settings']['button_ui']['text'] = fluentform_sanitize_html($fieldsArray['submitButton']['settings']['button_ui']['text']);
413 if (!empty($fieldsArray['submitButton']['settings']['button_ui']['img_url'])) {
414 $fieldsArray['submitButton']['settings']['button_ui']['img_url'] = sanitize_url($fieldsArray['submitButton']['settings']['button_ui']['img_url']);
415 }
416 }
417
418 $fieldsArray['fields'] = $this->sanitizeFieldMaps($fieldsArray['fields']);
419
420 return json_encode($fieldsArray);
421 }
422
423 private function sanitizeFieldMaps($fields)
424 {
425 if (!is_array($fields)) {
426 return $fields;
427 }
428
429 $attributesMap = [
430 'name' => 'sanitize_key',
431 'value' => 'sanitize_textarea_field',
432 'id' => 'sanitize_key',
433 'class' => 'sanitize_text_field',
434 'placeholder' => 'sanitize_text_field',
435 ];
436 $attributesKeys = array_keys($attributesMap);
437 $settingsMap = [
438 'container_class' => 'sanitize_text_field',
439 'label' => 'wp_kses_post',
440 'label_placement' => 'sanitize_text_field',
441 'help_message' => 'wp_kses_post',
442 'admin_field_label' => 'sanitize_text_field',
443 'prefix_label' => 'sanitize_text_field',
444 'suffix_label' => 'sanitize_text_field',
445 'unique_validation_message' => 'sanitize_text_field',
446 'advanced_options' => 'fluentform_options_sanitize',
447 'html_codes' => 'fluentform_sanitize_html',
448 ];
449 $settingsKeys = array_keys($settingsMap);
450 $stylePrefMap = [
451 'layout' => 'sanitize_key',
452 'media' => 'sanitize_url',
453 'alt_text' => 'sanitize_text_field',
454 ];
455 $stylePrefKeys = array_keys($stylePrefMap);
456
457 foreach ($fields as $fieldIndex => $field) {
458 $element = ArrayHelper::get($field, 'element');
459
460 if ('container' == $element) {
461 $columns = $field['columns'];
462 foreach ($columns as $columnIndex => $column) {
463 $fields[$fieldIndex]['columns'][$columnIndex]['fields'] = $this->sanitizeFieldMaps($column['fields']);
464 }
465 return $fields;
466 }
467
468 /*
469 * Handle Name or address fields
470 */
471 if (!empty($field['fields'])) {
472 $fields[$fieldIndex]['fields'] = $this->sanitizeFieldMaps($field['fields']);
473 return $fields;
474 }
475
476 if (!empty($field['attributes'])) {
477 $attributes = array_filter(ArrayHelper::only($field['attributes'], $attributesKeys));
478 foreach ($attributes as $key => $value) {
479 $fields[$fieldIndex]['attributes'][$key] = call_user_func($attributesMap[$key], $value);
480 }
481 }
482
483 if (!empty($field['settings'])) {
484 $settings = array_filter(ArrayHelper::only($field['settings'], $settingsKeys));
485 foreach ($settings as $key => $value) {
486 $fields[$fieldIndex]['settings'][$key] = call_user_func($settingsMap[$key], $value);
487 }
488 }
489
490 if (!empty($field['style_pref'])) {
491 $settings = array_filter(ArrayHelper::only($field['style_pref'], $stylePrefKeys));
492 foreach ($settings as $key => $value) {
493 $fields[$fieldIndex]['style_pref'][$key] = call_user_func($stylePrefMap[$key], $value);
494 }
495 }
496 }
497
498 return $fields;
499 }
500
501 /**
502 * Delete a from from database
503 */
504 public function delete()
505 {
506 $formId = $this->request->get('formId');
507
508 $this->model->where('id', $formId)->delete();
509
510 $maybeErrors = $this->deleteFormAssests($formId);
511
512 wp_send_json([
513 'message' => __('Successfully deleted the form.', 'fluentform'),
514 'errors' => $maybeErrors,
515 ], 200);
516 }
517
518 protected function deleteFormAssests($formId)
519 {
520 // Now Let's delete associate items
521 wpFluent()->table('fluentform_submissions')
522 ->where('form_id', $formId)
523 ->delete();
524
525 wpFluent()->table('fluentform_submission_meta')
526 ->where('form_id', $formId)
527 ->delete();
528
529 wpFluent()->table('fluentform_entry_details')
530 ->where('form_id', $formId)
531 ->delete();
532
533 wpFluent()->table('fluentform_form_meta')
534 ->where('form_id', $formId)
535 ->delete();
536
537 wpFluent()->table('fluentform_form_analytics')
538 ->where('form_id', $formId)
539 ->delete();
540
541 wpFluent()->table('fluentform_logs')
542 ->where('parent_source_id', $formId)
543 ->whereIn('source_type', ['submission_item', 'form_item', 'draft_submission_meta'])
544 ->delete();
545
546 ob_start();
547 if (defined('FLUENTFORMPRO')) {
548 try {
549 wpFluent()->table('fluentform_order_items')
550 ->where('form_id', $formId)
551 ->delete();
552
553 wpFluent()->table('fluentform_transactions')
554 ->where('form_id', $formId)
555 ->delete();
556 } catch (\Exception $exception) {
557 }
558 }
559
560 $errors = ob_get_clean();
561 return $errors;
562 }
563
564 /**
565 * Duplicate a from
566 */
567 public function duplicate()
568 {
569 $formId = absint($this->request->get('formId'));
570 $form = $this->model->where('id', $formId)->first();
571
572 $data = [
573 'title' => $form->title,
574 'status' => $form->status,
575 'appearance_settings' => $form->appearance_settings,
576 'form_fields' => $form->form_fields,
577 'type' => $form->type,
578 'has_payment' => $form->has_payment,
579 'conditions' => $form->conditions,
580 'created_by' => get_current_user_id(),
581 'created_at' => current_time('mysql'),
582 'updated_at' => current_time('mysql'),
583 ];
584
585 $newFormId = $this->model->insertGetId($data);
586
587 // Rename the form name here
588 wpFluent()->table('fluentform_forms')
589 ->where('id', $newFormId)
590 ->update([
591 'title' => $form->title . ' (#' . $newFormId . ')',
592 ]);
593
594 $formMetas = wpFluent()->table('fluentform_form_meta')
595 ->where('form_id', $formId)
596 ->whereNot('meta_key', ['_total_views'])
597 ->get();
598
599 // Required for duplicating PDF feeds
600 $extras = [];
601
602 foreach ($formMetas as $meta) {
603 if ('notifications' == $meta->meta_key || '_pdf_feeds' == $meta->meta_key) {
604 $extras[$meta->meta_key][] = $meta;
605 continue;
606 }
607 if ("ffc_form_settings_generated_css" == $meta->meta_key || "ffc_form_settings_meta" == $meta->meta_key) {
608 $meta->value = str_replace('ff_conv_app_' . $formId, 'ff_conv_app_' . $newFormId, $meta->value);
609 }
610 $metaData = [
611 'meta_key' => $meta->meta_key,
612 'value' => $meta->value,
613 'form_id' => $newFormId,
614 ];
615
616 wpFluent()->table('fluentform_form_meta')->insert($metaData);
617 }
618
619 $pdfFeedMap = $this->getPdfFeedMap($extras, $newFormId);
620 if (array_key_exists('notifications', $extras)) {
621 $extras = $this->notificationWithPdfMap($extras, $pdfFeedMap);
622 foreach ($extras['notifications'] as $notify) {
623 $notifyData = [
624 'meta_key' => $notify->meta_key,
625 'value' => $notify->value,
626 'form_id' => $newFormId,
627 ];
628 wpFluent()->table('fluentform_form_meta')->insert($notifyData);
629 }
630 }
631
632 do_action_deprecated(
633 'flentform_form_duplicated',
634 [
635 $newFormId
636 ],
637 FLUENTFORM_FRAMEWORK_UPGRADE,
638 'fluentform/form_duplicated',
639 'Use fluentform/form_duplicated instead of flentform_form_duplicated.'
640 );
641
642 do_action('flentform/form_duplicated', $newFormId);
643
644 wp_send_json([
645 'message' => __('Form has been successfully duplicated.', 'fluentform'),
646 'form_id' => $newFormId,
647 'redirect' => admin_url('admin.php?page=fluent_forms&route=editor&form_id=' . $newFormId),
648 ], 200);
649 }
650
651 /**
652 * Validate a form by form title & for duplicate name attributes
653 */
654 private function validate()
655 {
656 $fields = $this->request->get('formFields');
657 if ($fields) {
658 $duplicates = Helper::getDuplicateFieldNames($fields);
659 if ($duplicates) {
660 $duplicateString = implode(', ', $duplicates);
661 wp_send_json([
662 'title' => sprintf('Name attribute %s has duplicate value.', $duplicateString),
663 ], 422);
664 }
665 }
666
667 if (!sanitize_text_field($this->request->get('title'))) {
668 wp_send_json([
669 'title' => 'The title field is required.',
670 ], 422);
671 }
672 }
673
674 public function convertToConversational()
675 {
676 $formId = $this->request->get('form_id');
677 $form = $this->fetchForm($formId);
678
679 if (!$form) {
680 wp_send_json([
681 'message' => __('Form Not Found! Try Again.', 'fluentform'),
682 ], 422);
683 }
684
685 $conversationalMeta = $this->getMeta($formId, 'is_conversion_form', false);
686
687 $shouldConvert = in_array($conversationalMeta, [false, 'no']);
688
689 if ($shouldConvert) {
690 $formConverted['form_fields'] = \FluentForm\App\Services\FluentConversational\Classes\Converter\Converter::convertExistingForm($form);
691
692 $this->model->where('id', $formId)->update($formConverted);
693
694 $conversationalMetaValue = 'yes';
695 } else {
696 $conversationalMetaValue = 'no';
697 }
698
699 $this->updateMeta($formId, 'is_conversion_form', $conversationalMetaValue);
700
701 wp_send_json_success([
702 'message' => __('Form has been successfully converted.', 'fluentform'),
703 ], 200);
704 }
705
706 private function getAdminPermalink($route, $form)
707 {
708 $baseUrl = admin_url('admin.php?page=fluent_forms');
709 return $baseUrl . '&route=' . $route . '&form_id=' . $form->id;
710 }
711
712 private function getSettingsUrl($form)
713 {
714 $baseUrl = admin_url('admin.php?page=fluent_forms');
715 return $baseUrl . '&form_id=' . $form->id . '&route=settings&sub_route=form_settings#basic_settings';
716 }
717
718
719 /**
720 * Map pdf feed ID to replace with duplicated PDF feed ID when duplicating form
721 *
722 * @param array $extras
723 * @param array $newFormId
724 *
725 * @return array
726 */
727 private function getPdfFeedMap($extras, $newFormId)
728 {
729 $pdfFeedMap = [];
730 if (array_key_exists('_pdf_feeds', $extras)) {
731 foreach ($extras['_pdf_feeds'] as $pdf_feed) {
732 $pdfData = [
733 'meta_key' => $pdf_feed->meta_key,
734 'value' => $pdf_feed->value,
735 'form_id' => $newFormId,
736 ];
737 $pdfFeedMap[$pdf_feed->id] = wpFluent()->table('fluentform_form_meta')->insertGetId($pdfData);
738 }
739 }
740 return $pdfFeedMap;
741 }
742
743 /**
744 * Map notification data with PDF feed map
745 *
746 * @param array $extras
747 * @param array $pdfFeedMap
748 *
749 * @return array
750 */
751 private function notificationWithPdfMap($extras, $pdfFeedMap)
752 {
753 foreach ($extras['notifications'] as $key => $notification) {
754 $notificationValue = json_decode($notification->value);
755 $pdf_attachments = [];
756 if (isset($notificationValue->pdf_attachments) && count($notificationValue->pdf_attachments)) {
757 foreach ($notificationValue->pdf_attachments as $attachment) {
758 $pdf_attachments[] = json_encode($pdfFeedMap[$attachment]);
759 }
760 }
761 $notificationValue->pdf_attachments = $pdf_attachments;
762 $notification->value = json_encode($notificationValue);
763
764 $extras['notifications'][$key] = $notification;
765 }
766 return $extras;
767 }
768
769 public function findFormLocations()
770 {
771 $formId = intval($this->request->get('form_id'));
772
773 $excluded = ['attachment'];
774 $post_types = get_post_types(['show_in_menu' => true], 'objects', 'or');
775 $postTypes = [];
776 foreach($post_types as $post_type) {
777 $postTypeName = $post_type->name;
778 if (in_array($postTypeName, $excluded)) {
779 continue;
780 }
781 $postTypes[] = $postTypeName;
782 }
783
784 $params = array(
785 'post_type' => $postTypes,
786 'posts_per_page' => -1
787 );
788
789 $params = apply_filters_deprecated(
790 'fluentform_find_shortcode_params',
791 [
792 $params
793 ],
794 FLUENTFORM_FRAMEWORK_UPGRADE,
795 'fluentform/find_shortcode_params',
796 'Use fluentform/find_shortcode_params instead of fluentform_find_shortcode_params.'
797 );
798
799 $params = apply_filters('fluentform/find_shortcode_params', $params);
800
801 $formLocations = [];
802 $posts = get_posts($params);
803 foreach($posts as $post) {
804
805 $formIds = self::getShortCodeIds($post->post_content);
806 if(!empty($formIds) && in_array($formId,$formIds)) {
807
808 $postType = get_post_type_object($post->post_type);
809 $formLocations[] = [
810 'id' => $post->ID,
811 'name' => $postType->labels->singular_name,
812 'title' => (empty($post->post_title) ? $post->ID : $post->post_title),
813 'edit_link' => sprintf("%spost.php?post=%s&action=edit", admin_url(), $post->ID),
814 ];
815 }
816 }
817 $data = [
818 'locations' => $formLocations,
819 'status' => !empty($formLocations),
820 ];
821 wp_send_json($data, 200);
822
823 }
824
825 public static function getShortCodeIds($content)
826 {
827 $ids = [];
828 $tag = 'fluentform';
829 $selector = 'id';
830
831 if (function_exists('parse_blocks')) {
832 $parsedBlocks = parse_blocks($content);
833 foreach ($parsedBlocks as $block) {
834 if (!ArrayHelper::exists($block, 'blockName') || ArrayHelper::exists($block, 'attrs.formId')) {
835 continue;
836 }
837 $hasBlock = strpos($block['blockName'], 'fluentfom/guten-block') === 0;
838 if ($hasBlock) {
839 $ids[] = intval($block['attrs']['formId']);
840 }
841 }
842 }
843
844 $hasShortCode = has_shortcode($content, $tag);
845 if(!$hasShortCode){
846 return $ids;
847 }
848
849 preg_match_all('/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER);
850 if (empty($matches)) {
851 return $ids;
852 }
853
854
855 foreach ($matches as $shortcode) {
856 if (count($shortcode) >= 2 && $tag === $shortcode[2]) {
857 $parsedCode = str_replace(['[', ']', '&#91;', '&#93;'], '', $shortcode[0]);
858
859 $result = shortcode_parse_atts($parsedCode);
860
861 if (!empty($result[$selector])) {
862 $ids[] = $result[$selector];
863 }
864 }
865 }
866 return $ids;
867 }
868 }
869