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

1,353 lines 48.3 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 add_filter('fluentform/editor_init_element_input_mask', function ($item) {
547 if (!isset($item['settings']['mobile_keyboard_type'])) {
548 $item['settings']['mobile_keyboard_type'] = '';
549 }
550 return $item;
551 });
552
553 add_filter('fluentform/editor_init_element_input_email', function ($item) {
554 if (!isset($item['settings']['is_unique'])) {
555 $item['settings']['is_unique'] = 'no';
556 }
557 if (!isset($item['settings']['unique_validation_message'])) {
558 $item['settings']['unique_validation_message'] = __('Email address need to be unique.', 'fluentform');
559 }
560 if (!isset($item['settings']['prefix_label'])) {
561 $item['settings']['prefix_label'] = '';
562 }
563 if (!isset($item['settings']['suffix_label'])) {
564 $item['settings']['suffix_label'] = '';
565 }
566 return $item;
567 });
568
569 add_filter('fluentform/editor_init_element_input_text', function ($item) {
570 if (isset($item['attributes']['data-mask'])) {
571 if (!isset($item['settings']['data-mask-reverse'])) {
572 $item['settings']['data-mask-reverse'] = 'no';
573 }
574 if (!isset($item['settings']['data-clear-if-not-match'])) {
575 $item['settings']['data-clear-if-not-match'] = 'no';
576 }
577 } else {
578 if (!isset($item['settings']['is_unique'])) {
579 $item['settings']['is_unique'] = 'no';
580 }
581 if (!isset($item['settings']['unique_validation_message'])) {
582 $item['settings']['unique_validation_message'] = __('This field value need to be unique.', 'fluentform');
583 }
584 }
585
586 if (!isset($item['settings']['prefix_label'])) {
587 $item['settings']['prefix_label'] = '';
588 }
589 if (!isset($item['settings']['suffix_label'])) {
590 $item['settings']['suffix_label'] = '';
591 }
592 return $item;
593 });
594
595 if ($inputs = \FluentForm\App\Modules\Form\FormFieldsParser::getInputs($form, ['element'])) {
596 foreach ($inputs as $input) {
597 add_filter('fluentform/editor_init_element_' . $input['element'], function ($field) {
598 Helper::resolveValidationRulesGlobalOption($field);
599 return $field;
600 });
601 }
602 }
603
604 add_filter('fluentform/editor_init_element_recaptcha', function ($item, $form) {
605 $item['attributes']['name'] = 'g-recaptcha-response';
606 return $item;
607 }, 10, 2);
608
609 add_filter('fluentform/editor_init_element_hcaptcha', function ($item, $form) {
610 $item['attributes']['name'] = 'h-captcha-response';
611 return $item;
612 }, 10, 2);
613
614 add_filter('fluentform/editor_init_element_turnstile', function ($item, $form) {
615 $item['attributes']['name'] = 'cf-turnstile-response';
616 return $item;
617 }, 10, 2);
618
619 add_filter('fluentform/editor_init_element_address', function ($item) {
620 // Initialize autocomplete provider settings
621 if (!isset($item['settings']['autocomplete_provider'])) {
622 // If google autocomplete setting is enabled, set provider to google
623 if (ArrayHelper::get($item, 'settings.enable_g_autocomplete') === 'yes') {
624 $item['settings']['autocomplete_provider'] = 'google';
625 } else {
626 $item['settings']['autocomplete_provider'] = 'none';
627 }
628 }
629 if (!isset($item['settings']['enable_auto_locate'])) {
630 $item['settings']['enable_auto_locate'] = 'on_click'; // on_load, on_click, no
631 }
632 if (!isset($item['settings']['save_coordinates'])) {
633 $item['settings']['save_coordinates'] = 'no';
634 }
635
636 foreach ($item['fields'] as &$addressField) {
637 if (
638 !isset($addressField['settings']['label_placement']) &&
639 !isset($addressField['settings']['label_placement_options'])
640 ) {
641 $addressField['settings']['label_placement'] = '';
642 $addressField['settings']['label_placement_options'] = [
643 [
644 'value' => '',
645 'label' => __('Default', 'fluentform'),
646 ],
647 [
648 'value' => 'top',
649 'label' => __('Top', 'fluentform'),
650 ],
651 [
652 'value' => 'right',
653 'label' => __('Right', 'fluentform'),
654 ],
655 [
656 'value' => 'bottom',
657 'label' => __('Bottom', 'fluentform'),
658 ],
659 [
660 'value' => 'left',
661 'label' => __('Left', 'fluentform'),
662 ],
663 [
664 'value' => 'hide_label',
665 'label' => __('Hidden', 'fluentform'),
666 ],
667 ];
668 }
669 }
670 return $item;
671 });
672
673 add_filter('fluentform/editor_init_element_gdpr_agreement', function ($item, $form) {
674 $isConversationalForm = Helper::isConversionForm($form->id);
675
676 if ($isConversationalForm) {
677 $item['settings']['tc_agree_text'] = __('I accept', 'fluentform');
678 }
679
680 return $item;
681 }, 10, 2);
682
683 add_filter('fluentform/editor_init_element_terms_and_condition', function ($item, $form) {
684 $isConversationalForm = Helper::isConversionForm($form->id);
685
686 if ($isConversationalForm) {
687 $item['settings']['hide_disagree'] = false;
688 }
689
690 return $item;
691 }, 10, 2);
692 }, 10);
693
694 $app->addAction('fluentform/addons_page_render_fluentform_pdf', function () use ($app) {
695 $url = '';
696 if (!defined('FLUENTFORM_PDF_VERSION')) {
697 $url = wp_nonce_url(
698 self_admin_url('update.php?action=install-plugin&plugin=fluentforms-pdf'),
699 'install-plugin_fluentforms-pdf'
700 );
701 }
702
703 $app->view->render('admin.addons.pdf_promo', [
704 'public_url' => fluentFormMix(),
705 'install_url' => $url,
706 'is_installed' => defined('FLUENTFORM_PDF_VERSION'),
707 ]);
708 });
709
710 $app->addAction('fluentform/installed_by', function ($by) {
711 if (is_string($by) && !get_option('_ff_ins_by')) {
712 update_option('_ff_ins_by', sanitize_text_field($by), 'no');
713 }
714 });
715
716 // from Frontend.php
717 if (defined('WP_ROCKET_VERSION')) {
718 add_filter('rocket_excluded_inline_js_content', function ($lines) {
719 $lines[] = 'fluent_form_ff_form_instance';
720 $lines[] = 'fluentFormVars';
721 $lines[] = 'fluentform_payment';
722
723 return $lines;
724 });
725 }
726
727 // from Common.php
728 add_action('save_post', function ($post_id) use ($app) {
729
730 if (!is_post_type_viewable(get_post_type($post_id))) {
731 return;
732 }
733
734 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified by WordPress save_post action
735 $post_content = isset($_REQUEST['post_content']) ? wp_kses_post(wp_unslash($_REQUEST['post_content'])) : false;
736 if (!$post_content || !is_string($post_content)) {
737 $post = get_post($post_id);
738 $post_content = $post->post_content;
739 }
740
741 $shortcodeIds = Helper::getShortCodeIds(
742 $post_content,
743 'fluentform',
744 'id'
745 );
746
747 $attributes = ArrayHelper::get($shortcodeIds, 'attributes', []);
748 ArrayHelper::forget($shortcodeIds, 'attributes');
749
750 $shortcodeModalIds = Helper::getShortCodeIds(
751 $post_content,
752 'fluentform_modal',
753 'form_id'
754 );
755
756 $gutenbergIds = Helper::getFormsIdsFromBlocks($post_content);
757
758 if ($shortcodeModalIds) {
759 $modalAttributes = ArrayHelper::get($shortcodeModalIds, 'attributes', []);
760 ArrayHelper::forget($shortcodeModalIds, 'attributes');
761
762 $shortcodeIds = array_merge($shortcodeIds, $shortcodeModalIds);
763
764 if ($modalAttributes) {
765 $attributes = array_merge($attributes, $modalAttributes);
766 }
767 }
768
769 if ($gutenbergIds) {
770 $blockAttributes = ArrayHelper::get($gutenbergIds, 'attributes', []);
771 ArrayHelper::forget($gutenbergIds, 'attributes');
772
773 $shortcodeIds = array_merge($shortcodeIds, $gutenbergIds);
774
775 if ($blockAttributes) {
776 $attributes = array_merge($attributes, $blockAttributes);
777 }
778 }
779
780 $shortcodeIds = array_unique($shortcodeIds);
781
782 if ($attributes) {
783 $data = [];
784
785 foreach ($attributes as $attribute) {
786 $data[$attribute['formId']]['themes'][] = $attribute['theme'];
787 }
788
789 $shortcodeIds['attributes'] = $data;
790 }
791
792 if ($shortcodeIds) {
793 update_post_meta($post_id, '_has_fluentform', $shortcodeIds);
794 } elseif (get_post_meta($post_id, '_has_fluentform', true)) {
795 update_post_meta($post_id, '_has_fluentform', []);
796 }
797 });
798
799 $fluentformComponent = new Component($app);
800 $fluentformComponent->addRendererActions();
801 $fluentformComponent->addFluentFormShortCode();
802 $fluentformComponent->addFluentFormDefaultValueParser();
803 $fluentformComponent->addFluentformSubmissionInsertedFilter();
804 $fluentformComponent->addIsRenderableFilter();
805 $fluentformComponent->registerInputSanitizers();
806
807 add_action('wp', function () use ($app) {
808 // @todo: We will remove the fluentform_pages check from April 2021
809 $fluentFormPages = $app->request->get('fluent_forms_pages') || $app->request->get('fluentform_pages');
810
811 if ($fluentFormPages) {
812 add_action('wp_enqueue_scripts', function () use ($app) {
813 wp_enqueue_script('jquery');
814 wp_enqueue_script(
815 'fluent_forms_global',
816 fluentFormMix('js/fluent_forms_global.js'),
817 ['jquery'],
818 FLUENTFORM_VERSION,
819 true
820 );
821 $globalVars = [
822 'ajaxurl' => Helper::getAjaxUrl(),
823 'global_search_active' => apply_filters('fluentform/global_search_active', 'yes'),
824 'rest' => Helper::getRestInfo(),
825 ];
826 if (Acl::hasAnyFormPermission()) {
827 $globalVars['fluent_forms_admin_nonce'] = wp_create_nonce('fluent_forms_admin_nonce');
828 }
829 wp_localize_script('fluent_forms_global', 'fluent_forms_global_var', $globalVars);
830 wp_enqueue_style('fluent-form-styles');
831 $form = wpFluent()->table('fluentform_forms')->find(intval($app->request->get('preview_id')));
832 $postId = get_the_ID() ? get_the_ID() : 0;
833
834 $loadPublicStyle = apply_filters_deprecated(
835 'fluentform_load_default_public',
836 [
837 true,
838 $form,
839 $postId,
840 ],
841 FLUENTFORM_FRAMEWORK_UPGRADE,
842 'fluentform/load_default_public',
843 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
844 );
845
846 if (apply_filters('fluentform/load_default_public', $loadPublicStyle, $form, $postId)) {
847 wp_enqueue_style('fluentform-public-default');
848 }
849 wp_enqueue_script('fluent-form-submission');
850 wp_enqueue_style('fluent-form-preview', fluentFormMix('css/preview.css'), [], FLUENTFORM_VERSION);
851 if (!defined('FLUENTFORMPRO')) {
852 wp_enqueue_script(
853 'fluentform-preview_app',
854 fluentFormMix('js/form_preview_app.js'),
855 ['jquery'],
856 FLUENTFORM_VERSION,
857 true
858 );
859
860 wp_localize_script('fluentform-preview_app', 'fluent_preview_var', [
861 'i18n' => \FluentForm\App\Modules\Registerer\TranslationString::getPreviewI18n(),
862 ]);
863 }
864 });
865
866 (new \FluentForm\App\Modules\ProcessExteriorModule())->handleExteriorPages();
867 }
868 }, 1);
869
870 // Register api response log hooks
871 $app->addAction(
872 'fluentform/after_submission_api_response_success',
873 function ($form, $entryId, $data, $feed, $res, $msg = '') {
874 fluentform_after_submission_api_response_success($form, $entryId, $data, $feed, $res, $msg = '');
875 },
876 10,
877 6
878 );
879
880 $app->addAction(
881 'fluentform/after_submission_api_response_failed',
882 function ($form, $entryId, $data, $feed, $res, $msg = '') {
883 fluentform_after_submission_api_response_failed($form, $entryId, $data, $feed, $res, $msg = '');
884 },
885 10,
886 6
887 );
888
889 function fluentform_after_submission_api_response_success($form, $entryId, $data, $feed, $res, $msg = '')
890 {
891 try {
892 $isDev = 'production' != wpFluentForm()->getEnv();
893
894 $isDev = apply_filters_deprecated(
895 'fluentform_api_success_log',
896 [
897 $isDev,
898 $form,
899 $feed,
900 ],
901 FLUENTFORM_FRAMEWORK_UPGRADE,
902 'fluentform/api_success_log',
903 'Use fluentform/api_success_log instead of fluentform_api_success_log.'
904 );
905
906 if (!apply_filters('fluentform/api_success_log', $isDev, $form, $feed)) {
907 return;
908 }
909
910 wpFluent()->table('fluentform_submission_meta')->insert([
911 'response_id' => $entryId,
912 'form_id' => $form->id,
913 'meta_key' => 'api_log',
914 'value' => $msg,
915 'name' => $feed->formattedValue['name'],
916 'status' => 'success',
917 'created_at' => current_time('mysql'),
918 'updated_at' => current_time('mysql'),
919 ]);
920 } catch (Exception $e) {
921 if (defined('WP_DEBUG') && WP_DEBUG) {
922 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug logging only when WP_DEBUG is enabled, helps developers troubleshoot shortcode parsing issues
923 error_log($e->getMessage());
924 }
925 return '';
926 }
927 }
928
929 function fluentform_after_submission_api_response_failed($form, $entryId, $data, $feed, $res, $msg = '')
930 {
931 try {
932 $isDev = 'production' != wpFluentForm()->getEnv();
933
934 $isDev = apply_filters_deprecated(
935 'fluentform_api_failed_log',
936 [
937 $isDev,
938 $form,
939 $feed,
940 ],
941 FLUENTFORM_FRAMEWORK_UPGRADE,
942 'fluentform/api_failed_log',
943 'Use fluentform/api_failed_log instead of fluentform_api_failed_log.'
944 );
945
946 if (!apply_filters('fluentform/api_failed_log', $isDev, $form, $feed)) {
947 return;
948 }
949
950 wpFluent()->table('fluentform_submission_meta')->insert([
951 'response_id' => $entryId,
952 'form_id' => $form->id,
953 'meta_key' => 'api_log',
954 'value' => json_encode($res),
955 'name' => $feed->formattedValue['name'],
956 'status' => 'failed',
957 'created_at' => current_time('mysql'),
958 'updated_at' => current_time('mysql'),
959 ]);
960 } catch (Exception $e) {
961 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional logging for debugging
962 error_log($e->getMessage());
963 }
964 }
965
966 $app->addAction('fluentform/before_form_render', function ($form, $atts) {
967 $theme = ArrayHelper::get($atts, 'theme');
968
969 $styles = $theme ? [$theme] : [];
970
971 do_action(
972 'fluentform/load_form_assets',
973 $form->id,
974 $styles
975 );
976 }, 10, 2);
977
978 add_action('fluentform/load_form_assets', function ($formId, $styles = []) {
979 $formAssetLoader = (new \FluentForm\App\Modules\Form\Settings\FormCssJs());
980
981 $formAssetLoader->addCustomCssJs($formId);
982
983 $notLoadedStyles = [];
984
985 foreach ($styles as $style) {
986 if (!did_action('fluent_form/loaded_styler_' . $formId . '_' . $style)) {
987 $notLoadedStyles[] = $style;
988 }
989 }
990
991 // check if already loaded
992 if ($notLoadedStyles) {
993 $formAssetLoader->addStylerCSS($formId, $notLoadedStyles);
994 }
995 }, 10, 2);
996
997 $app->addAction('fluentform/submission_inserted', function ($insertId, $formData, $form) use ($app) {
998 $notificationManager = new \FluentForm\App\Hooks\Handlers\GlobalNotificationHandler($app);
999 $notificationManager->globalNotify($insertId, $formData, $form);
1000 }, 10, 3);
1001
1002 $app->addAction('fluentform/schedule_feed', function ($queueId) use ($app) {
1003 $scheduler = $app['fluentFormAsyncRequest'];
1004
1005 $scheduler->process($queueId);
1006 });
1007
1008 $app->addAction('init', function () use ($app) {
1009 new \FluentForm\App\Services\Integrations\MailChimp\MailChimpIntegration($app);
1010 new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
1011 // Load payment module
1012 if (Helper::isPaymentCompatible()) {
1013 (new FluentForm\App\Modules\Payments\PaymentHandler())->init();
1014 }
1015 });
1016
1017 $app->addAction('fluentform/form_element_start', function ($form) use ($app) {
1018 $honeyPot = new \FluentForm\App\Modules\Form\HoneyPot($app);
1019 $honeyPot->renderHoneyPot($form);
1020
1021 $tokenBasedSpamProtection = new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
1022 $tokenBasedSpamProtection->renderTokenField($form);
1023
1024 $cleanTalk = new \FluentForm\App\Modules\Form\CleanTalkHandler();
1025 $cleanTalk->setCleanTalkScript();
1026 });
1027
1028 $app->addAction('fluentform/before_insert_submission', function ($insertData, $requestData, $form) use ($app) {
1029 $honeyPot = new \FluentForm\App\Modules\Form\HoneyPot($app);
1030 $honeyPot->verify($insertData, $requestData, $form->id);
1031
1032 $tokenBasedSpamProtection = new \FluentForm\App\Modules\Form\TokenBasedSpamProtection($app);
1033 $tokenBasedSpamProtection->verify($insertData, $requestData, $form->id);
1034 }, 9, 3);
1035
1036 // The token-based spam check (FINDING-25) enforces on conversational forms too, but its ~1h TTL
1037 // token cannot be refreshed by the conversational JS app — it bakes hidden inputs statically at
1038 // render, so behind a full-page cache the token expires and rejects every legitimate submission.
1039 // Disable ONLY the token for conversational forms, resolved from server-side form meta (never the
1040 // client-supplied isFFConversational flag, which was the original bypass). The honeypot still applies.
1041 $app->addFilter('fluentform/token_based_spam_protection_status', function ($status, $formId) {
1042 if ($status && \FluentForm\App\Helpers\Helper::isConversionForm($formId)) {
1043 return false;
1044 }
1045 return $status;
1046 }, 10, 2);
1047
1048 // Maybe update current user allowed form ids,
1049 // if current user has specific form permission and capable to create form
1050 $app->addAction('fluentform/inserted_new_form', function ($formId) {
1051 \FluentForm\App\Services\Manager\FormManagerService::maybeAddUserAllowedFormIds($formId);
1052 });
1053
1054 add_action('fluentform/log_data', function ($data) use ($app) {
1055 $dataLogger = new \FluentForm\App\Modules\Logger\DataLogger($app);
1056 $dataLogger->log($data);
1057 });
1058
1059 // Support for third party plugin who do_action this hook on previous way (before 5.0.0 way)
1060 // In Fluent Forms 5.0.0 'ff_log_data' add_action replaced with action named 'fluentform/log_data'.
1061 // @todo - notify them for updating do_action name 'fluentform/log_data'.
1062 // @todo - We will remove bellow add_action after 2 or more version release latter.
1063 add_action('ff_log_data', function ($data) use ($app) {
1064 $dataLogger = new \FluentForm\App\Modules\Logger\DataLogger($app);
1065 $dataLogger->log($data);
1066 });
1067
1068 // widgets
1069 add_action('widgets_init', function () {
1070 register_widget('FluentForm\App\Modules\Widgets\SidebarWidgets');
1071 });
1072
1073 add_action('wp', function () {
1074 global $post;
1075
1076 if (!is_a($post, 'WP_Post')) {
1077 return;
1078 }
1079
1080 $fluentFormIds = get_post_meta($post->ID, '_has_fluentform', true);
1081 $attributes = ArrayHelper::get($fluentFormIds, 'attributes', []);
1082
1083 if (isset($fluentFormIds['attributes'])) {
1084 unset($fluentFormIds['attributes']);
1085 }
1086
1087 if ($fluentFormIds && is_array($fluentFormIds)) {
1088 foreach ($fluentFormIds as $formId) {
1089 do_action(
1090 'fluentform/load_form_assets',
1091 $formId,
1092 array_unique(ArrayHelper::get($attributes, $formId . '.themes', []))
1093 );
1094 }
1095 }
1096 });
1097
1098 add_filter('cron_schedules', function ($schedules) {
1099 $schedules['ff_every_five_minutes'] = [
1100 'interval' => 300,
1101 'display' => 'Every 5 minutes (FluentForm)',
1102 ];
1103
1104 return $schedules;
1105 }, 10, 1);
1106
1107 add_action('fluentform_do_scheduled_tasks', 'fluentFormHandleScheduledTasks');
1108 add_action('fluentform_do_email_report_scheduled_tasks', 'fluentFormHandleScheduledEmailReport');
1109
1110 add_action('fluentform/integration_action_result', function ($feed, $status, $note = '') {
1111 if (!isset($feed['scheduled_action_id']) || !$status) {
1112 return;
1113 }
1114 if (!$note) {
1115 $note = $status;
1116 }
1117
1118 $note = is_scalar($note)
1119 ? sanitize_text_field(wp_unslash((string) $note))
1120 : sanitize_text_field((string) wp_json_encode($note));
1121
1122 if (strlen($note) > 255) {
1123 if (function_exists('mb_substr')) {
1124 $note = mb_substr($note, 0, 251) . '...';
1125 } else {
1126 $note = substr($note, 0, 251) . '...';
1127 }
1128 }
1129
1130 $actionId = intval($feed['scheduled_action_id']);
1131 wpFluent()->table('ff_scheduled_actions')
1132 ->where('id', $actionId)
1133 ->update([
1134 'status' => $status,
1135 'note' => $note,
1136 'updated_at' => current_time('mysql'),
1137 ]);
1138 }, 10, 3);
1139
1140
1141 // Support for third party plugin who do_action this hook on previous way (before 5.0.0 way)
1142 // In Fluent Forms 5.0.0 'ff_integration_action_result' add_action replaced in above action named 'fluentform/integration_action_result'.
1143 // @todo - notify them for updating do_action name 'fluentform/integration_action_result'.
1144 // @todo - We will remove bellow add_action after 2 or more version release latter.
1145 add_action('ff_integration_action_result', function ($feed, $status, $note = '') {
1146 if (!isset($feed['scheduled_action_id']) || !$status) {
1147 return;
1148 }
1149 if (!$note) {
1150 $note = $status;
1151 }
1152
1153 $note = is_scalar($note)
1154 ? sanitize_text_field(wp_unslash((string) $note))
1155 : sanitize_text_field((string) wp_json_encode($note));
1156
1157 if (strlen($note) > 255) {
1158 if (function_exists('mb_substr')) {
1159 $note = mb_substr($note, 0, 251) . '...';
1160 } else {
1161 $note = substr($note, 0, 251) . '...';
1162 }
1163 }
1164
1165 $actionId = intval($feed['scheduled_action_id']);
1166 wpFluent()->table('ff_scheduled_actions')
1167 ->where('id', $actionId)
1168 ->update([
1169 'status' => $status,
1170 'note' => $note,
1171 ]);
1172 }, 10, 3);
1173
1174 add_action('fluentform/global_notify_completed', function ($insertId, $form) use ($app) {
1175 $isTruncate = apply_filters_deprecated(
1176 'fluentform_truncate_password_values',
1177 [
1178 true,
1179 $form->id,
1180 ],
1181 FLUENTFORM_FRAMEWORK_UPGRADE,
1182 'fluentform/truncate_password_values',
1183 'Use fluentform/truncate_password_values instead of fluentform_truncate_password_values.'
1184 );
1185
1186 if (strpos($form->form_fields, '"element":"input_password"') && apply_filters('fluentform/truncate_password_values', $isTruncate, $form->id)) {
1187 // we have password
1188 (new \FluentForm\App\Services\Integrations\GlobalNotificationService())->cleanUpPassword($insertId, $form);
1189 }
1190 }, 10, 2);
1191
1192 /*
1193 * Elementor Block Init
1194 */
1195
1196 if (defined('ELEMENTOR_VERSION')) {
1197 new \FluentForm\App\Modules\Widgets\ElementorWidget($app);
1198 }
1199 /*
1200 * Oxygen Widget Init
1201 */
1202
1203 add_action('init', function () {
1204 if (class_exists('OxyEl')) {
1205 if (file_exists(FLUENTFORM_DIR_PATH . 'app/Modules/Widgets/OxygenWidget.php')) {
1206 new FluentForm\App\Modules\Widgets\OxygenWidget();
1207 }
1208 }
1209 });
1210
1211 (new FluentForm\App\Services\Integrations\Slack\SlackNotificationActions($app))->register();
1212
1213 /*
1214 * Smartcode parser shortcodes
1215 */
1216
1217 new \FluentForm\App\Services\FormBuilder\Components\CustomSubmitButton();
1218
1219 add_action('enqueue_block_editor_assets', function () {
1220
1221 wp_enqueue_script(
1222 'fluentform-gutenberg-block',
1223 fluentFormMix('js/fluent_gutenblock.js'),
1224 ['wp-element', 'wp-polyfill', 'wp-i18n', 'wp-blocks', 'wp-components','wp-server-side-render', 'wp-block-editor'],
1225 FLUENTFORM_VERSION,
1226 true
1227 );
1228 wp_enqueue_style(
1229 'fluentform-gutenberg-block',
1230 fluentFormMix('css/fluent_gutenblock.css'),
1231 ['wp-edit-blocks'],
1232 FLUENTFORM_VERSION
1233 );
1234
1235 $forms = wpFluent()->table('fluentform_forms')
1236 ->select(['id', 'title'])
1237 ->orderBy('id', 'DESC')
1238 ->get()
1239 ->toArray();
1240
1241 array_unshift($forms, (object) [
1242 'id' => '',
1243 'title' => __('-- Select a form --', 'fluentform'),
1244 ]);
1245
1246 $presets = [
1247 [
1248 'label' => __('Default (Form Styler)', 'fluentform'),
1249 'value' => '',
1250 ],
1251 [
1252 'label' => __('Inherit Theme Style', 'fluentform'),
1253 'value' => 'ffs_inherit_theme',
1254 ],
1255 ];
1256
1257 $presets = apply_filters('fluentform/block_editor_style_presets', $presets);
1258
1259 wp_localize_script('fluentform-gutenberg-block', 'fluentform_block_vars', [
1260 'logo' => fluentFormMix('img/fluent_icon.svg'),
1261 'forms' => $forms,
1262 'style_presets' => $presets,
1263 'theme_style' => apply_filters('fluentform/load_theme_style', false) ? 'ffs_inherit_theme' : '',
1264 'conversational_demo_img' => fluentFormMix('img/conversational-form-demo.png'),
1265 'rest' => Helper::getRestInfo(),
1266 ]);
1267
1268 wp_enqueue_style(
1269 'fluentform-gutenberg-block',
1270 fluentFormMix('css/fluent_gutenblock.css'),
1271 ['wp-edit-blocks'],
1272 FLUENTFORM_VERSION
1273 );
1274 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public.css');
1275 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default.css');
1276
1277 if (is_rtl()) {
1278 $fluentFormPublicCss = fluentFormMix('css/fluent-forms-public-rtl.css');
1279 $fluentFormPublicDefaultCss = fluentFormMix('css/fluentform-public-default-rtl.css');
1280 }
1281
1282 wp_enqueue_style(
1283 'fluent-form-styles',
1284 $fluentFormPublicCss,
1285 [],
1286 FLUENTFORM_VERSION
1287 );
1288
1289 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Checking post ID in admin context
1290 $post_id = isset($_GET['post']) ? (int) $_GET['post'] : 0;
1291 $loadPublicStyle = apply_filters_deprecated(
1292 'fluentform_load_default_public',
1293 [
1294 true,
1295 (object) [],
1296 $post_id,
1297 ],
1298 FLUENTFORM_FRAMEWORK_UPGRADE,
1299 'fluentform/load_default_public',
1300 'Use fluentform/load_default_public instead of fluentform_load_default_public.'
1301 );
1302
1303 if (apply_filters('fluentform/load_default_public', $loadPublicStyle, (object) [], $post_id)) {
1304 wp_enqueue_style(
1305 'fluentform-public-default',
1306 $fluentFormPublicDefaultCss,
1307 [],
1308 FLUENTFORM_VERSION
1309 );
1310 }
1311 });
1312
1313
1314 if (function_exists('register_block_type')) {
1315 add_action('init', function () {
1316 // Use the dedicated GutenbergBlock class for block registration and rendering
1317 \FluentForm\App\Services\Blocks\GutenbergBlock::register();
1318 });
1319 }
1320
1321
1322 add_action('fluentform/before_updating_form', function ($form, $postData) {
1323 (new FluentForm\App\Services\Form\HistoryService())->init($form, $postData);
1324 }, 10, 2);
1325
1326
1327 // WordPress 6.3+ uses iframes for block editor preview
1328 // Official WordPress solution: Use enqueue_block_assets with proper context checking
1329 // See: https://make.wordpress.org/core/2023/07/18/miscellaneous-editor-changes-in-wordpress-6-3/
1330 add_action('enqueue_block_assets', function () {
1331 // enqueue_block_assets also fires on the front end, where wp_enqueue_scripts already loads these conditionally.
1332 if (!is_admin()) {
1333 return;
1334 }
1335
1336 $current_screen = function_exists('get_current_screen') ? get_current_screen() : null;
1337 if ($current_screen && !$current_screen->is_block_editor()) {
1338 return;
1339 }
1340
1341 // Enqueue Fluent Forms CSS for block editor iframe preview
1342 // These styles are necessary for the live form preview in the block editor
1343 wp_enqueue_style('fluent-forms-public', fluentFormMix('css/fluent-forms-public.css'), [], FLUENTFORM_VERSION);
1344 wp_enqueue_style('fluentform-public-default', fluentFormMix('css/fluentform-public-default.css'), [], FLUENTFORM_VERSION);
1345 });
1346
1347
1348
1349 // require the CLI
1350 if (defined('WP_CLI') && WP_CLI) {
1351 \WP_CLI::add_command('fluentform', '\FluentForm\App\Modules\CLI\Commands');
1352 }
1353