PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.15
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.15
6.2.15 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 All 197 releases
fluentform / app / Hooks / actions.php

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

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