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
← All changes | app/Services/FluentConversational/Classes/Form.php +73 -16 6.2.2 → 6.2.15 View file →
@@ -93,12 +93,14 @@
93 93 $paramKey = 'fluent-form';
94 94 }
95 95
96 96 wp_localize_script('fluent_forms_conversational_design', 'ffc_conv_vars', [
97 - 'form_id' => $formId,
98 - 'preview_url' => Helper::getFrontendFacingUrl('?' . $paramKey . '=' . $formId),
99 - 'fonts' => Fonts::getFonts(),
100 - 'has_pro' => defined('FLUENTFORMPRO'),
97 + 'form_id' => $formId,
98 + 'preview_url' => Helper::getFrontendFacingUrl('?' . $paramKey . '=' . $formId),
99 + 'fonts' => Fonts::getFonts(),
100 + 'has_pro' => defined('FLUENTFORMPRO'),
101 + 'has_pro_share_page' => defined('FLUENTFORMPRO') && class_exists('\FluentFormPro\classes\SharePage\SharePage'),
102 + 'upgrade_url' => fluentform_upgrade_url(),
101 103 ]);
102 104
103 105 wp_enqueue_style(
104 106 'fluent_forms_conversion_style',
@@ -156,9 +158,10 @@
156 158 'default_placeholder' => 'Type Your answer here',
157 159 'key_hint_text' => 'Key',
158 160 'key_hint_tooltip' => 'Press the key to select',
159 161 'choose_file' => '<b>Choose file</b> or <b>drag here</b>',
160 - 'limit' => 'Size limit: '
162 + 'limit' => 'Size limit: ',
163 + 'ranking_reset' => 'Reset order'
161 164 ],
162 165 ];
163 166
164 167 if ($settings && !isset($settings['i18n']['key_hint_text'])) {
@@ -165,8 +168,12 @@
165 168 $settings['i18n']['key_hint_text'] = $defaults['i18n']['key_hint_text'];
166 169 $settings['i18n']['key_hint_tooltip'] = $defaults['i18n']['key_hint_tooltip'];
167 170 }
168 171
172 + if ($settings && !isset($settings['i18n']['ranking_reset'])) {
173 + $settings['i18n']['ranking_reset'] = $defaults['i18n']['ranking_reset'];
174 + }
175 +
169 176 if (!$settings || empty($settings['title'])) {
170 177 $form = wpFluent()->table('fluentform_forms')->find($formId);
171 178 $settings['title'] = $form->title;
172 179 }
@@ -183,9 +190,9 @@
183 190 return $css;
184 191 }
185 192 }
186 193
187 - return $prefix . ' { background-color: #FFFFFF; }' . $prefix . ' .ffc-counter-div span { color: #0445AF; }' . $prefix . ' .ffc-counter-div .counter-icon-span svg { fill: #0445AF !important; }' . $prefix . ' .f-label-wrap, ' . $prefix . ' .f-answer { color: #0445AF !important; }' . $prefix . ' .f-label-wrap .f-key { border-color: #0445AF !important; }' . $prefix . ' .f-label-wrap .f-key-hint { border-color: #0445AF !important; }' . $prefix . ' .f-answer .f-radios-wrap ul li { background-color: rgba(4,69,175, 0.1) !important; border: 1px solid #0445AF; }' . $prefix . ' .f-answer .f-radios-wrap ul li:focus { background-color: rgba(4,69,175, 0.3) !important }' . $prefix . ' .f-answer .f-radios-wrap ul li:hover { background-color: rgba(4,69,175, 0.3) !important }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key { background-color: #0445AF !important; color: white; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key-hint { background-color: #0445AF; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected svg { fill: #0445AF !important; }' . $prefix . ' .f-answer input, ' . $prefix . ' .f-answer textarea{ color: #0445AF !important; box-shadow: #0445AF 0px 1px; }' . $prefix . ' .f-answer input:focus, ' . $prefix . ' .f-answer textarea:focus { box-shadow: #0445AF 0px 2px !important; }' . $prefix . ' .f-answer textarea::placeholder, ' . $prefix . ' .f-answer input::placeholder { color: #0445AF !important; }' . $prefix . ' .text-success { color: #0445AF !important; }' . $prefix . ' .f-answer .f-matrix-table tbody td { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-matrix-table input { border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .f-matrix-table input.f-radio-control:checked::after { background-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table input:focus::before { border-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table input.f-checkbox-control:checked { background-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table tbody tr::after { border-right-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table .f-table-cell.f-row-cell { box-shadow: rgba(4,69,175, 0.1) 0px 0px 0px 100vh inset; }' . $prefix . ' .f-answer .ff_file_upload_field_wrap { background-color: rgba(4,69,175, 0.1); border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff_file_upload_field_wrap:hover { background-color: rgba(4,69,175, 0.3);}' . $prefix . ' .f-answer .ff_file_upload_field_wrap:focus-within { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .f-answer .ff-upload-preview { border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-thumb { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details { border-left-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress { border-left-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress .ff-el-progress-bar { background-color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap::before { background-color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .f-star-field .f-star-field-star .symbolOutline { fill: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .f-star-field .f-star-field-rating { color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-hovered .symbolFill { fill: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-selected .symbolFill { fill: #0445AF; }' . $prefix . ' .f-answer .f-payment-summary-wrap tbody td { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-payment-summary-wrap tfoot th { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .stripe-inline-holder { border-bottom: 1px solid #0445AF; }' . $prefix . ' .f-answer .StripeElement--focus { border-bottom: 2.5px solid #0445AF; }' . $prefix . ' .ff_conv_input .f-info { color: #0445AF; }' . $prefix . ' .fh2 .f-text { color: #191919; }' . $prefix . ' .fh2 .f-tagline, ' . $prefix . ' .f-sub .f-help { color: rgba(25,25,25, 0.70); }' . $prefix . ' .fh2 .stripe-inline-header { color: #191919; }' . $prefix . ' .q-inner .o-btn-action, ' . $prefix . ' .footer-inner-wrap .f-nav { background-color: #0445AF; }' . $prefix . ' .q-inner .o-btn-action span, ' . $prefix . ' .footer-inner-wrap .f-nav a { color: #FFFFFF; } ' . $prefix . ' .f-enter .f-enter-desc { color: #0445AF; }' . $prefix . ' .footer-inner-wrap .f-nav a svg { fill: #FFFFFF; }' . $prefix . ' .vff-footer .f-progress-bar { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .vff-footer .f-progress-bar-inner { background-color: #0445AF; }' . $prefix . ' .q-inner .o-btn-action:hover { background-color: #0445AFD6; }' . $prefix . ' .q-inner .o-btn-action:focus::after { border-radius: 6px; inset: -3px; box-shadow: #0445AF 0px 0px 0px 2px; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key { color: #FFFFFF; }';
194 + return $prefix . ' { background-color: #FFFFFF; }' . $prefix . ' .ffc-counter-div span { color: #0445AF; }' . $prefix . ' .ffc-counter-div .counter-icon-span svg { fill: #0445AF !important; }' . $prefix . ' .f-label-wrap, ' . $prefix . ' .f-answer { color: #0445AF !important; }' . $prefix . ' .f-label-wrap .f-key { border-color: #0445AF !important; }' . $prefix . ' .f-label-wrap .f-key-hint { border-color: #0445AF !important; }' . $prefix . ' .f-answer .f-radios-wrap ul li { background-color: rgba(4,69,175, 0.1) !important; border: 1px solid #0445AF; }' . $prefix . ' .f-answer .f-radios-wrap ul li:focus { background-color: rgba(4,69,175, 0.3) !important }' . $prefix . ' .f-answer .f-radios-wrap ul li:hover { background-color: rgba(4,69,175, 0.3) !important }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key { background-color: #0445AF !important; color: white; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key-hint { background-color: #0445AF; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected svg { fill: #0445AF !important; }' . $prefix . ' .f-answer input, ' . $prefix . ' .f-answer textarea{ color: #0445AF !important; box-shadow: #0445AF 0px 1px; }' . $prefix . ' .f-answer input:focus, ' . $prefix . ' .f-answer textarea:focus { box-shadow: #0445AF 0px 2px !important; }' . $prefix . ' .f-answer textarea::placeholder, ' . $prefix . ' .f-answer input::placeholder { color: #0445AF !important; }' . $prefix . ' .text-success { color: #0445AF !important; }' . $prefix . ' .f-answer .f-matrix-table tbody td { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-matrix-table input { border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .f-matrix-table input.f-radio-control:checked::after { background-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table input:focus::before { border-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table input.f-checkbox-control:checked { background-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table tbody tr::after { border-right-color: #0445AF; }' . $prefix . ' .f-answer .f-matrix-table .f-table-cell.f-row-cell { box-shadow: rgba(4,69,175, 0.1) 0px 0px 0px 100vh inset; }' . $prefix . ' .f-answer .ff_file_upload_field_wrap { background-color: rgba(4,69,175, 0.1); border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff_file_upload_field_wrap:hover { background-color: rgba(4,69,175, 0.3);}' . $prefix . ' .f-answer .ff_file_upload_field_wrap:focus-within { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .f-answer .ff-upload-preview { border-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-thumb { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details { border-left-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress { border-left-color: rgba(4,69,175, 0.8); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .ff-upload-preview .ff-upload-details .ff-el-progress .ff-el-progress-bar { background-color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap::before { background-color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .f-star-field .f-star-field-star .symbolOutline { fill: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .f-star-field .f-star-field-rating { color: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .f-star-field-star .ff-rating-icon-svg-holder { display: block; line-height: 0; width: 100%; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .ff-rating-icon-svg { color: var(--ff-rating-inactive-color, rgba(4,69,175, 0.25)); display: block; height: auto; max-height: 64px; max-width: 64px; width: 100%; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .ff-rating-icon-svg [fill]:not([fill="none"]) { fill: currentColor !important; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap .ff-rating-icon-svg [stroke]:not([stroke="none"]) { stroke: currentColor !important; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-hovered .symbolFill { fill: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-hovered .ff-rating-icon-svg { color: var(--ff-rating-hover-color, rgba(4,69,175, 0.4)); }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-selected .symbolFill { fill: #0445AF; }' . $prefix . ' .f-answer .f-star-wrap .f-star-field-wrap.is-selected .ff-rating-icon-svg { color: var(--ff-rating-active-color, #0445AF); }' . $prefix . ' .f-answer .f-payment-summary-wrap tbody td { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .f-payment-summary-wrap tfoot th { background-color: rgba(4,69,175, 0.1); }' . $prefix . ' .f-answer .stripe-inline-holder { border-bottom: 1px solid #0445AF; }' . $prefix . ' .f-answer .StripeElement--focus { border-bottom: 2.5px solid #0445AF; }' . $prefix . ' .ff_conv_input .f-info { color: #0445AF; }' . $prefix . ' .fh2 .f-text { color: #191919; }' . $prefix . ' .fh2 .f-tagline, ' . $prefix . ' .f-sub .f-help { color: rgba(25,25,25, 0.70); }' . $prefix . ' .fh2 .stripe-inline-header { color: #191919; }' . $prefix . ' .q-inner .o-btn-action, ' . $prefix . ' .footer-inner-wrap .f-nav { background-color: #0445AF; }' . $prefix . ' .q-inner .o-btn-action span, ' . $prefix . ' .footer-inner-wrap .f-nav a { color: #FFFFFF; } ' . $prefix . ' .f-enter .f-enter-desc { color: #0445AF; }' . $prefix . ' .footer-inner-wrap .f-nav a svg { fill: #FFFFFF; }' . $prefix . ' .vff-footer .f-progress-bar { background-color: rgba(4,69,175, 0.3); }' . $prefix . ' .vff-footer .f-progress-bar-inner { background-color: #0445AF; }' . $prefix . ' .q-inner .o-btn-action:hover { background-color: #0445AFD6; }' . $prefix . ' .q-inner .o-btn-action:focus::after { border-radius: 6px; inset: -3px; box-shadow: #0445AF 0px 0px 0px 2px; }' . $prefix . ' .f-answer .f-radios-wrap ul li.f-selected .f-key { color: #FFFFFF; }';
188 195 }
189 196
190 197 public function render()
191 198 {
@@ -332,9 +339,10 @@
332 339 'quiz_score',
333 340 'save_progress_button',
334 341 'dynamic_field',
335 342 'rangeslider',
336 - 'net_promoter_score'
343 + 'net_promoter_score',
344 + 'input_ranking'
337 345 ];
338 346
339 347 if (defined('FLUENTFORM_SIGNATURE')) {
340 348 $acceptedFieldElements[] = 'signature';
@@ -547,17 +555,26 @@
547 555
548 556 public function renderShortcode($form)
549 557 {
550 558 $formId = $form->id;
559 + $fileUploadSettings = apply_filters('fluentform/file_upload_settings_for_js', [], $form);
560 +
551 561 $form = Converter::convert($form);
562 +
552 563 $this->enqueueScripts();
564 + do_action('fluentform/conversational_enqueue_assets', $form, $fileUploadSettings);
565 +
553 566 $submitCss = $this->getSubmitBttnStyle($form);
554 567 $metaSettings = $this->getMetaSettings($formId);
555 568 $designSettings = $this->getDesignSettings($formId);
556 569 $instanceId = $form->instance_index;
557 570 $varName = 'fluent_forms_global_var_' . $instanceId;
558 - wp_localize_script('fluent_forms_conversational_form', $varName, [
559 - 'fluent_forms_admin_nonce' => wp_create_nonce('fluent_forms_admin_nonce'),
571 +
572 + $localizedVars = [
573 + // SECURITY (H-01): do not emit the admin AJAX nonce on the public conversational form
574 + // page — the public form JS never uses it, and on a page an admin happens to view it
575 + // would embed that admin's own valid nonce. Emit it only for a viewer who could use it.
576 + 'fluent_forms_admin_nonce' => current_user_can('fluentform_dashboard_access') ? wp_create_nonce('fluent_forms_admin_nonce') : '',
560 577 'ajaxurl' => admin_url('admin-ajax.php'),
561 578 'nonce' => wp_create_nonce(),
562 579 'form' => $this->getLocalizedForm($form),
563 580 'assetBaseUrl' => FLUENT_CONVERSATIONAL_FORM_DIR_URL . 'public',
@@ -572,11 +589,18 @@
572 589 'unknown_error_txt' => __('An unknown error occurred', 'fluentform'),
573 590 'request_error_txt' => __('An error occurred while processing your request', 'fluentform'),
574 591 'paymentConfig' => $this->getPaymentConfig($form),
575 592 'date_i18n' => \FluentForm\App\Modules\Component\Component::getDatei18n(),
576 - 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete')
577 - ]);
593 + 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete'),
594 + 'file_upload_settings' => $fileUploadSettings,
595 + ];
578 596
597 + wp_localize_script(
598 + 'fluent_forms_conversational_form',
599 + $varName,
600 + apply_filters('fluentform/global_form_vars', $localizedVars)
601 + );
602 +
579 603 $hasSaveProgressButton = false;
580 604 $saveProgressButton = [];
581 605 foreach ($form->fields['fields'] as $item) {
582 606 if (isset($item['element']) && $item['element'] === 'save_progress_button') {
@@ -661,8 +685,27 @@
661 685 '_fluentform_' . $formId . '_fluentformnonce' => wp_create_nonce('fluentform-submit-form'),
662 686 '_wp_http_referer' => esc_attr(wp_unslash(wpFluentForm('request')->server('REQUEST_URI'))),
663 687 ];
664 688
689 + // SECURITY (FINDING-25): carry the anti-spam honeypot field (empty) and a freshly minted
690 + // token in the conversational submission. The conversational JS forwards every extra_input
691 + // into the submission payload, so these reach the server-side checks — which no longer skip
692 + // conversational forms — WITHOUT any client/JS change. This closes the bypass where adding
693 + // isFFConversational=1 disabled honeypot + token protection entirely.
694 + //
695 + // The token itself is disabled for conversational forms server-side (see the
696 + // fluentform/token_based_spam_protection_status filter in actions.php): its ~1h TTL cannot be
697 + // refreshed by the conversational JS, so behind a full-page cache the baked-in token would
698 + // expire and reject every submission. getConversationalTokenInput() therefore returns [] for
699 + // conversational forms; the honeypot (static empty field) still applies.
700 + $honeyPot = new \FluentForm\App\Modules\Form\HoneyPot(wpFluentForm());
701 + $inputs = array_merge($inputs, $honeyPot->getConversationalHoneypotInput($formId));
702 +
703 + $inputs = array_merge(
704 + $inputs,
705 + \FluentForm\App\Modules\Form\TokenBasedSpamProtection::getConversationalTokenInput($formId)
706 + );
707 +
665 708 return apply_filters('fluentform/conversational_extra_inputs', $inputs, $formId);
666 709 }
667 710
668 711 public function getRandomPhoto()
@@ -669,9 +712,9 @@
669 712 {
670 713 return fluentFormGetRandomPhoto();
671 714 }
672 715
673 - private function renderFormHtml($formId, $providedKey = '')
716 + public function renderFormHtml($formId, $providedKey = '')
674 717 {
675 718 $form = wpFluent()->table('fluentform_forms')->find($formId);
676 719
677 720 if (!$form) {
@@ -729,10 +772,14 @@
729 772 /* This filter is deprecated and will be removed soon */
730 773 $form = wpFluentForm()->applyFilters('fluentform_rendering_form', $form);
731 774
732 775 $form = wpFluentForm()->applyFilters('fluentform/rendering_form', $form);
776 + $fileUploadSettings = apply_filters('fluentform/file_upload_settings_for_js', [], $form);
777 +
733 778 $form = Converter::convert($form);
779 +
734 780 $this->enqueueScripts();
781 + do_action('fluentform/conversational_enqueue_assets', $form, $fileUploadSettings);
735 782
736 783 $formSettings = wpFluent()
737 784 ->table('fluentform_form_meta')
738 785 ->where('form_id', $form->id)
@@ -748,10 +795,13 @@
748 795 $submitCss = $this->getSubmitBttnStyle($form);
749 796
750 797 $designSettings = $this->getDesignSettings($formId);
751 798
752 - wp_localize_script('fluent_forms_conversational_form', 'fluent_forms_global_var', [
753 - 'fluent_forms_admin_nonce' => wp_create_nonce('fluent_forms_admin_nonce'),
799 + $localizedVars = [
800 + // SECURITY (H-01): do not emit the admin AJAX nonce on the public conversational form
801 + // page — the public form JS never uses it, and on a page an admin happens to view it
802 + // would embed that admin's own valid nonce. Emit it only for a viewer who could use it.
803 + 'fluent_forms_admin_nonce' => current_user_can('fluentform_dashboard_access') ? wp_create_nonce('fluent_forms_admin_nonce') : '',
754 804 'ajaxurl' => admin_url('admin-ajax.php'),
755 805 'nonce' => wp_create_nonce(),
756 806 'form' => $this->getLocalizedForm($form),
757 807 'form_id' => $form->id,
@@ -766,10 +816,17 @@
766 816 'request_error_txt' => __('An error occurred while processing your request', 'fluentform'),
767 817 'paymentConfig' => $this->getPaymentConfig($form),
768 818 'date_i18n' => \FluentForm\App\Modules\Component\Component::getDatei18n(),
769 819 'rest' => Helper::getRestInfo(),
770 - 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete')
771 - ]);
820 + 'file_delete_nonce' => wp_create_nonce('fluentform_file_delete'),
821 + 'file_upload_settings' => $fileUploadSettings,
822 + ];
823 +
824 + wp_localize_script(
825 + 'fluent_forms_conversational_form',
826 + 'fluent_forms_global_var',
827 + apply_filters('fluentform/global_form_vars', $localizedVars)
828 + );
772 829
773 830 $hasSaveProgressButton = false;
774 831 $saveProgressButton = [];
775 832 foreach ($form->fields['fields'] as $item) {