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

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