PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.8
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.8
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.8, at app/Hooks/actions.php

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