From e0f213284413dccff2fa1f15066fab26181207d3 Mon Sep 17 00:00:00 2001 From: liviu13 Date: Wed, 15 Jan 2025 17:20:31 +0200 Subject: [PATCH 01/12] gdpr update --- classes/helpers/FrmAppHelper.php | 12 +++++++++ classes/models/FrmSettings.php | 4 ++- classes/views/frm-settings/general.php | 37 ++++++++++++++++++++------ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/classes/helpers/FrmAppHelper.php b/classes/helpers/FrmAppHelper.php index c33f35e351..df1b0a98b6 100644 --- a/classes/helpers/FrmAppHelper.php +++ b/classes/helpers/FrmAppHelper.php @@ -4380,4 +4380,16 @@ public static function print_setting_error( $args ) { no_gdpr_cookies; + } } diff --git a/classes/models/FrmSettings.php b/classes/models/FrmSettings.php index 2469d53510..0d52e39c29 100644 --- a/classes/models/FrmSettings.php +++ b/classes/models/FrmSettings.php @@ -150,6 +150,8 @@ public function default_options() { 'new_tab_msg' => __( 'The page has been opened in a new tab.', 'formidable' ), 'email_to' => '[admin_email]', + 'enable_gdpr' => 0, + 'no_gdpr_cookies' => 0, 'no_ips' => 0, 'custom_header_ip' => 0, 'tracking' => FrmAppHelper::pro_is_installed(), @@ -398,7 +400,7 @@ private function update_settings( $params ) { $this->from_email = $params['frm_from_email']; $this->currency = $params['frm_currency']; - $checkboxes = array( 'mu_menu', 're_multi', 'fade_form', 'no_ips', 'custom_header_ip', 'tracking', 'admin_bar', 'summary_emails' ); + $checkboxes = array( 'mu_menu', 're_multi', 'fade_form', 'no_ips', 'no_gdpr_cookies', 'enable_gdpr', 'custom_header_ip', 'tracking', 'admin_bar', 'summary_emails' ); foreach ( $checkboxes as $set ) { $this->$set = isset( $params[ 'frm_' . $set ] ) ? absint( $params[ 'frm_' . $set ] ) : 0; } diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index 546eccbb4f..63aae08435 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -12,7 +12,7 @@ -

+

- -

- +

'frm_gdpr_options' ); +if ( ! $frm_settings->enable_gdpr ) { + $gdpr_options_wrapper_params['class'] .= ' frm_hidden'; +} $custom_header_ip_wrapper_params = array( 'class' => 'frm_custom_header_ip_cont' ); if ( $frm_settings->no_ips ) { $custom_header_ip_wrapper_params['class'] .= ' frm_hidden'; } ?> +

+ +

+ +

> + +

+ +

> + +

+ +

+

>

+ + +

+

+ + +

diff --git a/classes/views/frm-fields/front-end/gdpr/gdpr-field.php b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php new file mode 100644 index 0000000000..8ee7ccf174 --- /dev/null +++ b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php @@ -0,0 +1,31 @@ + + + +
+ +
+ +
+ +
\ No newline at end of file diff --git a/images/icons.svg b/images/icons.svg index 3e13eb6aae..709e0cbe2a 100755 --- a/images/icons.svg +++ b/images/icons.svg @@ -828,5 +828,6 @@ + From 7114a7690dd60f800cab38ea205cb6d2d2103355 Mon Sep 17 00:00:00 2001 From: liviu13 Date: Mon, 24 Feb 2025 15:02:45 +0200 Subject: [PATCH 03/12] merge master --- classes/models/fields/FrmFieldGdpr.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index 7c32e2835a..3d9f9e27d2 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -84,8 +84,8 @@ public function show_primary_options( $args ) { */ protected function extra_field_opts() { return array( - 'gdpr_agreement_text' => 'Agreement text', - 'gdpr_description' => 'Field description', + 'gdpr_agreement_text' => __( 'Agreement text', 'formidable' ), + 'gdpr_description' => '', ); } From 2f7c17a00289dd0442a0371da09eaba9a7309956 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 24 Feb 2025 16:06:16 -0400 Subject: [PATCH 04/12] Remove empty Other section with nothing in it --- classes/views/frm-settings/general.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index a73e245220..40756b4c17 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -49,8 +49,6 @@
-

- From c191474a731c986938d1e5a055af4899f006bd14 Mon Sep 17 00:00:00 2001 From: liviu13 Date: Tue, 25 Feb 2025 16:14:37 +0200 Subject: [PATCH 05/12] copy fixes --- classes/models/fields/FrmFieldGdpr.php | 4 +- classes/views/frm-settings/general.php | 2 - js/formidable.min.js | 56 +++++++++++++------------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index 3d9f9e27d2..e88c227107 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -34,7 +34,7 @@ class FrmFieldGdpr extends FrmFieldType { */ public function get_new_field_defaults() { $field = array( - 'name' => $this->get_new_field_name(), + 'name' => $this->get_new_field_name() . ' Agreement', 'description' => '', 'type' => $this->type, 'options' => '', @@ -84,7 +84,7 @@ public function show_primary_options( $args ) { */ protected function extra_field_opts() { return array( - 'gdpr_agreement_text' => __( 'Agreement text', 'formidable' ), + 'gdpr_agreement_text' => __( 'I consent to having this website store my submitted information so they can respond to my inquiry.', 'formidable' ), 'gdpr_description' => '', ); } diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index a73e245220..40756b4c17 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -49,8 +49,6 @@
-

- diff --git a/js/formidable.min.js b/js/formidable.min.js index 341c5d7732..64603471d5 100644 --- a/js/formidable.min.js +++ b/js/formidable.min.js @@ -1,14 +1,14 @@ function frmFrontFormJS(){let jsErrors=[];function triggerCustomEvent(el,eventName,data){if(typeof window.CustomEvent!=="function")return;const event=new CustomEvent(eventName);event.frmData=data;el.dispatchEvent(event)}function getFieldId(field,fullID){let nameParts,fieldId,isRepeating=false,fieldName="";if(field instanceof jQuery)fieldName=field.attr("name");else fieldName=field.name;if(typeof fieldName==="undefined")fieldName="";if(fieldName===""){if(field instanceof jQuery)fieldName=field.data("name"); else fieldName=field.getAttribute("data-name");if(typeof fieldName==="undefined")fieldName="";if(fieldName!==""&&fieldName)return fieldName;return 0}nameParts=fieldName.replace("item_meta[","").replace("[]","").split("]");if(nameParts.length<1)return 0;nameParts=nameParts.filter(function(n){return n!==""});fieldId=nameParts[0];if(nameParts.length===1)return fieldId;if(nameParts[1]==="[form"||nameParts[1]==="[row_ids")return 0;if(document.querySelector('input[name="item_meta['+fieldId+'][form]"]')){fieldId= nameParts[2].replace("[","");isRepeating=true}if("other"===fieldId)if(isRepeating)fieldId=nameParts[3].replace("[","");else fieldId=nameParts[1].replace("[","");if(fullID===true)if(fieldId===nameParts[0])fieldId=fieldId+"-"+nameParts[1].replace("[","");else fieldId=fieldId+"-"+nameParts[0]+"-"+nameParts[1].replace("[","");return fieldId}function disableSubmitButton($form){$form.find('input[type="submit"], input[type="button"], button[type="submit"], button.frm_save_draft').attr("disabled","disabled")} -function enableSubmitButton($form){$form.find('input[type="submit"], input[type="button"], button[type="submit"]').prop("disabled",false)}function disableSaveDraft($form){$form.find("a.frm_save_draft").css("pointer-events","none")}function enableSaveDraft($form){if(!$form.length)return;$form[0].querySelectorAll(".frm_save_draft").forEach(saveDraftButton=>{saveDraftButton.disabled=false;saveDraftButton.style.pointerEvents=""})}function validateForm(object){let errors,n,nl,fields,field;errors=[];const vanillaJsObject= -"function"===typeof object.get?object.get(0):object;vanillaJsObject?.querySelectorAll(".frm_required_field").forEach(requiredField=>{const isVisible=requiredField.offsetParent!==null;if(!isVisible)return;requiredField.querySelectorAll("input, select, textarea").forEach(requiredInput=>{if(hasClass(requiredInput,"frm_optional")||hasClass(requiredInput,"ed_button"))return;errors=checkRequiredField(requiredInput,errors)})});fields=jQuery(object).find("input,select,textarea");if(fields.length)for(n=0, -nl=fields.length;n -0)for(key in errors)addFieldError($fieldCont,key,errors)}function validateFieldValue(field,errors,onSubmit){if(field.type==="hidden");else if(field.type==="number")checkNumberField(field,errors);else if(field.type==="email")checkEmailField(field,errors,onSubmit);else if(field.type==="password")checkPasswordField(field,errors,onSubmit);else if(field.type==="url")checkUrlField(field,errors);else if(field.pattern!==null)checkPatternField(field,errors);triggerCustomEvent(document,"frm_validate_field_value", -{field:field,errors:errors,onSubmit:onSubmit})}function checkRequiredField(field,errors){let checkGroup,tempVal,i,placeholder,val="",fieldID="",fileID=field.getAttribute("data-frmfile");if(field.type==="hidden"&&fileID===null&&!isAppointmentField(field)&&!isInlineDatepickerField(field))return errors;if(field.type==="checkbox"||field.type==="radio"){checkGroup=jQuery('input[name="'+field.name+'"]').closest(".frm_required_field").find("input:checked");jQuery(checkGroup).each(function(){val=this.value})}else if(field.type=== -"file"||fileID){if(typeof fileID==="undefined"){fileID=getFieldId(field,true);fileID=fileID.replace("file","")}if(typeof errors[fileID]==="undefined")val=getFileVals(fileID);fieldID=fileID}else{if(hasClass(field,"frm_pos_none"))return errors;val=jQuery(field).val();if(val===null)val="";else if(typeof val!=="string"){tempVal=val;val="";for(i=0;i{saveDraftButton.disabled=false;saveDraftButton.style.pointerEvents=""})}function validateForm(object){let errors=[];const vanillaJsObject="function"=== +typeof object.get?object.get(0):object;vanillaJsObject?.querySelectorAll(".frm_required_field").forEach(requiredField=>{const isVisible=requiredField.offsetParent!==null;if(!isVisible)return;requiredField.querySelectorAll("input, select, textarea").forEach(requiredInput=>{if(hasClass(requiredInput,"frm_optional")||hasClass(requiredInput,"ed_button"))return;errors=checkRequiredField(requiredInput,errors)})});vanillaJsObject?.querySelectorAll("input,select,textarea").forEach(field=>{if(""===field.value){if("number"=== +field.type)checkValidity(field,errors);const isConfirmationField=field.name&&0===field.name.indexOf("item_meta[conf_");if(!isConfirmationField)return}validateFieldValue(field,errors,true);checkValidity(field,errors)});if(!hasInvisibleRecaptcha(object))errors=validateRecaptcha(object,errors);return errors}function checkValidity(field,errors){let fieldID;if("object"!==typeof field.validity||false!==field.validity.valid)return;fieldID=getFieldId(field,true);if("undefined"===typeof errors[fieldID])errors[fieldID]= +getFieldValidationMessage(field,"data-invmsg");if("function"===typeof field.reportValidity)field.reportValidity()}function hasClass(element,targetClass){return element.classList&&element.classList.contains(targetClass)}function maybeValidateChange(field){if(field.type==="url")maybeAddHttpToUrl(field);const form=field.closest("form");if(form&&hasClass(form,"frm_js_validate"))validateField(field)}function maybeAddHttpToUrl(field){const url=field.value;const matches=url.match(/^(https?|ftps?|mailto|news|feed|telnet):/); +if(field.value!==""&&matches===null)field.value="http://"+url}function validateField(field){let errors,key;errors=[];const fieldContainer=field.closest(".frm_form_field");if(!fieldContainer)return;if(hasClass(fieldContainer,"frm_required_field")&&!hasClass(field,"frm_optional"))errors=checkRequiredField(field,errors);if(errors.length<1)validateFieldValue(field,errors,false);const $fieldCont=jQuery(fieldContainer);removeFieldError($fieldCont);if(Object.keys(errors).length>0)for(key in errors)addFieldError($fieldCont, +key,errors)}function validateFieldValue(field,errors,onSubmit){if(field.type==="hidden");else if(field.type==="number")checkNumberField(field,errors);else if(field.type==="email")checkEmailField(field,errors,onSubmit);else if(field.type==="password")checkPasswordField(field,errors,onSubmit);else if(field.type==="url")checkUrlField(field,errors);else if(field.pattern!==null)checkPatternField(field,errors);triggerCustomEvent(document,"frm_validate_field_value",{field:field,errors:errors,onSubmit:onSubmit})} +function checkRequiredField(field,errors){let checkGroup,tempVal,i,placeholder,val="",fieldID="",fileID=field.getAttribute("data-frmfile");if(field.type==="hidden"&&fileID===null&&!isAppointmentField(field)&&!isInlineDatepickerField(field))return errors;if(field.type==="checkbox"||field.type==="radio"){checkGroup=jQuery('input[name="'+field.name+'"]').closest(".frm_required_field").find("input:checked");jQuery(checkGroup).each(function(){val=this.value})}else if(field.type==="file"||fileID){if(typeof fileID=== +"undefined"){fileID=getFieldId(field,true);fileID=fileID.replace("file","")}if(typeof errors[fileID]==="undefined")val=getFileVals(fileID);fieldID=fileID}else{if(hasClass(field,"frm_pos_none"))return errors;val=jQuery(field).val();if(val===null)val="";else if(typeof val!=="string"){tempVal=val;val="";for(i=0;i';previousInput=container.find('input[name="recaptcha_checked"]');if(previousInput.length)previousInput.replaceWith(input);else container.append(input)}afterFormSubmitted(object,response)},delay)}else if(Object.keys(response.errors).length){removeSubmitLoading(jQuery(object), "enable");contSubmit=true;removeAllErrors();$fieldCont=null;for(key in response.errors){$fieldCont=jQuery(object).find("#frm_field_"+key+"_container");if($fieldCont.length){if(!$fieldCont.is(":visible")){inCollapsedSection=$fieldCont.closest(".frm_toggle_container");if(inCollapsedSection.length){frmTrigger=inCollapsedSection.prev();if(!frmTrigger.hasClass("frm_trigger"))frmTrigger=frmTrigger.prev(".frm_trigger");frmTrigger.trigger("click")}}if($fieldCont.is(":visible")){addFieldError($fieldCont,key, -response.errors);contSubmit=false}}}jQuery(object).find(".frm-g-recaptcha, .g-recaptcha, .h-captcha").each(function(){const $recaptcha=jQuery(this),recaptchaID=$recaptcha.data("rid");if(typeof grecaptcha!=="undefined"&&grecaptcha)if(recaptchaID)grecaptcha.reset(recaptchaID);else grecaptcha.reset();if(typeof hcaptcha!=="undefined"&&hcaptcha)hcaptcha.reset()});jQuery(document).trigger("frmFormErrors",[object,response]);fieldset.removeClass("frm_doing_ajax");scrollToFirstField(object);if(contSubmit)object.submit(); -else{object.insertAdjacentHTML("afterbegin",response.error_message);checkForErrorsAndMaybeSetFocus()}}else{showFileLoading(object);object.submit()}};error=function(){jQuery(object).find('input[type="submit"], input[type="button"]').prop("disabled",false);object.submit()};postToAjaxUrl(object,data,success,error)}function postToAjaxUrl(form,data,success,error){let ajaxUrl,action,ajaxParams;ajaxUrl=frm_js.ajax_url;action=form.getAttribute("action");if("string"===typeof action&&-1!==action.indexOf("?action=frm_forms_preview"))ajaxUrl= -action.split("?action=frm_forms_preview")[0];ajaxParams={type:"POST",url:ajaxUrl,data:data,success:success};if("function"===typeof error)ajaxParams.error=error;jQuery.ajax(ajaxParams)}function afterFormSubmitted(object,response){const formCompleted=jQuery(response.content).find(".frm_message");if(formCompleted.length)jQuery(document).trigger("frmFormComplete",[object,response]);else jQuery(document).trigger("frmPageChanged",[object,response])}function afterFormSubmittedBeforeReplace(object,response){const formCompleted= -jQuery(response.content).find(".frm_message");if(formCompleted.length)triggerCustomEvent(document,"frmFormCompleteBeforeReplace",{object,response})}function removeAddedScripts(formContainer,formID){const endReplace=jQuery(".frm_end_ajax_"+formID);if(endReplace.length){formContainer.nextUntil(".frm_end_ajax_"+formID).remove();endReplace.remove()}}function maybeSlideOut(oldContent,newContent){let c,newClass="frm_slideout";if(newContent.indexOf(" frm_slide")!==-1){c=oldContent.children();if(newContent.indexOf(" frm_going_back")!== --1)newClass+=" frm_going_back";c.removeClass("frm_going_back");c.addClass(newClass);return 300}return 0}function addUrlParam(response){let url;if(history.pushState&&typeof response.page!=="undefined"){url=addQueryVar("frm_page",response.page);window.history.pushState({"html":response.html},"","?"+url)}}function addQueryVar(key,value){let kvp,i,x;key=encodeURI(key);value=encodeURI(value);kvp=document.location.search.substr(1).split("&");i=kvp.length;while(i--){x=kvp[i].split("=");if(x[0]==key){x[1]= -value;kvp[i]=x.join("=");break}}if(i<0)kvp[kvp.length]=[key,value].join("=");return kvp.join("&")}function addFieldError($fieldCont,key,jsErrors){let input,id,describedBy,roleString;if($fieldCont.length&&$fieldCont.is(":visible")){$fieldCont.addClass("frm_blank_field");input=$fieldCont.find("input, select, textarea");id=getErrorElementId(key,input.get(0));describedBy=input.attr("aria-describedby");if(typeof frmThemeOverride_frmPlaceError==="function")frmThemeOverride_frmPlaceError(key,jsErrors);else{if(-1!== -jsErrors[key].indexOf("'+jsErrors[key]+"")}if(typeof describedBy==="undefined")describedBy=id;else if(describedBy.indexOf(id)===-1&&describedBy.indexOf("frm_error_field_")===-1)if(input.data("error-first")===0)describedBy=describedBy+" "+id;else describedBy=id+" "+describedBy;input.attr("aria-describedby",describedBy)}input.attr("aria-invalid", -true);jQuery(document).trigger("frmAddFieldError",[$fieldCont,key,jsErrors])}}function getErrorElementId(key,input){if(isNaN(key)||!input||!input.id)return"frm_error_field_"+key;return"frm_error_"+input.id}function removeFieldError($fieldCont){const errorMessage=$fieldCont.find(".frm_error");const errorId=errorMessage.attr("id");const input=$fieldCont.find("input, select, textarea");let describedBy=input.attr("aria-describedby");const fieldContainer=$fieldCont.get(0);if(fieldContainer&&fieldContainer.classList)fieldContainer.classList.remove("frm_blank_field", -"has-error");errorMessage.remove();input.attr("aria-invalid",false);input.removeAttr("aria-describedby");if(typeof describedBy!=="undefined"){describedBy=describedBy.replace(errorId,"");input.attr("aria-describedby",describedBy)}}function removeAllErrors(){jQuery(".form-field").removeClass("frm_blank_field has-error");jQuery(".form-field .frm_error").replaceWith("");jQuery(".frm_error_style").remove()}function scrollToFirstField(object){if("function"===typeof object.get)object=object.get(0);const field= -object.querySelector(".frm_blank_field");if(field)frmFrontForm.scrollMsg(jQuery(field),object,true)}function showSubmitLoading($object){showLoadingIndicator($object);disableSubmitButton($object);disableSaveDraft($object)}function showLoadingIndicator($object){if(!$object.hasClass("frm_loading_form")&&!$object.hasClass("frm_loading_prev")){addLoadingClass($object);$object.trigger("frmStartFormLoading")}}function addLoadingClass($object){const loadingClass=isGoingToPrevPage($object)?"frm_loading_prev": -"frm_loading_form";$object.addClass(loadingClass)}function isGoingToPrevPage($object){return typeof frmProForm!=="undefined"&&frmProForm.goingToPreviousPage($object)}function removeSubmitLoading(_,enable,processesRunning){let loadingForm;if(processesRunning>0)return;loadingForm=jQuery(".frm_loading_form");loadingForm.removeClass("frm_loading_form");loadingForm.removeClass("frm_loading_prev");loadingForm.trigger("frmEndFormLoading");if(enable==="enable"){enableSubmitButton(loadingForm);enableSaveDraft(loadingForm)}} -function showFileLoading(object){let fileval,loading=document.getElementById("frm_loading");if(loading!==null){fileval=jQuery(object).find("input[type=file]").val();if(typeof fileval!=="undefined"&&fileval!=="")setTimeout(function(){jQuery(loading).fadeIn("slow")},2E3)}}function confirmClick(){const message=jQuery(this).data("frmconfirm");return confirm(message)}function onHoneypotFieldChange(){const css=jQuery(this).css("box-shadow");if(css.match(/inset/))this.parentNode.removeChild(this)}function maybeMakeHoneypotFieldsUntabbable(){document.addEventListener("keydown", -handleKeyUp);function handleKeyUp(event){let code;if("undefined"!==typeof event.key)code=event.key;else if("undefined"!==typeof event.keyCode&&9===event.keyCode)code="Tab";if("Tab"===code){makeHoneypotFieldsUntabbable();document.removeEventListener("keydown",handleKeyUp)}}function makeHoneypotFieldsUntabbable(){document.querySelectorAll(".frm_verify").forEach(function(input){if(input.id&&0===input.id.indexOf("frm_email_"))input.setAttribute("tabindex",-1)})}}function changeFocusWhenClickComboFieldLabel(){let label; -const comboInputsContainer=document.querySelectorAll(".frm_combo_inputs_container");comboInputsContainer.forEach(function(inputsContainer){if(!inputsContainer.closest(".frm_form_field"))return;label=inputsContainer.closest(".frm_form_field").querySelector(".frm_primary_label");if(!label)return;label.addEventListener("click",function(){inputsContainer.querySelector(".frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea").focus()})})}function maybeFocusOnComboSubField(element){if("FIELDSET"!== -element.nodeName)return false;if(!element.querySelector(".frm_combo_inputs_container"))return false;const comboSubfield=element.querySelector('[aria-invalid="true"]');if(comboSubfield){focusInput(comboSubfield);return true}return false}function checkForErrorsAndMaybeSetFocus(){let errors,element,timeoutCallback;if(!frm_js.focus_first_error)return;errors=document.querySelectorAll(".frm_form_field .frm_error");if(!errors.length)return;element=errors[0];do{element=element.previousSibling;if(-1!==["input", -"select","textarea"].indexOf(element.nodeName.toLowerCase())){focusInput(element);break}if(maybeFocusOnComboSubField(element))break;if("undefined"!==typeof element.classList){if(element.classList.contains("html-active"))timeoutCallback=function(){const textarea=element.querySelector("textarea");if(null!==textarea)textarea.focus()};else if(element.classList.contains("tmce-active"))timeoutCallback=function(){tinyMCE.activeEditor.focus()};if("function"===typeof timeoutCallback){setTimeout(timeoutCallback, -0);break}}}while(element.previousSibling)}function focusInput(input){if(input.offsetParent!==null)input.focus();else triggerCustomEvent(document,"frmMaybeDelayFocus",{input})}function documentOn(event,selector,handler,options){if("undefined"===typeof options)options=false;document.addEventListener(event,function(e){let target;for(target=e.target;target&&target!=this;target=target.parentNode)if(target&&target.matches&&target.matches(selector)){handler.call(target,e);break}},options)}function initFloatingLabels(){let checkFloatLabel, -checkDropdownLabel,runOnLoad,selector,floatClass;selector=".frm-show-form .frm_inside_container input, .frm-show-form .frm_inside_container select, .frm-show-form .frm_inside_container textarea";floatClass="frm_label_float_top";checkFloatLabel=function(input){let container,shouldFloatTop,firstOpt;container=input.closest(".frm_inside_container");if(!container)return;shouldFloatTop=input.value||document.activeElement===input;container.classList.toggle(floatClass,shouldFloatTop);if("SELECT"===input.tagName){firstOpt= -input.querySelector("option:first-child");if(shouldFloatTop){if(firstOpt.hasAttribute("data-label")){firstOpt.textContent=firstOpt.getAttribute("data-label");firstOpt.removeAttribute("data-label")}}else if(firstOpt.textContent){firstOpt.setAttribute("data-label",firstOpt.textContent);firstOpt.textContent=""}}};checkDropdownLabel=function(){document.querySelectorAll(".frm-show-form .frm_inside_container:not(."+floatClass+") select").forEach(function(input){const firstOpt=input.querySelector("option:first-child"); -if(firstOpt.textContent){firstOpt.setAttribute("data-label",firstOpt.textContent);firstOpt.textContent=""}})};["focus","blur","change"].forEach(function(eventName){documentOn(eventName,selector,function(event){checkFloatLabel(event.target)},true)});jQuery(document).on("change",selector,function(event){checkFloatLabel(event.target)});runOnLoad=function(firstLoad){if(firstLoad&&document.activeElement&&-1!==["INPUT","SELECT","TEXTAREA"].indexOf(document.activeElement.tagName))checkFloatLabel(document.activeElement); +response.errors);contSubmit=false}}}jQuery(object).find(".frm-g-recaptcha, .g-recaptcha, .h-captcha").each(function(){const $recaptcha=jQuery(this),recaptchaID=$recaptcha.data("rid");if(typeof grecaptcha!=="undefined"&&grecaptcha)if(recaptchaID)grecaptcha.reset(recaptchaID);else grecaptcha.reset();if(typeof hcaptcha!=="undefined"&&hcaptcha)hcaptcha.reset()});if(window.turnstile)object.querySelectorAll(".cf-turnstile").forEach(turnstileField=>turnstileField.dataset.rid&&turnstile.reset(turnstileField.dataset.rid)); +jQuery(document).trigger("frmFormErrors",[object,response]);fieldset.removeClass("frm_doing_ajax");scrollToFirstField(object);if(contSubmit)object.submit();else{object.insertAdjacentHTML("afterbegin",response.error_message);checkForErrorsAndMaybeSetFocus()}}else{showFileLoading(object);object.submit()}};error=function(){jQuery(object).find('input[type="submit"], input[type="button"]').prop("disabled",false);object.submit()};postToAjaxUrl(object,data,success,error)}function postToAjaxUrl(form,data, +success,error){let ajaxUrl,action,ajaxParams;ajaxUrl=frm_js.ajax_url;action=form.getAttribute("action");if("string"===typeof action&&-1!==action.indexOf("?action=frm_forms_preview"))ajaxUrl=action.split("?action=frm_forms_preview")[0];ajaxParams={type:"POST",url:ajaxUrl,data:data,success:success};if("function"===typeof error)ajaxParams.error=error;jQuery.ajax(ajaxParams)}function afterFormSubmitted(object,response){const formCompleted=jQuery(response.content).find(".frm_message");if(formCompleted.length)jQuery(document).trigger("frmFormComplete", +[object,response]);else jQuery(document).trigger("frmPageChanged",[object,response])}function afterFormSubmittedBeforeReplace(object,response){const formCompleted=jQuery(response.content).find(".frm_message");if(formCompleted.length)triggerCustomEvent(document,"frmFormCompleteBeforeReplace",{object,response})}function removeAddedScripts(formContainer,formID){const endReplace=jQuery(".frm_end_ajax_"+formID);if(endReplace.length){formContainer.nextUntil(".frm_end_ajax_"+formID).remove();endReplace.remove()}} +function maybeSlideOut(oldContent,newContent){let c,newClass="frm_slideout";if(newContent.indexOf(" frm_slide")!==-1){c=oldContent.children();if(newContent.indexOf(" frm_going_back")!==-1)newClass+=" frm_going_back";c.removeClass("frm_going_back");c.addClass(newClass);return 300}return 0}function addUrlParam(response){let url;if(history.pushState&&typeof response.page!=="undefined"){url=addQueryVar("frm_page",response.page);window.history.pushState({"html":response.html},"","?"+url)}}function addQueryVar(key, +value){let kvp,i,x;key=encodeURI(key);value=encodeURI(value);kvp=document.location.search.substr(1).split("&");i=kvp.length;while(i--){x=kvp[i].split("=");if(x[0]==key){x[1]=value;kvp[i]=x.join("=");break}}if(i<0)kvp[kvp.length]=[key,value].join("=");return kvp.join("&")}function addFieldError($fieldCont,key,jsErrors){let input,id,describedBy,roleString;if($fieldCont.length&&$fieldCont.is(":visible")){$fieldCont.addClass("frm_blank_field");input=$fieldCont.find("input, select, textarea");id=getErrorElementId(key, +input.get(0));describedBy=input.attr("aria-describedby");if(typeof frmThemeOverride_frmPlaceError==="function")frmThemeOverride_frmPlaceError(key,jsErrors);else{if(-1!==jsErrors[key].indexOf("'+jsErrors[key]+"")}if(typeof describedBy==="undefined")describedBy=id;else if(describedBy.indexOf(id)===-1&&describedBy.indexOf("frm_error_field_")=== +-1)if(input.data("error-first")===0)describedBy=describedBy+" "+id;else describedBy=id+" "+describedBy;input.attr("aria-describedby",describedBy)}input.attr("aria-invalid",true);jQuery(document).trigger("frmAddFieldError",[$fieldCont,key,jsErrors])}}function getErrorElementId(key,input){if(isNaN(key)||!input||!input.id)return"frm_error_field_"+key;return"frm_error_"+input.id}function removeFieldError($fieldCont){const errorMessage=$fieldCont.find(".frm_error");const errorId=errorMessage.attr("id"); +const input=$fieldCont.find("input, select, textarea");let describedBy=input.attr("aria-describedby");const fieldContainer=$fieldCont.get(0);if(fieldContainer&&fieldContainer.classList)fieldContainer.classList.remove("frm_blank_field","has-error");errorMessage.remove();input.attr("aria-invalid",false);input.removeAttr("aria-describedby");if(typeof describedBy!=="undefined"){describedBy=describedBy.replace(errorId,"");input.attr("aria-describedby",describedBy)}}function removeAllErrors(){jQuery(".form-field").removeClass("frm_blank_field has-error"); +jQuery(".form-field .frm_error").replaceWith("");jQuery(".frm_error_style").remove()}function scrollToFirstField(object){if("function"===typeof object.get)object=object.get(0);const field=object.querySelector(".frm_blank_field");if(field)frmFrontForm.scrollMsg(jQuery(field),object,true)}function showSubmitLoading($object){showLoadingIndicator($object);disableSubmitButton($object);disableSaveDraft($object)}function showLoadingIndicator($object){if(!$object.hasClass("frm_loading_form")&&!$object.hasClass("frm_loading_prev")){addLoadingClass($object); +$object.trigger("frmStartFormLoading")}}function addLoadingClass($object){const loadingClass=isGoingToPrevPage($object)?"frm_loading_prev":"frm_loading_form";$object.addClass(loadingClass)}function isGoingToPrevPage($object){return typeof frmProForm!=="undefined"&&frmProForm.goingToPreviousPage($object)}function removeSubmitLoading(_,enable,processesRunning){let loadingForm;if(processesRunning>0)return;loadingForm=jQuery(".frm_loading_form");loadingForm.removeClass("frm_loading_form");loadingForm.removeClass("frm_loading_prev"); +loadingForm.trigger("frmEndFormLoading");if(enable==="enable"){enableSubmitButton(loadingForm);enableSaveDraft(loadingForm)}}function showFileLoading(object){let fileval,loading=document.getElementById("frm_loading");if(loading!==null){fileval=jQuery(object).find("input[type=file]").val();if(typeof fileval!=="undefined"&&fileval!=="")setTimeout(function(){jQuery(loading).fadeIn("slow")},2E3)}}function confirmClick(){const message=jQuery(this).data("frmconfirm");return confirm(message)}function onHoneypotFieldChange(){const css= +jQuery(this).css("box-shadow");if(css.match(/inset/))this.parentNode.removeChild(this)}function maybeMakeHoneypotFieldsUntabbable(){document.addEventListener("keydown",handleKeyUp);function handleKeyUp(event){if("Tab"===event.key){makeHoneypotFieldsUntabbable();document.removeEventListener("keydown",handleKeyUp)}}function makeHoneypotFieldsUntabbable(){document.querySelectorAll(".frm_verify").forEach(function(input){if(input.id&&0===input.id.indexOf("frm_email_"))input.setAttribute("tabindex",-1)})} +}function changeFocusWhenClickComboFieldLabel(){let label;const comboInputsContainer=document.querySelectorAll(".frm_combo_inputs_container");comboInputsContainer.forEach(function(inputsContainer){if(!inputsContainer.closest(".frm_form_field"))return;label=inputsContainer.closest(".frm_form_field").querySelector(".frm_primary_label");if(!label)return;label.addEventListener("click",function(){inputsContainer.querySelector(".frm_form_field:first-child input, .frm_form_field:first-child select, .frm_form_field:first-child textarea").focus()})})} +function maybeFocusOnComboSubField(element){if("FIELDSET"!==element.nodeName)return false;if(!element.querySelector(".frm_combo_inputs_container"))return false;const comboSubfield=element.querySelector('[aria-invalid="true"]');if(comboSubfield){focusInput(comboSubfield);return true}return false}function checkForErrorsAndMaybeSetFocus(){let errors,element,timeoutCallback;if(!frm_js.focus_first_error)return;errors=document.querySelectorAll(".frm_form_field .frm_error");if(!errors.length)return;element= +errors[0];do{element=element.previousSibling;if(-1!==["input","select","textarea"].indexOf(element.nodeName.toLowerCase())){focusInput(element);break}if(maybeFocusOnComboSubField(element))break;if("undefined"!==typeof element.classList){if(element.classList.contains("html-active"))timeoutCallback=function(){const textarea=element.querySelector("textarea");if(null!==textarea)textarea.focus()};else if(element.classList.contains("tmce-active"))timeoutCallback=function(){tinyMCE.activeEditor.focus()}; +if("function"===typeof timeoutCallback){setTimeout(timeoutCallback,0);break}}}while(element.previousSibling)}function focusInput(input){if(input.offsetParent!==null)input.focus();else triggerCustomEvent(document,"frmMaybeDelayFocus",{input})}function documentOn(event,selector,handler,options){if("undefined"===typeof options)options=false;document.addEventListener(event,function(e){let target;for(target=e.target;target&&target!=this;target=target.parentNode)if(target&&target.matches&&target.matches(selector)){handler.call(target, +e);break}},options)}function initFloatingLabels(){let checkFloatLabel,checkDropdownLabel,runOnLoad,selector,floatClass;selector=".frm-show-form .frm_inside_container input, .frm-show-form .frm_inside_container select, .frm-show-form .frm_inside_container textarea";floatClass="frm_label_float_top";checkFloatLabel=function(input){let container,shouldFloatTop,firstOpt;container=input.closest(".frm_inside_container");if(!container)return;shouldFloatTop=input.value||document.activeElement===input;container.classList.toggle(floatClass, +shouldFloatTop);if("SELECT"===input.tagName){firstOpt=input.querySelector("option:first-child");if(shouldFloatTop){if(firstOpt.hasAttribute("data-label")){firstOpt.textContent=firstOpt.getAttribute("data-label");firstOpt.removeAttribute("data-label")}}else if(firstOpt.textContent){firstOpt.setAttribute("data-label",firstOpt.textContent);firstOpt.textContent=""}}};checkDropdownLabel=function(){document.querySelectorAll(".frm-show-form .frm_inside_container:not(."+floatClass+") select").forEach(function(input){const firstOpt= +input.querySelector("option:first-child");if(firstOpt.textContent){firstOpt.setAttribute("data-label",firstOpt.textContent);firstOpt.textContent=""}})};["focus","blur","change"].forEach(function(eventName){documentOn(eventName,selector,function(event){checkFloatLabel(event.target)},true)});jQuery(document).on("change",selector,function(event){checkFloatLabel(event.target)});runOnLoad=function(firstLoad){if(firstLoad&&document.activeElement&&-1!==["INPUT","SELECT","TEXTAREA"].indexOf(document.activeElement.tagName))checkFloatLabel(document.activeElement); else if(firstLoad)document.querySelectorAll(".frm_inside_container").forEach(function(container){const input=container.querySelector("input, select, textarea");if(input&&""!==input.value)checkFloatLabel(input)});checkDropdownLabel()};runOnLoad(true);jQuery(document).on("frmPageChanged",function(event){runOnLoad()});document.addEventListener("frm_after_start_over",function(event){runOnLoad()})}function shouldUpdateValidityMessage(target){if("INPUT"!==target.nodeName)return false;if(!target.dataset.invmsg)return false; if("text"!==target.getAttribute("type"))return false;if(target.classList.contains("frm_verify"))return false;return true}function maybeClearCustomValidityMessage(event,field){let key,isInvalid=false;if(!shouldUpdateValidityMessage(field))return;for(key in field.validity){if("customError"===key)continue;if("valid"!==key&&field.validity[key]===true){isInvalid=true;break}}if(!isInvalid)field.setCustomValidity("")}function maybeShowNewTabFallbackMessage(){let messageEl;if(!window.frmShowNewTabFallback)return; messageEl=document.querySelector("#frm_form_"+frmShowNewTabFallback.formId+"_container .frm_message");if(!messageEl)return;messageEl.insertAdjacentHTML("beforeend"," "+frmShowNewTabFallback.message)}function setCustomValidityMessage(){let forms,length,index;forms=document.getElementsByClassName("frm-show-form");length=forms.length;for(index=0;index Date: Fri, 28 Feb 2025 15:14:55 +0200 Subject: [PATCH 06/12] gdpr revisions update --- classes/helpers/FrmFieldsHelper.php | 1 + classes/models/fields/FrmFieldGdpr.php | 9 +++------ .../views/frm-fields/back-end/gdpr/primary-options.php | 6 ------ classes/views/frm-fields/front-end/gdpr/gdpr-field.php | 5 ----- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/classes/helpers/FrmFieldsHelper.php b/classes/helpers/FrmFieldsHelper.php index 92da9689c1..2f5fa1f3e8 100644 --- a/classes/helpers/FrmFieldsHelper.php +++ b/classes/helpers/FrmFieldsHelper.php @@ -1291,6 +1291,7 @@ public static function single_input_fields() { 'time', 'tag', 'password', + 'gdpr', ); return apply_filters( 'frm_single_input_fields', $fields ); } diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index e88c227107..5cc719f86f 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -57,8 +57,9 @@ public function get_new_field_defaults() { protected function field_settings_for_type() { return array( 'size' => true, - 'clear_on_focus' => true, - 'invalid' => true, + 'clear_on_focus' => false, + 'invalid' => false, + 'max' => false, ); } @@ -71,9 +72,6 @@ protected function field_settings_for_type() { public function show_primary_options( $args ) { $field = $args['field']; include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/gdpr/primary-options.php'; - FrmFieldsController::show_format_option( $field ); - - parent::show_primary_options( $args ); } /** @@ -85,7 +83,6 @@ public function show_primary_options( $args ) { protected function extra_field_opts() { return array( 'gdpr_agreement_text' => __( 'I consent to having this website store my submitted information so they can respond to my inquiry.', 'formidable' ), - 'gdpr_description' => '', ); } diff --git a/classes/views/frm-fields/back-end/gdpr/primary-options.php b/classes/views/frm-fields/back-end/gdpr/primary-options.php index 7f668ad5e4..dd62cc7299 100644 --- a/classes/views/frm-fields/back-end/gdpr/primary-options.php +++ b/classes/views/frm-fields/back-end/gdpr/primary-options.php @@ -23,9 +23,3 @@

-

- - -

diff --git a/classes/views/frm-fields/front-end/gdpr/gdpr-field.php b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php index 8ee7ccf174..4ab6357728 100644 --- a/classes/views/frm-fields/front-end/gdpr/gdpr-field.php +++ b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php @@ -8,7 +8,6 @@ if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } -$field_desc = $field['gdpr_description']; $agreement_text = $field['gdpr_agreement_text']; $field_id = $field['id']; $checked = FrmAppHelper::check_selected( $field['value'], 1 ) ? ' checked="checked"' : ''; @@ -25,7 +24,3 @@ - -
- -
\ No newline at end of file From ea4c59a83fe2e70796fef15dff11c1deb87176dd Mon Sep 17 00:00:00 2001 From: liviu13 Date: Wed, 5 Mar 2025 15:48:14 +0200 Subject: [PATCH 07/12] revisions update + QA issues fixes --- classes/controllers/FrmHooksController.php | 1 - classes/factories/FrmFieldFactory.php | 35 ++++++------ classes/helpers/FrmAppHelper.php | 2 +- classes/helpers/FrmFieldGdprHelper.php | 16 ++---- classes/models/FrmField.php | 37 ++++++------ classes/models/fields/FrmFieldGdpr.php | 56 +++++++++++++++---- classes/models/fields/FrmFieldType.php | 41 +++++++------- .../views/frm-fields/back-end/settings.php | 19 ++++++- .../frm-fields/front-end/gdpr/gdpr-field.php | 12 +++- classes/views/frm-settings/general.php | 11 ++-- css/frm_admin.css | 5 +- js/formidable_admin.js | 11 ++++ 12 files changed, 161 insertions(+), 85 deletions(-) diff --git a/classes/controllers/FrmHooksController.php b/classes/controllers/FrmHooksController.php index 4b1d02d940..ec99052bff 100644 --- a/classes/controllers/FrmHooksController.php +++ b/classes/controllers/FrmHooksController.php @@ -112,7 +112,6 @@ public static function load_hooks() { FrmTransLiteHooksController::load_hooks(); FrmStrpLiteHooksController::load_hooks(); - FrmFieldGdprHelper::load_hooks(); } /** diff --git a/classes/factories/FrmFieldFactory.php b/classes/factories/FrmFieldFactory.php index c3850e7e1a..765469754c 100644 --- a/classes/factories/FrmFieldFactory.php +++ b/classes/factories/FrmFieldFactory.php @@ -91,24 +91,25 @@ public static function get_field_type( $field_type, $field = 0 ) { */ private static function get_field_type_class( $field_type ) { $type_classes = array( - 'text' => 'FrmFieldText', - 'textarea' => 'FrmFieldTextarea', - 'select' => 'FrmFieldSelect', - 'radio' => 'FrmFieldRadio', - 'checkbox' => 'FrmFieldCheckbox', - 'number' => 'FrmFieldNumber', - 'phone' => 'FrmFieldPhone', - 'url' => 'FrmFieldUrl', - 'website' => 'FrmFieldUrl', - 'email' => 'FrmFieldEmail', - 'user_id' => 'FrmFieldUserID', - 'html' => 'FrmFieldHTML', - 'hidden' => 'FrmFieldHidden', - 'captcha' => 'FrmFieldCaptcha', - 'name' => 'FrmFieldName', - 'credit_card' => 'FrmFieldCreditCard', + 'text' => 'FrmFieldText', + 'textarea' => 'FrmFieldTextarea', + 'select' => 'FrmFieldSelect', + 'radio' => 'FrmFieldRadio', + 'checkbox' => 'FrmFieldCheckbox', + 'number' => 'FrmFieldNumber', + 'phone' => 'FrmFieldPhone', + 'url' => 'FrmFieldUrl', + 'website' => 'FrmFieldUrl', + 'email' => 'FrmFieldEmail', + 'user_id' => 'FrmFieldUserID', + 'html' => 'FrmFieldHTML', + 'hidden' => 'FrmFieldHidden', + 'captcha' => 'FrmFieldCaptcha', + 'name' => 'FrmFieldName', + 'credit_card' => 'FrmFieldCreditCard', // Submit button field. - FrmSubmitHelper::FIELD_TYPE => 'FrmFieldSubmit', + FrmSubmitHelper::FIELD_TYPE => 'FrmFieldSubmit', + FrmFieldGdprHelper::FIELD_TYPE => FrmFieldGdprHelper::get_gdpr_field_class( $field_type ), ); $class = isset( $type_classes[ $field_type ] ) ? $type_classes[ $field_type ] : ''; diff --git a/classes/helpers/FrmAppHelper.php b/classes/helpers/FrmAppHelper.php index f904640de8..4c42d49297 100644 --- a/classes/helpers/FrmAppHelper.php +++ b/classes/helpers/FrmAppHelper.php @@ -4420,6 +4420,6 @@ public static function print_setting_error( $args ) { */ public static function no_gdpr_cookies() { $frm_settings = self::get_settings(); - return (bool) $frm_settings->no_gdpr_cookies; + return (bool) ( $frm_settings->enable_gdpr && $frm_settings->no_gdpr_cookies ); } } diff --git a/classes/helpers/FrmFieldGdprHelper.php b/classes/helpers/FrmFieldGdprHelper.php index c4cff9f1de..2ee09d8c73 100644 --- a/classes/helpers/FrmFieldGdprHelper.php +++ b/classes/helpers/FrmFieldGdprHelper.php @@ -32,17 +32,14 @@ class FrmFieldGdprHelper { const FIELD_CLASS = 'FrmFieldGdpr'; /** - * Load hooks + * Hide GDPR field * * @since x.x - * @return void + * @return bool */ - public static function load_hooks() { + public static function hide_gdpr_field() { $settings = FrmAppHelper::get_settings(); - if ( $settings->enable_gdpr ) { - add_filter( 'frm_available_fields', array( __CLASS__, 'add_gdpr_field' ), 10, 1 ); - add_filter( 'frm_get_field_type_class', array( __CLASS__, 'init_gdpr_field_class' ), 10, 2 ); - } + return ! $settings->enable_gdpr; } /** @@ -64,14 +61,13 @@ public static function add_gdpr_field( $fields ) { * Initialize GDPR field Class name * * @since x.x - * @param string $class * @param string $field_type * @return string */ - public static function init_gdpr_field_class( $class, $field_type = '' ) { + public static function get_gdpr_field_class( $field_type = '' ) { if ( self::FIELD_TYPE === $field_type ) { return self::FIELD_CLASS; } - return $class; + return ''; } } diff --git a/classes/models/FrmField.php b/classes/models/FrmField.php index e7e62fbf1e..ad98056531 100644 --- a/classes/models/FrmField.php +++ b/classes/models/FrmField.php @@ -10,70 +10,75 @@ class FrmField { public static function field_selection() { $fields = array( - 'text' => array( + 'text' => array( 'name' => __( 'Text', 'formidable' ), 'icon' => 'frm_icon_font frm_text2_icon', ), - 'textarea' => array( + 'textarea' => array( 'name' => __( 'Paragraph', 'formidable' ), 'icon' => 'frm_icon_font frm_paragraph_icon', ), - 'checkbox' => array( + 'checkbox' => array( 'name' => __( 'Checkboxes', 'formidable' ), 'icon' => 'frm_icon_font frm_check_square_icon', ), - 'radio' => array( + 'radio' => array( 'name' => __( 'Radio Buttons', 'formidable' ), 'icon' => 'frm_icon_font frm_radio_checked_icon', ), - 'select' => array( + 'select' => array( 'name' => __( 'Dropdown', 'formidable' ), 'icon' => 'frm_icon_font frm_caret_square_down_icon', ), - 'email' => array( + 'email' => array( 'name' => __( 'Email', 'formidable' ), 'icon' => 'frm_icon_font frm_email_icon', ), - 'url' => array( + 'url' => array( 'name' => __( 'Website/URL', 'formidable' ), 'icon' => 'frm_icon_font frm_link_icon', ), - 'number' => array( + 'number' => array( 'name' => __( 'Number', 'formidable' ), 'icon' => 'frm_icon_font frm_hashtag_icon', ), - 'name' => array( + 'name' => array( 'name' => __( 'Name', 'formidable' ), 'icon' => 'frm_icon_font frm_user_name_icon', ), - 'phone' => array( + 'phone' => array( 'name' => __( 'Phone', 'formidable' ), 'icon' => 'frm_icon_font frm_phone_icon', ), - 'html' => array( + 'html' => array( 'name' => __( 'HTML', 'formidable' ), 'icon' => 'frm_icon_font frm_code_icon', ), - 'hidden' => array( + 'hidden' => array( 'name' => __( 'Hidden', 'formidable' ), 'icon' => 'frm_icon_font frm_eye_slash_icon', ), - 'user_id' => array( + 'user_id' => array( 'name' => __( 'User ID', 'formidable' ), 'icon' => 'frm_icon_font frm_user_icon', ), - 'captcha' => array( + 'captcha' => array( 'name' => self::get_captcha_field_name(), 'icon' => 'frm_icon_font frm_shield_check_icon', ), - 'credit_card' => array( + 'credit_card' => array( 'name' => __( 'Payment', 'formidable' ), 'icon' => 'frm_icon_font frm_credit_card_icon', ), - FrmSubmitHelper::FIELD_TYPE => array( + FrmSubmitHelper::FIELD_TYPE => array( 'name' => __( 'Submit', 'formidable' ), 'hide' => true, ), + FrmFieldGdprHelper::FIELD_TYPE => array( + 'name' => __( 'GDPR', 'formidable' ), + 'icon' => 'frm_icon_font frm-gdpr-icon', + 'hide' => FrmFieldGdprHelper::hide_gdpr_field(), + ), ); /** diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index 5cc719f86f..7cecd7ad58 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -33,19 +33,25 @@ class FrmFieldGdpr extends FrmFieldType { * @return array */ public function get_new_field_defaults() { - $field = array( - 'name' => $this->get_new_field_name() . ' Agreement', + if ( FrmFieldGdprHelper::hide_gdpr_field() ) { + return array( + 'name' => false, + 'description' => false, + 'type' => $this->type, + 'options' => false, + 'required' => false, + 'field_options' => false, + ); + } + + return array( + 'name' => $this->get_new_field_name() . ' Consent', 'description' => '', 'type' => $this->type, 'options' => '', - 'default_value' => '', 'required' => true, 'field_options' => $this->get_default_field_options(), ); - - $field_options = $this->new_field_settings(); - - return array_merge( $field, $field_options ); } /** @@ -55,11 +61,29 @@ public function get_new_field_defaults() { * @return bool[] */ protected function field_settings_for_type() { + if ( FrmFieldGdprHelper::hide_gdpr_field() ) { + return array( + 'size' => false, + 'clear_on_focus' => false, + 'default' => false, + 'invalid' => false, + 'max' => false, + 'readonly_required' => false, + 'required' => false, + 'label' => false, + 'css' => false, + 'label_position' => false, + 'description' => false, + ); + } + return array( - 'size' => true, - 'clear_on_focus' => false, - 'invalid' => false, - 'max' => false, + 'size' => true, + 'clear_on_focus' => false, + 'default' => false, + 'invalid' => false, + 'max' => false, + 'readonly_required' => true, ); } @@ -70,10 +94,20 @@ protected function field_settings_for_type() { * @param array $args The arguments. */ public function show_primary_options( $args ) { + if ( FrmFieldGdprHelper::hide_gdpr_field() ) { + return; + } $field = $args['field']; include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/gdpr/primary-options.php'; } + public function show_label_on_form_builder() { + if ( FrmFieldGdprHelper::hide_gdpr_field() ) { + return; + } + parent::show_label_on_form_builder(); + } + /** * Gets extra field options. * diff --git a/classes/models/fields/FrmFieldType.php b/classes/models/fields/FrmFieldType.php index 001a27a5b1..0a213a8100 100644 --- a/classes/models/fields/FrmFieldType.php +++ b/classes/models/fields/FrmFieldType.php @@ -338,27 +338,28 @@ public function display_field_settings() { */ protected function default_field_settings() { return array( - 'type' => $this->type, - 'label' => true, - 'required' => true, - 'unique' => false, - 'read_only' => false, - 'description' => true, - 'options' => true, - 'label_position' => true, - 'invalid' => false, - 'size' => false, + 'type' => $this->type, + 'label' => true, + 'required' => true, + 'readonly_required' => false, + 'unique' => false, + 'read_only' => false, + 'description' => true, + 'options' => true, + 'label_position' => true, + 'invalid' => false, + 'size' => false, // Shows the placeholder option. - 'clear_on_focus' => false, - 'css' => true, - 'conf_field' => false, - 'max' => true, - 'range' => false, - 'captcha_size' => false, - 'captcha_theme' => false, - 'format' => false, - 'show_image' => false, - 'default' => true, + 'clear_on_focus' => false, + 'css' => true, + 'conf_field' => false, + 'max' => true, + 'range' => false, + 'captcha_size' => false, + 'captcha_theme' => false, + 'format' => false, + 'show_image' => false, + 'default' => true, ); } diff --git a/classes/views/frm-fields/back-end/settings.php b/classes/views/frm-fields/back-end/settings.php index f7198a6ece..76c1de2153 100644 --- a/classes/views/frm-fields/back-end/settings.php +++ b/classes/views/frm-fields/back-end/settings.php @@ -53,6 +53,23 @@ } } ?> + + +
+ 'width:24px' ) ); ?> + + ', '' ); + ?> + +
+ +

diff --git a/classes/views/frm-fields/front-end/gdpr/gdpr-field.php b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php index 4ab6357728..e028c2fb40 100644 --- a/classes/views/frm-fields/front-end/gdpr/gdpr-field.php +++ b/classes/views/frm-fields/front-end/gdpr/gdpr-field.php @@ -14,7 +14,7 @@ $label_id = 'frm-gdpr-accept-' . $field_id; ?> - +
+ +
+ +
+ diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index 40756b4c17..c64f359e6c 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -60,14 +60,14 @@ if ( ! $frm_settings->enable_gdpr ) { $gdpr_options_wrapper_params['class'] .= ' frm_hidden'; } -$custom_header_ip_wrapper_params = array( 'class' => 'frm_custom_header_ip_cont' ); -if ( $frm_settings->no_ips ) { +$custom_header_ip_wrapper_params = array( 'class' => 'frm_custom_header_ip_cont frm_gdpr_options' ); +if ( $frm_settings->no_ips || ! $frm_settings->enable_gdpr ) { $custom_header_ip_wrapper_params['class'] .= ' frm_hidden'; } ?>

@@ -85,9 +85,6 @@

- -

-

>

+

+ Date: Thu, 6 Mar 2025 15:59:56 +0200 Subject: [PATCH 08/12] fix showing gdpr field label when disabled for regular users, add gdpr note under general settings, switch block the required checkbox by beign selectable via javascript instead of disabled html attribute as this will make the required to be ignored by the form --- classes/models/fields/FrmFieldGdpr.php | 38 +++++++++++++------ .../views/frm-fields/back-end/settings.php | 2 +- classes/views/frm-settings/general.php | 9 ++++- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index 7cecd7ad58..e6ebf68e84 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -63,17 +63,16 @@ public function get_new_field_defaults() { protected function field_settings_for_type() { if ( FrmFieldGdprHelper::hide_gdpr_field() ) { return array( - 'size' => false, - 'clear_on_focus' => false, - 'default' => false, - 'invalid' => false, - 'max' => false, - 'readonly_required' => false, - 'required' => false, - 'label' => false, - 'css' => false, - 'label_position' => false, - 'description' => false, + 'size' => false, + 'clear_on_focus' => false, + 'default' => false, + 'invalid' => false, + 'max' => false, + 'required' => false, + 'label' => false, + 'css' => false, + 'label_position' => false, + 'description' => false, ); } @@ -84,6 +83,7 @@ protected function field_settings_for_type() { 'invalid' => false, 'max' => false, 'readonly_required' => true, + 'required' => true, ); } @@ -139,4 +139,20 @@ protected function include_form_builder_file() { protected function include_front_form_file() { return FrmAppHelper::plugin_path() . self::VIEW_PATH; } + + /** + * Hide the field name/label if the GDPR field is disabled. + * + * @since x.x + * + * @param array $args The arguments. + * @param string $html The HTML. + * @return string + */ + protected function before_replace_html_shortcodes( $args, $html ) { + if ( FrmFieldGdprHelper::hide_gdpr_field() && ! current_user_can( 'frm_edit_forms' ) ) { + return ''; + } + return $html; + } } diff --git a/classes/views/frm-fields/back-end/settings.php b/classes/views/frm-fields/back-end/settings.php index 76c1de2153..9588c44906 100644 --- a/classes/views/frm-fields/back-end/settings.php +++ b/classes/views/frm-fields/back-end/settings.php @@ -85,7 +85,7 @@
diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index c64f359e6c..ceceba1801 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -92,8 +92,13 @@

- -

+

+ %s', 'https://formidableforms.com/knowledgebase/gdpr-settings/', esc_html__( 'here', 'formidable' ) ); + ?> +

+

Date: Thu, 6 Mar 2025 20:12:49 +0200 Subject: [PATCH 09/12] fix unit test when a default_value is not set --- classes/helpers/FrmAppHelper.php | 2 +- classes/models/FrmField.php | 4 +++- classes/models/fields/FrmFieldGdpr.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/classes/helpers/FrmAppHelper.php b/classes/helpers/FrmAppHelper.php index 4c42d49297..b06cf2432a 100644 --- a/classes/helpers/FrmAppHelper.php +++ b/classes/helpers/FrmAppHelper.php @@ -4420,6 +4420,6 @@ public static function print_setting_error( $args ) { */ public static function no_gdpr_cookies() { $frm_settings = self::get_settings(); - return (bool) ( $frm_settings->enable_gdpr && $frm_settings->no_gdpr_cookies ); + return $frm_settings->enable_gdpr && $frm_settings->no_gdpr_cookies; } } diff --git a/classes/models/FrmField.php b/classes/models/FrmField.php index ad98056531..a6d12154fe 100644 --- a/classes/models/FrmField.php +++ b/classes/models/FrmField.php @@ -383,7 +383,9 @@ public static function create( $values, $return = true ) { $values = FrmAppHelper::maybe_filter_array( $values, array( 'name', 'description' ) ); foreach ( array( 'name', 'description', 'type', 'default_value' ) as $col ) { - $new_values[ $col ] = $values[ $col ]; + if ( isset( $values[ $col ] ) ) { + $new_values[ $col ] = $values[ $col ]; + } } $new_values['options'] = self::maybe_filter_options( $values['options'] ); diff --git a/classes/models/fields/FrmFieldGdpr.php b/classes/models/fields/FrmFieldGdpr.php index e6ebf68e84..101023661d 100644 --- a/classes/models/fields/FrmFieldGdpr.php +++ b/classes/models/fields/FrmFieldGdpr.php @@ -45,7 +45,7 @@ public function get_new_field_defaults() { } return array( - 'name' => $this->get_new_field_name() . ' Consent', + 'name' => $this->get_new_field_name() . __( ' Consent', 'formidable' ), 'description' => '', 'type' => $this->type, 'options' => '', From 93ddc1d43b5f608eb542eba0bfb14f741fc79a2b Mon Sep 17 00:00:00 2001 From: liviu13 Date: Thu, 6 Mar 2025 22:12:18 +0200 Subject: [PATCH 10/12] show the GDPR option if the old value of no_ips is enabled --- classes/views/frm-settings/general.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index ceceba1801..3e9cccd67d 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -67,7 +67,7 @@ ?>

From 4442e68185f50a2d272fb76f3a4976c055885682 Mon Sep 17 00:00:00 2001 From: liviu13 Date: Mon, 10 Mar 2025 10:58:46 +0200 Subject: [PATCH 11/12] revisions update --- classes/helpers/FrmAppHelper.php | 12 ++++++++++++ classes/views/frm-settings/general.php | 12 +++++++----- css/frm_admin.css | 4 ++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/classes/helpers/FrmAppHelper.php b/classes/helpers/FrmAppHelper.php index 716e3a5953..172e8de692 100644 --- a/classes/helpers/FrmAppHelper.php +++ b/classes/helpers/FrmAppHelper.php @@ -4445,6 +4445,18 @@ public static function print_setting_error( $args ) { enable_gdpr || $frm_settings->no_ips || $frm_settings->custom_header_ip || $frm_settings->no_gdpr_cookies; + } + /** * Check if GDPR cookies are disabled. * diff --git a/classes/views/frm-settings/general.php b/classes/views/frm-settings/general.php index 3e9cccd67d..a5c9efe529 100644 --- a/classes/views/frm-settings/general.php +++ b/classes/views/frm-settings/general.php @@ -2,6 +2,8 @@ if ( ! defined( 'ABSPATH' ) ) { die( 'You are not allowed to call this page directly.' ); } +$is_gdpr_enabled = FrmAppHelper::is_gdpr_enabled(); + ?>

@@ -57,17 +59,17 @@

'frm_gdpr_options' ); -if ( ! $frm_settings->enable_gdpr ) { +if ( ! $is_gdpr_enabled ) { $gdpr_options_wrapper_params['class'] .= ' frm_hidden'; } $custom_header_ip_wrapper_params = array( 'class' => 'frm_custom_header_ip_cont frm_gdpr_options' ); -if ( $frm_settings->no_ips || ! $frm_settings->enable_gdpr ) { +if ( $frm_settings->no_ips || ! $is_gdpr_enabled ) { $custom_header_ip_wrapper_params['class'] .= ' frm_hidden'; } ?>

@@ -75,7 +77,7 @@

>

@@ -95,7 +97,7 @@

%s', 'https://formidableforms.com/knowledgebase/gdpr-settings/', esc_html__( 'here', 'formidable' ) ); + printf( esc_html__( 'Learn more about our GDPR settings', 'formidable' ) . ' %s', 'https://formidableforms.com/knowledgebase/gdpr-settings/', esc_html__( 'here', 'formidable' ) ); ?>

diff --git a/css/frm_admin.css b/css/frm_admin.css index e3aeef5753..8b1a67061e 100644 --- a/css/frm_admin.css +++ b/css/frm_admin.css @@ -5968,6 +5968,10 @@ p.frm-inline-select, .frm-single-settings .frm_single_option .frm_remove_tag:before { content: ""; } +.frm-single-settings input[type="checkbox"][readonly] { + opacity: 0.5; + pointer-events: none; +} .advanced_settings .frm_logic_row { margin: 14px 0; From 868501fb2a00984f7e0f238580cc8053ff5d1d83 Mon Sep 17 00:00:00 2001 From: liviu13 Date: Mon, 10 Mar 2025 16:04:09 +0200 Subject: [PATCH 12/12] remove pointer-events from disabled option from gdpr related options --- css/frm_admin.css | 1 - 1 file changed, 1 deletion(-) diff --git a/css/frm_admin.css b/css/frm_admin.css index 8b1a67061e..e6e9f0c0c9 100644 --- a/css/frm_admin.css +++ b/css/frm_admin.css @@ -7623,7 +7623,6 @@ ul.frm_two_col { } .multiselect-container button.multiselect-option.disabled { opacity: 0.5; - pointer-events: none; } .frm_code_list.frm-full-hover a span { max-width: 83px;