PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.6
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.6
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 / Hooks / actions.php

actions.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 6.2.6, at app/Hooks/actions.php

1,278 lines 44.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined('ABSPATH') or die;
4
5 use FluentForm\App\Modules\Component\Component;
6 use FluentForm\App\Modules\Acl\Acl;
7 use FluentForm\App\Helpers\Helper;
8 use FluentForm\Framework\Helpers\ArrayHelper;
9
10 /**
11 * All registered action's handlers should be in app\Hooks\Handlers,
12 * addAction is similar to add_action and addCustomAction is just a
13 * wrapper over add_action which will add a prefix to the hook name
14 * using the plugin slug to make it unique in all wordpress plugins,
15 * ex: $app->addCustomAction('foo', ['FooHandler', 'handleFoo']) is
16 * equivalent to add_action('slug-foo', ['FooHandler', 'handleFoo']).
17 */
18
19 /**
20 * @var $app FluentForm\Framework\Foundation\Application
21 */
22
23 // From MenuProvider.php
24 $app->addAction(
25 'admin_menu',
26 function () use ($app) {
27 (new \FluentForm\App\Modules\Registerer\Menu($app))->register();
28 }
29 );
30
31 $app->addAction(
32 'fluentform/form_application_view_editor',
33 function ($formId) use ($app) {
34 (new \FluentForm\App\Modules\Registerer\Menu($app))->renderEditor($formId);
35 }
36 );
37
38 $app->addAction(
39 'fluentform/form_application_view_settings',
40 function ($formId) use ($app) {
41 (new \FluentForm\App\Modules\Registerer\Menu($app))->renderSettings($formId);
42 }
43 );
44
45 $app->addAction(
46 'fluentform/form_settings_container_form_settings',
47 function ($formId) use ($app) {
48 (new \FluentForm\App\Modules\Registerer\Menu($app))->renderFormSettings($formId);
49 }
50 );
51
52 $app->addAction(
53 'fluentform/global_settings_component_settings',
54 function () use ($app) {
55 (new \FluentForm\App\Modules\Renderer\GlobalSettings\Settings($app))->render();
56 }
57 );
58
59 $app->addAction(
60 'fluentform/global_settings_component_reCaptcha',
61 function () use ($app) {
62 (new \FluentForm\App\Modules\Renderer\GlobalSettings\Settings($app))->render();
63 }
64 );
65
66 $app->addAction(
67 'fluentform/global_settings_component_hCaptcha',
68 function () use ($app) {
69 (new \FluentForm\App\Modules\Renderer\GlobalSettings\Settings($app))->render();
70 }
71 );
72
73 // Register DefaultStyleApplicator on init so it works for REST API requests too
74 add_action('init', function () {
75 new \FluentForm\App\Modules\Form\DefaultStyleApplicator();
76 }, 9);
77
78 // From Backend.php
79 add_action('admin_init', function () use ($app) {
80 (new \FluentForm\App\Modules\Registerer\Menu($app))->reisterScripts();
81 (new \FluentForm\App\Modules\Registerer\AdminBar())->register();
82 (new \FluentForm\App\Modules\Ai\AiController())->boot();
83 (new \FluentForm\App\Modules\Report\ReportHandler())->register($app);
84 }, 9);
85
86 add_action('admin_enqueue_scripts', function () use ($app) {
87 (new \FluentForm\App\Modules\Registerer\Menu($app))->enqueuePageScripts();
88 }, 10);
89
90 // Add Entries Menu
91 $app->addAction('fluentform/form_application_view_entries', function ($form_id) {
92 (new \FluentForm\App\Modules\Entries\EntryViewRenderer())->renderEntries($form_id);
93 });
94
95 $app->addAction('fluentform/after_form_navigation', function ($form_id) use ($app) {
96 (new \FluentForm\App\Modules\Registerer\Menu($app))->addCopyShortcodeButton($form_id);
97 (new \FluentForm\App\Modules\Registerer\Menu($app))->addPreviewButton($form_id);
98 });
99
100 $app->addAction('media_buttons', function () {
101 (new \FluentForm\App\Modules\EditorButtonModule())->addButton();
102 });
103
104 /*
105 * Addons Page
106 */
107 $app->addAction('fluentform/addons_page_render_fluentform_add_ons', function () {
108 (new \FluentForm\App\Modules\AddOnModule())->showFluentAddOns();
109 });
110
111 $app->addAction('fluentform/addons_page_render_suggested_plugins', function () {
112 (new \FluentForm\App\Modules\AddOnModule())->showSuggestedPlugins();
113 });
114
115 $app->addAction('fluentform/global_menu', function () use ($app) {
116 $menu = new \FluentForm\App\Modules\Registerer\Menu($app);
117 $menu->renderGlobalMenu();
118 if ('yes' != get_option('fluentform_scheduled_actions_migrated')) {
119 \FluentForm\Database\Migrations\ScheduledActions::migrate();
120 }
121
122 $hookName = 'fluentform_do_scheduled_tasks';
123 if (!wp_next_scheduled($hookName)) {
124 wp_schedule_event(time(), 'ff_every_five_minutes', $hookName);
125 }
126
127 $emailReportHookName = 'fluentform_do_email_report_scheduled_tasks';
128 if (!wp_next_scheduled($emailReportHookName)) {
129 wp_schedule_event(time(), 'daily', $emailReportHookName);
130 }
131 });
132
133 $app->addAction('wp_dashboard_setup', function () {
134 $acl = new \FluentForm\App\Modules\Acl\Acl();
135
136 if (!$acl::getCurrentUserCapability()) {
137 return;
138 }
139 wp_add_dashboard_widget('fluentform_stat_widget', __('Fluent Forms Latest Form Submissions', 'fluentform'), function () {
140 (new \FluentForm\App\Modules\DashboardWidgetModule())->showStat();
141 }, 10, 1);
142 });
143
144 add_action('admin_init', function () {
145 $disablePages = [
146 'fluent_forms',
147 'fluent_forms_transfer',
148 'fluent_forms_settings',
149 'fluent_forms_add_ons',
150 'fluent_forms_docs',
151 'fluent_forms_all_entries',
152 'msformentries',
153 'fluent_forms_payment_entries',
154 'fluent_forms_reports'
155 ];
156
157 $page = wpFluentForm('request')->get('page');
158
159 if ($page && in_array($page, $disablePages)) {
160 remove_all_actions('admin_notices');
161 \FluentForm\App\Modules\Registerer\ReviewQuery::register();
162 \FluentForm\App\Modules\Registerer\MigrationNotice::register();
163 }
164 });
165
166 add_action('wp_print_scripts', function () {
167 if (is_admin()) {
168 if (\FluentForm\App\Helpers\Helper::isFluentAdminPage()) {
169 $option = get_option('_fluentform_global_form_settings');
170 $isSkip = 'no' == \FluentForm\Framework\Helpers\ArrayHelper::get($option, 'misc.noConflictStatus');
171
172 $isSkip = apply_filters_deprecated(
173 'fluentform_skip_no_conflict',
174 [
175 $isSkip
176 ],
177 FLUENTFORM_FRAMEWORK_UPGRADE,
178 'fluentform/skip_no_conflict',
179 'Use fluentform/skip_no_conflict instead of fluentform_skip_no_conflict.'
180 );
181
182 $isSkip = apply_filters('fluentform/skip_no_conflict', $isSkip);
183
184 if ($isSkip) {
185 return;
186 }
187
188 global $wp_scripts;
189 if (!$wp_scripts) {
190 return;
191 }
192
193 $pluginUrl = plugins_url();
194 // Get an array of slugs to exclude from dequeue
195 $excludeSlugs = apply_filters('fluentform/exclude_js_slugs_from_dequeue', ['fluentform']);
196
197 foreach ($wp_scripts->queue as $script) {
198 if (!isset($wp_scripts->registered[$script])) {
199 continue;
200 }
201
202 $src = $wp_scripts->registered[$script]->src;
203
204 // Check if the script is in the plugins directory
205 if (false !== strpos($src, $pluginUrl)) {
206 // Only dequeue if none of the exclude slugs are in the script src
207 $shouldDequeue = true;
208 foreach ($excludeSlugs as $slug) {
209 if (false !== strpos($src, $slug)) {
210 $shouldDequeue = false;
211 break;
212 }
213 }
214
215 if ($shouldDequeue) {
216 wp_dequeue_script($wp_scripts->registered[$script]->handle);
217 }
218 }
219 }
220 }
221 }
222 }, 1);
223
224 $app->addAction('fluentform/loading_editor_assets', function ($form) {
225 add_filter('fluentform/editor_init_element_input_name', function ($field) {
226 if (empty($field['settings']['label_placement'])) {
227 $field['settings']['label_placement'] = '';
228 }
229 return $field;
230 });
231
232 add_filter('fluentform/editor_init_element_step_start', function ($item) {
233 if (!isset($item['settings']['progress_layout'])) {
234 $item['settings']['progress_layout'] = 'top';
235 }
236
237 if (!isset($item['settings']['tabs_show_progress_bar'])) {
238 $item['settings']['tabs_show_progress_bar'] = 'no';
239 }
240
241 return $item;
242 });
243
244 $upgradableCheckInputs = [
245 'input_radio',
246 'select',
247 'select_country',
248 'input_checkbox',
249 ];
250 foreach ($upgradableCheckInputs as $upgradeElement) {
251 add_filter('fluentform/editor_init_element_' . $upgradeElement, function ($element) use ($upgradeElement, $form) {
252
253 if (!\FluentForm\Framework\Helpers\ArrayHelper::get($element, 'settings.advanced_options')) {
254 $formattedOptions = [];
255 $oldOptions = \FluentForm\Framework\Helpers\ArrayHelper::get($element, 'options', []);
256 foreach ($oldOptions as $value => $label) {
257 $formattedOptions[] = [
258 'label' => $label,
259 'value' => $value,
260 'calc_value' => '',
261 'image' => '',
262 ];
263 }
264 $element['settings']['advanced_options'] = $formattedOptions;
265 $element['settings']['enable_image_input'] = false;
266 $element['settings']['calc_value_status'] = false;
267 unset($element['options']);
268
269 if ('input_radio' == $upgradeElement || 'input_checkbox' == $upgradeElement) {
270 $element['editor_options']['template'] = 'inputCheckable';
271 }
272 }
273
274 if (!isset($element['settings']['layout_class']) && in_array($upgradeElement, ['input_radio', 'input_checkbox'])) {
275 $element['settings']['layout_class'] = '';
276 }
277
278 if (!isset($element['settings']['dynamic_default_value'])) {
279 $element['settings']['dynamic_default_value'] = '';
280 }
281
282 if ('select_country' != $upgradeElement && !isset($element['settings']['randomize_options'])) {
283 $element['settings']['randomize_options'] = 'no';
284 }
285
286 if ('select' == $upgradeElement && \FluentForm\Framework\Helpers\ArrayHelper::get($element, 'attributes.multiple')) {
287 if (empty($element['settings']['max_selection'])) {
288 $element['settings']['max_selection'] = '';
289 }
290 if (isset($element['settings']['enable_select_2'])) {
291 \FluentForm\Framework\Helpers\ArrayHelper::forget($element, 'settings.enable_select_2');
292 }
293 }
294
295 if (
296 (
297 (
298 'select' == $upgradeElement &&
299 !\FluentForm\Framework\Helpers\ArrayHelper::get($element, 'attributes.multiple')
300 ) ||
301 'select_country' == $upgradeElement
302 ) &&
303 !isset($element['settings']['enable_select_2'])
304 ) {
305 $element['settings']['enable_select_2'] = 'no';
306 }
307
308 if ('select_country' != $upgradeElement && !isset($element['settings']['values_visible'])) {
309 $element['settings']['values_visible'] = false;
310 }
311
312 if ('select' == $upgradeElement && !isset($element['settings']['enable_option_groups'])) {
313 $element['settings']['enable_option_groups'] = 'no';
314 }
315
316
317
318 return $element;
319 });
320 }
321
322 $upgradableFileInputs = [
323 'input_file',
324 'input_image',
325 ];
326 foreach ($upgradableFileInputs as $upgradeElement) {
327 add_filter('fluentform/editor_init_element_' . $upgradeElement, function ($element) {
328 if (!isset($element['settings']['upload_file_location'])) {
329 $element['settings']['upload_file_location'] = 'default';
330 }
331 if (!isset($element['settings']['file_location_type'])) {
332 $element['settings']['file_location_type'] = 'follow_global_settings';
333 }
334 if ('input_image' === $element['element']) {
335 if (!isset($element['settings']['enable_crop'])) {
336 $element['settings']['enable_crop'] = 'no';
337 }
338 if (!isset($element['settings']['crop_mode'])) {
339 $element['settings']['crop_mode'] = (
340 isset($element['settings']['enforce_image_dimensions']) &&
341 $element['settings']['enforce_image_dimensions'] === 'yes'
342 ) ? 'dimensions' : 'ratio';
343 }
344 if (!isset($element['settings']['crop_ratio'])) {
345 $element['settings']['crop_ratio'] = 'free';
346 }
347 if (!isset($element['settings']['enforce_image_dimensions'])) {
348 $element['settings']['enforce_image_dimensions'] = 'no';
349 }
350 if (!isset($element['settings']['crop_width'])) {
351 $element['settings']['crop_width'] = '';
352 }
353 if (!isset($element['settings']['crop_height'])) {
354 $element['settings']['crop_height'] = '';
355 }
356 }
357 return $element;
358 });
359 }
360
361 $prefixSuffixInputs = [
362 'textarea',
363 'input_url',
364 'input_password',
365 ];
366
367 foreach ($prefixSuffixInputs as $inputType) {
368 add_filter('fluentform/editor_init_element_' . $inputType, function ($item) {
369 if (!isset($item['settings']['prefix_label'])) {
370 $item['settings']['prefix_label'] = '';
371 }
372 if (!isset($item['settings']['suffix_label'])) {
373 $item['settings']['suffix_label'] = '';
374 }
375 return $item;
376 });
377 }
378
379 add_filter('fluentform/editor_init_element_gdpr_agreement', function ($element) {
380 if (!isset($element['settings']['required_field_message'])) {
381 $element['settings']['required_field_message'] = '';
382 }
383 return $element;
384 });
385
386 add_filter('fluentform/editor_init_element_input_text', function ($element) {
387 if (!isset($element['attributes']['maxlength'])) {
388 $element['attributes']['maxlength'] = '';
389 }
390 return $element;
391 });
392
393 add_filter('fluentform/editor_init_element_textarea', function ($element) {
394 if (!isset($element['attributes']['maxlength'])) {
395 $element['attributes']['maxlength'] = '';
396 }
397 return $element;
398 });
399
400 add_filter('fluentform/editor_init_element_input_date', function ($item) {
401 if (!isset($item['settings']['date_config'])) {
402 $item['settings']['date_config'] = '';
403 }
404 return $item;
405 });
406
407 add_filter('fluentform/editor_init_element_ratings', function ($item) {
408 if (!isset($item['settings']['icon_source'])) {
409 $item['settings']['icon_source'] = 'preset';
410 }
411
412 if (!isset($item['settings']['icon_type'])) {
413 $item['settings']['icon_type'] = \FluentForm\App\Services\FormBuilder\RatingIcon::DEFAULT_ICON;
414 }
415
416 if (!isset($item['settings']['custom_icon_svg'])) {
417 $item['settings']['custom_icon_svg'] = '';
418 }
419
420 if (!isset($item['settings']['inactive_color'])) {
421 $item['settings']['inactive_color'] = \FluentForm\App\Services\FormBuilder\RatingIcon::DEFAULT_INACTIVE_COLOR;
422 }
423
424 if (!isset($item['settings']['active_color'])) {
425 $item['settings']['active_color'] = \FluentForm\App\Services\FormBuilder\RatingIcon::DEFAULT_ACTIVE_COLOR;
426 }
427
428 return $item;
429 });
430
431
432 add_filter('fluentform/editor_init_element_container', function ($item) {
433 if (!isset($item['settings']['conditional_logics'])) {
434 $item['settings']['conditional_logics'] = [];
435 }
436
437 if (!isset($item['settings']['container_width'])) {
438 $item['settings']['container_width'] = '';
439 }
440
441 if (!isset($item['settings']['is_width_auto_calc'])) {
442 $item['settings']['is_width_auto_calc'] = true;
443 }
444
445 if (!isset($item['settings']['render_recaptcha_v3_badge'])) {
446 $item['settings']['render_recaptcha_v3_badge'] = false;
447 }
448
449 $shouldSetWidth = !empty($item['columns']) && (!isset($item['columns'][0]['width']) || !$item['columns'][0]['width']);
450
451 if ($shouldSetWidth) {
452 $perColumn = round(100 / count($item['columns']), 2);
453
454 foreach ($item['columns'] as &$column) {
455 $column['width'] = $perColumn;
456 }
457 }
458
459 return $item;
460 });
461
462 add_filter('fluentform/editor_init_element_input_number', function ($item) {
463 if (!isset($item['settings']['number_step'])) {
464 $item['settings']['number_step'] = '';
465 }
466 if (!isset($item['settings']['numeric_formatter'])) {
467 $item['settings']['numeric_formatter'] = '';
468 }
469 if (!isset($item['settings']['prefix_label'])) {
470 $item['settings']['prefix_label'] = '';
471 }
472 if (!isset($item['settings']['suffix_label'])) {
473 $item['settings']['suffix_label'] = '';
474 }
475 if (!isset($item['settings']['mobile_keyboard_type_number'])) {
476 $item['settings']['mobile_keyboard_type_number'] = '';
477 }
478
479 return $item;
480 });
481
482 add_filter('fluentform/editor_init_element_input_mask', function ($item) {
483 if (!isset($item['settings']['mobile_keyboard_type'])) {
484 $item['settings']['mobile_keyboard_type'] = '';
485 }
486 return $item;
487 });
488
489 add_filter('fluentform/editor_init_element_input_email', function ($item) {
490 if (!isset($item['settings']['is_unique'])) {
491 $item['settings']['is_unique'] = 'no';
492 }
493 if (!isset($item['settings']['unique_validation_message'])) {
494 $item['settings']['unique_validation_message'] = __('Email address need to be unique.', 'fluentform');
495 }
496 if (!isset($item['settings']['prefix_label'])) {
497 $item['settings']['prefix_label'] = '';
498 }
499 if (!isset($item['settings']['suffix_label'])) {
500 $item['settings']['suffix_label'] = '';
501 }
502 return $item;
503 });
504
505
506 add_filter('fluentform/editor_init_element_input_text', function ($item) {
507 if (isset($item['attributes']['data-mask'])) {
508 if (!isset($item['settings']['data-mask-reverse'])) {
509 $item['settings']['data-mask-reverse'] = 'no';
510 }
511 if (!isset($item['settings']['data-clear-if-not-match'])) {
512 $item['settings']['data-clear-if-not-match'] = 'no';
513 }
514 } else {
515 if (!isset($item['settings']['is_unique'])) {
516 $item['settings']['is_unique'] = 'no';
517 }
518 if (!isset($item['settings']['unique_validation_message'])) {
519 $item['settings']['unique_validation_message'] = __('This field value need to be unique.', 'fluentform');
520 }
521 }
522
523 if (!isset($item['settings']['prefix_label'])) {
524 $item['settings']['prefix_label'] = '';
525 }
526 if (!isset($item['settings']['suffix_label'])) {
527 $item['settings']['suffix_label'] = '';
528 }
529 return $item;
530 });
531
532 if ($inputs = \FluentForm\App\Modules\Form\FormFieldsParser::getInputs($form, ['element'])) {
533 foreach ($inputs as $input) {
534 add_filter('fluentform/editor_init_element_'. $input['element'], function ($field) {
535 Helper::resolveValidationRulesGlobalOption($field);
536 return $field;
537 });
538 }
539 }
540
541 add_filter('fluentform/editor_init_element_recaptcha', function ($item, $form) {
542 $item['attributes']['name'] = 'g-recaptcha-response';
543 return $item;
544 }, 10, 2);
545
546 add_filter('fluentform/editor_init_element_hcaptcha', function ($item, $form) {
547 $item['attributes']['name'] = 'h-captcha-response';
548 return $item;
549 }, 10, 2);
550
551 add_filter('fluentform/editor_init_element_turnstile', function ($item, $form) {
552 $item['attributes']['name'] = 'cf-turnstile-response';
553 return $item;
554 }, 10, 2);
555
556 add_filter('fluentform/editor_init_element_address', function ($item) {
557 // Initialize autocomplete provider settings
558 if (!isset($item['settings']['autocomplete_provider'])) {
559 // If google autocomplete setting is enabled, set provider to google
560 if (ArrayHelper::get($item, 'settings.enable_g_autocomplete') === 'yes') {
561 $item['settings']['autocomplete_provider'] = 'google';
562 } else {
563 $item['settings']['autocomplete_provider'] = 'none';
564 }
565 }
566 if (!isset($item['settings']['enable_auto_locate'])) {
567 $item['settings']['enable_auto_locate'] = 'on_click'; // on_load, on_click, no
568 }
569 if (!isset($item['settings']['save_coordinates'])) {
570 $item['settings']['save_coordinates'] = 'no';
571 }
572
573 foreach ($item['fields'] as &$addressField) {
574 if (
575 !isset($addressField['settings']['label_placement']) &&
576 !isset($addressField['settings']['label_placement_options'])
577 ) {
578 $addressField['settings']['label_placement'] = '';
579 $addressField['settings']['label_placement_options'] = [
580 [
581 'value' => '',
582 'label' => __('Default', 'fluentform'),
583 ],
584 [
585 'value' => 'top',
586 'label' => __('Top', 'fluentform'),
587 ],
588 [
589 'value' => 'right',
590 'label' => __('Right', 'fluentform'),
591 ],
592 [
593 'value' => 'bottom',
594 'label' => __('Bottom', 'fluentform'),
595 ],
596 [
597 'value' => 'left',
598 'label' => __('Left', 'fluentform'),
599 ],
600 [
601 'value' => 'hide_label',
602 'label' => __('Hidden', 'fluentform'),
603 ],
604 ];
605 }
606 }
607 return $item;
608 });
609
610 add_filter('fluentform/editor_init_element_gdpr_agreement', function ($item, $form) {
611 $isConversationalForm = Helper::isConversionForm($form->id);
612
613 if ($isConversationalForm) {
614 $item['settings']['tc_agree_text'] = __('I accept', 'fluentform');
615 }
616
617 return $item;
618 }, 10, 2);
619
620 add_filter('fluentform/editor_init_element_terms_and_condition', function ($item, $form) {
621 $isConversationalForm = Helper::isConversionForm($form->id);
622
623 if ($isConversationalForm) {
624 $item['settings']['hide_disagree'] = false;
625 }
626
627 return $item;
628 }, 10, 2);
629 }, 10);
630
631 $app->addAction('fluentform/addons_page_render_fluentform_pdf', function () use ($app) {
632 $url = '';
633 if (!defined('FLUENTFORM_PDF_VERSION')) {
634 $url = wp_nonce_url(
635 self_admin_url('update.php?action=install-plugin&plugin=fluentforms-pdf'),
636 'install-plugin_fluentforms-pdf'
637 );
638 }
639
640 $app->view->render('admin.addons.pdf_promo', [
641 'public_url' => fluentFormMix(),
642 'install_url' => $url,
643 'is_installed' => defined('FLUENTFORM_PDF_VERSION'),
644 ]);
645 });
646
647 $app->addAction('fluentform/installed_by', function ($by) {
648 if (is_string($by) && !get_option('_ff_ins_by')) {
649 update_option('_ff_ins_by', sanitize_text_field($by), 'no');
650 }
651 });
652
653 // from Frontend.php
654 if (defined('WP_ROCKET_VERSION')) {
655 add_filter('rocket_excluded_inline_js_content', function ($lines) {
656 $lines[] = 'fluent_form_ff_form_instance';
657 $lines[] = 'fluentFormVars';
658 $lines[] = 'fluentform_payment';
659
660 return $lines;
661 });
662 }
663
664 // from Common.php
665 add_action('save_post', function ($post_id) use ($app) {
666
667 if (!is_post_type_viewable(get_post_type($post_id))) {
668 return;
669 }
670
671 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by WordPress save_post action
672 $post_content = isset($_REQUEST['post_content']) ? wp_kses_post(wp_unslash($_REQUEST['post_content'])) : false;
673 if ($post_content && is_string($post_content)) {
674 // Already sanitized above
675 } else {
676 $post = get_post($post_id);
677 $post_content = $post->post_content;
678 }
679
680 $shortcodeIds = Helper::getShortCodeIds(
681 $post_content,
682 'fluentform',
683 'id'
684 );
685
686 $attributes = ArrayHelper::get($shortcodeIds, 'attributes', []);
687 ArrayHelper::forget($shortcodeIds, 'attributes');
688
689 $shortcodeModalIds = Helper::getShortCodeIds(
690 $post_content,
691 'fluentform_modal',
692 'form_id'
693 );
694
695 $gutenbergIds = Helper::getFormsIdsFromBlocks($post_content);
696
697 if ($shortcodeModalIds) {
698 $modalAttributes = ArrayHelper::get($shortcodeModalIds, 'attributes', []);
699 ArrayHelper::forget($shortcodeModalIds, 'attributes');
700
701 $shortcodeIds = array_merge($shortcodeIds, $shortcodeModalIds);
702
703 if ($modalAttributes) {
704 $attributes = array_merge($attributes, $modalAttributes);
705 }
706 }
707
708 if ($gutenbergIds) {
709 $blockAttributes = ArrayHelper::get($gutenbergIds, 'attributes', []);
710 ArrayHelper::forget($gutenbergIds, 'attributes');
711
712 $shortcodeIds = array_merge($shortcodeIds, $gutenbergIds);
713
714 if ($blockAttributes) {
715 $attributes = array_merge($attributes, $blockAttributes);
716 }
717 }
718
719 $shortcodeIds = array_unique($shortcodeIds);
720
721 if ($attributes) {
722 $data = [];
723
724 foreach ($attributes as $attribute) {
725 $data[$attribute['formId']]['themes'][] = $attribute['theme'];
726 }
727
728 $shortcodeIds['attributes'] = $data;
729 }
730
731 if ($shortcodeIds) {
732 update_post_meta($post_id, '_has_fluentform', $shortcodeIds);
733 } elseif (get_post_meta($post_id, '_has_fluentform', true)) {
734 update_post_meta($post_id, '_has_fluentform', []);
735 }
736 });
737
738 $fluentformComponent = new Component($app);
739 $fluentformComponent->addRendererActions();
740 $fluentformComponent->addFluentFormShortCode();
741 $fluentformComponent->addFluentFormDefaultValueParser();
742 $fluentformComponent->addFluentformSubmissionInsertedFilter();
743 $fluentformComponent->addIsRenderableFilter();
744 $fluentformComponent->registerInputSanitizers();
745
746 add_action('wp', function () use ($app) {
747 // @todo: We will remove the fluentform_pages check from April 2021
748 $fluentFormPages = $app->request->get('fluent_forms_pages') || $app->request->get('fluentform_pages');
749
750 if ($fluentFormPages) {
751 add_action('wp_enqueue_scripts', function () use ($app) {
752 wp_enqueue_script('jquery');
753 wp_enqueue_script(
754 'fluent_forms_global',
755 fluentFormMix('js/fluent_forms_global.js'),
756 ['jquery'],
757 FLUENTFORM_VERSION,
758 true
759 );
760 $globalVars = [
761 'ajaxurl' => Helper::getAjaxUrl(),
762 'global_search_active' => apply_filters('fluentform/global_search_active', 'yes'),
763 'rest' => Helper::getRestInfo()
764 ];
765 if (Acl::hasAnyFormPermission()) {
766 $globalVars['fluent_forms_admin_nonce'] = wp_create_nonce('fluent_forms_admin_nonce');
767 }
768 wp_localize_script('fluent_forms_global', 'fluent_forms_global_var', $globalVars);
769 wp_enqueue_style('fluent-form-styles');
770 $form = wpFluent()->table('fluentform_forms')->find(intval($app->request->get('preview_id')));
771 $postId = get_the_ID() ?: 0;
772
773 $loadPublicStyle = apply_filters_deprecated(
774 'fluentform_load_default_public',
775 [
776 true,
777 $form,
778 $postId
779 ],
780 FLUENTFORM_FRAMEWORK_UPGRADE,
781 'fluentform/load_default_public',
782 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
783 );
784
785 if (apply_filters('fluentform/load_default_public', $loadPublicStyle, $form, $postId)) {
786 wp_enqueue_style('fluentform-public-default');
787 }
788 wp_enqueue_script('fluent-form-submission');
789 wp_enqueue_style('fluent-form-preview', fluentFormMix('css/preview.css'), [], FLUENTFORM_VERSION);
790 if (!defined('FLUENTFORMPRO')) {
791 wp_enqueue_script(
792 'fluentform-preview_app',
793 fluentFormMix('js/form_preview_app.js'),
794 ['jquery'],
795 FLUENTFORM_VERSION,
796 true
797 );
798
799 wp_localize_script('fluentform-preview_app', 'fluent_preview_var', [
800 'i18n' => \FluentForm\App\Modules\Registerer\TranslationString::getPreviewI18n()
801 ]);
802 }
803 });
804
805 (new \FluentForm\App\Modules\ProcessExteriorModule())->handleExteriorPages();
806 }
807 }, 1);
808
809 // Register api response log hooks
810 $app->addAction(
811 'fluentform/after_submission_api_response_success',
812 function ($form, $entryId, $data, $feed, $res, $msg = '') {
813 fluentform_after_submission_api_response_success($form, $entryId, $data, $feed, $res, $msg = '');
814 },
815 10,
816 6
817 );
818
819 $app->addAction(
820 'fluentform/after_submission_api_response_failed',
821 function ($form, $entryId, $data, $feed, $res, $msg = '') {
822 fluentform_after_submission_api_response_failed($form, $entryId, $data, $feed, $res, $msg = '');
823 },
824 10,
825 6
826 );
827
828 function fluentform_after_submission_api_response_success($form, $entryId, $data, $feed, $res, $msg = '')
829 {
830 try {
831 $isDev = 'production' != wpFluentForm()->getEnv();
832
833 $isDev = apply_filters_deprecated(
834 'fluentform_api_success_log',
835 [
836 $isDev,
837 $form,
838 $feed
839 ],
840 FLUENTFORM_FRAMEWORK_UPGRADE,
841 'fluentform/api_success_log',
842 'Use fluentform/api_success_log instead of fluentform_api_success_log.'
843 );
844
845 if (!apply_filters('fluentform/api_success_log', $isDev, $form, $feed)) {
846 return;
847 }
848
849 wpFluent()->table('fluentform_submission_meta')->insert([
850 'response_id' => $entryId,
851 'form_id' => $form->id,
852 'meta_key' => 'api_log',
853 'value' => $msg,
854 'name' => $feed->formattedValue['name'],
855 'status' => 'success',
856 'created_at' => current_time('mysql'),
857 'updated_at' => current_time('mysql'),
858 ]);
859 } catch (Exception $e) {
860 if (defined('WP_DEBUG') && WP_DEBUG) {
861 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging only when WP_DEBUG is enabled, helps developers troubleshoot shortcode parsing issues
862 error_log($e->getMessage());
863 }
864 return '';
865 }
866 }
867
868 function fluentform_after_submission_api_response_failed($form, $entryId, $data, $feed, $res, $msg = '')
869 {
870 try {
871 $isDev = 'production' != wpFluentForm()->getEnv();
872
873 $isDev = apply_filters_deprecated(
874 'fluentform_api_failed_log',
875 [
876 $isDev,
877 $form,
878 $feed
879 ],
880 FLUENTFORM_FRAMEWORK_UPGRADE,
881 'fluentform/api_failed_log',
882 'Use fluentform/api_failed_log instead of fluentform_api_failed_log.'
883 );
884
885 if (!apply_filters('fluentform/api_failed_log', $isDev, $form, $feed)) {
886 return;
887 }
888
889 wpFluent()->table('fluentform_submission_meta')->insert([
890 'response_id' => $entryId,
891 'form_id' => $form->id,
892 'meta_key' => 'api_log',
893 'value' => json_encode($res),
894 'name' => $feed->formattedValue['name'],
895 'status' => 'failed',
896 'created_at' => current_time('mysql'),
897 'updated_at' => current_time('mysql'),
898 ]);
899 } catch (Exception $e) {
900 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional logging for debugging
901 error_log($e->getMessage());
902 }
903 }
904
905 $app->addAction('fluentform/before_form_render', function ($form, $atts) {
906 $theme = ArrayHelper::get($atts, 'theme');
907
908 $styles = $theme ? [$theme] : [];
909
910 do_action(
911 'fluentform/load_form_assets',
912 $form->id,
913 $styles
914 );
915 }, 10, 2);
916
917 add_action('fluentform/load_form_assets', function ($formId, $styles = []) {
918 $formAssetLoader = (new \FluentForm\App\Modules\Form\Settings\FormCssJs());
919
920 $formAssetLoader->addCustomCssJs($formId);
921
922 $notLoadedStyles = [];
923
924 foreach ($styles as $style) {
925 if (!did_action('fluent_form/loaded_styler_' . $formId . '_' . $style)) {
926 $notLoadedStyles[] = $style;
927 }
928 }
929
930 // check if already loaded
931 if ($notLoadedStyles) {
932 $formAssetLoader->addStylerCSS($formId, $notLoadedStyles);
933 }
934 }, 10, 2);
935
936 $app->addAction('fluentform/submission_inserted', function ($insertId, $formData, $form) use ($app) {
937 $notificationManager = new \FluentForm\App\Hooks\Handlers\GlobalNotificationHandler($app);
938 $notificationManager->globalNotify($insertId, $formData, $form);
939 }, 10, 3);
940
941 $app->addAction('fluentform/schedule_feed', function ($queueId) use ($app) {
942 $scheduler = $app['fluentFormAsyncRequest'];
943
944 $scheduler->process($queueId);
945 });
946
947 $app->addAction('init', function () use ($app) {
948 new \FluentForm\App\Services\Integrations\MailChimp\MailChimpIntegration($app);
949 new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
950 // Load payment module
951 if (Helper::isPaymentCompatible()) {
952 (new FluentForm\App\Modules\Payments\PaymentHandler())->init();
953 }
954 });
955
956 $app->addAction('fluentform/form_element_start', function ($form) use ($app) {
957 $honeyPot = new \FluentForm\App\Modules\Form\HoneyPot($app);
958 $honeyPot->renderHoneyPot($form);
959
960 $tokenBasedSpamProtection = new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
961 $tokenBasedSpamProtection->renderTokenField($form);
962
963 $cleanTalk = new \FluentForm\App\Modules\Form\CleanTalkHandler();
964 $cleanTalk->setCleanTalkScript();
965 });
966
967 $app->addAction('fluentform/before_insert_submission', function ($insertData, $requestData, $form) use ($app) {
968 $honeyPot = new \FluentForm\App\Modules\Form\HoneyPot($app);
969 $honeyPot->verify($insertData, $requestData, $form->id);
970
971 $tokenBasedSpamProtection = new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
972 $tokenBasedSpamProtection->verify($insertData, $requestData, $form->id);
973 }, 9, 3);
974
975 // Maybe update current user allowed form ids,
976 // if current user has specific form permission and capable to create form
977 $app->addAction('fluentform/inserted_new_form', function ($formId){
978 \FluentForm\App\Services\Manager\FormManagerService::maybeAddUserAllowedFormIds($formId);
979 });
980
981 add_action('fluentform/log_data', function ($data) use ($app) {
982 $dataLogger = new \FluentForm\App\Modules\Logger\DataLogger($app);
983 $dataLogger->log($data);
984 });
985
986 // Support for third party plugin who do_action this hook on previous way (before 5.0.0 way)
987 // In Fluent Forms 5.0.0 'ff_log_data' add_action replaced with action named 'fluentform/log_data'.
988 // @todo - notify them for updating do_action name 'fluentform/log_data'.
989 // @todo - We will remove bellow add_action after 2 or more version release latter.
990 add_action('ff_log_data', function ($data) use ($app) {
991 $dataLogger = new \FluentForm\App\Modules\Logger\DataLogger($app);
992 $dataLogger->log($data);
993 });
994
995 // widgets
996 add_action('widgets_init', function () {
997 register_widget('FluentForm\App\Modules\Widgets\SidebarWidgets');
998 });
999
1000 add_action('wp', function () {
1001 global $post;
1002
1003 if (!is_a($post, 'WP_Post')) {
1004 return;
1005 }
1006
1007 $fluentFormIds = get_post_meta($post->ID, '_has_fluentform', true);
1008 $attributes = ArrayHelper::get($fluentFormIds, 'attributes', []);
1009
1010 if (isset($fluentFormIds['attributes'])) {
1011 unset($fluentFormIds['attributes']);
1012 }
1013
1014 if ($fluentFormIds && is_array($fluentFormIds)) {
1015 foreach ($fluentFormIds as $formId) {
1016 do_action(
1017 'fluentform/load_form_assets',
1018 $formId,
1019 array_unique(ArrayHelper::get($attributes, $formId . '.themes', []))
1020 );
1021 }
1022 }
1023 });
1024
1025 add_filter('cron_schedules', function ($schedules) {
1026 $schedules['ff_every_five_minutes'] = [
1027 'interval' => 300,
1028 'display' => 'Every 5 minutes (FluentForm)',
1029 ];
1030
1031 return $schedules;
1032 }, 10, 1);
1033
1034 add_action('fluentform_do_scheduled_tasks', 'fluentFormHandleScheduledTasks');
1035 add_action('fluentform_do_email_report_scheduled_tasks', 'fluentFormHandleScheduledEmailReport');
1036
1037 add_action('fluentform/integration_action_result', function ($feed, $status, $note = '') {
1038 if (!isset($feed['scheduled_action_id']) || !$status) {
1039 return;
1040 }
1041 if (!$note) {
1042 $note = $status;
1043 }
1044
1045 if (strlen($note) > 255) {
1046 if (function_exists('mb_substr')) {
1047 $note = mb_substr($note, 0, 251) . '...';
1048 } else {
1049 $note = substr($note, 0, 251) . '...';
1050 }
1051 }
1052
1053 $actionId = intval($feed['scheduled_action_id']);
1054 wpFluent()->table('ff_scheduled_actions')
1055 ->where('id', $actionId)
1056 ->update([
1057 'status' => $status,
1058 'note' => $note,
1059 'updated_at' => current_time('mysql'),
1060 ]);
1061 }, 10, 3);
1062
1063
1064 // Support for third party plugin who do_action this hook on previous way (before 5.0.0 way)
1065 // In Fluent Forms 5.0.0 'ff_integration_action_result' add_action replaced in above action named 'fluentform/integration_action_result'.
1066 // @todo - notify them for updating do_action name 'fluentform/integration_action_result'.
1067 // @todo - We will remove bellow add_action after 2 or more version release latter.
1068 add_action('ff_integration_action_result', function ($feed, $status, $note = '') {
1069 if (!isset($feed['scheduled_action_id']) || !$status) {
1070 return;
1071 }
1072 if (!$note) {
1073 $note = $status;
1074 }
1075
1076 if (strlen($note) > 255) {
1077 if (function_exists('mb_substr')) {
1078 $note = mb_substr($note, 0, 251) . '...';
1079 } else {
1080 $note = substr($note, 0, 251) . '...';
1081 }
1082 }
1083
1084 $actionId = intval($feed['scheduled_action_id']);
1085 wpFluent()->table('ff_scheduled_actions')
1086 ->where('id', $actionId)
1087 ->update([
1088 'status' => $status,
1089 'note' => $note,
1090 ]);
1091 }, 10, 3);
1092
1093 add_action('fluentform/global_notify_completed', function ($insertId, $form) use ($app) {
1094 $isTruncate = apply_filters_deprecated(
1095 'fluentform_truncate_password_values',
1096 [
1097 true,
1098 $form->id
1099 ],
1100 FLUENTFORM_FRAMEWORK_UPGRADE,
1101 'fluentform/truncate_password_values',
1102 'Use fluentform/truncate_password_values instead of fluentform_truncate_password_values.'
1103 );
1104
1105 if (strpos($form->form_fields, '"element":"input_password"') && apply_filters('fluentform/truncate_password_values', $isTruncate, $form->id)) {
1106 // we have password
1107 (new \FluentForm\App\Services\Integrations\GlobalNotificationService())->cleanUpPassword($insertId, $form);
1108 }
1109 }, 10, 2);
1110
1111 /*
1112 * Elementor Block Init
1113 */
1114
1115 if (defined('ELEMENTOR_VERSION')) {
1116 new \FluentForm\App\Modules\Widgets\ElementorWidget($app);
1117 }
1118 /*
1119 * Oxygen Widget Init
1120 */
1121
1122 add_action('init', function () {
1123 if (class_exists('OxyEl')) {
1124 if (file_exists(FLUENTFORM_DIR_PATH . 'app/Modules/Widgets/OxygenWidget.php')) {
1125 new FluentForm\App\Modules\Widgets\OxygenWidget();
1126 }
1127 }
1128 });
1129
1130 (new FluentForm\App\Services\Integrations\Slack\SlackNotificationActions($app))->register();
1131
1132 /*
1133 * Smartcode parser shortcodes
1134 */
1135
1136 new \FluentForm\App\Services\FormBuilder\Components\CustomSubmitButton();
1137
1138 add_action('enqueue_block_editor_assets', function () {
1139
1140 wp_enqueue_script(
1141 'fluentform-gutenberg-block',
1142 fluentFormMix('js/fluent_gutenblock.js'),
1143 ['wp-element', 'wp-polyfill', 'wp-i18n', 'wp-blocks', 'wp-components','wp-server-side-render', 'wp-block-editor'],
1144 FLUENTFORM_VERSION,
1145 true
1146 );
1147 wp_enqueue_style(
1148 'fluentform-gutenberg-block',
1149 fluentFormMix('css/fluent_gutenblock.css'),
1150 ['wp-edit-blocks'],
1151 FLUENTFORM_VERSION
1152 );
1153
1154
1155 $forms = wpFluent()->table('fluentform_forms')
1156 ->select(['id', 'title'])
1157 ->orderBy('id', 'DESC')
1158 ->get()
1159 ->toArray();
1160
1161 array_unshift($forms, (object) [
1162 'id' => '',
1163 'title' => __('-- Select a form --', 'fluentform'),
1164 ]);
1165
1166 $presets = [
1167 [
1168 'label' => __('Default (Form Styler)', 'fluentform'),
1169 'value' => '',
1170 ],
1171 [
1172 'label' => __('Inherit Theme Style', 'fluentform'),
1173 'value' => 'ffs_inherit_theme'
1174 ],
1175 ];
1176
1177 $presets = apply_filters('fluentform/block_editor_style_presets', $presets);
1178
1179 wp_localize_script('fluentform-gutenberg-block', 'fluentform_block_vars', [
1180 'logo' => fluentFormMix('img/fluent_icon.svg'),
1181 'forms' => $forms,
1182 'style_presets' => $presets,
1183 'theme_style' => apply_filters('fluentform/load_theme_style', false) ? 'ffs_inherit_theme' : '',
1184 'conversational_demo_img' => fluentFormMix('img/conversational-form-demo.png'),
1185 'rest' => Helper::getRestInfo()
1186 ]);
1187
1188 wp_enqueue_style(
1189 'fluentform-gutenberg-block',
1190 fluentFormMix('css/fluent_gutenblock.css'),
1191 ['wp-edit-blocks'],
1192 FLUENTFORM_VERSION
1193 );
1194 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public.css');
1195 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default.css');
1196
1197 if (is_rtl()) {
1198 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public-rtl.css');
1199 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default-rtl.css');
1200 }
1201
1202 wp_enqueue_style(
1203 'fluent-form-styles',
1204 $fluentFormPublicCss,
1205 [],
1206 FLUENTFORM_VERSION
1207 );
1208
1209 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Checking post ID in admin context
1210 $post_id = isset($_GET['post']) ? (int)$_GET['post'] : 0;
1211 $loadPublicStyle = apply_filters_deprecated(
1212 'fluentform_load_default_public',
1213 [
1214 true,
1215 (object)[],
1216 $post_id
1217 ],
1218 FLUENTFORM_FRAMEWORK_UPGRADE,
1219 'fluentform/load_default_public',
1220 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
1221 );
1222
1223 if (apply_filters('fluentform/load_default_public', $loadPublicStyle, (object)[], $post_id)) {
1224 wp_enqueue_style(
1225 'fluentform-public-default',
1226 $fluentFormPublicDefaultCss,
1227 [],
1228 FLUENTFORM_VERSION
1229 );
1230 }
1231 });
1232
1233
1234 if (function_exists('register_block_type')) {
1235 add_action('init', function () {
1236 // Use the dedicated GutenbergBlock class for block registration and rendering
1237 \FluentForm\App\Services\Blocks\GutenbergBlock::register();
1238 });
1239 }
1240
1241
1242 add_action('fluentform/before_updating_form',function ($form, $postData){
1243 (new FluentForm\App\Services\Form\HistoryService())->init($form, $postData);
1244 },10,2);
1245
1246
1247 // WordPress 6.3+ uses iframes for block editor preview
1248 // Official WordPress solution: Use enqueue_block_assets with proper context checking
1249 // See: https://make.wordpress.org/core/2023/07/18/miscellaneous-editor-changes-in-wordpress-6-3/
1250 add_action('enqueue_block_assets', function() {
1251 // Check if we're in the block editor context (not frontend)
1252 // This works for both the editor UI and the iframe preview in WordPress 6.3+
1253 if (!is_admin() && !wp_is_block_theme()) {
1254 return;
1255 }
1256
1257 // Additional check: Only load if we're actually in a block editor screen
1258 if (is_admin()) {
1259 $current_screen = function_exists('get_current_screen') ? get_current_screen() : null;
1260 if ($current_screen && !$current_screen->is_block_editor()) {
1261 return;
1262 }
1263 }
1264
1265 // Enqueue Fluent Forms CSS for block editor iframe preview
1266 // These styles are necessary for the live form preview in the block editor
1267 wp_enqueue_style('fluent-forms-public', fluentFormMix('css/fluent-forms-public.css'), [], FLUENTFORM_VERSION);
1268 wp_enqueue_style('fluentform-public-default', fluentFormMix('css/fluentform-public-default.css'), [], FLUENTFORM_VERSION);
1269
1270 });
1271
1272
1273
1274 // require the CLI
1275 if (defined('WP_CLI') && WP_CLI) {
1276 \WP_CLI::add_command('fluentform', '\FluentForm\App\Modules\CLI\Commands');
1277 }
1278