Plugin Directory

Changeset 3248039


Ignore:
Timestamp:
02/27/2025 06:15:00 PM (13 months ago)
Author:
hcaptcha
Message:

Update to version 4.11.0 from GitHub

Location:
hcaptcha-for-forms-and-more
Files:
234 added
158 edited
1 copied

Legend:

Unmodified
Added
Removed
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/css/forms.css

    r3233179 r3248039  
    4545}
    4646
     47#hcaptcha-chart-message {
     48    padding: 5px 10px;
     49    border: 1px solid #c3c4c7;
     50    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
     51    color: #50575e;
     52    background-color: #f6f7f7;
     53    text-align: center;
     54}
     55
    4756@media (max-width: 782px) {
    4857    #hcaptcha-options #hcaptcha-forms-wrap table tbody tr td {
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/css/forms.min.css

    r3233179 r3248039  
    1 #hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{padding:8px 10px}.hcaptcha-forms-sample-bg{aspect-ratio:2845/1637;background-image:url(../images/forms-page.png);background-position:50%;background-repeat:no-repeat;background-size:cover;box-sizing:border-box;filter:blur(1px);-webkit-filter:blur(1px);width:100%}.hcaptcha-forms-sample-text{background-color:rgba(92,111,138,.8);border:3px solid #f0f2f5;color:#f0f2f5;left:50%;padding:20px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);width:80%;z-index:1}.hcaptcha-forms-sample-text p{font-size:1.3em}#hcaptcha-options .hcaptcha-forms-sample-text p a{color:#f0f2f5}#hcaptcha-forms-chart{aspect-ratio:3/1;background-color:#fff;margin:auto;position:relative;width:100%}@media (max-width:782px){#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{min-height:19.5px;padding-block-end:3px;padding-block-start:3px;padding-inline-end:8px;padding-inline-start:35%}#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td.column-primary{padding:3px 10px}}
     1#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{padding:8px 10px}.hcaptcha-forms-sample-bg{aspect-ratio:2845/1637;background-image:url(../images/forms-page.png);background-position:50%;background-repeat:no-repeat;background-size:cover;box-sizing:border-box;filter:blur(1px);-webkit-filter:blur(1px);width:100%}.hcaptcha-forms-sample-text{background-color:rgba(92,111,138,.8);border:3px solid #f0f2f5;color:#f0f2f5;left:50%;padding:20px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);width:80%;z-index:1}.hcaptcha-forms-sample-text p{font-size:1.3em}#hcaptcha-options .hcaptcha-forms-sample-text p a{color:#f0f2f5}#hcaptcha-forms-chart{aspect-ratio:3/1;background-color:#fff;margin:auto;position:relative;width:100%}#hcaptcha-chart-message{background-color:#f6f7f7;border:1px solid #c3c4c7;box-shadow:0 1px 1px rgba(0,0,0,.04);color:#50575e;padding:5px 10px;text-align:center}@media (max-width:782px){#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{min-height:19.5px;padding-block-end:3px;padding-block-start:3px;padding-inline-end:8px;padding-inline-start:35%}#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td.column-primary{padding:3px 10px}}
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/css/settings-base.css

    r3233179 r3248039  
    3838    margin-inline-end: 30px;
    3939    color: #646970;
    40     border-bottom: 2px solid transparent;
    4140}
    4241
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/css/settings-base.min.css

    r3233179 r3248039  
    1 body.settings_page_hcaptcha{background:#f0f2f5;color:#5c6f8a}.wrap h1.hcaptcha-settings-header{align-items:center;display:flex;font-size:34px;font-weight:700}.hcaptcha-logo{height:64px;margin-block-end:10px;margin-block-start:10px;margin-inline-end:5px;margin-inline-start:0}.hcaptcha-settings-tabs{background:#fff;display:flex;flex-wrap:wrap;justify-content:space-between;line-height:4.5em;margin:10px -20px 0;padding:0 20px;position:sticky;top:0;z-index:2}.hcaptcha-settings-tab{border-bottom:2px solid transparent;color:#646970;display:inline-block;font-size:1.1em;margin-inline-end:30px;text-decoration:none}.hcaptcha-settings-tab:hover{border-bottom-color:#025176!important;border-bottom:2px solid;color:#666}.hcaptcha-settings-tab.active{border-bottom:2px solid #0075ab}.hcaptcha-header-bar{align-items:center;background:#f0f2f5;display:flex;justify-content:space-between;margin:0 -20px;padding:0 20px;position:sticky;top:60px;z-index:2}#hcaptcha-options h2{color:#5c6f8a;font-size:1.5em}#hcaptcha-options h2~*{display:none}#hcaptcha-options h3{color:#5c6f8a;margin:1.5em 0 1em}#hcaptcha-options .notice-dismiss:before{color:#5c6f8a}#hcaptcha-options table tbody tr td{margin:0;padding:0;position:relative}#hcaptcha-options table tr td fieldset input[type=checkbox]{border:none;box-shadow:none;display:inline;height:1.25rem;margin-block-end:0;margin-block-start:-.125rem;margin-inline-end:.5rem;margin-inline-start:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:before{background:url(../images/checkbox-off.svg);background-size:cover;content:"";display:inline-block;height:1.25rem;margin:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:checked:before{background:no-repeat url(../images/checkbox-on.svg);background-size:cover}#hcaptcha-options fieldset:disabled{color:#dadada}#hcaptcha-options .button-primary{background-color:#026593;border-color:#026593;color:#fff}#hcaptcha-options .button-primary:hover{background-color:#025176}#hcaptcha-options .button-secondary{background-color:#fff;border-color:#026593;color:#026593}#hcaptcha-options .button-secondary:hover{background-color:#ccc}#hcaptcha-options a{color:#0075ab}#hcaptcha-navigation a{border-color:#0075ab}#hcaptcha-options a.hcaptcha-settings-tab{color:#5c6f8a}#hcaptcha-options .helper:before{background:#5c6f8a;border-radius:1.2em;color:#fff;content:"?";height:1.2em;inset-inline-end:0;position:absolute;text-align:center;top:0;transform:translateY(-27px);width:1.2em}#hcaptcha-options fieldset+.helper:before{top:50%;transform:translate(25px,-.7em)}.rtl #hcaptcha-options fieldset+.helper:before{transform:translate(-25px,-.8em)}#hcaptcha-options .helper .helper-content{background:#5c6f8a;box-sizing:border-box;color:#f0f2f5;display:none;inset-inline-end:0;padding:.5em 1em;position:absolute;top:0;transform:translate(1px,10px);width:100%}.rtl #hcaptcha-options .helper .helper-content{transform:translate(-1px,10px)}#hcaptcha-options fieldset+.helper .helper-content{top:50%;transform:translate(25px,25px);width:calc(100% + 25px)}#hcaptcha-options .helper:hover{cursor:help}#hcaptcha-options .helper:hover .helper-content{display:block;z-index:1}#hcaptcha-options .helper .helper-content:after{border:10px solid transparent;border-bottom-color:#5c6f8a;content:"";inset-inline-end:0;position:absolute;top:0;transform:translateY(-100%)}#hcaptcha-options .helper .helper-content a{color:#fff}#hcaptcha-message{box-sizing:border-box}#hcaptcha-message>p{font-size:13px;font-weight:600;line-height:1.5;margin:.5em 0}@keyframes blink{0%{opacity:1}16.7%{opacity:0}33.3%{opacity:1}50%{opacity:0}66.7%{opacity:1}83.3%{opacity:0}to{opacity:1}}.blink{animation:blink 3s linear}.hcaptcha-hide{display:none}.hcaptcha-excerpt{display:block;max-width:100%;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:max-content}.hcaptcha-excerpt:hover{overflow:visible}.hcaptcha-excerpt:hover .hcaptcha-hide{background:#5c6f8a;border:1px solid #c3c4c7;border-radius:6px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);color:#f0f2f5;display:block;inset-inline-start:50%;max-width:300px;padding:8px 10px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);white-space:normal;width:max-content;z-index:1}@media (max-width:782px){#hcaptcha-options .wp-list-table .toggle-row{top:15px}#hcaptcha-options .wp-list-table tr.is-expanded .toggle-row{top:6.5px}#hcaptcha-options .widefat tbody th.check-column{padding:0;vertical-align:middle}#hcaptcha-options .widefat thead td.check-column,.widefat tfoot td.check-column{padding-left:0}#hcaptcha-options .widefat th input[type=checkbox]{margin-bottom:0}#hcaptcha-options .wp-list-table .is-expanded td:not(.hidden){overflow:visible}.hcaptcha-settings-tabs{margin:unset;margin-block-end:0;margin-block-start:10px;margin-inline-end:-12px;margin-inline-start:-10px;padding-block-end:0;padding-block-start:0;padding-inline-end:12px;padding-inline-start:10px}.hcaptcha-excerpt{display:table-cell;height:44px;vertical-align:middle}tr.is-expanded .hcaptcha-excerpt{height:19.5px}}@media (max-width:600px){#hcaptcha-options table tbody{grid-template-columns:1fr}#hcaptcha-options table tbody tr{position:relative}#hcaptcha-options fieldset+.helper:before{transform:translateY(-.7em)}#hcaptcha-options fieldset+.helper .helper-content{transform:translateY(25px);width:100%}#hcaptcha-options .helper{z-index:1}.hcaptcha-settings-tab{inset-inline-end:15px}}
     1body.settings_page_hcaptcha{background:#f0f2f5;color:#5c6f8a}.wrap h1.hcaptcha-settings-header{align-items:center;display:flex;font-size:34px;font-weight:700}.hcaptcha-logo{height:64px;margin-block-end:10px;margin-block-start:10px;margin-inline-end:5px;margin-inline-start:0}.hcaptcha-settings-tabs{background:#fff;display:flex;flex-wrap:wrap;justify-content:space-between;line-height:4.5em;margin:10px -20px 0;padding:0 20px;position:sticky;top:0;z-index:2}.hcaptcha-settings-tab{color:#646970;display:inline-block;font-size:1.1em;margin-inline-end:30px;text-decoration:none}.hcaptcha-settings-tab:hover{border-bottom-color:#025176!important;border-bottom:2px solid;color:#666}.hcaptcha-settings-tab.active{border-bottom:2px solid #0075ab}.hcaptcha-header-bar{align-items:center;background:#f0f2f5;display:flex;justify-content:space-between;margin:0 -20px;padding:0 20px;position:sticky;top:60px;z-index:2}#hcaptcha-options h2{color:#5c6f8a;font-size:1.5em}#hcaptcha-options h2~*{display:none}#hcaptcha-options h3{color:#5c6f8a;margin:1.5em 0 1em}#hcaptcha-options .notice-dismiss:before{color:#5c6f8a}#hcaptcha-options table tbody tr td{margin:0;padding:0;position:relative}#hcaptcha-options table tr td fieldset input[type=checkbox]{border:none;box-shadow:none;display:inline;height:1.25rem;margin-block-end:0;margin-block-start:-.125rem;margin-inline-end:.5rem;margin-inline-start:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:before{background:url(../images/checkbox-off.svg);background-size:cover;content:"";display:inline-block;height:1.25rem;margin:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:checked:before{background:no-repeat url(../images/checkbox-on.svg);background-size:cover}#hcaptcha-options fieldset:disabled{color:#dadada}#hcaptcha-options .button-primary{background-color:#026593;border-color:#026593;color:#fff}#hcaptcha-options .button-primary:hover{background-color:#025176}#hcaptcha-options .button-secondary{background-color:#fff;border-color:#026593;color:#026593}#hcaptcha-options .button-secondary:hover{background-color:#ccc}#hcaptcha-options a{color:#0075ab}#hcaptcha-navigation a{border-color:#0075ab}#hcaptcha-options a.hcaptcha-settings-tab{color:#5c6f8a}#hcaptcha-options .helper:before{background:#5c6f8a;border-radius:1.2em;color:#fff;content:"?";height:1.2em;inset-inline-end:0;position:absolute;text-align:center;top:0;transform:translateY(-27px);width:1.2em}#hcaptcha-options fieldset+.helper:before{top:50%;transform:translate(25px,-.7em)}.rtl #hcaptcha-options fieldset+.helper:before{transform:translate(-25px,-.8em)}#hcaptcha-options .helper .helper-content{background:#5c6f8a;box-sizing:border-box;color:#f0f2f5;display:none;inset-inline-end:0;padding:.5em 1em;position:absolute;top:0;transform:translate(1px,10px);width:100%}.rtl #hcaptcha-options .helper .helper-content{transform:translate(-1px,10px)}#hcaptcha-options fieldset+.helper .helper-content{top:50%;transform:translate(25px,25px);width:calc(100% + 25px)}#hcaptcha-options .helper:hover{cursor:help}#hcaptcha-options .helper:hover .helper-content{display:block;z-index:1}#hcaptcha-options .helper .helper-content:after{border:10px solid transparent;border-bottom-color:#5c6f8a;content:"";inset-inline-end:0;position:absolute;top:0;transform:translateY(-100%)}#hcaptcha-options .helper .helper-content a{color:#fff}#hcaptcha-message{box-sizing:border-box}#hcaptcha-message>p{font-size:13px;font-weight:600;line-height:1.5;margin:.5em 0}@keyframes blink{0%{opacity:1}16.7%{opacity:0}33.3%{opacity:1}50%{opacity:0}66.7%{opacity:1}83.3%{opacity:0}to{opacity:1}}.blink{animation:blink 3s linear}.hcaptcha-hide{display:none}.hcaptcha-excerpt{display:block;max-width:100%;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:max-content}.hcaptcha-excerpt:hover{overflow:visible}.hcaptcha-excerpt:hover .hcaptcha-hide{background:#5c6f8a;border:1px solid #c3c4c7;border-radius:6px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);color:#f0f2f5;display:block;inset-inline-start:50%;max-width:300px;padding:8px 10px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);white-space:normal;width:max-content;z-index:1}@media (max-width:782px){#hcaptcha-options .wp-list-table .toggle-row{top:15px}#hcaptcha-options .wp-list-table tr.is-expanded .toggle-row{top:6.5px}#hcaptcha-options .widefat tbody th.check-column{padding:0;vertical-align:middle}#hcaptcha-options .widefat thead td.check-column,.widefat tfoot td.check-column{padding-left:0}#hcaptcha-options .widefat th input[type=checkbox]{margin-bottom:0}#hcaptcha-options .wp-list-table .is-expanded td:not(.hidden){overflow:visible}.hcaptcha-settings-tabs{margin:unset;margin-block-end:0;margin-block-start:10px;margin-inline-end:-12px;margin-inline-start:-10px;padding-block-end:0;padding-block-start:0;padding-inline-end:12px;padding-inline-start:10px}.hcaptcha-excerpt{display:table-cell;height:44px;vertical-align:middle}tr.is-expanded .hcaptcha-excerpt{height:19.5px}}@media (max-width:600px){#hcaptcha-options table tbody{grid-template-columns:1fr}#hcaptcha-options table tbody tr{position:relative}#hcaptcha-options fieldset+.helper:before{transform:translateY(-.7em)}#hcaptcha-options fieldset+.helper .helper-content{transform:translateY(25px);width:100%}#hcaptcha-options .helper{z-index:1}.hcaptcha-settings-tab{inset-inline-end:15px}}
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/events.js

    r3233179 r3248039  
    55 * @param HCaptchaEventsObject.bulkAction
    66 * @param HCaptchaEventsObject.bulkNonce
     7 * @param HCaptchaEventsObject.bulkMessage
    78 * @param HCaptchaEventsObject.failed
    89 * @param HCaptchaEventsObject.failedLabel
     
    123124
    124125    initChart();
     126    hCaptchaSettingsBase.showSuccessMessage( HCaptchaEventsObject.bulkMessage );
    125127    document.getElementById( 'doaction' ).addEventListener( 'click', handleBulkAction );
    126128};
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/events.min.js

    r3233179 r3248039  
    1 (()=>{var e=function(e){var t,a;t=document.getElementById("eventsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaEventsObject.succeedLabel,data:HCaptchaEventsObject.succeed,borderWidth:1},{label:HCaptchaEventsObject.failedLabel,data:HCaptchaEventsObject.failed,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaEventsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),n=s.get("action");if("-1"!==n){var c=s.getAll("bulk-checkbox[]");if(c.length){var o={action:HCaptchaEventsObject.bulkAction,nonce:HCaptchaEventsObject.bulkNonce,bulk:n,ids:JSON.stringify(c)};e.post({url:HCaptchaEventsObject.ajaxUrl,data:o,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
     1(()=>{var e=function(e){var t,a;t=document.getElementById("eventsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaEventsObject.succeedLabel,data:HCaptchaEventsObject.succeed,borderWidth:1},{label:HCaptchaEventsObject.failedLabel,data:HCaptchaEventsObject.failed,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaEventsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),hCaptchaSettingsBase.showSuccessMessage(HCaptchaEventsObject.bulkMessage),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),n=s.get("action");if("-1"!==n){var c=s.getAll("bulk-checkbox[]");if(c.length){var o={action:HCaptchaEventsObject.bulkAction,nonce:HCaptchaEventsObject.bulkNonce,bulk:n,ids:JSON.stringify(c)};e.post({url:HCaptchaEventsObject.ajaxUrl,data:o,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/forms.js

    r3233179 r3248039  
    55 * @param HCaptchaFormsObject.bulkAction
    66 * @param HCaptchaFormsObject.bulkNonce
     7 * @param HCaptchaFormsObject.bulkMessage
    78 * @param HCaptchaFormsObject.served
    89 * @param HCaptchaFormsObject.servedLabel
     
    99100        }
    100101
     102        const datepicker = document.getElementById( 'hcaptcha-datepicker' );
    101103        const data = {
    102104            action: HCaptchaFormsObject.bulkAction,
     
    104106            bulk,
    105107            ids: JSON.stringify( ids ),
     108            date: datepicker?.value ?? '',
    106109        };
    107110
     
    128131
    129132    initChart();
     133    hCaptchaSettingsBase.showSuccessMessage( HCaptchaFormsObject.bulkMessage );
    130134    document.getElementById( 'doaction' ).addEventListener( 'click', handleBulkAction );
    131135};
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/forms.min.js

    r3233179 r3248039  
    1 (()=>{var e=function(e){var t,a;t=document.getElementById("formsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaFormsObject.servedLabel,backgroundColor:"rgba(2,101,147,0.5)",data:HCaptchaFormsObject.served,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaFormsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),o=s.get("action");if("-1"!==o){var r=s.getAll("bulk-checkbox[]").map((function(e){var t=a.querySelector('input[name="bulk-checkbox[]"][value="'.concat(e,'"]')).closest("tr");return{source:t.querySelector("td.name .hcaptcha-excerpt").dataset.source,formId:t.querySelector("td.form_id").textContent}}));if(r.length){var c={action:HCaptchaFormsObject.bulkAction,nonce:HCaptchaFormsObject.bulkNonce,bulk:o,ids:JSON.stringify(r)};e.post({url:HCaptchaFormsObject.ajaxUrl,data:c,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
     1(()=>{var e=function(e){var t,a;t=document.getElementById("formsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaFormsObject.servedLabel,backgroundColor:"rgba(2,101,147,0.5)",data:HCaptchaFormsObject.served,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaFormsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),hCaptchaSettingsBase.showSuccessMessage(HCaptchaFormsObject.bulkMessage),document.getElementById("doaction").addEventListener("click",(function(t){var a;t.preventDefault();var s=t.target.closest("form"),o=new FormData(s),c=o.get("action");if("-1"!==c){var r=o.getAll("bulk-checkbox[]").map((function(e){var t=s.querySelector('input[name="bulk-checkbox[]"][value="'.concat(e,'"]')).closest("tr");return{source:t.querySelector("td.name .hcaptcha-excerpt").dataset.source,formId:t.querySelector("td.form_id").textContent}}));if(r.length){var n=document.getElementById("hcaptcha-datepicker"),i={action:HCaptchaFormsObject.bulkAction,nonce:HCaptchaFormsObject.bulkNonce,bulk:c,ids:JSON.stringify(r),date:null!==(a=null==n?void 0:n.value)&&void 0!==a?a:""};e.post({url:HCaptchaFormsObject.ajaxUrl,data:i,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/settings-base.js

    r3233179 r3248039  
    136136
    137137    setHeaderBarTop();
    138 
    139138    highLight();
    140139
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/settings-list-page-base.js

    r3233179 r3248039  
    11/* global HCaptchaListPageBaseObject, flatpickr */
    22
    3 /**
    4  * @param flatpickr.l10ns
    5  */
    6 document.addEventListener( 'DOMContentLoaded', function() {
     3const settingsListPagePage = ( function() {
     4    /**
     5     * @param flatpickr.l10ns
     6     */
     7
    78    /**
    89     * @type {HTMLInputElement}
     
    8788        selectorElement.setAttribute(
    8889            'aria-expanded',
    89             selectorElement.style.display === 'block' ? 'true' : 'false'
     90            selectorElement.style.display === 'block' ? 'true' : 'false',
    9091        );
    9192    }
     
    222223    }
    223224
     225    /**
     226     * Public properties and functions.
     227     */
     228    const app = {};
     229
    224230    bindEvents();
    225231    initFlatPicker();
     232
     233    return app;
    226234} );
     235
     236window.hCaptchaSettingsListPagePage = settingsListPagePage;
     237
     238document.addEventListener( 'DOMContentLoaded', settingsListPagePage );
  • hcaptcha-for-forms-and-more/tags/4.11.0/assets/js/settings-list-page-base.min.js

    r3233179 r3248039  
    1 (()=>{function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(e){for(var n=1;n<arguments.length;n++){var a=null!=arguments[n]?arguments[n]:{};n%2?t(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function r(t,n,r){return(n=function(t){var n=function(t,n){if("object"!=e(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var a=r.call(t,n||"default");if("object"!=e(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(t)}(t,"string");return"symbol"==e(n)?n:n+""}(n))in t?Object.defineProperty(t,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[n]=r,t}document.addEventListener("DOMContentLoaded",(function(){var e=document.getElementById("hcaptcha-datepicker");if(e){var t,r,a="hcaptcha-is-selected",o=HCaptchaListPageBaseObject.delimiter,c=HCaptchaListPageBaseObject.locale,i=document.getElementById("hcaptcha-options"),l=document.querySelector(".hcaptcha-filter"),u=document.getElementById("hcaptcha-datepicker-popover-button"),p=l.querySelector('input[type="radio"][data-default]');document.addEventListener("click",f),i.querySelector("#hcaptcha-datepicker-popover-button").addEventListener("click",d),i.querySelectorAll('[type="radio"]').forEach((function(e){e.addEventListener("change",v)})),i.querySelector('[type="reset"]').addEventListener("click",b),i.addEventListener("submit",s),i.querySelector("#current-page-selector").addEventListener("keydown",y),r=l.querySelector('input[value="custom"]'),t=flatpickr(e,{mode:"range",inline:!0,allowInput:!1,enableTime:!1,clickOpens:!1,altInput:!0,altFormat:"M j, Y",dateFormat:"Y-m-d",locale:n(n({},flatpickr.l10ns[c]||{}),{},{rangeSeparator:o}),onChange:function(e,t,n){r.checked=!0,m(r.parentElement),t&&(u.textContent=n.altInput.value)}}),v({},r.checked)}function s(t){var n;t.preventDefault(),this.querySelectorAll('input[type="radio"]').forEach((function(e){e.name=""})),(n=u.nextElementSibling).setAttribute("aria-expanded","false"),n.style.display="none";var r=new URL(window.location.href),a=r.searchParams;a.delete("date"),e.value&&a.append("date",e.value),window.location.href=r.toString()}function d(e){e.preventDefault(),e.stopPropagation();var t=e.target.nextElementSibling;"none"===t.style.display||""===t.style.display?t.style.display="block":t.style.display="none",t.setAttribute("aria-expanded","block"===t.style.display?"true":"false")}function y(e){if("Enter"===e.key){e.preventDefault();var t=new URL(window.location.href),n=parseInt(t.searchParams.get("paged")),r=parseInt(e.target.value);(isNaN(n)||n<1)&&(n=1),isNaN(r)||r<1||(t.searchParams.delete("paged"),r!==n&&(t.searchParams.set("paged",r.toString()),window.location.href=t.href))}}function f(e){var t=document.querySelector(".hcaptcha-datepicker-popover");t.contains(e.target)||(t.style.display="none")}function m(e){l.querySelectorAll("label").forEach((function(e){e.classList.remove(a)})),e.classList.add(a)}function b(e){e.preventDefault(),p.checked=!0,v()}function v(){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=l.querySelector("input:checked"),a=r.parentElement,c=n?e:r,i=c.value.split(o),p=c.nextElementSibling;u.textContent=n?p.value:a.textContent,m(a),Array.isArray(i)&&2===i.length?t.setDate(i):t.clear()}}))})();
     1(()=>{function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(e){for(var n=1;n<arguments.length;n++){var a=null!=arguments[n]?arguments[n]:{};n%2?t(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function r(t,n,r){return(n=function(t){var n=function(t,n){if("object"!=e(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var a=r.call(t,n||"default");if("object"!=e(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(t)}(t,"string");return"symbol"==e(n)?n:n+""}(n))in t?Object.defineProperty(t,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[n]=r,t}var a=function(){var e=document.getElementById("hcaptcha-datepicker");if(e){var t,r,a="hcaptcha-is-selected",o=HCaptchaListPageBaseObject.delimiter,c=HCaptchaListPageBaseObject.locale,i=document.getElementById("hcaptcha-options"),l=document.querySelector(".hcaptcha-filter"),u=document.getElementById("hcaptcha-datepicker-popover-button"),p=l.querySelector('input[type="radio"][data-default]');return document.addEventListener("click",f),i.querySelector("#hcaptcha-datepicker-popover-button").addEventListener("click",d),i.querySelectorAll('[type="radio"]').forEach((function(e){e.addEventListener("change",b)})),i.querySelector('[type="reset"]').addEventListener("click",v),i.addEventListener("submit",s),i.querySelector("#current-page-selector").addEventListener("keydown",y),r=l.querySelector('input[value="custom"]'),t=flatpickr(e,{mode:"range",inline:!0,allowInput:!1,enableTime:!1,clickOpens:!1,altInput:!0,altFormat:"M j, Y",dateFormat:"Y-m-d",locale:n(n({},flatpickr.l10ns[c]||{}),{},{rangeSeparator:o}),onChange:function(e,t,n){r.checked=!0,m(r.parentElement),t&&(u.textContent=n.altInput.value)}}),b({},r.checked),{}}function s(t){var n;t.preventDefault(),this.querySelectorAll('input[type="radio"]').forEach((function(e){e.name=""})),(n=u.nextElementSibling).setAttribute("aria-expanded","false"),n.style.display="none";var r=new URL(window.location.href),a=r.searchParams;a.delete("date"),e.value&&a.append("date",e.value),window.location.href=r.toString()}function d(e){e.preventDefault(),e.stopPropagation();var t=e.target.nextElementSibling;"none"===t.style.display||""===t.style.display?t.style.display="block":t.style.display="none",t.setAttribute("aria-expanded","block"===t.style.display?"true":"false")}function y(e){if("Enter"===e.key){e.preventDefault();var t=new URL(window.location.href),n=parseInt(t.searchParams.get("paged")),r=parseInt(e.target.value);(isNaN(n)||n<1)&&(n=1),isNaN(r)||r<1||(t.searchParams.delete("paged"),r!==n&&(t.searchParams.set("paged",r.toString()),window.location.href=t.href))}}function f(e){var t=document.querySelector(".hcaptcha-datepicker-popover");t.contains(e.target)||(t.style.display="none")}function m(e){l.querySelectorAll("label").forEach((function(e){e.classList.remove(a)})),e.classList.add(a)}function v(e){e.preventDefault(),p.checked=!0,b()}function b(){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=l.querySelector("input:checked"),a=r.parentElement,c=n?e:r,i=c.value.split(o),p=c.nextElementSibling;u.textContent=n?p.value:a.textContent,m(a),Array.isArray(i)&&2===i.length?t.setDate(i):t.clear()}};window.hCaptchaSettingsListPagePage=a,document.addEventListener("DOMContentLoaded",a)})();
  • hcaptcha-for-forms-and-more/tags/4.11.0/changelog.txt

    r3233179 r3248039  
     1= 4.11.0 =
     2* Added Really Simple CAPTCHA plugin integration.
     3* Added compatibility with the UsersWP plugin v1.2.28.
     4* Added compatibility with Perfmatters plugin.
     5* Added support for the Fluent Login form.
     6* Added confirmation messages upon deletion of events on the Forms and Events pages.
     7* Added asynchronous migrations for large databases.
     8* Added hCaptcha error messages to the Contact Form 7 when JavaScript is disabled.
     9* Optimized Forms page performance for large databases with millions of entries.
     10* Fixed processing wpDiscuz comment form with wpDiscuz custom ajax.
     11* Fixed adding hCaptcha internal fields to Avada from submission.
     12* Fixed ASC ordering by date on the Events page.
     13* Fixed selection of a time interval on the Events page when site local time was not GMT.
     14* Fixed losing options during plugin update in rare cases.
     15* Fixed the live hCaptcha tag on the Contact Form 7 edit page after insertion but before saving the form.
     16* Fixed shortcode processing in the Contact Form 7 form when Auto-Add was off.
     17* Fixed error on theme installation.
     18* Tested with WooCommerce 9.7.
     19
    120= 4.10.0 =
    221* Added support for wp_login_form() function and LoginOut block.
     
    219238* Fixed Content Security Policy headers processing.
    220239
     240= 3.10.1 =
     241* Added filter `hcap_add_csp_headers` to allow adding Content Security Policy headers.
     242* Fixed Content Security Policy headers processing.
     243
    221244= 3.10.0 =
    222245* Tested with WordPress 6.5.
     
    276299* Added optional Enterprise settings.
    277300* Fixed improper display of the "rate plugin" message on options.php.
    278 * Fixed colored border of hCaptcha challenge arrow.
     301* Fixed the colored border of hCaptcha challenge arrow.
    279302
    280303= 3.6.0 =
     
    300323* Added hCaptcha field to Ninja Forms admin editor.
    301324* Added invisible hCaptcha support for Ninja Forms.
    302 * Added the ability to process customized MailChimp forms.
     325* Added the ability to process customized Mailchimp forms.
    303326* Added HTML Forms integration.
    304327* Added the Auto Theme option to follow light/dark theme settings on site.
     
    359382
    360383= 3.3.0 =
    361 * Color scheme in admin UI has been updated.
     384* The color scheme in the admin UI has been updated.
    362385* Added compatibility with Passster.
    363386* Added compatibility with Theme My Login.
  • hcaptcha-for-forms-and-more/tags/4.11.0/hcaptcha.php

    r3233179 r3248039  
    1111 * Plugin URI:           https://www.hcaptcha.com/
    1212 * Description:          hCaptcha keeps out bots and spam while putting privacy first. It is a drop-in replacement for reCAPTCHA.
    13  * Version:              4.10.0
     13 * Version:              4.11.0
    1414 * Requires at least:    5.3
    1515 * Requires PHP:         7.2
     
    2222 *
    2323 * WC requires at least: 3.0
    24  * WC tested up to:      9.6
     24 * WC tested up to:      9.7
    2525 */
    2626
     
    4040 * Plugin version.
    4141 */
    42 const HCAPTCHA_VERSION = '4.10.0';
     42const HCAPTCHA_VERSION = '4.11.0';
    4343
    4444/**
  • hcaptcha-for-forms-and-more/tags/4.11.0/readme.txt

    r3233179 r3248039  
    55Tested up to: 6.7
    66Requires PHP: 7.2
    7 Stable tag: 4.10.0
     7Stable tag: 4.11.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    3535* **Logged-in Users:** Optionally turn off hCaptcha for logged-in users.
    3636* **Delayed API Loading:** Load the hCaptcha API instantly or on user interaction for zero page load impact.
    37 * **White List IPs:** Whitelist certain IPs to skip hCaptcha verification.
     37* **Allowlist IPs:** Allowlist certain IPs to skip hCaptcha verification.
    3838* **Multisite Support:** Sync hCaptcha settings across a Multisite Network.
    3939
     
    5959The purpose of a CAPTCHA is to distinguish between people and machines via a challenge-response test, and thus increase the cost of spamming or otherwise abusing websites by keeping out bots.
    6060
    61 To use this plugin, install it and enter your sitekey and secret in the Settings -> hCaptcha menu after signing up on hCaptcha.com.
     61To use this plugin, install it and enter your sitekey and secret in the Settings hCaptcha menu after signing up on hCaptcha.com.
    6262
    6363[hCaptcha Free](https://www.hcaptcha.com/) lets websites block bots and other forms of abuse via humanity challenges.
     
    88881. Install hCaptcha either via the WordPress.org plugin repository (best) or by uploading the files to your server. ([Upload instructions](https://www.wpbeginner.com/beginners-guide/step-by-step-guide-to-install-a-wordpress-plugin-for-beginners/))
    89892. Activate the hCaptcha plugin on the 'Plugins' admin page
    90 3. Enter your site key and secret on the Settings->hCaptcha->General page
    91 4. Enable desired Integrations on the Settings->hCaptcha->Integrations page
     903. Enter your site key and secret on the Settings→hCaptcha→General page
     914. Enable desired Integrations on the Settings→hCaptcha→Integrations page
    9292
    9393== Frequently Asked Questions ==
     
    115115`
    116116
    117 The shortcode adds not only the hCaptcha div to the form, but also a nonce field. You can set your own nonce action and name. For this, use arguments in the shortcode:
     117The shortcode adds not only the hCaptcha div to the form but also a nonce field. You can set your own nonce action and name. For this, use arguments in the shortcode:
    118118
    119119`
     
    398398    }
    399399
    400     // Turn off protection for Gravity form with id = 1.
     400    // Turn off protection for a Gravity form with id = 1.
    401401    return false;
    402402}
     
    449449`
    450450
    451 = How to whitelist certain IPs =
     451= How to allowlist certain IPs =
    452452
    453453You can use the following filter. It should be added to your plugin's (or mu-plugin's) main file. This filter won't work being added to a theme's functions.php file.
     
    455455`
    456456/**
    457  * Filter user IP to check if it is whitelisted.
    458  * For whitelisted IPs, hCaptcha will not be shown.
     457 * Filter user IP to check if it is allowlisted.
     458 * For allowlisted IPs, hCaptcha will not be shown.
    459459 *
    460  * @param bool   $whitelisted Whether IP is whitelisted.
     460 * @param bool   $allowlisted Whether IP is allowlisted.
    461461 * @param string $ip          IP.
    462462 *
    463463 * @return bool
    464464 */
    465 function my_hcap_whitelist_ip( $whitelisted, $ip ) {
    466 
    467   // Whitelist local IPs.
     465function my_hcap_allowlist_ip( $allowlisted, $ip ) {
     466
     467  // Allowlist local IPs.
    468468  if ( false === $ip ) {
    469469    return true;
    470470  }
    471471
    472   // Whitelist some other IPs.
     472  // Allowlist some other IPs.
    473473  if ( '1.1.1.1' === $ip ) {
    474474    return true;
    475475  }
    476476
    477   return $whitelisted;
     477  return $allowlisted;
    478478}
    479479
    480 add_filter( 'hcap_whitelist_ip', 'my_hcap_whitelist_ip', 10, 2 );
     480add_filter( 'hcap_whitelist_ip', 'my_hcap_allowlist_ip', 10, 2 );
    481481`
    482482
     
    568568* Essential Blocks Form
    569569* Extra Comment, Contact, Email Optin and Login Forms
    570 * Fluent Forms
     570* Fluent Forms, including Login Form
    571571* Forminator Forms
    572572* Formidable Forms
     
    587587* Passster Protection Form
    588588* Profile Builder Login, Recover Password, and Register Forms
     589* Really Simple CAPTCHA
    589590* Quform Forms
    590591* Sendinblue Form
     
    616617[open a pull request](https://github.com/hCaptcha/hcaptcha-wordpress-plugin).
    617618
    618 We also suggest emailing the authors of plugins you'd like to support hCaptcha: it will usually take them only an hour or two to add native support. This will simplify your use of hCaptcha, and is the best solution in the long run.
     619We also suggest emailing the authors of plugins you'd like to support hCaptcha: it will usually take them only an hour or two to add native support. This will simplify your use of hCaptcha and is the best solution in the long run.
    619620
    620621You may use native hCaptcha support if available for your plugin. Please check with your plugin author if native support is not yet available.
     
    627628
    628629== Changelog ==
     630
     631= 4.11.0 =
     632* Added Really Simple CAPTCHA plugin integration.
     633* Added compatibility with the UsersWP plugin v1.2.28.
     634* Added compatibility with Perfmatters plugin.
     635* Added support for the Fluent Login form.
     636* Added confirmation messages upon deletion of events on the Forms and Events pages.
     637* Added asynchronous migrations for large databases.
     638* Added hCaptcha error messages to the Contact Form 7 when JavaScript is disabled.
     639* Optimized Forms page performance for large databases with millions of entries.
     640* Fixed processing wpDiscuz comment form with wpDiscuz custom ajax.
     641* Fixed adding hCaptcha internal fields to Avada from submission.
     642* Fixed ASC ordering by date on the Events page.
     643* Fixed selection of a time interval on the Events page when site local time was not GMT.
     644* Fixed losing options during plugin update in rare cases.
     645* Fixed the live hCaptcha tag on the Contact Form 7 edit page after insertion but before saving the form.
     646* Fixed shortcode processing in the Contact Form 7 form when Auto-Add was off.
     647* Fixed error on theme installation.
     648* Tested with WooCommerce 9.7.
    629649
    630650= 4.10.0 =
     
    637657* Added deletion of events on the Events page.
    638658* Improved error messaging for hCaptcha verification.
    639 * Fixed IP detection in the WordPress core via filter. Now syncs with hCaptcha event information when IP collection is activated.
     659* Fixed IP detection in the WordPress core via filter. Now syncs with hCaptcha event information when an IP collection is activated.
    640660* Fixed fatal error with the WPForms plugin in rare cases.
    641661* Fixed error message at the first entry to the login page when Hide Login Errors in on.
     
    653673* Added the ability to install plugins and themes from the Integrations page.
    654674* Added ability to hide the login errors.
    655 * Added anonymous collection of IP and User Agent data in locally stored analytics to simplify GDPR compliance.
     675* Added an anonymous collection of IP and User Agent data in locally stored analytics to simplify GDPR compliance.
    656676* Added extended info about IP address on the Events page on hover.
    657677* Added selecting any page on Forms and Events.
     
    660680* Fixed fatal error as a consequence of a bug in the TutorLMS.
    661681* Fixed help text box layout on the General page.
    662 * Fixed dismiss and reset Notifications actions.
     682* Fixed the dismiss and reset Notifications actions.
    663683* Fixed duplication of entries in the Events table.
    664684
     
    672692* Added 'theme' badge to themes on the Integrations page.
    673693* Updated hCaptcha API error codes.
    674 * Fixed processing of Divi form with diacritical marks.
     694* Fixed processing of a Divi form with diacritical marks.
    675695* Fixed deactivating of all themes by Ctrl+Click on the Integrations page.
    676696* Fixed theme name display upon activation.
     
    693713* Added compatibility with Akismet tag in Contact Form 7.
    694714* Added compatibility with Elementor Element Caching.
    695 * Added activation and deactivation of plugins network wide if hCaptcha is set network wide.
     715* Added activation and deactivation of plugin network wide if hCaptcha is set network wide.
    696716* Added ability to use shortcode in the Jetpack Classic form.
    697717* Added ability to use shortcode in the Mailchimp for WP form.
     
    733753* Fixed error messaging when there are several Jetpack forms on the same page.
    734754* Fixed unconditional forcing hCaptcha in Jetpack forms.
    735 * Fixed appearance of Beaver Builder editor with "Turn Off When Logged In" setting.
    736 * Fixed appearance of Contact Form 7 editor with "Turn Off When Logged In" setting.
    737 * Fixed appearance of Essential Addons editor with "Turn Off When Logged In" setting.
    738 * Fixed appearance of Gravity Forms editor with "Turn Off When Logged In" setting.
    739 * Fixed appearance of Fluent Forms editor with "Turn Off When Logged In" setting.
    740 * Fixed appearance of Forminator editor with "Turn Off When Logged In" setting.
    741 * Fixed appearance of Formidable Forms with "Turn Off When Logged In" setting.
    742 * Fixed appearance of Ninja Forms editor with "Turn Off When Logged In" setting.
    743 * Fixed appearance of WPForms editor with "Turn Off When Logged In" setting.
     755* Fixed the appearance of Beaver Builder editor with "Turn Off When Logged In" setting.
     756* Fixed the appearance of Contact Form 7 editor with "Turn Off When Logged In" setting.
     757* Fixed the appearance of Essential Addons editor with "Turn Off When Logged In" setting.
     758* Fixed the appearance of Gravity Forms editor with "Turn Off When Logged In" setting.
     759* Fixed the appearance of Fluent Forms editor with "Turn Off When Logged In" setting.
     760* Fixed the appearance of Forminator editor with "Turn Off When Logged In" setting.
     761* Fixed the appearance of Formidable Forms with "Turn Off When Logged In" setting.
     762* Fixed the appearance of Ninja Forms editor with "Turn Off When Logged In" setting.
     763* Fixed the appearance of WPForms editor with "Turn Off When Logged In" setting.
    744764* Fixed fatal error on Gravity Forms Entries page.
    745765* Fixed Elementor preview.
     
    844864* Tested with WooCommerce 8.7.
    845865
    846 = 3.10.1 =
    847 * Added filter `hcap_add_csp_headers` to allow adding Content Security Policy headers.
    848 * Fixed Content Security Policy headers processing.
    849 
    850 = 3.10.0 =
    851 * Tested with WordPress 6.5.
    852 * Tested with WooCommerce 8.6.
    853 * The minimum required WordPress version is now 5.1.
    854 * Added Force hCaptcha check before submit feature.
    855 * Added Elementor Pro Login integration.
    856 * Added Login/Signup Popup integration.
    857 * Added CoBlocks integration.
    858 * Added Enterprise parameters to the System Info page.
    859 * Added checking of Enterprise parameters before saving.
    860 * Improved translation on Settings pages.
    861 * Improved error reporting for Active hCaptcha on the General page.
    862 * Fixed hCaptcha error codes table.
    863 * Fixed Settings pages layout with Chrome 122.
    864 * Fixed Content Security Policy headers.
    865 * Fixed fatal error with Formidable Forms 6.8.2.
    866 
    867 = 3.9.0 =
    868 * Added Spectra — WordPress Gutenberg Blocks integration.
    869 * Added Akismet integration.
    870 * Added test of hCaptcha completion before checking the site config.
    871 * Added site config check upon changing Enterprise params.
    872 * Added auto verify feature for forms in widgets.
    873 * Fixed site config check upon changing site and secret keys.
    874 * Fixed the list of themes after activation on the Integrations page.
    875 * Fixed jumping WooCommerce checkout page to hCaptcha on a page load.
    876 * Fixed missing hCaptcha on the Divi Comment Form.
    877 
    878 = 3.8.1 =
    879 * Fixed activation and deactivation of plugin and themes on the Integrations page.
    880 
    881 = 3.8.0 =
    882 * Added search of plugin and themes on the Integrations page.
    883 * Added toggling of sections on the General page.
    884 * Added new dialog on activation and deactivation of plugin and themes.
    885 * Added selection of a new theme on deactivation of the current one.
    886 * Added 'backend' to optional Enterprise settings.
    887 * Added filter `hcap_api_host`, allowing to filter the API host.
    888 * Added filter `hcap_api_src`, allowing to filter the API source url with params.
    889 * Updated integration with Back In Stock Notifier.
    890 * Fixed Brevo (formerly Sendinblue) plugin position on Integrations page.
    891 * Fixed testing config with test accounts.
    892 * Fixed saving Notification state.
    893 * Fixed compatibility of Ninja Forms with GeoDirectory.
    894 * Fixed compatibility of Beaver Builder with GeoDirectory.
    895 * Fixed compatibility of Divi with GeoDirectory.
    896 * Fixed compatibility of MailPoet with GeoDirectory.
    897 * Fixed compatibility of Passster with GeoDirectory.
    898 * Fixed styles of Settings pages on mobile.
    899 
    900 = 3.7.1 =
    901 * Fixed adding arguments to api.js for Enterprise accounts.
    902 
    903 = 3.7.0 =
    904 * Tested with WooCommerce 8.5.
    905 * Added optional Enterprise settings.
    906 * Fixed improper display of the "rate plugin" message on options.php.
    907 * Fixed colored border of hCaptcha challenge arrow.
    908 
    909 = 3.6.0 =
    910 * Tested with WooCommerce 8.4.
    911 * Added compatibility with BuddyPress 12.0.
    912 * Added hCaptcha tag to Contact Form 7 Admin Editor.
    913 * Added support for WPForms embedded forms.
    914 * Added Affiliates Login Form integration.
    915 * Added Affiliates Register Form integration.
    916 * Improved login forms security.
    917 * Improved inline scripts to optimize page load time.
    918 * Improved Integrations settings page - the Save Changes button moved up for better user experience.
    919 * Fixed hCaptcha position in BuddyPress.
    920 * Fixed hCaptcha position in wpDiscuz.
    921 * Fixed fatal error in Brizy integration.
    922 * Fixed auto-detection of hCaptcha language.
    923 * Fixed and added some translations.
    924 
    925 = 3.5.0 =
    926 * Tested with PHP 8.3.
    927 * Tested with WooCommerce 8.3.
    928 * Added hCaptcha field to Gravity Forms admin editor.
    929 * Added hCaptcha field to Ninja Forms admin editor.
    930 * Added invisible hCaptcha support for Ninja Forms.
    931 * Added the ability to process customized Mailchimp forms.
    932 * Added HTML Forms integration.
    933 * Added the Auto Theme option to follow light/dark theme settings on site.
    934 * Added support for WP Twenty Twenty-One theme dark mode.
    935 * Added support for WP Dark Mode plugin.
    936 * Added support for Droit Dark Mode plugin.
    937 * Added ability to activate/deactivate themes from the Integrations settings page.
    938 * Fixed loading of local .mo files.
    939 * Fixed inability to send Divi Contact Form.
    940 * Fixed MailPoet issues in admin.
    941 
    942 = 3.4.1 =
    943 * Tested with WordPress 6.4.
    944 * Tested with WooCommerce 8.2.
    945 * Added MailPoet integration.
    946 * Added Simple Download Monitor integration.
    947 * Added WP Job Openings integration.
    948 * Added Simple Basic Contact Form integration.
    949 * Added Easy Digital Downloads Login Form integration.
    950 * Added Easy Digital Downloads Lost Password Form integration.
    951 * Added Easy Digital Downloads Register Form integration.
    952 * Added purging of old failed login data to keep the `hcaptcha_login_data` option size small.
    953 * Fixed compatibility with HPOS in WooCommerce.
    954 * Fixed fatal error caused by broken backward compatibility in the Ultimate Member 2.7.0.
    955 * Fixed SystemInfo on multisite.
    956 * Fixed the missing dependency of WooCommerce checkout script.
    957 * Fixed fatal error occurred during login under some conditions.
    958 * Fixed the inability to send the Divi Contact Form when Divi Email Optin was active.
    959 
    960 = 3.3.3 =
    961 * Added compatibility with LearnDash.
    962 * Added requirement to check the site config after changes in credentials.
    963 * Added filter `hcap_login_limit_exceeded`, allowing to filter the login limit exceeded status.
    964 * Changed Brevo (formerly Sendinblue) logo.
    965 * Fixed activation of hCaptcha with empty keys.
    966 * Fixed autocomplete of the Site Key field by LastPass.
    967 * Fixed form detection for Auto-Verify.
    968 * Fixed Brevo form working in the post content only.
    969 * Fixed hCaptcha not loading correctly for a Brevo form.
    970 * Fixed Passster form working in the post content only.
    971 * Fixed LearnDash form working in the post content only.
    972 * Fixed auto-verify form not working on the homepage.
    973 
    974 = 3.3.2 =
    975 * Improved Beaver Builder login sequence.
    976 * Improved Classified Listing login sequence.
    977 * Improved Divi login sequence.
    978 * Improved MemberPress login sequence.
    979 * Improved Paid Membership Pro login sequence.
    980 * Improved Profile Builder login sequence.
    981 * Improved Ultimate Member login sequence.
    982 * Improved Wordfence login sequence.
    983 * Improved native WordPress login sequence.
    984 * Fixed login error when WP Login form option was `'on'` and WC Login form option was `'off'`.
    985 * Fixed compatibility with WPS Hide Login.
    986 * Fixed compatibility with All-In-One Security.
    987 * Fixed compatibility with Rename wp-admin Login.
    988 
    989 = 3.3.0 =
    990 * Color scheme in admin UI has been updated.
    991 * Added compatibility with Passster.
    992 * Added compatibility with Theme My Login.
    993 * Added compatibility with Gravity Perks Nested Forms.
    994 * Added compatibility with Wordfence Login Security.
    995 * Added compatibility with Wordfence Security.
    996 * Added compatibility with UsersWP.
    997 * Added compatibility with Kadence Advanced Form.
    998 * Improved support for a Kadence simple form.
    999 * Replaced deprecated ajaxStop events.
    1000 * Fixed error on a Classified Listing Login form.
    1001 * Fixed admin page title.
    1002 
    1003 = 3.2.0 =
    1004 * Tested with WooCommerce 8.0.
    1005 * Added ability to use hCaptcha field provided by the Fluent Forms plugin.
    1006 * Added ability to use hCaptcha field provided by the Forminator plugin.
    1007 * Added ability to use hCaptcha field provided by the Quform plugin.
    1008 * Added hCaptcha reset to allow sending an Elementor form several times without reloading the page.
    1009 * Added hCaptcha reset to allow sending a Forminator form several times without reloading the page.
    1010 * Added hCaptcha reset to allow sending a Quform form several times without reloading the page.
    1011 * Blocked hCaptcha settings on Fluent Forms admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1012 * Blocked hCaptcha settings on Forminator admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1013 * Blocked hCaptcha settings on Quform admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1014 * Fixed Fluent Forms submit error.
    1015 * Fixed positioning of hCaptcha in Fluent Form.
    1016 * Fixed deprecation errors in debug.log that occurred with Fluent Forms.
    1017 * Fixed Forminator form display error.
    1018 * Fixed dynamic display of settings in sample hCaptcha.
    1019 
    1020 = 3.1.0 =
    1021 * Added notification system.
    1022 * Fixed mode selection for sample hCaptcha on the General settings page.
    1023 
    1024 = 3.0.1 =
    1025 * Fixed error on Contact Form 7 validation.
    1026 * Fixed checkboxes disabled status after activation of a plugin on the Integrations page.
    1027 
    1028 = 3.0.0 =
    1029 * Dropped support for PHP 5.6. The minimum required PHP version is now 7.0.
    1030 * Tested with WordPress 6.3.
    1031 * Tested with WooCommerce 7.9.
    1032 * Added hCaptcha config check to the General settings page.
    1033 * Added dynamic display of settings in sample hCaptcha.
    1034 * Added compatibility with Ajax Gravity Forms.
    1035 * Added compatibility with Profile Builder.
    1036 * Added compatibility with an Easy Digital Downloads Checkout form.
    1037 
    1038866[See changelog for all versions](https://plugins.svn.wordpress.org/hcaptcha-for-forms-and-more/trunk/changelog.txt).
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Admin/Events/Events.php

    r3233179 r3248039  
    2121     */
    2222    public const TABLE_NAME = 'hcaptcha_events';
     23
     24    /**
     25     * Served items limit.
     26     */
     27    public const SERVED_LIMIT = 1000;
    2328
    2429    /**
     
    131136        global $wpdb;
    132137
    133         $args          = wp_parse_args(
    134             $args,
    135             [
    136                 'columns' => [],
    137                 'offset'  => 0,
    138                 'limit'   => 20,
    139                 'order'   => 'ASC',
    140                 'orderby' => '',
    141                 'dates'   => [],
    142             ]
    143         );
    144         $args['dates'] = $args['dates'] ?: self::get_default_dates();
     138        $args = self::prepare_args( $args );
    145139
    146140        $columns           = implode( ',', $args['columns'] );
     
    150144        $where_date_nested = self::get_where_date_gmt_nested( $args );
    151145        $orderby           = self::get_order_by( $args );
    152         $limit             = absint( $args['limit'] );
     146        $limit             = $args['limit'];
    153147
    154148        // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     
    160154                WHERE $where_date",
    161155            $wpdb->prepare(
    162                 "SELECT
    163                         $columns
     156                "SELECT $columns
    164157                        FROM $table_name
    165158                        WHERE $where_date_nested
     
    210203        global $wpdb;
    211204
    212         $args          = wp_parse_args(
    213             $args,
    214             [
    215                 'offset'  => 0,
    216                 'limit'   => 20,
    217                 'order'   => 'ASC',
    218                 'orderby' => '',
    219                 'dates'   => [],
    220             ]
    221         );
    222         $args['dates'] = $args['dates'] ?: self::get_default_dates();
     205        $args = self::prepare_args( $args );
    223206
    224207        $table_name = $wpdb->prefix . self::TABLE_NAME;
    225208        $where_date = self::get_where_date_gmt( $args );
    226209        $orderby    = self::get_order_by( $args );
    227         $offset     = absint( $args['offset'] );
    228         $limit      = absint( $args['limit'] );
    229 
     210        $offset     = $args['offset'];
     211        $limit      = $args['limit'];
     212
     213        // We need to collect id also to distinguish rows on the Forms page.
    230214        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    231215        $results = (array) $wpdb->get_results(
    232216            $wpdb->prepare(
    233217            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    234                 "SELECT
    235                         SQL_CALC_FOUND_ROWS
    236                         id, source, form_id, COUNT(*) as served
     218                "SELECT SQL_CALC_FOUND_ROWS id, source, form_id, COUNT(*) as served
    237219                        FROM $table_name
    238220                        WHERE $where_date
     
    258240        }
    259241
    260         $where = "($where) AND " . $where_date;
     242        $where        = "($where) AND " . $where_date;
     243        $served_limit = self::SERVED_LIMIT;
    261244
    262245        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    263246        $served = (array) $wpdb->get_results(
    264247        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    265             "SELECT date_gmt FROM $table_name WHERE $where"
     248            "SELECT date_gmt
     249                    FROM $table_name FORCE INDEX (date_gmt)
     250                    WHERE $where
     251                    ORDER BY date_gmt
     252                    LIMIT $served_limit"
    266253        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    267254        );
     
    327314        $dates = $args['dates'];
    328315
    329         if ( $dates ) {
    330             $dates[1] = $dates[1] ?? $dates[0];
    331 
    332             $dates[0] .= ' 00:00:00';
    333             $dates[1] .= ' 23:59:59';
    334 
    335             foreach ( $dates as &$date ) {
    336                 $date = wp_date( 'Y-m-d H:i:s', strtotime( $date ) );
    337             }
    338 
    339             unset( $date );
    340 
    341             $where_date = sprintf(
    342                 "date_gmt BETWEEN '%s' AND '%s'",
    343                 esc_sql( $dates[0] ),
    344                 esc_sql( $dates[1] )
    345             );
    346         } else {
    347             $where_date = '1=1';
    348         }
    349 
    350         return $where_date;
     316        if ( ! $dates ) {
     317            return '1=1';
     318        }
     319
     320        $dates = self::prepare_gmt_dates( $dates );
     321
     322        return sprintf(
     323            "date_gmt BETWEEN '%s' AND '%s'",
     324            esc_sql( $dates[0] ),
     325            esc_sql( $dates[1] )
     326        );
    351327    }
    352328
     
    363339        $dates = $args['dates'];
    364340
    365         if ( $dates ) {
    366             $dates[1] = $dates[1] ?? $dates[0];
    367 
    368             $dates[0] .= ' 00:00:00';
    369             $dates[1] .= ' 23:59:59';
    370 
    371             foreach ( $dates as &$date ) {
    372                 $date = wp_date( 'Y-m-d H:i:s', strtotime( $date ) );
    373             }
    374 
    375             unset( $date );
    376 
    377             $table_name = $wpdb->prefix . self::TABLE_NAME;
    378             $offset     = absint( $args['offset'] );
    379 
    380             $where_date = sprintf(
    381                 "date_gmt BETWEEN '%s' AND '%s'
    382                         AND date_gmt <= (
    383                             SELECT date_gmt
    384                             FROM %s
    385                             WHERE date_gmt BETWEEN '%s' AND '%s'
    386                             ORDER BY date_gmt DESC
    387                             LIMIT %d, 1
    388                         )
    389                         ",
    390                 esc_sql( $dates[0] ),
    391                 esc_sql( $dates[1] ),
    392                 $table_name,
    393                 esc_sql( $dates[0] ),
    394                 esc_sql( $dates[1] ),
    395                 $offset
    396             );
    397         } else {
    398             $where_date = '1=1';
    399         }
    400 
    401         return $where_date;
     341        if ( ! $dates ) {
     342            return '1=1';
     343        }
     344
     345        $dates      = self::prepare_gmt_dates( $dates );
     346        $table_name = $wpdb->prefix . self::TABLE_NAME;
     347        $order      = $args['order'];
     348        $offset     = $args['offset'];
     349        $compare    = 'DESC' === $order ? '<=' : '>=';
     350
     351        return sprintf(
     352            "date_gmt BETWEEN '%s' AND '%s'
     353                    AND date_gmt %s (
     354                        SELECT date_gmt
     355                        FROM %s
     356                        WHERE date_gmt BETWEEN '%s' AND '%s'
     357                        ORDER BY date_gmt %s
     358                        LIMIT %d, 1
     359                    )
     360                    ",
     361            esc_sql( $dates[0] ),
     362            esc_sql( $dates[1] ),
     363            $compare,
     364            $table_name,
     365            esc_sql( $dates[0] ),
     366            esc_sql( $dates[1] ),
     367            $order,
     368            $offset
     369        );
     370    }
     371
     372    /**
     373     * Prepare dates.
     374     *
     375     * @param array $dates Dates.
     376     *
     377     * @return array
     378     */
     379    public static function prepare_gmt_dates( array $dates ): array {
     380        $dates[1] = $dates[1] ?? $dates[0];
     381
     382        $dates[0] .= ' 00:00:00';
     383        $dates[1] .= ' 23:59:59';
     384
     385        foreach ( $dates as &$date ) {
     386            $date = get_gmt_from_date( $date );
     387        }
     388
     389        unset( $date );
     390
     391        return $dates;
    402392    }
    403393
     
    411401    private static function get_order_by( array $args ): string {
    412402        $orderby = $args['orderby'];
    413         $orderby = 'name' === $orderby ? 'source' : $orderby;
    414         $order   = strtoupper( $args['order'] );
     403        $order   = $args['order'];
    415404        $order   = 'ASC' === $order ? '' : $order;
    416405
     
    423412     * @return array
    424413     */
    425     private static function get_default_dates(): array {
     414    public static function get_default_dates(): array {
    426415        $end_date   = date_create_immutable( 'now', wp_timezone() );
    427416        $start_date = $end_date;
     
    495484        return preg_match( '/^' . $regex . '$/is', $subject );
    496485    }
     486
     487    /**
     488     * Prepare arguments.
     489     *
     490     * @param array $args Arguments.
     491     *
     492     * @return array
     493     */
     494    private static function prepare_args( array $args ): array {
     495        $args = wp_parse_args(
     496            $args,
     497            [
     498                'columns' => [],
     499                'offset'  => 0,
     500                'limit'   => 20,
     501                'order'   => 'ASC',
     502                'orderby' => '',
     503                'dates'   => [],
     504            ]
     505        );
     506
     507        $args['columns'] = array_map( 'strtolower', $args['columns'] );
     508        $args['offset']  = absint( $args['offset'] );
     509        $args['limit']   = max( 1, absint( $args['limit'] ) );
     510        $order           = strtoupper( $args['order'] );
     511        $args['order']   = in_array( $order, [ 'ASC', 'DESC' ], true ) ? $order : 'ASC';
     512        $orderby         = strtolower( $args['orderby'] );
     513        $args['orderby'] = in_array( $orderby, $args['columns'], true ) ? $orderby : '';
     514        $dates           = (array) $args['dates'];
     515        $args['dates']   = $dates ?: self::get_default_dates();
     516
     517        return $args;
     518    }
    497519}
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Admin/Events/EventsTable.php

    r3233179 r3248039  
    105105        $orderby = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'date_gmt';
    106106        $date    = isset( $_GET['date'] )
     107            // We need filter_input here to keep the delimiter intact.
    107108            ? filter_input( INPUT_GET, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
    108             : ''; // We need filter_input here to keep delimiter intact.
     109            : '';
    109110        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    110111
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Admin/Events/FormsTable.php

    r3233179 r3248039  
    9696        $orderby = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'source';
    9797        $date    = isset( $_GET['date'] )
     98            // We need filter_input here to keep the delimiter intact.
    9899            ? filter_input( INPUT_GET, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
    99             : ''; // We need filter_input here to keep delimiter intact.
     100            : '';
    100101        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    101102
    102         $dates    = explode( ListPageBase::TIMESPAN_DELIMITER, $date );
    103         $dates    = array_filter( array_map( 'trim', $dates ) );
    104         $per_page = $this->get_items_per_page( self::ITEMS_PER_PAGE, $this->per_page_default );
    105         $offset   = ( $paged - 1 ) * $per_page;
    106         $args     = [
     103        $dates        = explode( ListPageBase::TIMESPAN_DELIMITER, $date );
     104        $dates        = array_filter( array_map( 'trim', $dates ) );
     105        $column_slugs = str_replace( [ 'cb', 'name' ], [ 'id', 'source' ], array_keys( $this->columns ) );
     106        $per_page     = $this->get_items_per_page( self::ITEMS_PER_PAGE, $this->per_page_default );
     107        $offset       = ( $paged - 1 ) * $per_page;
     108        $args         = [
     109            'columns' => $column_slugs,
    107110            'offset'  => $offset,
    108111            'limit'   => $per_page,
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Affiliates/Login.php

    r3114572 r3248039  
    5757     */
    5858    public function print_inline_styles(): void {
    59         $css = <<<CSS
     59        /* language=CSS */
     60        $css = '
    6061    .affiliates-dashboard .h-captcha {
    6162        margin-top: 2rem;
    6263    }
    63 CSS;
     64';
    6465
    6566        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Asgaros/Base.php

    r3114572 r3248039  
    104104     */
    105105    public function print_inline_styles(): void {
    106         $css = <<<CSS
     106        /* language=CSS */
     107        $css = '
    107108    #af-wrapper div.editor-row.editor-row-hcaptcha {
    108109        display: flex;
     
    113114        margin-bottom: 0;
    114115    }
    115 CSS;
     116';
    116117
    117118        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Avada/Form.php

    r3114572 r3248039  
    3636    public function init_hooks(): void {
    3737        add_action( 'fusion_form_after_open', [ $this, 'form_after_open' ], 10, 2 );
     38        add_filter( 'fusion_builder_form_submission_data', [ $this, 'submission_data' ] );
    3839        add_action( 'fusion_element_button_content', [ $this, 'add_hcaptcha' ], 10, 2 );
    3940        add_filter( 'fusion_form_demo_mode', [ $this, 'verify' ] );
     
    5152    public function form_after_open( array $args, array $params ): void {
    5253        $this->form_id = isset( $params['id'] ) ? (int) $params['id'] : 0;
     54    }
     55
     56    /**
     57     * Filter submission data.
     58     *
     59     * @param array|mixed $data Submission data.
     60     *
     61     * @return array
     62     */
     63    public function submission_data( $data ): array {
     64        $data = (array) $data;
     65
     66        unset(
     67            $data['data']['hcaptcha-widget-id'],
     68            $data['data']['h-captcha-response'],
     69            $data['data']['g-recaptcha-response']
     70        );
     71
     72        return $data;
    5373    }
    5474
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Brizy/Base.php

    r3114572 r3248039  
    132132        $style_shown = true;
    133133
    134         $css = <<<CSS
     134        /* language=CSS */
     135        $css = '
    135136    .brz-forms2.brz-forms2__item .h-captcha {
    136137        margin-bottom: 0;
    137138    }
    138 CSS;
     139';
    139140
    140141        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/BuddyPress/CreateGroup.php

    r3114572 r3248039  
    100100     */
    101101    public function print_inline_styles(): void {
    102         $css = <<<'CSS'
     102        /* language=CSS */
     103        $css = '
    103104    #buddypress .h-captcha {
    104105        margin-top: 15px;
    105106    }
    106 CSS;
     107';
    107108        HCaptcha::css_display( $css );
    108109    }
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/CF7/Admin.php

    r3200161 r3248039  
    6060            add_action( 'current_screen', [ $this, 'current_screen' ] );
    6161        }
     62
     63        add_filter( 'hcap_print_hcaptcha_scripts', '__return_true' );
    6264    }
    6365
     
    329331        }
    330332
     333        if ( ! current_user_can( 'edit_posts' ) ) {
     334            wp_send_json_error( esc_html__( 'You do not have permission to update the form.', 'hcaptcha-for-forms-and-more' ) );
     335
     336            return; // For testing purposes.
     337        }
     338
    331339        $shortcode = html_entity_decode( filter_input( INPUT_POST, 'shortcode', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
    332340        $form      = html_entity_decode( filter_input( INPUT_POST, 'form', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/CF7/CF7.php

    r3185570 r3248039  
    3636
    3737    /**
     38     * Field type.
     39     */
     40    public const FIELD_TYPE = 'hcaptcha';
     41
     42    /**
    3843     * Init hooks.
    3944     *
     
    138143        $class     = $attr['cf7-class'] ?? '';
    139144        $hcap_form = preg_replace(
    140             [ '/(<h-captcha\s+?class="h-captcha")/', '#</h-captcha>#' ],
    141             [ '<span id="' . esc_attr( $id ) . '" class="wpcf7-form-control h-captcha ' . esc_attr( $class ) . '"', '</span>' ],
     145            [
     146                '/(<h-captcha\s+?class="h-captcha")/',
     147                '#</h-captcha>#',
     148            ],
     149            [
     150                '<span id="' . esc_attr( $id ) . '" class="wpcf7-form-control h-captcha ' . esc_attr( $class ) . '"',
     151                '</span>',
     152            ],
    142153            $hcap_form
    143154        );
     155
     156        $submission         = WPCF7_Submission::get_instance();
     157        $hcap_invalid_field = $submission ? $submission->get_invalid_field( 'hcap-cf7' ) : [];
     158        $reason             = $hcap_invalid_field['reason'] ?? '';
     159        $not_valid_tip      = $reason ? '<span class="wpcf7-not-valid-tip" aria-hidden="true">' . $reason . '</span>' : '';
    144160
    145161        return (
    146162            '<span class="wpcf7-form-control-wrap" data-name="' . self::DATA_NAME . '">' .
    147163            $hcap_form .
    148             '</span>'
     164            '</span>' .
     165            $not_valid_tip
    149166        );
    150167    }
     
    203220        if (
    204221            ! $this->mode_auto &&
    205             ! ( $this->mode_embed && $this->has_field( $submission, 'hcaptcha' ) )
     222            ! ( $this->mode_embed && $this->has_field( $submission, self::FIELD_TYPE ) )
    206223        ) {
    207224            return $result;
     
    228245     */
    229246    protected function has_field( WPCF7_Submission $submission, string $type ): bool {
    230         $form_fields = $submission->get_contact_form()->scan_form_tags();
    231 
    232         foreach ( $form_fields as $form_field ) {
    233             if ( $type === $form_field->type ) {
    234                 return true;
     247        $has_field    = false;
     248        $contact_form = $submission->get_contact_form();
     249
     250        if ( self::FIELD_TYPE === $type && has_shortcode( $contact_form->form_html(), 'cf7-hcaptcha' ) ) {
     251            $has_field = true;
     252        } else {
     253            $form_fields = $contact_form->scan_form_tags();
     254
     255            foreach ( $form_fields as $form_field ) {
     256                if ( $type === $form_field->type ) {
     257                    $has_field = true;
     258                }
    235259            }
    236260        }
    237261
    238         return false;
     262        /**
     263         * Filter whether form has a field of given type.
     264         *
     265         * @param bool $has_field Form has field.
     266         */
     267        return apply_filters( 'hcap_cf7_has_field', $has_field, $submission, $type );
    239268    }
    240269
     
    255284        $result->invalidate(
    256285            [
    257                 'type' => 'hcaptcha',
     286                'type' => self::FIELD_TYPE,
    258287                'name' => self::DATA_NAME,
    259288            ],
     
    292321     */
    293322    public function print_inline_styles(): void {
    294         $css = <<<CSS
     323        /* language=CSS */
     324        $css = '
    295325    span[data-name="hcap-cf7"] .h-captcha {
    296326        margin-bottom: 0;
     
    301331        margin-top: 2rem;
    302332    }
    303 CSS;
     333';
    304334
    305335        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/CoBlocks/Form.php

    r3114572 r3248039  
    203203     */
    204204    public function print_inline_styles(): void {
    205         $css = <<<CSS
     205        /* language=CSS */
     206        $css = '
    206207    .wp-block-coblocks-form .h-captcha {
    207208        margin-bottom: 25px;
    208209    }
    209 CSS;
     210';
    210211
    211212        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ColorlibCustomizer/Base.php

    r3114572 r3248039  
    1111
    1212/**
    13  * Class Login
     13 * Class Base
    1414 */
    1515abstract class Base {
     
    6565
    6666        if ( 'normal' === $hcaptcha_size ) {
    67             $css = <<<CSS
     67            /* language=CSS */
     68            $css = '
    6869    .ml-container #login {
    6970        min-width: 350px;
    7071    }
    71 CSS;
     72';
    7273        }
    7374
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ColorlibCustomizer/Login.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #loginform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ColorlibCustomizer/LostPassword.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #lostpasswordform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ColorlibCustomizer/Register.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #registerform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/DelayedScript/DelayedScript.php

    r3215681 r3248039  
    1919     *
    2020     * @param string $js    js code to wrap in setTimeout().
    21      * @param int    $delay Delay in ms. Negative means no delay, just wait for user interaction.
     21     * @param int    $delay Delay in ms. Negative means no delay, wait for user interaction.
    2222     *
    2323     * @return string
     
    2525     */
    2626    public static function create( string $js, int $delay = -1 ): string {
    27         $js = <<<JS
     27        /* language=JS */
     28        $js = "
    2829    ( () => {
    2930        'use strict';
     
    7576        } );
    7677    } )();
    77 JS;
     78";
    7879
    7980        return "<script>\n" . HCaptcha::js_minify( $js ) . "\n</script>\n";
     
    8485     *
    8586     * @param array $args  Arguments.
    86      * @param int   $delay Delay in ms. Negative means no delay, just wait for user interaction.
     87     * @param int   $delay Delay in ms. Negative means no delay, wait for user interaction.
    8788     */
    8889    public static function launch( array $args, int $delay = -1 ): void {
    8990        unset( $args['id'], $args['async'] );
    9091
    91         $js = <<<JS
     92        /* language=JS */
     93        $js = "
    9294            const t = document.getElementsByTagName( 'script' )[0];
    9395            const s = document.createElement( 'script' );
    9496            s.type  = 'text/javascript';
    9597            s.id = 'hcaptcha-api';
    96 JS;
     98";
    9799
    98         $js = "$js\n";
     100        $js = trim( $js, " \n\r" );
    99101
    100102        // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     
    107109            }
    108110
    109             $js .= "\t\t\ts['$key'] = '$arg';\n";
     111            $js .= "\n\t\t\ts['$key'] = '$arg';";
    110112        }
    111113
    112         $js .= <<<JS
     114        /* language=JS */
     115        $js .= '
    113116            s.async = true;
    114117            t.parentNode.insertBefore( s, t );
    115 JS;
     118';
     119
     120        $js = trim( $js, " \n\r" );
    116121
    117122        echo self::create( $js, $delay );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/DownloadManager/DownloadManager.php

    r3185570 r3248039  
    119119     */
    120120    public function print_inline_styles(): void {
    121         $css = <<<CSS
     121        /* language=CSS */
     122        $css = '
    122123    .wpdm-button-area + .h-captcha {
    123124        margin-bottom: 1rem;
     
    128129        color: #fff !important;
    129130    }
    130 CSS;
     131';
    131132
    132133        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ElementorPro/HCaptchaHandler.php

    r3185570 r3248039  
    498498     */
    499499    public function print_inline_styles(): void {
    500         $css = <<<CSS
     500        /* language=CSS */
     501        $css = '
    501502    .elementor-field-type-hcaptcha .elementor-field {
    502503        background: transparent !important;
     
    506507        margin-bottom: unset;
    507508    }
    508 CSS;
     509';
    509510
    510511        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ElementorPro/Login.php

    r3129246 r3248039  
    107107     */
    108108    public function print_inline_styles(): void {
    109         $css = <<<CSS
     109        /* language=CSS */
     110        $css = '
    110111    .elementor-widget-login .h-captcha {
    111112        margin-bottom: 0;
    112113    }
    113 CSS;
     114';
    114115
    115116        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/EssentialAddons/Register.php

    r3185570 r3248039  
    9090     */
    9191    public function print_inline_styles(): void {
    92         $css = <<<CSS
     92        /* language=CSS */
     93        $css = '
    9394    #eael-register-form .h-captcha {
    9495        margin-top: 1rem;
    9596        margin-bottom: 0;
    9697    }
    97 CSS;
     98';
    9899
    99100        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/EssentialBlocks/Form.php

    r3114572 r3248039  
    124124     */
    125125    public function print_inline_styles(): void {
    126         $css = <<<CSS
     126        /* language=CSS */
     127        $css = '
    127128    .wp-block-essential-blocks-form .h-captcha {
    128129        margin: 15px 0 0 0;
    129130    }
    130 CSS;
     131';
    131132
    132133        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/FluentForm/Form.php

    r3185570 r3248039  
    1515use FluentForm\App\Models\Form as FluentForm;
    1616use FluentForm\App\Modules\Form\FormFieldsParser;
     17use FluentForm\Framework\Helpers\ArrayHelper;
     18use HCaptcha\Abstracts\LoginBase;
    1719use HCaptcha\Helpers\HCaptcha;
    1820use HCaptcha\Main;
     
    2123/**
    2224 * Class Form
     25 *
     26 * Can be used as a login form also.
    2327 */
    24 class Form {
     28class Form extends LoginBase {
    2529
    2630    /**
    2731     * Nonce action.
    2832     */
    29     private const ACTION = 'hcaptcha_fluentform';
     33    protected const ACTION = 'hcaptcha_fluentform';
    3034
    3135    /**
    3236     * Nonce name.
    3337     */
    34     private const NONCE = 'hcaptcha_fluentform_nonce';
     38    protected const NONCE = 'hcaptcha_fluentform_nonce';
    3539
    3640    /**
     
    5761
    5862    /**
    59      * Constructor.
    60      */
    61     public function __construct() {
    62         $this->init_hooks();
    63     }
    64 
    65     /**
    6663     * Init hooks.
    6764     *
    6865     * @return void
    6966     */
    70     private function init_hooks(): void {
     67    protected function init_hooks(): void {
    7168        add_filter( 'fluentform/rendering_field_html_hcaptcha', [ $this, 'render_field_hcaptcha' ], 10, 3 );
    7269        add_action( 'fluentform/render_item_submit_button', [ $this, 'add_hcaptcha' ], 9, 2 );
     
    131128     */
    132129    public function verify( array $errors, array $data, FluentForm $form, array $fields ): array {
     130        if ( $this->is_login_form( $form ) ) {
     131            $email    = (string) ArrayHelper::get( $data, 'email' );
     132            $password = (string) ArrayHelper::get( $data, 'password' );
     133            $user     = get_user_by( 'email', $email );
     134
     135            if ( $user && wp_check_password( $password, $user->user_pass, $user->ID ) ) {
     136                $this->login( $email, $user );
     137            } else {
     138                $this->login_failed( $email );
     139            }
     140
     141            if ( ! $this->is_login_limit_exceeded() ) {
     142                return $errors;
     143            }
     144
     145            wp_send_json(
     146                __( 'Login failed. Please reload the page.', 'hcaptcha-for-forms-and-more' ),
     147                423
     148            );
     149
     150            // For testing purposes.
     151            return $errors;
     152        }
     153
    133154        remove_filter( 'pre_http_request', [ $this, 'pre_http_request' ] );
    134155
     
    202223        wp_deregister_script( $fluent_forms_conversational_script );
    203224
    204         $form = $this->get_captcha();
     225        $form = $this->get_hcaptcha();
    205226        $form = str_replace(
    206227            [
     
    307328    public function fluentform_has_hcaptcha(): bool {
    308329        add_filter( 'pre_http_request', [ $this, 'pre_http_request' ], 10, 3 );
     330
    309331        return false;
    310332    }
     
    349371     */
    350372    public function print_inline_styles(): void {
    351         $css = <<<CSS
     373        /* language=CSS */
     374        $css = '
    352375    .frm-fluent-form .h-captcha {
    353376        line-height: 0;
    354377        margin-bottom: 0;
    355378    }
    356 CSS;
     379';
    357380
    358381        HCaptcha::css_display( $css );
     
    368391     */
    369392    protected function has_own_hcaptcha( $form ): bool {
    370         FormFieldsParser::resetData();
    371 
    372         if ( FormFieldsParser::hasElement( $form, 'hcaptcha' ) ) {
    373             return true;
    374         }
    375 
    376         return false;
     393        return $this->has_element( $form, 'hcaptcha' );
    377394    }
    378395
     
    382399     * @return string
    383400     */
    384     private function get_captcha(): string {
     401    protected function get_hcaptcha(): string {
     402        $form = FluentForm::find( $this->form_id );
     403
     404        if ( $this->is_login_form( $form ) && ! $this->is_login_limit_exceeded() ) {
     405            return '';
     406        }
     407
    385408        $args = [
    386409            'action' => self::ACTION,
     
    396419
    397420    /**
     421     * Whether the form is a login form.
     422     *
     423     * @param FluentForm|stdClass $form Form.
     424     *
     425     * @return bool
     426     */
     427    private function is_login_form( $form ): bool {
     428
     429        return (
     430            has_action( 'fluentform/before_insert_submission' ) &&
     431            $this->has_element( $form, 'input_email' ) &&
     432            $this->has_element( $form, 'input_password' )
     433        );
     434    }
     435
     436    /**
     437     * Whether the form has an element.
     438     *
     439     * @param FluentForm|stdClass $form         Form.
     440     * @param string              $element_name Element name.
     441     *
     442     * @return bool
     443     */
     444    private function has_element( $form, string $element_name ): bool {
     445        FormFieldsParser::resetData();
     446
     447        return FormFieldsParser::hasElement( $form, $element_name );
     448    }
     449
     450    /**
    398451     * Get hCaptcha wrapped as Fluent Forms field.
    399452     *
     
    403456        ob_start();
    404457
     458        /* language=HTML */
    405459        ?>
    406460        <div class="ff-el-group">
     
    409463                    <?php
    410464                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    411                     echo $this->get_captcha();
     465                    echo $this->get_hcaptcha();
    412466                    ?>
    413467                </div>
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/GravityForms/Form.php

    r3233179 r3248039  
    252252     */
    253253    public function print_inline_styles(): void {
    254         $css = <<<CSS
     254        /* language=CSS */
     255        $css = '
    255256    .gform_previous_button + .h-captcha {
    256257        margin-top: 2rem;
     
    285286        margin: 1em 0 0 0 !important;
    286287    }
    287 CSS;
     288';
    288289
    289290        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/HTMLForms/Form.php

    r3114572 r3248039  
    197197     */
    198198    public function print_inline_styles(): void {
    199         $css = <<<CSS
     199        /* language=CSS */
     200        $css = '
    200201    #form-preview .h-captcha {
    201202        margin-bottom: 2rem;
     
    205206        margin-top: 2rem;
    206207    }
    207 CSS;
     208';
    208209
    209210        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Helpers/HCaptcha.php

    r3233179 r3248039  
    405405     */
    406406    public static function css_display( string $css, bool $wrap = true ): void {
     407        $css = trim( $css, " \n\r" );
     408
    407409        if ( $wrap ) {
    408410            echo "<style>\n";
     
    425427     */
    426428    public static function css_minify( string $css ): string {
     429        $css = trim( $css, " \n\r" );
     430
    427431        if ( defined( 'SCRIPT_DEBUG' ) && constant( 'SCRIPT_DEBUG' ) ) {
    428432            return $css;
     
    446450     */
    447451    public static function js_display( string $js, bool $wrap = true ): void {
     452        $js = trim( $js, " \n\r" );
     453
    448454        if ( $wrap ) {
    449455            echo "<script>\n";
     
    466472     */
    467473    public static function js_minify( string $js ): string {
     474        $js = trim( $js, " \n\r" );
     475
    468476        if ( defined( 'SCRIPT_DEBUG' ) && constant( 'SCRIPT_DEBUG' ) ) {
    469477            return $js;
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Jetpack/Base.php

    r3215681 r3248039  
    143143        }
    144144
    145         $message = <<< HTML
     145        $message = '
    146146<div class="contact-form__input-error">
    147147    <span class="contact-form__warning-icon">
     
    149149        <i aria-hidden="true"></i>
    150150    </span>
    151     <span>$this->error_message</span>
     151    <span>' . $this->error_message . '</span>
    152152</div>
    153 HTML;
     153';
    154154
    155155        return $hcaptcha . $message;
     
    201201     */
    202202    public function print_inline_styles(): void {
    203         $css = <<<CSS
     203        /* language=CSS */
     204        $css = '
    204205    form.contact-form .grunion-field-hcaptcha-wrap.grunion-field-wrap {
    205206        flex-direction: row !important;
     
    210211        margin-bottom: 0;
    211212    }
    212 CSS;
     213';
    213214
    214215        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/LearnDash/Register.php

    r3215681 r3248039  
    107107     */
    108108    public function print_inline_styles(): void {
    109         $css = <<<CSS
     109        /* language=CSS */
     110        $css = '
    110111    #learndash_registerform .h-captcha {
    111112        margin-bottom: 0;
    112113    }
    113 CSS;
     114';
    114115
    115116        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/LoginSignupPopup/Login.php

    r3114572 r3248039  
    120120     */
    121121    public function print_inline_styles(): void {
    122         $css = <<<CSS
     122        /* language=CSS */
     123        $css = '
    123124    .xoo-el-form-container div[data-section="login"] .h-captcha {
    124125        margin-bottom: 25px;
    125126    }
    126 CSS;
     127';
    127128
    128129        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/LoginSignupPopup/Register.php

    r3114572 r3248039  
    141141     */
    142142    public function print_inline_styles(): void {
    143         $css = <<<CSS
     143        /* language=CSS */
     144        $css = '
    144145    .xoo-el-form-container div[data-section="register"] .h-captcha {
    145146        margin-bottom: 25px;
    146147    }
    147 CSS;
     148';
    148149
    149150        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Main.php

    r3233179 r3248039  
    2020use HCaptcha\CACSP\Compatibility;
    2121use HCaptcha\CF7\CF7;
     22use HCaptcha\CF7\ReallySimpleCaptcha;
    2223use HCaptcha\DelayedScript\DelayedScript;
    2324use HCaptcha\Divi\Fix;
     
    190191
    191192        add_action( 'plugins_loaded', [ $this, 'load_modules' ], self::LOAD_PRIORITY + 1 );
    192         add_filter( 'hcap_whitelist_ip', [ $this, 'whitelist_ip' ], -PHP_INT_MAX, 2 );
     193        add_filter( 'hcap_whitelist_ip', [ $this, 'allowlist_ip' ], -PHP_INT_MAX, 2 );
    193194        add_action( 'before_woocommerce_init', [ $this, 'declare_wc_compatibility' ] );
    194195
     
    252253         * Do not load hCaptcha functionality:
    253254         * - if a user is logged in and the option 'off_when_logged_in' is set;
    254          * - for whitelisted IPs;
     255         * - for allowlisted IPs;
    255256         * - when the site key or the secret key is empty (after first plugin activation).
    256257         */
     
    258259            ( is_user_logged_in() && $settings->is_on( 'off_when_logged_in' ) ) ||
    259260            /**
    260              * Filters the user IP to check whether it is whitelisted.
     261             * Filters the user IP to check whether it is allowlisted.
    261262             *
    262              * @param bool         $whitelisted IP is whitelisted.
     263             * @param bool         $allowlisted IP is allowlisted.
    263264             * @param string|false $ip          IP string or false for local addresses.
    264265             */
     
    438439     * @return void
    439440     * @noinspection CssUnusedSymbol
     441     * @noinspection CssUnknownTarget
    440442     */
    441443    public function print_inline_styles(): void {
     
    445447        $bg                 = $settings->get_custom_theme_background() ?: 'initial';
    446448
    447         $css = <<<CSS
     449        /* language=CSS */
     450        $css = '
    448451    .h-captcha {
    449452        position: relative;
     
    469472
    470473    .h-captcha::before {
    471         content: '';
     474        content: \'\';
    472475        display: block;
    473476        position: absolute;
    474477        top: 0;
    475478        left: 0;
    476         background: url( $div_logo_url ) no-repeat;
     479        background: url( ' . $div_logo_url . ' ) no-repeat;
    477480        border: 1px solid transparent;
    478481        border-radius: 4px;
     
    502505    html.wp-dark-mode-active .h-captcha[data-theme="auto"]::before,
    503506    html.drdt-dark-mode .h-captcha[data-theme="auto"]::before {
    504         background-image: url( $div_logo_white_url );
     507        background-image: url( ' . $div_logo_white_url . ' );
    505508        background-repeat: no-repeat;
    506509        background-color: #333;
     
    509512
    510513    .h-captcha[data-theme="custom"]::before {
    511         background-color: $bg;
     514        background-color: ' . $bg . ';
    512515    }
    513516
     
    523526        border-style: none;
    524527    }
    525 CSS;
     528';
    526529
    527530        HCaptcha::css_display( $css );
     
    535538     */
    536539    public function login_head(): void {
    537         $css = <<<'CSS'
     540        /* language=CSS */
     541        $css = '
    538542    @media (max-width: 349px) {
    539543        .h-captcha {
     
    553557        }
    554558    }
    555 CSS;
     559';
    556560
    557561        HCaptcha::css_display( $css );
     
    588592        $host = preg_replace( '#(http|https)://#', '', $host );
    589593
    590         // We need to add scheme here, otherwise wp_parse_url returns null.
     594        // We need to add a scheme here, otherwise wp_parse_url returns null.
    591595        $host = (string) wp_parse_url( 'https://' . $host, PHP_URL_HOST );
    592596
     
    753757        // @codeCoverageIgnoreStart
    754758        if ( class_exists( FeaturesUtil::class ) ) {
    755             FeaturesUtil::declare_compatibility( 'custom_order_tables', constant( 'HCAPTCHA_FILE' ), true );
     759            FeaturesUtil::declare_compatibility( 'custom_order_tables', constant( 'HCAPTCHA_FILE' ) );
    756760        }
    757761        // @codeCoverageIgnoreEnd
     
    759763
    760764    /**
    761      * Filter user IP to check if it is whitelisted.
    762      * For whitelisted IPs, hCaptcha will not be shown.
    763      *
    764      * @param bool|mixed   $whitelisted Whether IP is whitelisted.
     765     * Filter user IP to check if it is allowlisted.
     766     * For allowlisted IPs, hCaptcha will not be shown.
     767     *
     768     * @param bool|mixed   $allowlisted Whether IP is allowlisted.
    765769     * @param string|false $client_ip   Client IP.
    766770     *
    767771     * @return bool|mixed
    768772     */
    769     public function whitelist_ip( $whitelisted, $client_ip ) {
     773    public function allowlist_ip( $allowlisted, $client_ip ) {
    770774        $ips = explode(
    771775            "\n",
     
    802806        }
    803807
    804         return $whitelisted;
     808        return $allowlisted;
    805809    }
    806810
     
    973977                [ 'cf7_status', null ],
    974978                'contact-form-7/wp-contact-form-7.php',
    975                 [ CF7::class, Admin::class ],
     979                [ CF7::class, Admin::class, ReallySimpleCaptcha::class ],
    976980            ],
    977981            'Cookies and Content Security Policy'  => [
     
    14911495    /**
    14921496     * Is plugin active.
    1493      * When network wide activated, check if the plugin is network active.
     1497     * When network is widely activated, check if the plugin is network active.
    14941498     *
    14951499     * @param string $plugin_name Plugin name.
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Maintenance/Login.php

    r3200161 r3248039  
    122122     */
    123123    public function print_inline_styles(): void {
    124         $css = <<<CSS
     124        /* language=CSS */
     125        $css = '
    125126    body.maintenance > .login-form-container {
    126127        min-width: 343px;
     
    136137        margin-top: 2em;
    137138    }
    138 CSS;
     139';
    139140
    140141        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Migrations/Migrations.php

    r3166267 r3248039  
    88namespace HCaptcha\Migrations;
    99
     10use ActionScheduler;
     11use ActionScheduler_Store;
    1012use HCaptcha\Admin\Events\Events;
    1113use HCaptcha\Settings\PluginSettingsBase;
     
    3739
    3840    /**
     41     * Migration completed status.
     42     */
     43    public const COMPLETED = - 3;
     44
     45    /**
    3946     * Priority of the plugins_loaded action to load Migrations.
    4047     */
     
    4552     */
    4653    private const PLUGIN_NAME = 'hCaptcha Plugin';
     54
     55    /**
     56     * Action Scheduler group name.
     57     */
     58    private const AS_GROUP = 'hcaptcha';
    4759
    4860    /**
     
    5870     * @return void
    5971     */
    60     public function init(): void {
     72    private function init(): void {
    6173        if ( ! $this->is_allowed() ) {
    6274            return;
     
    7385    private function init_hooks(): void {
    7486        add_action( 'plugins_loaded', [ $this, 'migrate' ], self::LOAD_PRIORITY );
     87        add_action( 'plugins_loaded', [ $this, 'load_action_scheduler' ], -10 );
     88
     89        add_action( 'async_migrate_4_11_0', [ $this, 'async_migrate_4_11_0' ] );
     90    }
     91
     92    /**
     93     * Load action scheduler.
     94     *
     95     * @return void
     96     */
     97    public function load_action_scheduler(): void {
     98        require_once HCAPTCHA_PATH . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
    7599    }
    76100
     
    88112            get_class_methods( $this ),
    89113            static function ( $migration ) {
    90                 return false !== strpos( $migration, 'migrate_' );
     114                return 0 === strpos( $migration, 'migrate_' );
    91115            }
    92116        );
     
    141165     * Determine if migration is allowed.
    142166     */
    143     public function is_allowed(): bool {
     167    private function is_allowed(): bool {
    144168        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    145169        if ( isset( $_GET['service-worker'] ) ) {
     
    148172
    149173        return (
    150             ( is_admin() && ! wp_doing_ajax() ) ||
     174            is_admin() ||
    151175            wp_doing_cron() ||
    152176            ( defined( 'WP_CLI' ) && constant( 'WP_CLI' ) )
     
    317341        }
    318342
    319         update_option( PluginSettingsBase::OPTION_NAME, $new_options );
     343        // This two lines is a precaution for a case if options in a new format already exist.
     344        $options = get_option( PluginSettingsBase::OPTION_NAME, [] );
     345        $options = array_merge( $new_options, $options );
     346
     347        update_option( PluginSettingsBase::OPTION_NAME, $options );
    320348
    321349        foreach ( array_keys( $options_map ) as $old_option_name ) {
     
    384412
    385413    /**
     414     * Migrate to 4.11.0
     415     *
     416     * @return bool|null
     417     * @noinspection PhpUnused
     418     */
     419    protected function migrate_4_11_0(): ?bool {
     420        return $this->run_async( __FUNCTION__ );
     421    }
     422
     423    /**
     424     * Async migration to 4.11.0.
     425     *
     426     * @return void
     427     */
     428    public function async_migrate_4_11_0(): void {
     429        global $wpdb;
     430
     431        $table_name = $wpdb->prefix . Events::TABLE_NAME;
     432
     433        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     434        // phpcs:disable WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     435        $result = $wpdb->query(
     436            "CREATE INDEX idx_date_source_form
     437                    ON $table_name
     438                    (date_gmt, source, form_id)"
     439        );
     440
     441        if ( $result ) {
     442            $wpdb->query( "DROP INDEX hcaptcha_id on $table_name" );
     443        }
     444        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     445        // phpcs:enable WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     446
     447        $this->mark_completed();
     448    }
     449
     450    /**
    386451     * Save license level in settings.
    387452     *
     
    404469        update_option( PluginSettingsBase::OPTION_NAME, $option );
    405470    }
     471
     472    /**
     473     * Run async action.
     474     *
     475     * @param string $method Method name.
     476     * @param array  $args   Arguments.
     477     *
     478     * @return bool|null
     479     * @noinspection PhpSameParameterValueInspection
     480     */
     481    private function run_async( string $method, array $args = [] ): ?bool {
     482        $hook      = 'async_' . $method;
     483        $group     = self::AS_GROUP;
     484        $transient = $group . '_' . $hook;
     485
     486        $status = (int) get_transient( $transient );
     487
     488        if ( self::COMPLETED === $status ) {
     489            delete_transient( $transient );
     490
     491            return true;
     492        }
     493
     494        if ( ! $status ) {
     495            set_transient( $transient, self::STARTED );
     496        }
     497
     498        add_action(
     499            'action_scheduler_init',
     500            function () use ( $hook, $args, $group ) {
     501                $transient = $group . '_' . $hook;
     502                $status    = $this->create_as_action( $hook, $args, $group );
     503
     504                if ( self::FAILED === $status ) {
     505                    set_transient( $transient, $status );
     506                }
     507            }
     508        );
     509
     510        return null;
     511    }
     512
     513    /**
     514     * Create an AS action.
     515     *
     516     * @param string $hook  Hook name.
     517     * @param array  $args  Hook arguments.
     518     * @param string $group Group name.
     519     *
     520     * @return int Started or failed.
     521     */
     522    private function create_as_action( string $hook, array $args, string $group ): int {
     523        $actions = as_get_scheduled_actions(
     524            [
     525                'hook'   => $hook,
     526                'args'   => $args,
     527                'group'  => $group,
     528                'status' => [ // All statuses except completed.
     529                    ActionScheduler_Store::STATUS_PENDING,
     530                    ActionScheduler_Store::STATUS_RUNNING,
     531                    ActionScheduler_Store::STATUS_FAILED,
     532                    ActionScheduler_Store::STATUS_CANCELED,
     533                ],
     534            ]
     535        );
     536
     537        if ( empty( $actions ) ) {
     538            // Plan the unique action.
     539            $action_id = as_enqueue_async_action( $hook, $args, $group, true );
     540
     541            return $action_id ? self::STARTED : self::FAILED;
     542        }
     543
     544        // Get the last action status.
     545        $last_action_id = max( array_map( 'intval', array_keys( $actions ) ) );
     546        $store          = ActionScheduler::store();
     547        $status         = $store ? $store->get_status( $last_action_id ) : ActionScheduler_Store::STATUS_FAILED;
     548
     549        $started = in_array(
     550            $status,
     551            [
     552                ActionScheduler_Store::STATUS_PENDING,
     553                ActionScheduler_Store::STATUS_RUNNING,
     554            ],
     555            true
     556        );
     557
     558        return $started ? self::STARTED : self::FAILED;
     559    }
     560
     561    /**
     562     * Mark async migration as completed.
     563     *
     564     * @return void
     565     */
     566    private function mark_completed(): void {
     567        $hook      = current_action();
     568        $group     = self::AS_GROUP;
     569        $transient = $group . '_' . $hook;
     570
     571        set_transient( $transient, self::COMPLETED );
     572    }
    406573}
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Passster/Protect.php

    r3185570 r3248039  
    165165     */
    166166    public function print_inline_styles(): void {
    167         $css = <<<CSS
     167        /* language=CSS */
     168        $css = '
    168169    .passster-form .h-captcha {
    169170        margin-bottom: 5px;
    170171    }
    171 CSS;
     172';
    172173
    173174        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/ProfileBuilder/Login.php

    r3233179 r3248039  
    8686     */
    8787    public function print_inline_styles(): void {
    88         $css = <<<CSS
     88        /* language=CSS */
     89        $css = '
    8990    #wppb-loginform .h-captcha {
    9091        margin-bottom: 14px;
    9192    }
    92 CSS;
     93';
    9394
    9495        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/Abstracts/SettingsBase.php

    r3185570 r3248039  
    892892        }
    893893
    894         register_setting( $this->option_group(), $this->option_name() );
     894        $args = [
     895            'sanitize_callback' => [ $this, 'sanitize_option_callback' ],
     896        ];
     897
     898        register_setting( $this->option_group(), $this->option_name(), $args );
    895899
    896900        /**
     
    913917            );
    914918        }
     919    }
     920
     921    /**
     922     * Filters an option value following sanitization.
     923     *
     924     * @param array|mixed $value The sanitized option value.
     925     *
     926     * @return array
     927     */
     928    public function sanitize_option_callback( $value ): array {
     929        // Remove unexpected settings.
     930        $settings = array_intersect_key( (array) $value, $this->form_fields() );
     931
     932        foreach ( $settings as $key => $setting ) {
     933            $type = $this->form_fields[ $key ]['type'];
     934
     935            switch ( $type ) {
     936                case 'checkbox':
     937                    $settings[ $key ] = array_map( 'sanitize_text_field', $setting );
     938                    break;
     939                case 'textarea':
     940                    $settings[ $key ] = wp_kses_post( $setting );
     941                    break;
     942                default:
     943                    $settings[ $key ] = sanitize_text_field( $setting );
     944            }
     945        }
     946
     947        return $settings;
    915948    }
    916949
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/EventsPage.php

    r3233179 r3248039  
    88namespace HCaptcha\Settings;
    99
     10use HCaptcha\Admin\Events\Events;
    1011use HCaptcha\Admin\Events\EventsTable;
    1112use HCaptcha\Helpers\DB;
     
    5657
    5758    /**
    58      * Init class hooks.
    59      */
    60     protected function init_hooks(): void {
    61         parent::init_hooks();
    62 
    63         add_action( 'wp_ajax_' . self::BULK_ACTION, [ $this, 'bulk_action' ] );
    64     }
    65 
    66     /**
    6759     * Get page title.
    6860     *
     
    108100
    109101        $this->prepare_chart_data();
    110     }
    111 
    112     /**
    113      * Ajax callback for bulk actions.
    114      *
    115      * @return void
    116      */
    117     public function bulk_action(): void {
    118         $this->run_checks( self::BULK_ACTION );
    119 
    120         // Nonce is checked by check_ajax_referer() in run_checks().
    121         // phpcs:disable WordPress.Security.NonceVerification.Missing
    122         $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
    123         $ids  = isset( $_POST['ids'] )
    124             ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
    125             : [];
    126         // phpcs:enable WordPress.Security.NonceVerification.Missing
    127 
    128         if ( 'trash' === $bulk ) {
    129             if ( ! $this->delete_hcaptcha_events( $ids ) ) {
    130                 wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
    131             }
    132 
    133             wp_send_json_success();
    134 
    135             // For testing purposes.
    136             return;
    137         }
    138 
    139         wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
    140102    }
    141103
     
    174136                'bulkAction'   => self::BULK_ACTION,
    175137                'bulkNonce'    => wp_create_nonce( self::BULK_ACTION ),
     138                'bulkMessage'  => $this->get_clean_transient(),
    176139                'succeed'      => $this->succeed,
    177140                'failed'       => $this->failed,
     
    282245     * Delete hCaptcha events by IDs.
    283246     *
    284      * @param array $ids Array of event IDs to delete.
     247     * @param array $args Arguments.
    285248     *
    286249     * @return bool
    287250     */
    288     private function delete_hcaptcha_events( array $ids ): bool {
     251    protected function delete_events( array $args ): bool {
    289252        global $wpdb;
    290253
    291         $table_name = $wpdb->prefix . 'hcaptcha_events';
    292 
    293         $in = DB::prepare_in( $ids, '%d' );
     254        $ids = $args['ids'] ?? [];
     255
     256        $table_name = $wpdb->prefix . Events::TABLE_NAME;
     257        $in         = DB::prepare_in( $ids, '%d' );
    294258
    295259        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/FormsPage.php

    r3233179 r3248039  
    88namespace HCaptcha\Settings;
    99
     10use HCaptcha\Admin\Events\Events;
    1011use HCaptcha\Admin\Events\FormsTable;
    1112use KAGG\Settings\Abstracts\SettingsBase;
     
    4849
    4950    /**
    50      * Init class hooks.
    51      */
    52     protected function init_hooks(): void {
    53         parent::init_hooks();
    54 
    55         add_action( 'wp_ajax_' . self::BULK_ACTION, [ $this, 'bulk_action' ] );
    56     }
    57 
    58     /**
    5951     * Get page title.
    6052     *
     
    9890
    9991        $this->prepare_chart_data();
    100     }
    101 
    102     /**
    103      * Ajax callback for bulk actions.
    104      *
    105      * @return void
    106      */
    107     public function bulk_action(): void {
    108         $this->run_checks( self::BULK_ACTION );
    109 
    110         // Nonce is checked by check_ajax_referer() in run_checks().
    111         // phpcs:disable WordPress.Security.NonceVerification.Missing
    112         $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
    113         $ids  = isset( $_POST['ids'] )
    114             ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
    115             : [];
    116         // phpcs:enable WordPress.Security.NonceVerification.Missing
    117 
    118         if ( 'trash' === $bulk ) {
    119             if ( ! $this->delete_hcaptcha_events_by_forms( $ids ) ) {
    120                 wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
    121             }
    122 
    123             wp_send_json_success();
    124 
    125             // For testing purposes.
    126             return;
    127         }
    128 
    129         wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
    13092    }
    13193
     
    164126                'bulkAction'  => self::BULK_ACTION,
    165127                'bulkNonce'   => wp_create_nonce( self::BULK_ACTION ),
     128                'bulkMessage' => $this->get_clean_transient(),
    166129                'served'      => $this->served,
    167130                'servedLabel' => __( 'Served', 'hcaptcha-for-forms-and-more' ),
     
    219182                </p>
    220183            </canvas>
     184                <?php
     185                if ( count( $this->list_table->served ) >= Events::SERVED_LIMIT ) {
     186                    echo '<div id="hcaptcha-chart-message">';
     187                    printf(
     188                    /* translators: 1: Number of elements. */
     189                        esc_html__( 'The chart is limited to displaying a maximum of %1$s elements.', 'hcaptcha-for-forms-and-more' ),
     190                        esc_html( number_format_i18n( Events::SERVED_LIMIT ) )
     191                    );
     192                    echo '</div>';
     193                }
     194                ?>
    221195        </div>
    222196        <div id="hcaptcha-forms-wrap">
     
    257231     * Delete hCaptcha events by forms.
    258232     *
    259      * @param array $ids Array of event IDs to delete.
     233     * @param array $args Arguments.
    260234     *
    261235     * @return bool
    262236     */
    263     private function delete_hcaptcha_events_by_forms( array $ids ): bool {
     237    protected function delete_events( array $args ): bool {
    264238        global $wpdb;
    265239
    266         $table_name = $wpdb->prefix . 'hcaptcha_events';
     240        $ids   = $args['ids'] ?? [];
     241        $dates = $args['dates'] ?? [];
     242        $dates = $dates ?: Events::get_default_dates();
     243        $dates = Events::prepare_gmt_dates( $dates );
     244
     245        $table_name = $wpdb->prefix . Events::TABLE_NAME;
    267246        $conditions = [];
    268247        $values     = [];
    269248
     249        if ( ! $ids ) {
     250            return false;
     251        }
     252
    270253        foreach ( $ids as $item ) {
    271             $conditions[] = '(source = %s AND form_id = %d)';
     254            $conditions[] = '(source = %s AND form_id = %s)';
    272255            $values[]     = $item['source'];
    273256            $values[]     = $item['formId'];
     
    275258
    276259        $where_clause = implode( ' OR ', $conditions );
     260        $where_clause = "($where_clause) AND date_gmt BETWEEN %s AND %s";
    277261
    278262        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     
    281265            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
    282266                "DELETE FROM $table_name WHERE $where_clause",
    283                 ...$values
     267                ...$values,
     268                ...$dates
    284269            )
    285270        );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/General.php

    r3233179 r3248039  
    535535            ],
    536536            'whitelisted_ips'      => [
    537                 'label'   => __( 'Whitelisted IPs', 'hcaptcha-for-forms-and-more' ),
     537                'label'   => __( 'Allowlisted IPs', 'hcaptcha-for-forms-and-more' ),
    538538                'type'    => 'textarea',
    539539                'section' => self::SECTION_OTHER,
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/Integrations.php

    r3233179 r3248039  
    1616use WP_Filesystem_Base;
    1717use WP_Theme;
    18 use WP_Upgrader;
    1918
    2019/**
     
    300299                'type'    => 'checkbox',
    301300                'options' => [
    302                     'form'  => __( 'Form Auto-Add', 'hcaptcha-for-forms-and-more' ),
    303                     'embed' => __( 'Form Embed', 'hcaptcha-for-forms-and-more' ),
    304                     'live'  => __( 'Live Form in Admin', 'hcaptcha-for-forms-and-more' ),
     301                    'form'        => __( 'Form Auto-Add', 'hcaptcha-for-forms-and-more' ),
     302                    'embed'       => __( 'Form Embed', 'hcaptcha-for-forms-and-more' ),
     303                    'live'        => __( 'Live Form in Admin', 'hcaptcha-for-forms-and-more' ),
     304                    'replace_rsc' => __( 'Replace Really Simple CAPTCHA', 'hcaptcha-for-forms-and-more' ),
    305305                ],
    306306            ],
     
    12481248     */
    12491249    protected function maybe_activate_plugin( string $plugin ) {
    1250 
    12511250        if ( hcaptcha()->is_plugin_active( $plugin ) ) {
    12521251            return true;
     
    12661265
    12671266        ob_start();
    1268 
    12691267        $result = $this->activate_plugin( $plugin );
    1270 
    12711268        ob_end_clean();
    12721269
     
    12821279     */
    12831280    protected function install_plugin( string $plugin ): ?WP_Error {
    1284 
    12851281        $plugin = trim( explode( '/', $plugin )[0] );
    12861282
     
    12961292        }
    12971293
    1298         require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    1299         require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
     1294        if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
     1295            // @codeCoverageIgnoreStart
     1296            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     1297            require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
     1298            // @codeCoverageIgnoreEnd
     1299        }
    13001300
    13011301        $api = plugins_api(
     
    14571457     * @param string $theme Theme to activate.
    14581458     *
    1459      * @return null|WP_Error Null on success, WP_Error on failure.
    1460      */
    1461     protected function activate_theme( string $theme ): ?WP_Error {
    1462         if ( ! wp_get_theme( $theme )->exists() ) {
    1463             return new WP_Error(
    1464                 'theme_not_found',
    1465                 __( 'Theme not found.', 'hcaptcha-for-forms-and-more' )
    1466             );
     1459     * @return null|true|WP_Error Null on success, WP_Error on failure.
     1460     */
     1461    protected function activate_theme( string $theme ) {
     1462        if ( wp_get_theme()->get_stylesheet() === $theme ) {
     1463            return true;
    14671464        }
    14681465
     
    14931490     * @return null|WP_Error Null on success, WP_Error on failure.
    14941491     */
    1495     private function install_theme( string $theme ): ?WP_Error {
     1492    protected function install_theme( string $theme ): ?WP_Error {
    14961493        $theme = trim( $theme );
    14971494
     
    15101507        }
    15111508
    1512         require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    1513         require_once ABSPATH . 'wp-admin/includes/theme.php';
     1509        if ( ! class_exists( 'Theme_Upgrader', false ) ) {
     1510            // @codeCoverageIgnoreStart
     1511            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     1512            require_once ABSPATH . 'wp-admin/includes/theme.php';
     1513            // @codeCoverageIgnoreEnd
     1514        }
    15141515
    15151516        $api = themes_api(
     
    15221523
    15231524        if ( is_wp_error( $api ) ) {
    1524             return new WP_Error( $api->get_error_code(), $api->get_error_message() );
     1525            return $api;
    15251526        }
    15261527
     
    16111612     *
    16121613     * @return string
    1613      * @noinspection PhpVoidFunctionResultUsedInspection
    16141614     */
    16151615    protected function get_default_theme(): string {
     
    16781678     * Install entity (plugin or theme).
    16791679     *
    1680      * @param WP_Upgrader          $upgrader      Upgrader instance.
    1681      * @param WP_Ajax_Upgrader_Skin $skin          Upgrader skin instance.
    1682      * @param string                $download_link Download link.
     1680     * @param Plugin_Upgrader|Theme_Upgrader|object $upgrader      Upgrader instance.
     1681     * @param WP_Ajax_Upgrader_Skin|object          $skin          Upgrader skin instance.
     1682     * @param string                                $download_link Download link.
    16831683     *
    16841684     * @return WP_Error|null
    1685      * @noinspection PhpPossiblePolymorphicInvocationInspection
    1686      */
    1687     protected function install_entity( WP_Upgrader $upgrader, WP_Ajax_Upgrader_Skin $skin, string $download_link ): ?WP_Error {
     1685     */
     1686    protected function install_entity( object $upgrader, object $skin, string $download_link ): ?WP_Error {
    16881687        $result = $upgrader->install( $download_link );
    16891688
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/ListPageBase.php

    r3233179 r3248039  
    5050
    5151    /**
     52     * Transient name where to store a page bulk action message.
     53     */
     54    protected const TRANSIENT = 'hcaptcha_page_base';
     55
     56    /**
    5257     * Default date format.
    5358     */
     
    5560
    5661    /**
     62     * Bulk ajax action.
     63     * Must be overridden in child classes.
     64     * Here is for testing purposes.
     65     */
     66    public const BULK_ACTION = '';
     67
     68    /**
    5769     * Chart time unit.
    5870     *
     
    6779     */
    6880    protected $allowed = false;
     81
     82    /**
     83     * Delete hCaptcha events by IDs.
     84     *
     85     * @param array $args Arguments.
     86     *
     87     * @return bool
     88     */
     89    abstract protected function delete_events( array $args ): bool;
    6990
    7091    /**
     
    7697        add_action( 'admin_init', [ $this, 'admin_init' ] );
    7798        add_action( 'kagg_settings_header', [ $this, 'date_picker_display' ] );
     99        add_action( 'wp_ajax_' . static::BULK_ACTION, [ $this, 'bulk_action' ] );
    78100    }
    79101
     
    259281
    260282    /**
     283     * Ajax callback for bulk actions.
     284     *
     285     * @return void
     286     */
     287    public function bulk_action(): void {
     288        $this->run_checks( static::BULK_ACTION );
     289
     290        // Nonce is checked by check_ajax_referer() in run_checks().
     291        // phpcs:disable WordPress.Security.NonceVerification.Missing
     292        $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
     293        $ids  = isset( $_POST['ids'] )
     294            ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
     295            : [];
     296        $date = isset( $_POST['date'] )
     297            // We need filter_input here to keep the delimiter intact.
     298            ? filter_input( INPUT_POST, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
     299            : '';
     300        // phpcs:enable WordPress.Security.NonceVerification.Missing
     301
     302        $dates = explode( self::TIMESPAN_DELIMITER, $date );
     303        $dates = array_filter( array_map( 'trim', $dates ) );
     304
     305        if ( 'trash' === $bulk ) {
     306            $args = [
     307                'ids'   => $ids,
     308                'dates' => $dates,
     309            ];
     310
     311            if ( ! $this->delete_events( $args ) ) {
     312                wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
     313
     314                // For testing purposes.
     315                return;
     316            }
     317
     318            set_transient(
     319                self::TRANSIENT,
     320                __( 'Selected items have been successfully deleted.', 'hcaptcha-for-forms-and-more' )
     321            );
     322
     323            wp_send_json_success();
     324
     325            // For testing purposes.
     326            return;
     327        }
     328
     329        wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
     330    }
     331
     332    /**
     333     * Get and clean the transient.
     334     *
     335     * @return string
     336     */
     337    protected function get_clean_transient(): string {
     338        $bulk_message = (string) get_transient( self::TRANSIENT );
     339
     340        if ( $bulk_message ) {
     341            delete_transient( self::TRANSIENT );
     342        }
     343
     344        return $bulk_message;
     345    }
     346
     347    /**
    261348     * Sets the timespan (or date range) for performing mysql queries.
    262349     *
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/Settings.php

    r3200161 r3248039  
    77
    88// phpcs:ignore Generic.Commenting.DocComment.MissingShort
    9 /** @noinspection ContractViolationInspection */
    109
    1110namespace HCaptcha\Settings;
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Settings/SystemInfo.php

    r3114572 r3248039  
    187187        $data .= $this->data( 'Turn Off When Logged In', $this->is_on( 'off_when_logged_in' ) );
    188188        $data .= $this->data( 'Disable reCAPTCHA Compatibility', $this->is_on( 'recaptcha_compat_off' ) );
    189         $data .= $this->data( 'Whitelisted IPs', $this->is_empty( $settings->get( 'whitelisted_ips' ) ) );
     189        $data .= $this->data( 'Allowlisted IPs', $this->is_empty( $settings->get( 'whitelisted_ips' ) ) );
    190190        $data .= $this->data( 'Login attempts before hCaptcha', $settings->get( 'login_limit' ) );
    191191        $data .= $this->data( 'Failed login attempts interval, min', $settings->get( 'login_interval' ) );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/SimpleMembership/Login.php

    r3166267 r3248039  
    9797     */
    9898    public function print_inline_styles(): void {
    99         $css = <<<CSS
     99        /* language=CSS */
     100        $css = '
    100101    #swpm-login-form .h-captcha {
    101102        margin: 10px 0;
    102103    }
    103 CSS;
     104';
    104105
    105106        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/SimpleMembership/LostPassword.php

    r3166267 r3248039  
    9898     */
    9999    public function print_inline_styles(): void {
    100         $css = <<<CSS
     100        /* language=CSS */
     101        $css = '
    101102    #swpm-pw-reset-form .h-captcha {
    102103        margin: 10px 0;
    103104    }
    104 CSS;
     105';
    105106
    106107        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/SimpleMembership/Register.php

    r3166267 r3248039  
    9898     */
    9999    public function print_inline_styles(): void {
    100         $css = <<<CSS
     100        /* language=CSS */
     101        $css = '
    101102    #swpm-registration-form .h-captcha {
    102103        margin: 10px 0;
    103104    }
    104 CSS;
     105';
    105106
    106107        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Spectra/Form.php

    r3143189 r3248039  
    155155        $style_shown = true;
    156156
    157         $css = <<<CSS
     157        /* language=CSS */
     158        $css = '
    158159    .uagb-forms-main-form .h-captcha {
    159160        margin-bottom: 20px;
    160161    }
    161 CSS;
     162';
    162163
    163164        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/SupportCandy/Base.php

    r3114572 r3248039  
    140140        $style_shown = true;
    141141
    142         $css = <<<CSS
     142        /* language=CSS */
     143        $css = '
    143144    form.wpsc-create-ticket .h-captcha {
    144145        margin: 0 15px 15px 15px;
    145146    }
    146 CSS;
     147';
    147148
    148149        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/UsersWP/Register.php

    r3114572 r3248039  
    8080        $template = (string) ob_get_clean();
    8181
    82         ob_start();
    83 
    84         $args = [
     82        $args     = [
    8583            'action' => static::ACTION,
    8684            'name'   => static::NONCE,
     
    9088            ],
    9189        ];
    92 
    93         HCaptcha::form_display( $args );
    94 
    95         $captcha = (string) ob_get_clean();
    96         $search  = '<input type="submit"';
     90        $hcaptcha = HCaptcha::form( $args );
     91        $search   = '/(<(?:input|button) type="submit")/';
    9792
    9893        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    99         echo str_replace( $search, $captcha . $search, $template );
     94        echo preg_replace( $search, $hcaptcha . '$1', $template );
    10095    }
    10196
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WC/Login.php

    r3114572 r3248039  
    7171     */
    7272    public function print_inline_styles(): void {
    73         $css = <<<CSS
     73        /* language=CSS */
     74        $css = '
    7475    .woocommerce-form-login .h-captcha {
    7576        margin-top: 2rem;
    7677    }
    77 CSS;
     78';
    7879
    7980        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WC/LostPassword.php

    r3114572 r3248039  
    6060     */
    6161    public function print_inline_styles(): void {
    62         $css = <<<CSS
     62        /* language=CSS */
     63        $css = '
    6364    .woocommerce-ResetPassword .h-captcha {
    6465        margin-top: 0.5rem;
    6566    }
    66 CSS;
     67';
    6768
    6869        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WC/Register.php

    r3114572 r3248039  
    9494     */
    9595    public function print_inline_styles(): void {
    96         $css = <<<CSS
     96        /* language=CSS */
     97        $css = '
    9798    .woocommerce-form-register .h-captcha {
    9899        margin-top: 2rem;
    99100    }
    100 CSS;
     101';
    101102
    102103        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WP/Base.php

    r3129246 r3248039  
    2323     *
    2424     * @return string
     25     * @noinspection PhpUndefinedFunctionInspection
    2526     */
    2627    private function get_login_url(): string {
     
    2829            // Integration with WPS Hide Login plugin.
    2930            return wp_parse_url( Plugin::get_instance()->new_login_url(), PHP_URL_PATH );
     31        }
     32
     33        if ( function_exists( 'perfmatters_login_url' ) ) {
     34            // Integration with Perfmatters plugin.
     35            return wp_parse_url( perfmatters_login_url(), PHP_URL_PATH );
    3036        }
    3137
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WP/Comment.php

    r3233179 r3248039  
    115115        $comment_data = (array) $comment_data;
    116116
    117         if ( is_admin() ) {
     117        if ( is_admin() || wp_doing_ajax() ) {
    118118            return $comment_data;
    119119        }
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WPDiscuz/Comment.php

    r3129246 r3248039  
    138138     */
    139139    public function print_inline_styles(): void {
    140         $css = <<<CSS
     140        /* language=CSS */
     141        $css = '
    141142    .wpd-field-hcaptcha .h-captcha {
    142143        margin-left: auto;
    143144    }
    144 CSS;
     145';
    145146
    146147        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WPDiscuz/Subscribe.php

    r3114572 r3248039  
    7979     */
    8080    public function print_inline_styles(): void {
    81         $css = <<<CSS
     81        /* language=CSS */
     82        $css = '
    8283    #wpdiscuz-subscribe-form .h-captcha {
    8384        margin-top: 5px;
    8485        margin-left: auto;
    8586    }
    86 CSS;
     87';
    8788
    8889        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WPForms/Form.php

    r3233179 r3248039  
    126126     */
    127127    public function print_inline_styles(): void {
    128         $css = <<<CSS
     128        /* language=CSS */
     129        $css = '
    129130    div.wpforms-container-full .wpforms-form .h-captcha {
    130131        position: relative;
     
    152153        position: relative;
    153154    }
    154 CSS;
     155';
    155156
    156157        HCaptcha::css_display( $css );
     
    197198
    198199        if ( isset( $fields['hcaptcha-heading'] ) ) {
    199             $notice_content = <<<HTML
     200            $notice_content = '
    200201<div
    201202        id="wpforms-setting-row-hcaptcha-heading"
     
    209210            </div>
    210211            <div class="wpforms-specific-note-content">
    211                 <p><strong>$label</strong></p>
    212                 <p>$description</p>
     212                <p><strong>' . $label . '</strong></p>
     213                <p>' . $description . '</p>
    213214            </div>
    214215        </div>
    215216    </span>
    216217</div>
    217 HTML;
     218';
    218219
    219220            $fields['hcaptcha-heading'] .= $notice_content;
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/WPForo/Base.php

    r3114572 r3248039  
    129129        $style_shown = true;
    130130
    131         $css = <<<CSS
     131        /* language=CSS */
     132        $css = '
    132133    #wpforo #wpforo-wrap div .h-captcha {
    133134        position: relative;
     
    142143        margin: 0 -20px;
    143144    }
    144 CSS;
     145';
    145146
    146147        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/Wordfence/General.php

    r3129246 r3248039  
    8585     */
    8686    public function print_inline_styles(): void {
    87         $css = <<<CSS
    88 #loginform[style="position: relative;"] > .h-captcha {
    89     visibility: hidden !important;
    90 }
    91 CSS;
     87        /* language=CSS */
     88        $css = '
     89    #loginform[style="position: relative;"] > .h-captcha {
     90        visibility: hidden !important;
     91    }
     92';
    9293
    9394        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/tags/4.11.0/src/php/includes/request.php

    r3233179 r3248039  
    320320}
    321321
    322 if ( ! function_exists( 'hcaptcha_get_verify_output' ) ) {
    323     /**
    324      * Get verify output.
    325      *
    326      * @param string $empty_message     Empty message.
    327      * @param string $fail_message      Fail message.
     322if ( ! function_exists( 'hcaptcha_get_verify_message' ) ) {
     323    /**
     324     * Get 'verify' message.
     325     *
    328326     * @param string $nonce_field_name  Nonce field name.
    329327     * @param string $nonce_action_name Nonce action name.
    330328     *
    331      * @deprecated 4.7.0
    332      *
    333329     * @return null|string Null on success, error message on failure.
    334330     */
    335     function hcaptcha_get_verify_output( string $empty_message, string $fail_message, string $nonce_field_name, string $nonce_action_name ): ?string {
    336         _deprecated_function( __FUNCTION__, '4.7.0', 'hcaptcha_verify_post' );
    337 
    338         if ( ! empty( $empty_message ) || ! empty( $fail_message ) ) {
    339             // @codeCoverageIgnoreStart
    340             _deprecated_argument( __FUNCTION__, '2.1.0' );
    341             // @codeCoverageIgnoreEnd
    342         }
    343 
     331    function hcaptcha_get_verify_message( string $nonce_field_name, string $nonce_action_name ): ?string {
    344332        return hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
    345333    }
    346334}
    347335
    348 if ( ! function_exists( 'hcaptcha_get_verify_message' ) ) {
    349     /**
    350      * Get 'verify' message.
     336if ( ! function_exists( 'hcaptcha_get_verify_message_html' ) ) {
     337    /**
     338     * Get verify message HTML.
    351339     *
    352340     * @param string $nonce_field_name  Nonce field name.
     
    355343     * @return null|string Null on success, error message on failure.
    356344     */
    357     function hcaptcha_get_verify_message( string $nonce_field_name, string $nonce_action_name ): ?string {
    358         return hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
    359     }
    360 }
    361 
    362 if ( ! function_exists( 'hcaptcha_get_verify_message_html' ) ) {
    363     /**
    364      * Get verify message HTML.
    365      *
    366      * @param string $nonce_field_name  Nonce field name.
    367      * @param string $nonce_action_name Nonce action name.
    368      *
    369      * @return null|string Null on success, error message on failure.
    370      */
    371345    function hcaptcha_get_verify_message_html( string $nonce_field_name, string $nonce_action_name ): ?string {
    372346        $message = hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/autoload.php

    r3233179 r3248039  
    2323require_once __DIR__ . '/composer/autoload_real.php';
    2424
    25 return ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18::getLoader();
     25return ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e::getLoader();
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/composer/autoload_classmap.php

    r3233179 r3248039  
    4141    'HCaptcha\\CF7\\Base' => $baseDir . '/src/php/CF7/Base.php',
    4242    'HCaptcha\\CF7\\CF7' => $baseDir . '/src/php/CF7/CF7.php',
     43    'HCaptcha\\CF7\\ReallySimpleCaptcha' => $baseDir . '/src/php/CF7/ReallySimpleCaptcha.php',
    4344    'HCaptcha\\ClassifiedListing\\Contact' => $baseDir . '/src/php/ClassifiedListing/Contact.php',
    4445    'HCaptcha\\ClassifiedListing\\Login' => $baseDir . '/src/php/ClassifiedListing/Login.php',
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/composer/autoload_real.php

    r3233179 r3248039  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18
     5class ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e
    66{
    77    private static $loader;
     
    2323        }
    2424
    25         spl_autoload_register(array('ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18', 'loadClassLoader'), true, true);
     25        require __DIR__ . '/platform_check.php';
     26
     27        spl_autoload_register(array('ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e', 'loadClassLoader'), true, true);
    2628        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    27         spl_autoload_unregister(array('ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e', 'loadClassLoader'));
    2830
    2931        require __DIR__ . '/autoload_static.php';
    30         call_user_func(\Composer\Autoload\ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::getInitializer($loader));
    3133
    3234        $loader->setClassMapAuthoritative(true);
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/composer/autoload_static.php

    r3233179 r3248039  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18
     7class ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e
    88{
    99    public static $prefixLengthsPsr4 = array (
     
    6969        'HCaptcha\\CF7\\Base' => __DIR__ . '/../..' . '/src/php/CF7/Base.php',
    7070        'HCaptcha\\CF7\\CF7' => __DIR__ . '/../..' . '/src/php/CF7/CF7.php',
     71        'HCaptcha\\CF7\\ReallySimpleCaptcha' => __DIR__ . '/../..' . '/src/php/CF7/ReallySimpleCaptcha.php',
    7172        'HCaptcha\\ClassifiedListing\\Contact' => __DIR__ . '/../..' . '/src/php/ClassifiedListing/Contact.php',
    7273        'HCaptcha\\ClassifiedListing\\Login' => __DIR__ . '/../..' . '/src/php/ClassifiedListing/Login.php',
     
    216217    {
    217218        return \Closure::bind(function () use ($loader) {
    218             $loader->prefixLengthsPsr4 = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$prefixLengthsPsr4;
    219             $loader->prefixDirsPsr4 = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$prefixDirsPsr4;
    220             $loader->classMap = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$classMap;
     219            $loader->prefixLengthsPsr4 = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$prefixLengthsPsr4;
     220            $loader->prefixDirsPsr4 = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$prefixDirsPsr4;
     221            $loader->classMap = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$classMap;
    221222
    222223        }, null, ClassLoader::class);
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/composer/installed.json

    r3064004 r3248039  
    130130            },
    131131            "install-path": "../matthiasmullie/path-converter"
     132        },
     133        {
     134            "name": "woocommerce/action-scheduler",
     135            "version": "3.9.2",
     136            "version_normalized": "3.9.2.0",
     137            "source": {
     138                "type": "git",
     139                "url": "https://github.com/woocommerce/action-scheduler.git",
     140                "reference": "efbb7953f72a433086335b249292f280dd43ddfe"
     141            },
     142            "dist": {
     143                "type": "zip",
     144                "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/efbb7953f72a433086335b249292f280dd43ddfe",
     145                "reference": "efbb7953f72a433086335b249292f280dd43ddfe",
     146                "shasum": ""
     147            },
     148            "require": {
     149                "php": ">=7.1"
     150            },
     151            "require-dev": {
     152                "phpunit/phpunit": "^7.5",
     153                "woocommerce/woocommerce-sniffs": "0.1.0",
     154                "wp-cli/wp-cli": "~2.5.0",
     155                "yoast/phpunit-polyfills": "^2.0"
     156            },
     157            "time": "2025-02-03T09:09:30+00:00",
     158            "type": "wordpress-plugin",
     159            "extra": {
     160                "scripts-description": {
     161                    "test": "Run unit tests",
     162                    "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
     163                    "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier"
     164                }
     165            },
     166            "installation-source": "dist",
     167            "notification-url": "https://packagist.org/downloads/",
     168            "license": [
     169                "GPL-3.0-or-later"
     170            ],
     171            "description": "Action Scheduler for WordPress and WooCommerce",
     172            "homepage": "https://actionscheduler.org/",
     173            "support": {
     174                "issues": "https://github.com/woocommerce/action-scheduler/issues",
     175                "source": "https://github.com/woocommerce/action-scheduler/tree/3.9.2"
     176            },
     177            "install-path": "../woocommerce/action-scheduler"
    132178        }
    133179    ],
  • hcaptcha-for-forms-and-more/tags/4.11.0/vendor/composer/installed.php

    r3233179 r3248039  
    22    'root' => array(
    33        'name' => 'hcaptcha/hcaptcha-wordpress-plugin',
    4         'pretty_version' => '4.10.0',
    5         'version' => '4.10.0.0',
    6         'reference' => '3f3d675e6a0c12404a0a7aa20b4472b5d37ea88d',
     4        'pretty_version' => '4.11.0',
     5        'version' => '4.11.0.0',
     6        'reference' => '83b1b3615b255290d2a5050750f078835392d129',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1212    'versions' => array(
    1313        'hcaptcha/hcaptcha-wordpress-plugin' => array(
    14             'pretty_version' => '4.10.0',
    15             'version' => '4.10.0.0',
    16             'reference' => '3f3d675e6a0c12404a0a7aa20b4472b5d37ea88d',
     14            'pretty_version' => '4.11.0',
     15            'version' => '4.11.0.0',
     16            'reference' => '83b1b3615b255290d2a5050750f078835392d129',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
     
    3838            'dev_requirement' => false,
    3939        ),
     40        'woocommerce/action-scheduler' => array(
     41            'pretty_version' => '3.9.2',
     42            'version' => '3.9.2.0',
     43            'reference' => 'efbb7953f72a433086335b249292f280dd43ddfe',
     44            'type' => 'wordpress-plugin',
     45            'install_path' => __DIR__ . '/../woocommerce/action-scheduler',
     46            'aliases' => array(),
     47            'dev_requirement' => false,
     48        ),
    4049    ),
    4150);
  • hcaptcha-for-forms-and-more/trunk/assets/css/forms.css

    r3233179 r3248039  
    4545}
    4646
     47#hcaptcha-chart-message {
     48    padding: 5px 10px;
     49    border: 1px solid #c3c4c7;
     50    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
     51    color: #50575e;
     52    background-color: #f6f7f7;
     53    text-align: center;
     54}
     55
    4756@media (max-width: 782px) {
    4857    #hcaptcha-options #hcaptcha-forms-wrap table tbody tr td {
  • hcaptcha-for-forms-and-more/trunk/assets/css/forms.min.css

    r3233179 r3248039  
    1 #hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{padding:8px 10px}.hcaptcha-forms-sample-bg{aspect-ratio:2845/1637;background-image:url(../images/forms-page.png);background-position:50%;background-repeat:no-repeat;background-size:cover;box-sizing:border-box;filter:blur(1px);-webkit-filter:blur(1px);width:100%}.hcaptcha-forms-sample-text{background-color:rgba(92,111,138,.8);border:3px solid #f0f2f5;color:#f0f2f5;left:50%;padding:20px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);width:80%;z-index:1}.hcaptcha-forms-sample-text p{font-size:1.3em}#hcaptcha-options .hcaptcha-forms-sample-text p a{color:#f0f2f5}#hcaptcha-forms-chart{aspect-ratio:3/1;background-color:#fff;margin:auto;position:relative;width:100%}@media (max-width:782px){#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{min-height:19.5px;padding-block-end:3px;padding-block-start:3px;padding-inline-end:8px;padding-inline-start:35%}#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td.column-primary{padding:3px 10px}}
     1#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{padding:8px 10px}.hcaptcha-forms-sample-bg{aspect-ratio:2845/1637;background-image:url(../images/forms-page.png);background-position:50%;background-repeat:no-repeat;background-size:cover;box-sizing:border-box;filter:blur(1px);-webkit-filter:blur(1px);width:100%}.hcaptcha-forms-sample-text{background-color:rgba(92,111,138,.8);border:3px solid #f0f2f5;color:#f0f2f5;left:50%;padding:20px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);width:80%;z-index:1}.hcaptcha-forms-sample-text p{font-size:1.3em}#hcaptcha-options .hcaptcha-forms-sample-text p a{color:#f0f2f5}#hcaptcha-forms-chart{aspect-ratio:3/1;background-color:#fff;margin:auto;position:relative;width:100%}#hcaptcha-chart-message{background-color:#f6f7f7;border:1px solid #c3c4c7;box-shadow:0 1px 1px rgba(0,0,0,.04);color:#50575e;padding:5px 10px;text-align:center}@media (max-width:782px){#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td{min-height:19.5px;padding-block-end:3px;padding-block-start:3px;padding-inline-end:8px;padding-inline-start:35%}#hcaptcha-options #hcaptcha-forms-wrap table tbody tr td.column-primary{padding:3px 10px}}
  • hcaptcha-for-forms-and-more/trunk/assets/css/settings-base.css

    r3233179 r3248039  
    3838    margin-inline-end: 30px;
    3939    color: #646970;
    40     border-bottom: 2px solid transparent;
    4140}
    4241
  • hcaptcha-for-forms-and-more/trunk/assets/css/settings-base.min.css

    r3233179 r3248039  
    1 body.settings_page_hcaptcha{background:#f0f2f5;color:#5c6f8a}.wrap h1.hcaptcha-settings-header{align-items:center;display:flex;font-size:34px;font-weight:700}.hcaptcha-logo{height:64px;margin-block-end:10px;margin-block-start:10px;margin-inline-end:5px;margin-inline-start:0}.hcaptcha-settings-tabs{background:#fff;display:flex;flex-wrap:wrap;justify-content:space-between;line-height:4.5em;margin:10px -20px 0;padding:0 20px;position:sticky;top:0;z-index:2}.hcaptcha-settings-tab{border-bottom:2px solid transparent;color:#646970;display:inline-block;font-size:1.1em;margin-inline-end:30px;text-decoration:none}.hcaptcha-settings-tab:hover{border-bottom-color:#025176!important;border-bottom:2px solid;color:#666}.hcaptcha-settings-tab.active{border-bottom:2px solid #0075ab}.hcaptcha-header-bar{align-items:center;background:#f0f2f5;display:flex;justify-content:space-between;margin:0 -20px;padding:0 20px;position:sticky;top:60px;z-index:2}#hcaptcha-options h2{color:#5c6f8a;font-size:1.5em}#hcaptcha-options h2~*{display:none}#hcaptcha-options h3{color:#5c6f8a;margin:1.5em 0 1em}#hcaptcha-options .notice-dismiss:before{color:#5c6f8a}#hcaptcha-options table tbody tr td{margin:0;padding:0;position:relative}#hcaptcha-options table tr td fieldset input[type=checkbox]{border:none;box-shadow:none;display:inline;height:1.25rem;margin-block-end:0;margin-block-start:-.125rem;margin-inline-end:.5rem;margin-inline-start:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:before{background:url(../images/checkbox-off.svg);background-size:cover;content:"";display:inline-block;height:1.25rem;margin:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:checked:before{background:no-repeat url(../images/checkbox-on.svg);background-size:cover}#hcaptcha-options fieldset:disabled{color:#dadada}#hcaptcha-options .button-primary{background-color:#026593;border-color:#026593;color:#fff}#hcaptcha-options .button-primary:hover{background-color:#025176}#hcaptcha-options .button-secondary{background-color:#fff;border-color:#026593;color:#026593}#hcaptcha-options .button-secondary:hover{background-color:#ccc}#hcaptcha-options a{color:#0075ab}#hcaptcha-navigation a{border-color:#0075ab}#hcaptcha-options a.hcaptcha-settings-tab{color:#5c6f8a}#hcaptcha-options .helper:before{background:#5c6f8a;border-radius:1.2em;color:#fff;content:"?";height:1.2em;inset-inline-end:0;position:absolute;text-align:center;top:0;transform:translateY(-27px);width:1.2em}#hcaptcha-options fieldset+.helper:before{top:50%;transform:translate(25px,-.7em)}.rtl #hcaptcha-options fieldset+.helper:before{transform:translate(-25px,-.8em)}#hcaptcha-options .helper .helper-content{background:#5c6f8a;box-sizing:border-box;color:#f0f2f5;display:none;inset-inline-end:0;padding:.5em 1em;position:absolute;top:0;transform:translate(1px,10px);width:100%}.rtl #hcaptcha-options .helper .helper-content{transform:translate(-1px,10px)}#hcaptcha-options fieldset+.helper .helper-content{top:50%;transform:translate(25px,25px);width:calc(100% + 25px)}#hcaptcha-options .helper:hover{cursor:help}#hcaptcha-options .helper:hover .helper-content{display:block;z-index:1}#hcaptcha-options .helper .helper-content:after{border:10px solid transparent;border-bottom-color:#5c6f8a;content:"";inset-inline-end:0;position:absolute;top:0;transform:translateY(-100%)}#hcaptcha-options .helper .helper-content a{color:#fff}#hcaptcha-message{box-sizing:border-box}#hcaptcha-message>p{font-size:13px;font-weight:600;line-height:1.5;margin:.5em 0}@keyframes blink{0%{opacity:1}16.7%{opacity:0}33.3%{opacity:1}50%{opacity:0}66.7%{opacity:1}83.3%{opacity:0}to{opacity:1}}.blink{animation:blink 3s linear}.hcaptcha-hide{display:none}.hcaptcha-excerpt{display:block;max-width:100%;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:max-content}.hcaptcha-excerpt:hover{overflow:visible}.hcaptcha-excerpt:hover .hcaptcha-hide{background:#5c6f8a;border:1px solid #c3c4c7;border-radius:6px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);color:#f0f2f5;display:block;inset-inline-start:50%;max-width:300px;padding:8px 10px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);white-space:normal;width:max-content;z-index:1}@media (max-width:782px){#hcaptcha-options .wp-list-table .toggle-row{top:15px}#hcaptcha-options .wp-list-table tr.is-expanded .toggle-row{top:6.5px}#hcaptcha-options .widefat tbody th.check-column{padding:0;vertical-align:middle}#hcaptcha-options .widefat thead td.check-column,.widefat tfoot td.check-column{padding-left:0}#hcaptcha-options .widefat th input[type=checkbox]{margin-bottom:0}#hcaptcha-options .wp-list-table .is-expanded td:not(.hidden){overflow:visible}.hcaptcha-settings-tabs{margin:unset;margin-block-end:0;margin-block-start:10px;margin-inline-end:-12px;margin-inline-start:-10px;padding-block-end:0;padding-block-start:0;padding-inline-end:12px;padding-inline-start:10px}.hcaptcha-excerpt{display:table-cell;height:44px;vertical-align:middle}tr.is-expanded .hcaptcha-excerpt{height:19.5px}}@media (max-width:600px){#hcaptcha-options table tbody{grid-template-columns:1fr}#hcaptcha-options table tbody tr{position:relative}#hcaptcha-options fieldset+.helper:before{transform:translateY(-.7em)}#hcaptcha-options fieldset+.helper .helper-content{transform:translateY(25px);width:100%}#hcaptcha-options .helper{z-index:1}.hcaptcha-settings-tab{inset-inline-end:15px}}
     1body.settings_page_hcaptcha{background:#f0f2f5;color:#5c6f8a}.wrap h1.hcaptcha-settings-header{align-items:center;display:flex;font-size:34px;font-weight:700}.hcaptcha-logo{height:64px;margin-block-end:10px;margin-block-start:10px;margin-inline-end:5px;margin-inline-start:0}.hcaptcha-settings-tabs{background:#fff;display:flex;flex-wrap:wrap;justify-content:space-between;line-height:4.5em;margin:10px -20px 0;padding:0 20px;position:sticky;top:0;z-index:2}.hcaptcha-settings-tab{color:#646970;display:inline-block;font-size:1.1em;margin-inline-end:30px;text-decoration:none}.hcaptcha-settings-tab:hover{border-bottom-color:#025176!important;border-bottom:2px solid;color:#666}.hcaptcha-settings-tab.active{border-bottom:2px solid #0075ab}.hcaptcha-header-bar{align-items:center;background:#f0f2f5;display:flex;justify-content:space-between;margin:0 -20px;padding:0 20px;position:sticky;top:60px;z-index:2}#hcaptcha-options h2{color:#5c6f8a;font-size:1.5em}#hcaptcha-options h2~*{display:none}#hcaptcha-options h3{color:#5c6f8a;margin:1.5em 0 1em}#hcaptcha-options .notice-dismiss:before{color:#5c6f8a}#hcaptcha-options table tbody tr td{margin:0;padding:0;position:relative}#hcaptcha-options table tr td fieldset input[type=checkbox]{border:none;box-shadow:none;display:inline;height:1.25rem;margin-block-end:0;margin-block-start:-.125rem;margin-inline-end:.5rem;margin-inline-start:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:before{background:url(../images/checkbox-off.svg);background-size:cover;content:"";display:inline-block;height:1.25rem;margin:0;width:2.3611rem}#hcaptcha-options table tr td fieldset input[type=checkbox]:checked:before{background:no-repeat url(../images/checkbox-on.svg);background-size:cover}#hcaptcha-options fieldset:disabled{color:#dadada}#hcaptcha-options .button-primary{background-color:#026593;border-color:#026593;color:#fff}#hcaptcha-options .button-primary:hover{background-color:#025176}#hcaptcha-options .button-secondary{background-color:#fff;border-color:#026593;color:#026593}#hcaptcha-options .button-secondary:hover{background-color:#ccc}#hcaptcha-options a{color:#0075ab}#hcaptcha-navigation a{border-color:#0075ab}#hcaptcha-options a.hcaptcha-settings-tab{color:#5c6f8a}#hcaptcha-options .helper:before{background:#5c6f8a;border-radius:1.2em;color:#fff;content:"?";height:1.2em;inset-inline-end:0;position:absolute;text-align:center;top:0;transform:translateY(-27px);width:1.2em}#hcaptcha-options fieldset+.helper:before{top:50%;transform:translate(25px,-.7em)}.rtl #hcaptcha-options fieldset+.helper:before{transform:translate(-25px,-.8em)}#hcaptcha-options .helper .helper-content{background:#5c6f8a;box-sizing:border-box;color:#f0f2f5;display:none;inset-inline-end:0;padding:.5em 1em;position:absolute;top:0;transform:translate(1px,10px);width:100%}.rtl #hcaptcha-options .helper .helper-content{transform:translate(-1px,10px)}#hcaptcha-options fieldset+.helper .helper-content{top:50%;transform:translate(25px,25px);width:calc(100% + 25px)}#hcaptcha-options .helper:hover{cursor:help}#hcaptcha-options .helper:hover .helper-content{display:block;z-index:1}#hcaptcha-options .helper .helper-content:after{border:10px solid transparent;border-bottom-color:#5c6f8a;content:"";inset-inline-end:0;position:absolute;top:0;transform:translateY(-100%)}#hcaptcha-options .helper .helper-content a{color:#fff}#hcaptcha-message{box-sizing:border-box}#hcaptcha-message>p{font-size:13px;font-weight:600;line-height:1.5;margin:.5em 0}@keyframes blink{0%{opacity:1}16.7%{opacity:0}33.3%{opacity:1}50%{opacity:0}66.7%{opacity:1}83.3%{opacity:0}to{opacity:1}}.blink{animation:blink 3s linear}.hcaptcha-hide{display:none}.hcaptcha-excerpt{display:block;max-width:100%;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap;width:max-content}.hcaptcha-excerpt:hover{overflow:visible}.hcaptcha-excerpt:hover .hcaptcha-hide{background:#5c6f8a;border:1px solid #c3c4c7;border-radius:6px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.1);color:#f0f2f5;display:block;inset-inline-start:50%;max-width:300px;padding:8px 10px;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);white-space:normal;width:max-content;z-index:1}@media (max-width:782px){#hcaptcha-options .wp-list-table .toggle-row{top:15px}#hcaptcha-options .wp-list-table tr.is-expanded .toggle-row{top:6.5px}#hcaptcha-options .widefat tbody th.check-column{padding:0;vertical-align:middle}#hcaptcha-options .widefat thead td.check-column,.widefat tfoot td.check-column{padding-left:0}#hcaptcha-options .widefat th input[type=checkbox]{margin-bottom:0}#hcaptcha-options .wp-list-table .is-expanded td:not(.hidden){overflow:visible}.hcaptcha-settings-tabs{margin:unset;margin-block-end:0;margin-block-start:10px;margin-inline-end:-12px;margin-inline-start:-10px;padding-block-end:0;padding-block-start:0;padding-inline-end:12px;padding-inline-start:10px}.hcaptcha-excerpt{display:table-cell;height:44px;vertical-align:middle}tr.is-expanded .hcaptcha-excerpt{height:19.5px}}@media (max-width:600px){#hcaptcha-options table tbody{grid-template-columns:1fr}#hcaptcha-options table tbody tr{position:relative}#hcaptcha-options fieldset+.helper:before{transform:translateY(-.7em)}#hcaptcha-options fieldset+.helper .helper-content{transform:translateY(25px);width:100%}#hcaptcha-options .helper{z-index:1}.hcaptcha-settings-tab{inset-inline-end:15px}}
  • hcaptcha-for-forms-and-more/trunk/assets/js/events.js

    r3233179 r3248039  
    55 * @param HCaptchaEventsObject.bulkAction
    66 * @param HCaptchaEventsObject.bulkNonce
     7 * @param HCaptchaEventsObject.bulkMessage
    78 * @param HCaptchaEventsObject.failed
    89 * @param HCaptchaEventsObject.failedLabel
     
    123124
    124125    initChart();
     126    hCaptchaSettingsBase.showSuccessMessage( HCaptchaEventsObject.bulkMessage );
    125127    document.getElementById( 'doaction' ).addEventListener( 'click', handleBulkAction );
    126128};
  • hcaptcha-for-forms-and-more/trunk/assets/js/events.min.js

    r3233179 r3248039  
    1 (()=>{var e=function(e){var t,a;t=document.getElementById("eventsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaEventsObject.succeedLabel,data:HCaptchaEventsObject.succeed,borderWidth:1},{label:HCaptchaEventsObject.failedLabel,data:HCaptchaEventsObject.failed,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaEventsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),n=s.get("action");if("-1"!==n){var c=s.getAll("bulk-checkbox[]");if(c.length){var o={action:HCaptchaEventsObject.bulkAction,nonce:HCaptchaEventsObject.bulkNonce,bulk:n,ids:JSON.stringify(c)};e.post({url:HCaptchaEventsObject.ajaxUrl,data:o,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
     1(()=>{var e=function(e){var t,a;t=document.getElementById("eventsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaEventsObject.succeedLabel,data:HCaptchaEventsObject.succeed,borderWidth:1},{label:HCaptchaEventsObject.failedLabel,data:HCaptchaEventsObject.failed,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaEventsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),hCaptchaSettingsBase.showSuccessMessage(HCaptchaEventsObject.bulkMessage),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),n=s.get("action");if("-1"!==n){var c=s.getAll("bulk-checkbox[]");if(c.length){var o={action:HCaptchaEventsObject.bulkAction,nonce:HCaptchaEventsObject.bulkNonce,bulk:n,ids:JSON.stringify(c)};e.post({url:HCaptchaEventsObject.ajaxUrl,data:o,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
  • hcaptcha-for-forms-and-more/trunk/assets/js/forms.js

    r3233179 r3248039  
    55 * @param HCaptchaFormsObject.bulkAction
    66 * @param HCaptchaFormsObject.bulkNonce
     7 * @param HCaptchaFormsObject.bulkMessage
    78 * @param HCaptchaFormsObject.served
    89 * @param HCaptchaFormsObject.servedLabel
     
    99100        }
    100101
     102        const datepicker = document.getElementById( 'hcaptcha-datepicker' );
    101103        const data = {
    102104            action: HCaptchaFormsObject.bulkAction,
     
    104106            bulk,
    105107            ids: JSON.stringify( ids ),
     108            date: datepicker?.value ?? '',
    106109        };
    107110
     
    128131
    129132    initChart();
     133    hCaptchaSettingsBase.showSuccessMessage( HCaptchaFormsObject.bulkMessage );
    130134    document.getElementById( 'doaction' ).addEventListener( 'click', handleBulkAction );
    131135};
  • hcaptcha-for-forms-and-more/trunk/assets/js/forms.min.js

    r3233179 r3248039  
    1 (()=>{var e=function(e){var t,a;t=document.getElementById("formsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaFormsObject.servedLabel,backgroundColor:"rgba(2,101,147,0.5)",data:HCaptchaFormsObject.served,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaFormsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),document.getElementById("doaction").addEventListener("click",(function(t){t.preventDefault();var a=t.target.closest("form"),s=new FormData(a),o=s.get("action");if("-1"!==o){var r=s.getAll("bulk-checkbox[]").map((function(e){var t=a.querySelector('input[name="bulk-checkbox[]"][value="'.concat(e,'"]')).closest("tr");return{source:t.querySelector("td.name .hcaptcha-excerpt").dataset.source,formId:t.querySelector("td.form_id").textContent}}));if(r.length){var c={action:HCaptchaFormsObject.bulkAction,nonce:HCaptchaFormsObject.bulkNonce,bulk:o,ids:JSON.stringify(r)};e.post({url:HCaptchaFormsObject.ajaxUrl,data:c,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
     1(()=>{var e=function(e){var t,a;t=document.getElementById("formsChart"),a=window.innerWidth>600?3:2,new Chart(t,{type:"bar",data:{datasets:[{label:HCaptchaFormsObject.servedLabel,backgroundColor:"rgba(2,101,147,0.5)",data:HCaptchaFormsObject.served,borderWidth:1}]},options:{responsive:!0,maintainAspectRatio:!0,aspectRatio:a,scales:{x:{type:"time",time:{displayFormats:{millisecond:"HH:mm:ss",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm",day:"dd.MM.yyyy",week:"dd.MM.yyyy",month:"dd.MM.yyyy",quarter:"dd.MM.yyyy",year:"dd.MM.yyyy"},tooltipFormat:"dd.MM.yyyy HH:mm",unit:HCaptchaFormsObject.unit}},y:{beginAtZero:!0,ticks:{precision:0}}}}}),hCaptchaSettingsBase.showSuccessMessage(HCaptchaFormsObject.bulkMessage),document.getElementById("doaction").addEventListener("click",(function(t){var a;t.preventDefault();var s=t.target.closest("form"),o=new FormData(s),c=o.get("action");if("-1"!==c){var r=o.getAll("bulk-checkbox[]").map((function(e){var t=s.querySelector('input[name="bulk-checkbox[]"][value="'.concat(e,'"]')).closest("tr");return{source:t.querySelector("td.name .hcaptcha-excerpt").dataset.source,formId:t.querySelector("td.form_id").textContent}}));if(r.length){var n=document.getElementById("hcaptcha-datepicker"),i={action:HCaptchaFormsObject.bulkAction,nonce:HCaptchaFormsObject.bulkNonce,bulk:c,ids:JSON.stringify(r),date:null!==(a=null==n?void 0:n.value)&&void 0!==a?a:""};e.post({url:HCaptchaFormsObject.ajaxUrl,data:i,beforeSend:function(){return hCaptchaSettingsBase.showSuccessMessage(HCaptchaListPageBaseObject.DoingBulk)}}).done((function(e){e.success?window.location.reload():hCaptchaSettingsBase.showErrorMessage(e.data)})).fail((function(e){hCaptchaSettingsBase.showErrorMessage(e.statusText)}))}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noItems)}else hCaptchaSettingsBase.showErrorMessage(HCaptchaListPageBaseObject.noAction)}))};window.hCaptchaForms=e,jQuery(document).ready(e)})();
  • hcaptcha-for-forms-and-more/trunk/assets/js/settings-base.js

    r3233179 r3248039  
    136136
    137137    setHeaderBarTop();
    138 
    139138    highLight();
    140139
  • hcaptcha-for-forms-and-more/trunk/assets/js/settings-list-page-base.js

    r3233179 r3248039  
    11/* global HCaptchaListPageBaseObject, flatpickr */
    22
    3 /**
    4  * @param flatpickr.l10ns
    5  */
    6 document.addEventListener( 'DOMContentLoaded', function() {
     3const settingsListPagePage = ( function() {
     4    /**
     5     * @param flatpickr.l10ns
     6     */
     7
    78    /**
    89     * @type {HTMLInputElement}
     
    8788        selectorElement.setAttribute(
    8889            'aria-expanded',
    89             selectorElement.style.display === 'block' ? 'true' : 'false'
     90            selectorElement.style.display === 'block' ? 'true' : 'false',
    9091        );
    9192    }
     
    222223    }
    223224
     225    /**
     226     * Public properties and functions.
     227     */
     228    const app = {};
     229
    224230    bindEvents();
    225231    initFlatPicker();
     232
     233    return app;
    226234} );
     235
     236window.hCaptchaSettingsListPagePage = settingsListPagePage;
     237
     238document.addEventListener( 'DOMContentLoaded', settingsListPagePage );
  • hcaptcha-for-forms-and-more/trunk/assets/js/settings-list-page-base.min.js

    r3233179 r3248039  
    1 (()=>{function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(e){for(var n=1;n<arguments.length;n++){var a=null!=arguments[n]?arguments[n]:{};n%2?t(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function r(t,n,r){return(n=function(t){var n=function(t,n){if("object"!=e(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var a=r.call(t,n||"default");if("object"!=e(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(t)}(t,"string");return"symbol"==e(n)?n:n+""}(n))in t?Object.defineProperty(t,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[n]=r,t}document.addEventListener("DOMContentLoaded",(function(){var e=document.getElementById("hcaptcha-datepicker");if(e){var t,r,a="hcaptcha-is-selected",o=HCaptchaListPageBaseObject.delimiter,c=HCaptchaListPageBaseObject.locale,i=document.getElementById("hcaptcha-options"),l=document.querySelector(".hcaptcha-filter"),u=document.getElementById("hcaptcha-datepicker-popover-button"),p=l.querySelector('input[type="radio"][data-default]');document.addEventListener("click",f),i.querySelector("#hcaptcha-datepicker-popover-button").addEventListener("click",d),i.querySelectorAll('[type="radio"]').forEach((function(e){e.addEventListener("change",v)})),i.querySelector('[type="reset"]').addEventListener("click",b),i.addEventListener("submit",s),i.querySelector("#current-page-selector").addEventListener("keydown",y),r=l.querySelector('input[value="custom"]'),t=flatpickr(e,{mode:"range",inline:!0,allowInput:!1,enableTime:!1,clickOpens:!1,altInput:!0,altFormat:"M j, Y",dateFormat:"Y-m-d",locale:n(n({},flatpickr.l10ns[c]||{}),{},{rangeSeparator:o}),onChange:function(e,t,n){r.checked=!0,m(r.parentElement),t&&(u.textContent=n.altInput.value)}}),v({},r.checked)}function s(t){var n;t.preventDefault(),this.querySelectorAll('input[type="radio"]').forEach((function(e){e.name=""})),(n=u.nextElementSibling).setAttribute("aria-expanded","false"),n.style.display="none";var r=new URL(window.location.href),a=r.searchParams;a.delete("date"),e.value&&a.append("date",e.value),window.location.href=r.toString()}function d(e){e.preventDefault(),e.stopPropagation();var t=e.target.nextElementSibling;"none"===t.style.display||""===t.style.display?t.style.display="block":t.style.display="none",t.setAttribute("aria-expanded","block"===t.style.display?"true":"false")}function y(e){if("Enter"===e.key){e.preventDefault();var t=new URL(window.location.href),n=parseInt(t.searchParams.get("paged")),r=parseInt(e.target.value);(isNaN(n)||n<1)&&(n=1),isNaN(r)||r<1||(t.searchParams.delete("paged"),r!==n&&(t.searchParams.set("paged",r.toString()),window.location.href=t.href))}}function f(e){var t=document.querySelector(".hcaptcha-datepicker-popover");t.contains(e.target)||(t.style.display="none")}function m(e){l.querySelectorAll("label").forEach((function(e){e.classList.remove(a)})),e.classList.add(a)}function b(e){e.preventDefault(),p.checked=!0,v()}function v(){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=l.querySelector("input:checked"),a=r.parentElement,c=n?e:r,i=c.value.split(o),p=c.nextElementSibling;u.textContent=n?p.value:a.textContent,m(a),Array.isArray(i)&&2===i.length?t.setDate(i):t.clear()}}))})();
     1(()=>{function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(e){for(var n=1;n<arguments.length;n++){var a=null!=arguments[n]?arguments[n]:{};n%2?t(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):t(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function r(t,n,r){return(n=function(t){var n=function(t,n){if("object"!=e(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var a=r.call(t,n||"default");if("object"!=e(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(t)}(t,"string");return"symbol"==e(n)?n:n+""}(n))in t?Object.defineProperty(t,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[n]=r,t}var a=function(){var e=document.getElementById("hcaptcha-datepicker");if(e){var t,r,a="hcaptcha-is-selected",o=HCaptchaListPageBaseObject.delimiter,c=HCaptchaListPageBaseObject.locale,i=document.getElementById("hcaptcha-options"),l=document.querySelector(".hcaptcha-filter"),u=document.getElementById("hcaptcha-datepicker-popover-button"),p=l.querySelector('input[type="radio"][data-default]');return document.addEventListener("click",f),i.querySelector("#hcaptcha-datepicker-popover-button").addEventListener("click",d),i.querySelectorAll('[type="radio"]').forEach((function(e){e.addEventListener("change",b)})),i.querySelector('[type="reset"]').addEventListener("click",v),i.addEventListener("submit",s),i.querySelector("#current-page-selector").addEventListener("keydown",y),r=l.querySelector('input[value="custom"]'),t=flatpickr(e,{mode:"range",inline:!0,allowInput:!1,enableTime:!1,clickOpens:!1,altInput:!0,altFormat:"M j, Y",dateFormat:"Y-m-d",locale:n(n({},flatpickr.l10ns[c]||{}),{},{rangeSeparator:o}),onChange:function(e,t,n){r.checked=!0,m(r.parentElement),t&&(u.textContent=n.altInput.value)}}),b({},r.checked),{}}function s(t){var n;t.preventDefault(),this.querySelectorAll('input[type="radio"]').forEach((function(e){e.name=""})),(n=u.nextElementSibling).setAttribute("aria-expanded","false"),n.style.display="none";var r=new URL(window.location.href),a=r.searchParams;a.delete("date"),e.value&&a.append("date",e.value),window.location.href=r.toString()}function d(e){e.preventDefault(),e.stopPropagation();var t=e.target.nextElementSibling;"none"===t.style.display||""===t.style.display?t.style.display="block":t.style.display="none",t.setAttribute("aria-expanded","block"===t.style.display?"true":"false")}function y(e){if("Enter"===e.key){e.preventDefault();var t=new URL(window.location.href),n=parseInt(t.searchParams.get("paged")),r=parseInt(e.target.value);(isNaN(n)||n<1)&&(n=1),isNaN(r)||r<1||(t.searchParams.delete("paged"),r!==n&&(t.searchParams.set("paged",r.toString()),window.location.href=t.href))}}function f(e){var t=document.querySelector(".hcaptcha-datepicker-popover");t.contains(e.target)||(t.style.display="none")}function m(e){l.querySelectorAll("label").forEach((function(e){e.classList.remove(a)})),e.classList.add(a)}function v(e){e.preventDefault(),p.checked=!0,b()}function b(){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=l.querySelector("input:checked"),a=r.parentElement,c=n?e:r,i=c.value.split(o),p=c.nextElementSibling;u.textContent=n?p.value:a.textContent,m(a),Array.isArray(i)&&2===i.length?t.setDate(i):t.clear()}};window.hCaptchaSettingsListPagePage=a,document.addEventListener("DOMContentLoaded",a)})();
  • hcaptcha-for-forms-and-more/trunk/changelog.txt

    r3233179 r3248039  
     1= 4.11.0 =
     2* Added Really Simple CAPTCHA plugin integration.
     3* Added compatibility with the UsersWP plugin v1.2.28.
     4* Added compatibility with Perfmatters plugin.
     5* Added support for the Fluent Login form.
     6* Added confirmation messages upon deletion of events on the Forms and Events pages.
     7* Added asynchronous migrations for large databases.
     8* Added hCaptcha error messages to the Contact Form 7 when JavaScript is disabled.
     9* Optimized Forms page performance for large databases with millions of entries.
     10* Fixed processing wpDiscuz comment form with wpDiscuz custom ajax.
     11* Fixed adding hCaptcha internal fields to Avada from submission.
     12* Fixed ASC ordering by date on the Events page.
     13* Fixed selection of a time interval on the Events page when site local time was not GMT.
     14* Fixed losing options during plugin update in rare cases.
     15* Fixed the live hCaptcha tag on the Contact Form 7 edit page after insertion but before saving the form.
     16* Fixed shortcode processing in the Contact Form 7 form when Auto-Add was off.
     17* Fixed error on theme installation.
     18* Tested with WooCommerce 9.7.
     19
    120= 4.10.0 =
    221* Added support for wp_login_form() function and LoginOut block.
     
    219238* Fixed Content Security Policy headers processing.
    220239
     240= 3.10.1 =
     241* Added filter `hcap_add_csp_headers` to allow adding Content Security Policy headers.
     242* Fixed Content Security Policy headers processing.
     243
    221244= 3.10.0 =
    222245* Tested with WordPress 6.5.
     
    276299* Added optional Enterprise settings.
    277300* Fixed improper display of the "rate plugin" message on options.php.
    278 * Fixed colored border of hCaptcha challenge arrow.
     301* Fixed the colored border of hCaptcha challenge arrow.
    279302
    280303= 3.6.0 =
     
    300323* Added hCaptcha field to Ninja Forms admin editor.
    301324* Added invisible hCaptcha support for Ninja Forms.
    302 * Added the ability to process customized MailChimp forms.
     325* Added the ability to process customized Mailchimp forms.
    303326* Added HTML Forms integration.
    304327* Added the Auto Theme option to follow light/dark theme settings on site.
     
    359382
    360383= 3.3.0 =
    361 * Color scheme in admin UI has been updated.
     384* The color scheme in the admin UI has been updated.
    362385* Added compatibility with Passster.
    363386* Added compatibility with Theme My Login.
  • hcaptcha-for-forms-and-more/trunk/hcaptcha.php

    r3233179 r3248039  
    1111 * Plugin URI:           https://www.hcaptcha.com/
    1212 * Description:          hCaptcha keeps out bots and spam while putting privacy first. It is a drop-in replacement for reCAPTCHA.
    13  * Version:              4.10.0
     13 * Version:              4.11.0
    1414 * Requires at least:    5.3
    1515 * Requires PHP:         7.2
     
    2222 *
    2323 * WC requires at least: 3.0
    24  * WC tested up to:      9.6
     24 * WC tested up to:      9.7
    2525 */
    2626
     
    4040 * Plugin version.
    4141 */
    42 const HCAPTCHA_VERSION = '4.10.0';
     42const HCAPTCHA_VERSION = '4.11.0';
    4343
    4444/**
  • hcaptcha-for-forms-and-more/trunk/readme.txt

    r3233179 r3248039  
    55Tested up to: 6.7
    66Requires PHP: 7.2
    7 Stable tag: 4.10.0
     7Stable tag: 4.11.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    3535* **Logged-in Users:** Optionally turn off hCaptcha for logged-in users.
    3636* **Delayed API Loading:** Load the hCaptcha API instantly or on user interaction for zero page load impact.
    37 * **White List IPs:** Whitelist certain IPs to skip hCaptcha verification.
     37* **Allowlist IPs:** Allowlist certain IPs to skip hCaptcha verification.
    3838* **Multisite Support:** Sync hCaptcha settings across a Multisite Network.
    3939
     
    5959The purpose of a CAPTCHA is to distinguish between people and machines via a challenge-response test, and thus increase the cost of spamming or otherwise abusing websites by keeping out bots.
    6060
    61 To use this plugin, install it and enter your sitekey and secret in the Settings -> hCaptcha menu after signing up on hCaptcha.com.
     61To use this plugin, install it and enter your sitekey and secret in the Settings hCaptcha menu after signing up on hCaptcha.com.
    6262
    6363[hCaptcha Free](https://www.hcaptcha.com/) lets websites block bots and other forms of abuse via humanity challenges.
     
    88881. Install hCaptcha either via the WordPress.org plugin repository (best) or by uploading the files to your server. ([Upload instructions](https://www.wpbeginner.com/beginners-guide/step-by-step-guide-to-install-a-wordpress-plugin-for-beginners/))
    89892. Activate the hCaptcha plugin on the 'Plugins' admin page
    90 3. Enter your site key and secret on the Settings->hCaptcha->General page
    91 4. Enable desired Integrations on the Settings->hCaptcha->Integrations page
     903. Enter your site key and secret on the Settings→hCaptcha→General page
     914. Enable desired Integrations on the Settings→hCaptcha→Integrations page
    9292
    9393== Frequently Asked Questions ==
     
    115115`
    116116
    117 The shortcode adds not only the hCaptcha div to the form, but also a nonce field. You can set your own nonce action and name. For this, use arguments in the shortcode:
     117The shortcode adds not only the hCaptcha div to the form but also a nonce field. You can set your own nonce action and name. For this, use arguments in the shortcode:
    118118
    119119`
     
    398398    }
    399399
    400     // Turn off protection for Gravity form with id = 1.
     400    // Turn off protection for a Gravity form with id = 1.
    401401    return false;
    402402}
     
    449449`
    450450
    451 = How to whitelist certain IPs =
     451= How to allowlist certain IPs =
    452452
    453453You can use the following filter. It should be added to your plugin's (or mu-plugin's) main file. This filter won't work being added to a theme's functions.php file.
     
    455455`
    456456/**
    457  * Filter user IP to check if it is whitelisted.
    458  * For whitelisted IPs, hCaptcha will not be shown.
     457 * Filter user IP to check if it is allowlisted.
     458 * For allowlisted IPs, hCaptcha will not be shown.
    459459 *
    460  * @param bool   $whitelisted Whether IP is whitelisted.
     460 * @param bool   $allowlisted Whether IP is allowlisted.
    461461 * @param string $ip          IP.
    462462 *
    463463 * @return bool
    464464 */
    465 function my_hcap_whitelist_ip( $whitelisted, $ip ) {
    466 
    467   // Whitelist local IPs.
     465function my_hcap_allowlist_ip( $allowlisted, $ip ) {
     466
     467  // Allowlist local IPs.
    468468  if ( false === $ip ) {
    469469    return true;
    470470  }
    471471
    472   // Whitelist some other IPs.
     472  // Allowlist some other IPs.
    473473  if ( '1.1.1.1' === $ip ) {
    474474    return true;
    475475  }
    476476
    477   return $whitelisted;
     477  return $allowlisted;
    478478}
    479479
    480 add_filter( 'hcap_whitelist_ip', 'my_hcap_whitelist_ip', 10, 2 );
     480add_filter( 'hcap_whitelist_ip', 'my_hcap_allowlist_ip', 10, 2 );
    481481`
    482482
     
    568568* Essential Blocks Form
    569569* Extra Comment, Contact, Email Optin and Login Forms
    570 * Fluent Forms
     570* Fluent Forms, including Login Form
    571571* Forminator Forms
    572572* Formidable Forms
     
    587587* Passster Protection Form
    588588* Profile Builder Login, Recover Password, and Register Forms
     589* Really Simple CAPTCHA
    589590* Quform Forms
    590591* Sendinblue Form
     
    616617[open a pull request](https://github.com/hCaptcha/hcaptcha-wordpress-plugin).
    617618
    618 We also suggest emailing the authors of plugins you'd like to support hCaptcha: it will usually take them only an hour or two to add native support. This will simplify your use of hCaptcha, and is the best solution in the long run.
     619We also suggest emailing the authors of plugins you'd like to support hCaptcha: it will usually take them only an hour or two to add native support. This will simplify your use of hCaptcha and is the best solution in the long run.
    619620
    620621You may use native hCaptcha support if available for your plugin. Please check with your plugin author if native support is not yet available.
     
    627628
    628629== Changelog ==
     630
     631= 4.11.0 =
     632* Added Really Simple CAPTCHA plugin integration.
     633* Added compatibility with the UsersWP plugin v1.2.28.
     634* Added compatibility with Perfmatters plugin.
     635* Added support for the Fluent Login form.
     636* Added confirmation messages upon deletion of events on the Forms and Events pages.
     637* Added asynchronous migrations for large databases.
     638* Added hCaptcha error messages to the Contact Form 7 when JavaScript is disabled.
     639* Optimized Forms page performance for large databases with millions of entries.
     640* Fixed processing wpDiscuz comment form with wpDiscuz custom ajax.
     641* Fixed adding hCaptcha internal fields to Avada from submission.
     642* Fixed ASC ordering by date on the Events page.
     643* Fixed selection of a time interval on the Events page when site local time was not GMT.
     644* Fixed losing options during plugin update in rare cases.
     645* Fixed the live hCaptcha tag on the Contact Form 7 edit page after insertion but before saving the form.
     646* Fixed shortcode processing in the Contact Form 7 form when Auto-Add was off.
     647* Fixed error on theme installation.
     648* Tested with WooCommerce 9.7.
    629649
    630650= 4.10.0 =
     
    637657* Added deletion of events on the Events page.
    638658* Improved error messaging for hCaptcha verification.
    639 * Fixed IP detection in the WordPress core via filter. Now syncs with hCaptcha event information when IP collection is activated.
     659* Fixed IP detection in the WordPress core via filter. Now syncs with hCaptcha event information when an IP collection is activated.
    640660* Fixed fatal error with the WPForms plugin in rare cases.
    641661* Fixed error message at the first entry to the login page when Hide Login Errors in on.
     
    653673* Added the ability to install plugins and themes from the Integrations page.
    654674* Added ability to hide the login errors.
    655 * Added anonymous collection of IP and User Agent data in locally stored analytics to simplify GDPR compliance.
     675* Added an anonymous collection of IP and User Agent data in locally stored analytics to simplify GDPR compliance.
    656676* Added extended info about IP address on the Events page on hover.
    657677* Added selecting any page on Forms and Events.
     
    660680* Fixed fatal error as a consequence of a bug in the TutorLMS.
    661681* Fixed help text box layout on the General page.
    662 * Fixed dismiss and reset Notifications actions.
     682* Fixed the dismiss and reset Notifications actions.
    663683* Fixed duplication of entries in the Events table.
    664684
     
    672692* Added 'theme' badge to themes on the Integrations page.
    673693* Updated hCaptcha API error codes.
    674 * Fixed processing of Divi form with diacritical marks.
     694* Fixed processing of a Divi form with diacritical marks.
    675695* Fixed deactivating of all themes by Ctrl+Click on the Integrations page.
    676696* Fixed theme name display upon activation.
     
    693713* Added compatibility with Akismet tag in Contact Form 7.
    694714* Added compatibility with Elementor Element Caching.
    695 * Added activation and deactivation of plugins network wide if hCaptcha is set network wide.
     715* Added activation and deactivation of plugin network wide if hCaptcha is set network wide.
    696716* Added ability to use shortcode in the Jetpack Classic form.
    697717* Added ability to use shortcode in the Mailchimp for WP form.
     
    733753* Fixed error messaging when there are several Jetpack forms on the same page.
    734754* Fixed unconditional forcing hCaptcha in Jetpack forms.
    735 * Fixed appearance of Beaver Builder editor with "Turn Off When Logged In" setting.
    736 * Fixed appearance of Contact Form 7 editor with "Turn Off When Logged In" setting.
    737 * Fixed appearance of Essential Addons editor with "Turn Off When Logged In" setting.
    738 * Fixed appearance of Gravity Forms editor with "Turn Off When Logged In" setting.
    739 * Fixed appearance of Fluent Forms editor with "Turn Off When Logged In" setting.
    740 * Fixed appearance of Forminator editor with "Turn Off When Logged In" setting.
    741 * Fixed appearance of Formidable Forms with "Turn Off When Logged In" setting.
    742 * Fixed appearance of Ninja Forms editor with "Turn Off When Logged In" setting.
    743 * Fixed appearance of WPForms editor with "Turn Off When Logged In" setting.
     755* Fixed the appearance of Beaver Builder editor with "Turn Off When Logged In" setting.
     756* Fixed the appearance of Contact Form 7 editor with "Turn Off When Logged In" setting.
     757* Fixed the appearance of Essential Addons editor with "Turn Off When Logged In" setting.
     758* Fixed the appearance of Gravity Forms editor with "Turn Off When Logged In" setting.
     759* Fixed the appearance of Fluent Forms editor with "Turn Off When Logged In" setting.
     760* Fixed the appearance of Forminator editor with "Turn Off When Logged In" setting.
     761* Fixed the appearance of Formidable Forms with "Turn Off When Logged In" setting.
     762* Fixed the appearance of Ninja Forms editor with "Turn Off When Logged In" setting.
     763* Fixed the appearance of WPForms editor with "Turn Off When Logged In" setting.
    744764* Fixed fatal error on Gravity Forms Entries page.
    745765* Fixed Elementor preview.
     
    844864* Tested with WooCommerce 8.7.
    845865
    846 = 3.10.1 =
    847 * Added filter `hcap_add_csp_headers` to allow adding Content Security Policy headers.
    848 * Fixed Content Security Policy headers processing.
    849 
    850 = 3.10.0 =
    851 * Tested with WordPress 6.5.
    852 * Tested with WooCommerce 8.6.
    853 * The minimum required WordPress version is now 5.1.
    854 * Added Force hCaptcha check before submit feature.
    855 * Added Elementor Pro Login integration.
    856 * Added Login/Signup Popup integration.
    857 * Added CoBlocks integration.
    858 * Added Enterprise parameters to the System Info page.
    859 * Added checking of Enterprise parameters before saving.
    860 * Improved translation on Settings pages.
    861 * Improved error reporting for Active hCaptcha on the General page.
    862 * Fixed hCaptcha error codes table.
    863 * Fixed Settings pages layout with Chrome 122.
    864 * Fixed Content Security Policy headers.
    865 * Fixed fatal error with Formidable Forms 6.8.2.
    866 
    867 = 3.9.0 =
    868 * Added Spectra — WordPress Gutenberg Blocks integration.
    869 * Added Akismet integration.
    870 * Added test of hCaptcha completion before checking the site config.
    871 * Added site config check upon changing Enterprise params.
    872 * Added auto verify feature for forms in widgets.
    873 * Fixed site config check upon changing site and secret keys.
    874 * Fixed the list of themes after activation on the Integrations page.
    875 * Fixed jumping WooCommerce checkout page to hCaptcha on a page load.
    876 * Fixed missing hCaptcha on the Divi Comment Form.
    877 
    878 = 3.8.1 =
    879 * Fixed activation and deactivation of plugin and themes on the Integrations page.
    880 
    881 = 3.8.0 =
    882 * Added search of plugin and themes on the Integrations page.
    883 * Added toggling of sections on the General page.
    884 * Added new dialog on activation and deactivation of plugin and themes.
    885 * Added selection of a new theme on deactivation of the current one.
    886 * Added 'backend' to optional Enterprise settings.
    887 * Added filter `hcap_api_host`, allowing to filter the API host.
    888 * Added filter `hcap_api_src`, allowing to filter the API source url with params.
    889 * Updated integration with Back In Stock Notifier.
    890 * Fixed Brevo (formerly Sendinblue) plugin position on Integrations page.
    891 * Fixed testing config with test accounts.
    892 * Fixed saving Notification state.
    893 * Fixed compatibility of Ninja Forms with GeoDirectory.
    894 * Fixed compatibility of Beaver Builder with GeoDirectory.
    895 * Fixed compatibility of Divi with GeoDirectory.
    896 * Fixed compatibility of MailPoet with GeoDirectory.
    897 * Fixed compatibility of Passster with GeoDirectory.
    898 * Fixed styles of Settings pages on mobile.
    899 
    900 = 3.7.1 =
    901 * Fixed adding arguments to api.js for Enterprise accounts.
    902 
    903 = 3.7.0 =
    904 * Tested with WooCommerce 8.5.
    905 * Added optional Enterprise settings.
    906 * Fixed improper display of the "rate plugin" message on options.php.
    907 * Fixed colored border of hCaptcha challenge arrow.
    908 
    909 = 3.6.0 =
    910 * Tested with WooCommerce 8.4.
    911 * Added compatibility with BuddyPress 12.0.
    912 * Added hCaptcha tag to Contact Form 7 Admin Editor.
    913 * Added support for WPForms embedded forms.
    914 * Added Affiliates Login Form integration.
    915 * Added Affiliates Register Form integration.
    916 * Improved login forms security.
    917 * Improved inline scripts to optimize page load time.
    918 * Improved Integrations settings page - the Save Changes button moved up for better user experience.
    919 * Fixed hCaptcha position in BuddyPress.
    920 * Fixed hCaptcha position in wpDiscuz.
    921 * Fixed fatal error in Brizy integration.
    922 * Fixed auto-detection of hCaptcha language.
    923 * Fixed and added some translations.
    924 
    925 = 3.5.0 =
    926 * Tested with PHP 8.3.
    927 * Tested with WooCommerce 8.3.
    928 * Added hCaptcha field to Gravity Forms admin editor.
    929 * Added hCaptcha field to Ninja Forms admin editor.
    930 * Added invisible hCaptcha support for Ninja Forms.
    931 * Added the ability to process customized Mailchimp forms.
    932 * Added HTML Forms integration.
    933 * Added the Auto Theme option to follow light/dark theme settings on site.
    934 * Added support for WP Twenty Twenty-One theme dark mode.
    935 * Added support for WP Dark Mode plugin.
    936 * Added support for Droit Dark Mode plugin.
    937 * Added ability to activate/deactivate themes from the Integrations settings page.
    938 * Fixed loading of local .mo files.
    939 * Fixed inability to send Divi Contact Form.
    940 * Fixed MailPoet issues in admin.
    941 
    942 = 3.4.1 =
    943 * Tested with WordPress 6.4.
    944 * Tested with WooCommerce 8.2.
    945 * Added MailPoet integration.
    946 * Added Simple Download Monitor integration.
    947 * Added WP Job Openings integration.
    948 * Added Simple Basic Contact Form integration.
    949 * Added Easy Digital Downloads Login Form integration.
    950 * Added Easy Digital Downloads Lost Password Form integration.
    951 * Added Easy Digital Downloads Register Form integration.
    952 * Added purging of old failed login data to keep the `hcaptcha_login_data` option size small.
    953 * Fixed compatibility with HPOS in WooCommerce.
    954 * Fixed fatal error caused by broken backward compatibility in the Ultimate Member 2.7.0.
    955 * Fixed SystemInfo on multisite.
    956 * Fixed the missing dependency of WooCommerce checkout script.
    957 * Fixed fatal error occurred during login under some conditions.
    958 * Fixed the inability to send the Divi Contact Form when Divi Email Optin was active.
    959 
    960 = 3.3.3 =
    961 * Added compatibility with LearnDash.
    962 * Added requirement to check the site config after changes in credentials.
    963 * Added filter `hcap_login_limit_exceeded`, allowing to filter the login limit exceeded status.
    964 * Changed Brevo (formerly Sendinblue) logo.
    965 * Fixed activation of hCaptcha with empty keys.
    966 * Fixed autocomplete of the Site Key field by LastPass.
    967 * Fixed form detection for Auto-Verify.
    968 * Fixed Brevo form working in the post content only.
    969 * Fixed hCaptcha not loading correctly for a Brevo form.
    970 * Fixed Passster form working in the post content only.
    971 * Fixed LearnDash form working in the post content only.
    972 * Fixed auto-verify form not working on the homepage.
    973 
    974 = 3.3.2 =
    975 * Improved Beaver Builder login sequence.
    976 * Improved Classified Listing login sequence.
    977 * Improved Divi login sequence.
    978 * Improved MemberPress login sequence.
    979 * Improved Paid Membership Pro login sequence.
    980 * Improved Profile Builder login sequence.
    981 * Improved Ultimate Member login sequence.
    982 * Improved Wordfence login sequence.
    983 * Improved native WordPress login sequence.
    984 * Fixed login error when WP Login form option was `'on'` and WC Login form option was `'off'`.
    985 * Fixed compatibility with WPS Hide Login.
    986 * Fixed compatibility with All-In-One Security.
    987 * Fixed compatibility with Rename wp-admin Login.
    988 
    989 = 3.3.0 =
    990 * Color scheme in admin UI has been updated.
    991 * Added compatibility with Passster.
    992 * Added compatibility with Theme My Login.
    993 * Added compatibility with Gravity Perks Nested Forms.
    994 * Added compatibility with Wordfence Login Security.
    995 * Added compatibility with Wordfence Security.
    996 * Added compatibility with UsersWP.
    997 * Added compatibility with Kadence Advanced Form.
    998 * Improved support for a Kadence simple form.
    999 * Replaced deprecated ajaxStop events.
    1000 * Fixed error on a Classified Listing Login form.
    1001 * Fixed admin page title.
    1002 
    1003 = 3.2.0 =
    1004 * Tested with WooCommerce 8.0.
    1005 * Added ability to use hCaptcha field provided by the Fluent Forms plugin.
    1006 * Added ability to use hCaptcha field provided by the Forminator plugin.
    1007 * Added ability to use hCaptcha field provided by the Quform plugin.
    1008 * Added hCaptcha reset to allow sending an Elementor form several times without reloading the page.
    1009 * Added hCaptcha reset to allow sending a Forminator form several times without reloading the page.
    1010 * Added hCaptcha reset to allow sending a Quform form several times without reloading the page.
    1011 * Blocked hCaptcha settings on Fluent Forms admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1012 * Blocked hCaptcha settings on Forminator admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1013 * Blocked hCaptcha settings on Quform admin pages with a notice having a link to the hCaptcha plugin General settings page.
    1014 * Fixed Fluent Forms submit error.
    1015 * Fixed positioning of hCaptcha in Fluent Form.
    1016 * Fixed deprecation errors in debug.log that occurred with Fluent Forms.
    1017 * Fixed Forminator form display error.
    1018 * Fixed dynamic display of settings in sample hCaptcha.
    1019 
    1020 = 3.1.0 =
    1021 * Added notification system.
    1022 * Fixed mode selection for sample hCaptcha on the General settings page.
    1023 
    1024 = 3.0.1 =
    1025 * Fixed error on Contact Form 7 validation.
    1026 * Fixed checkboxes disabled status after activation of a plugin on the Integrations page.
    1027 
    1028 = 3.0.0 =
    1029 * Dropped support for PHP 5.6. The minimum required PHP version is now 7.0.
    1030 * Tested with WordPress 6.3.
    1031 * Tested with WooCommerce 7.9.
    1032 * Added hCaptcha config check to the General settings page.
    1033 * Added dynamic display of settings in sample hCaptcha.
    1034 * Added compatibility with Ajax Gravity Forms.
    1035 * Added compatibility with Profile Builder.
    1036 * Added compatibility with an Easy Digital Downloads Checkout form.
    1037 
    1038866[See changelog for all versions](https://plugins.svn.wordpress.org/hcaptcha-for-forms-and-more/trunk/changelog.txt).
  • hcaptcha-for-forms-and-more/trunk/src/php/Admin/Events/Events.php

    r3233179 r3248039  
    2121     */
    2222    public const TABLE_NAME = 'hcaptcha_events';
     23
     24    /**
     25     * Served items limit.
     26     */
     27    public const SERVED_LIMIT = 1000;
    2328
    2429    /**
     
    131136        global $wpdb;
    132137
    133         $args          = wp_parse_args(
    134             $args,
    135             [
    136                 'columns' => [],
    137                 'offset'  => 0,
    138                 'limit'   => 20,
    139                 'order'   => 'ASC',
    140                 'orderby' => '',
    141                 'dates'   => [],
    142             ]
    143         );
    144         $args['dates'] = $args['dates'] ?: self::get_default_dates();
     138        $args = self::prepare_args( $args );
    145139
    146140        $columns           = implode( ',', $args['columns'] );
     
    150144        $where_date_nested = self::get_where_date_gmt_nested( $args );
    151145        $orderby           = self::get_order_by( $args );
    152         $limit             = absint( $args['limit'] );
     146        $limit             = $args['limit'];
    153147
    154148        // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     
    160154                WHERE $where_date",
    161155            $wpdb->prepare(
    162                 "SELECT
    163                         $columns
     156                "SELECT $columns
    164157                        FROM $table_name
    165158                        WHERE $where_date_nested
     
    210203        global $wpdb;
    211204
    212         $args          = wp_parse_args(
    213             $args,
    214             [
    215                 'offset'  => 0,
    216                 'limit'   => 20,
    217                 'order'   => 'ASC',
    218                 'orderby' => '',
    219                 'dates'   => [],
    220             ]
    221         );
    222         $args['dates'] = $args['dates'] ?: self::get_default_dates();
     205        $args = self::prepare_args( $args );
    223206
    224207        $table_name = $wpdb->prefix . self::TABLE_NAME;
    225208        $where_date = self::get_where_date_gmt( $args );
    226209        $orderby    = self::get_order_by( $args );
    227         $offset     = absint( $args['offset'] );
    228         $limit      = absint( $args['limit'] );
    229 
     210        $offset     = $args['offset'];
     211        $limit      = $args['limit'];
     212
     213        // We need to collect id also to distinguish rows on the Forms page.
    230214        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    231215        $results = (array) $wpdb->get_results(
    232216            $wpdb->prepare(
    233217            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    234                 "SELECT
    235                         SQL_CALC_FOUND_ROWS
    236                         id, source, form_id, COUNT(*) as served
     218                "SELECT SQL_CALC_FOUND_ROWS id, source, form_id, COUNT(*) as served
    237219                        FROM $table_name
    238220                        WHERE $where_date
     
    258240        }
    259241
    260         $where = "($where) AND " . $where_date;
     242        $where        = "($where) AND " . $where_date;
     243        $served_limit = self::SERVED_LIMIT;
    261244
    262245        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    263246        $served = (array) $wpdb->get_results(
    264247        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    265             "SELECT date_gmt FROM $table_name WHERE $where"
     248            "SELECT date_gmt
     249                    FROM $table_name FORCE INDEX (date_gmt)
     250                    WHERE $where
     251                    ORDER BY date_gmt
     252                    LIMIT $served_limit"
    266253        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    267254        );
     
    327314        $dates = $args['dates'];
    328315
    329         if ( $dates ) {
    330             $dates[1] = $dates[1] ?? $dates[0];
    331 
    332             $dates[0] .= ' 00:00:00';
    333             $dates[1] .= ' 23:59:59';
    334 
    335             foreach ( $dates as &$date ) {
    336                 $date = wp_date( 'Y-m-d H:i:s', strtotime( $date ) );
    337             }
    338 
    339             unset( $date );
    340 
    341             $where_date = sprintf(
    342                 "date_gmt BETWEEN '%s' AND '%s'",
    343                 esc_sql( $dates[0] ),
    344                 esc_sql( $dates[1] )
    345             );
    346         } else {
    347             $where_date = '1=1';
    348         }
    349 
    350         return $where_date;
     316        if ( ! $dates ) {
     317            return '1=1';
     318        }
     319
     320        $dates = self::prepare_gmt_dates( $dates );
     321
     322        return sprintf(
     323            "date_gmt BETWEEN '%s' AND '%s'",
     324            esc_sql( $dates[0] ),
     325            esc_sql( $dates[1] )
     326        );
    351327    }
    352328
     
    363339        $dates = $args['dates'];
    364340
    365         if ( $dates ) {
    366             $dates[1] = $dates[1] ?? $dates[0];
    367 
    368             $dates[0] .= ' 00:00:00';
    369             $dates[1] .= ' 23:59:59';
    370 
    371             foreach ( $dates as &$date ) {
    372                 $date = wp_date( 'Y-m-d H:i:s', strtotime( $date ) );
    373             }
    374 
    375             unset( $date );
    376 
    377             $table_name = $wpdb->prefix . self::TABLE_NAME;
    378             $offset     = absint( $args['offset'] );
    379 
    380             $where_date = sprintf(
    381                 "date_gmt BETWEEN '%s' AND '%s'
    382                         AND date_gmt <= (
    383                             SELECT date_gmt
    384                             FROM %s
    385                             WHERE date_gmt BETWEEN '%s' AND '%s'
    386                             ORDER BY date_gmt DESC
    387                             LIMIT %d, 1
    388                         )
    389                         ",
    390                 esc_sql( $dates[0] ),
    391                 esc_sql( $dates[1] ),
    392                 $table_name,
    393                 esc_sql( $dates[0] ),
    394                 esc_sql( $dates[1] ),
    395                 $offset
    396             );
    397         } else {
    398             $where_date = '1=1';
    399         }
    400 
    401         return $where_date;
     341        if ( ! $dates ) {
     342            return '1=1';
     343        }
     344
     345        $dates      = self::prepare_gmt_dates( $dates );
     346        $table_name = $wpdb->prefix . self::TABLE_NAME;
     347        $order      = $args['order'];
     348        $offset     = $args['offset'];
     349        $compare    = 'DESC' === $order ? '<=' : '>=';
     350
     351        return sprintf(
     352            "date_gmt BETWEEN '%s' AND '%s'
     353                    AND date_gmt %s (
     354                        SELECT date_gmt
     355                        FROM %s
     356                        WHERE date_gmt BETWEEN '%s' AND '%s'
     357                        ORDER BY date_gmt %s
     358                        LIMIT %d, 1
     359                    )
     360                    ",
     361            esc_sql( $dates[0] ),
     362            esc_sql( $dates[1] ),
     363            $compare,
     364            $table_name,
     365            esc_sql( $dates[0] ),
     366            esc_sql( $dates[1] ),
     367            $order,
     368            $offset
     369        );
     370    }
     371
     372    /**
     373     * Prepare dates.
     374     *
     375     * @param array $dates Dates.
     376     *
     377     * @return array
     378     */
     379    public static function prepare_gmt_dates( array $dates ): array {
     380        $dates[1] = $dates[1] ?? $dates[0];
     381
     382        $dates[0] .= ' 00:00:00';
     383        $dates[1] .= ' 23:59:59';
     384
     385        foreach ( $dates as &$date ) {
     386            $date = get_gmt_from_date( $date );
     387        }
     388
     389        unset( $date );
     390
     391        return $dates;
    402392    }
    403393
     
    411401    private static function get_order_by( array $args ): string {
    412402        $orderby = $args['orderby'];
    413         $orderby = 'name' === $orderby ? 'source' : $orderby;
    414         $order   = strtoupper( $args['order'] );
     403        $order   = $args['order'];
    415404        $order   = 'ASC' === $order ? '' : $order;
    416405
     
    423412     * @return array
    424413     */
    425     private static function get_default_dates(): array {
     414    public static function get_default_dates(): array {
    426415        $end_date   = date_create_immutable( 'now', wp_timezone() );
    427416        $start_date = $end_date;
     
    495484        return preg_match( '/^' . $regex . '$/is', $subject );
    496485    }
     486
     487    /**
     488     * Prepare arguments.
     489     *
     490     * @param array $args Arguments.
     491     *
     492     * @return array
     493     */
     494    private static function prepare_args( array $args ): array {
     495        $args = wp_parse_args(
     496            $args,
     497            [
     498                'columns' => [],
     499                'offset'  => 0,
     500                'limit'   => 20,
     501                'order'   => 'ASC',
     502                'orderby' => '',
     503                'dates'   => [],
     504            ]
     505        );
     506
     507        $args['columns'] = array_map( 'strtolower', $args['columns'] );
     508        $args['offset']  = absint( $args['offset'] );
     509        $args['limit']   = max( 1, absint( $args['limit'] ) );
     510        $order           = strtoupper( $args['order'] );
     511        $args['order']   = in_array( $order, [ 'ASC', 'DESC' ], true ) ? $order : 'ASC';
     512        $orderby         = strtolower( $args['orderby'] );
     513        $args['orderby'] = in_array( $orderby, $args['columns'], true ) ? $orderby : '';
     514        $dates           = (array) $args['dates'];
     515        $args['dates']   = $dates ?: self::get_default_dates();
     516
     517        return $args;
     518    }
    497519}
  • hcaptcha-for-forms-and-more/trunk/src/php/Admin/Events/EventsTable.php

    r3233179 r3248039  
    105105        $orderby = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'date_gmt';
    106106        $date    = isset( $_GET['date'] )
     107            // We need filter_input here to keep the delimiter intact.
    107108            ? filter_input( INPUT_GET, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
    108             : ''; // We need filter_input here to keep delimiter intact.
     109            : '';
    109110        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    110111
  • hcaptcha-for-forms-and-more/trunk/src/php/Admin/Events/FormsTable.php

    r3233179 r3248039  
    9696        $orderby = isset( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'source';
    9797        $date    = isset( $_GET['date'] )
     98            // We need filter_input here to keep the delimiter intact.
    9899            ? filter_input( INPUT_GET, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
    99             : ''; // We need filter_input here to keep delimiter intact.
     100            : '';
    100101        // phpcs:enable WordPress.Security.NonceVerification.Recommended
    101102
    102         $dates    = explode( ListPageBase::TIMESPAN_DELIMITER, $date );
    103         $dates    = array_filter( array_map( 'trim', $dates ) );
    104         $per_page = $this->get_items_per_page( self::ITEMS_PER_PAGE, $this->per_page_default );
    105         $offset   = ( $paged - 1 ) * $per_page;
    106         $args     = [
     103        $dates        = explode( ListPageBase::TIMESPAN_DELIMITER, $date );
     104        $dates        = array_filter( array_map( 'trim', $dates ) );
     105        $column_slugs = str_replace( [ 'cb', 'name' ], [ 'id', 'source' ], array_keys( $this->columns ) );
     106        $per_page     = $this->get_items_per_page( self::ITEMS_PER_PAGE, $this->per_page_default );
     107        $offset       = ( $paged - 1 ) * $per_page;
     108        $args         = [
     109            'columns' => $column_slugs,
    107110            'offset'  => $offset,
    108111            'limit'   => $per_page,
  • hcaptcha-for-forms-and-more/trunk/src/php/Affiliates/Login.php

    r3114572 r3248039  
    5757     */
    5858    public function print_inline_styles(): void {
    59         $css = <<<CSS
     59        /* language=CSS */
     60        $css = '
    6061    .affiliates-dashboard .h-captcha {
    6162        margin-top: 2rem;
    6263    }
    63 CSS;
     64';
    6465
    6566        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Asgaros/Base.php

    r3114572 r3248039  
    104104     */
    105105    public function print_inline_styles(): void {
    106         $css = <<<CSS
     106        /* language=CSS */
     107        $css = '
    107108    #af-wrapper div.editor-row.editor-row-hcaptcha {
    108109        display: flex;
     
    113114        margin-bottom: 0;
    114115    }
    115 CSS;
     116';
    116117
    117118        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Avada/Form.php

    r3114572 r3248039  
    3636    public function init_hooks(): void {
    3737        add_action( 'fusion_form_after_open', [ $this, 'form_after_open' ], 10, 2 );
     38        add_filter( 'fusion_builder_form_submission_data', [ $this, 'submission_data' ] );
    3839        add_action( 'fusion_element_button_content', [ $this, 'add_hcaptcha' ], 10, 2 );
    3940        add_filter( 'fusion_form_demo_mode', [ $this, 'verify' ] );
     
    5152    public function form_after_open( array $args, array $params ): void {
    5253        $this->form_id = isset( $params['id'] ) ? (int) $params['id'] : 0;
     54    }
     55
     56    /**
     57     * Filter submission data.
     58     *
     59     * @param array|mixed $data Submission data.
     60     *
     61     * @return array
     62     */
     63    public function submission_data( $data ): array {
     64        $data = (array) $data;
     65
     66        unset(
     67            $data['data']['hcaptcha-widget-id'],
     68            $data['data']['h-captcha-response'],
     69            $data['data']['g-recaptcha-response']
     70        );
     71
     72        return $data;
    5373    }
    5474
  • hcaptcha-for-forms-and-more/trunk/src/php/Brizy/Base.php

    r3114572 r3248039  
    132132        $style_shown = true;
    133133
    134         $css = <<<CSS
     134        /* language=CSS */
     135        $css = '
    135136    .brz-forms2.brz-forms2__item .h-captcha {
    136137        margin-bottom: 0;
    137138    }
    138 CSS;
     139';
    139140
    140141        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/BuddyPress/CreateGroup.php

    r3114572 r3248039  
    100100     */
    101101    public function print_inline_styles(): void {
    102         $css = <<<'CSS'
     102        /* language=CSS */
     103        $css = '
    103104    #buddypress .h-captcha {
    104105        margin-top: 15px;
    105106    }
    106 CSS;
     107';
    107108        HCaptcha::css_display( $css );
    108109    }
  • hcaptcha-for-forms-and-more/trunk/src/php/CF7/Admin.php

    r3200161 r3248039  
    6060            add_action( 'current_screen', [ $this, 'current_screen' ] );
    6161        }
     62
     63        add_filter( 'hcap_print_hcaptcha_scripts', '__return_true' );
    6264    }
    6365
     
    329331        }
    330332
     333        if ( ! current_user_can( 'edit_posts' ) ) {
     334            wp_send_json_error( esc_html__( 'You do not have permission to update the form.', 'hcaptcha-for-forms-and-more' ) );
     335
     336            return; // For testing purposes.
     337        }
     338
    331339        $shortcode = html_entity_decode( filter_input( INPUT_POST, 'shortcode', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
    332340        $form      = html_entity_decode( filter_input( INPUT_POST, 'form', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
  • hcaptcha-for-forms-and-more/trunk/src/php/CF7/CF7.php

    r3185570 r3248039  
    3636
    3737    /**
     38     * Field type.
     39     */
     40    public const FIELD_TYPE = 'hcaptcha';
     41
     42    /**
    3843     * Init hooks.
    3944     *
     
    138143        $class     = $attr['cf7-class'] ?? '';
    139144        $hcap_form = preg_replace(
    140             [ '/(<h-captcha\s+?class="h-captcha")/', '#</h-captcha>#' ],
    141             [ '<span id="' . esc_attr( $id ) . '" class="wpcf7-form-control h-captcha ' . esc_attr( $class ) . '"', '</span>' ],
     145            [
     146                '/(<h-captcha\s+?class="h-captcha")/',
     147                '#</h-captcha>#',
     148            ],
     149            [
     150                '<span id="' . esc_attr( $id ) . '" class="wpcf7-form-control h-captcha ' . esc_attr( $class ) . '"',
     151                '</span>',
     152            ],
    142153            $hcap_form
    143154        );
     155
     156        $submission         = WPCF7_Submission::get_instance();
     157        $hcap_invalid_field = $submission ? $submission->get_invalid_field( 'hcap-cf7' ) : [];
     158        $reason             = $hcap_invalid_field['reason'] ?? '';
     159        $not_valid_tip      = $reason ? '<span class="wpcf7-not-valid-tip" aria-hidden="true">' . $reason . '</span>' : '';
    144160
    145161        return (
    146162            '<span class="wpcf7-form-control-wrap" data-name="' . self::DATA_NAME . '">' .
    147163            $hcap_form .
    148             '</span>'
     164            '</span>' .
     165            $not_valid_tip
    149166        );
    150167    }
     
    203220        if (
    204221            ! $this->mode_auto &&
    205             ! ( $this->mode_embed && $this->has_field( $submission, 'hcaptcha' ) )
     222            ! ( $this->mode_embed && $this->has_field( $submission, self::FIELD_TYPE ) )
    206223        ) {
    207224            return $result;
     
    228245     */
    229246    protected function has_field( WPCF7_Submission $submission, string $type ): bool {
    230         $form_fields = $submission->get_contact_form()->scan_form_tags();
    231 
    232         foreach ( $form_fields as $form_field ) {
    233             if ( $type === $form_field->type ) {
    234                 return true;
     247        $has_field    = false;
     248        $contact_form = $submission->get_contact_form();
     249
     250        if ( self::FIELD_TYPE === $type && has_shortcode( $contact_form->form_html(), 'cf7-hcaptcha' ) ) {
     251            $has_field = true;
     252        } else {
     253            $form_fields = $contact_form->scan_form_tags();
     254
     255            foreach ( $form_fields as $form_field ) {
     256                if ( $type === $form_field->type ) {
     257                    $has_field = true;
     258                }
    235259            }
    236260        }
    237261
    238         return false;
     262        /**
     263         * Filter whether form has a field of given type.
     264         *
     265         * @param bool $has_field Form has field.
     266         */
     267        return apply_filters( 'hcap_cf7_has_field', $has_field, $submission, $type );
    239268    }
    240269
     
    255284        $result->invalidate(
    256285            [
    257                 'type' => 'hcaptcha',
     286                'type' => self::FIELD_TYPE,
    258287                'name' => self::DATA_NAME,
    259288            ],
     
    292321     */
    293322    public function print_inline_styles(): void {
    294         $css = <<<CSS
     323        /* language=CSS */
     324        $css = '
    295325    span[data-name="hcap-cf7"] .h-captcha {
    296326        margin-bottom: 0;
     
    301331        margin-top: 2rem;
    302332    }
    303 CSS;
     333';
    304334
    305335        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/CoBlocks/Form.php

    r3114572 r3248039  
    203203     */
    204204    public function print_inline_styles(): void {
    205         $css = <<<CSS
     205        /* language=CSS */
     206        $css = '
    206207    .wp-block-coblocks-form .h-captcha {
    207208        margin-bottom: 25px;
    208209    }
    209 CSS;
     210';
    210211
    211212        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/ColorlibCustomizer/Base.php

    r3114572 r3248039  
    1111
    1212/**
    13  * Class Login
     13 * Class Base
    1414 */
    1515abstract class Base {
     
    6565
    6666        if ( 'normal' === $hcaptcha_size ) {
    67             $css = <<<CSS
     67            /* language=CSS */
     68            $css = '
    6869    .ml-container #login {
    6970        min-width: 350px;
    7071    }
    71 CSS;
     72';
    7273        }
    7374
  • hcaptcha-for-forms-and-more/trunk/src/php/ColorlibCustomizer/Login.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #loginform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/trunk/src/php/ColorlibCustomizer/LostPassword.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #lostpasswordform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/trunk/src/php/ColorlibCustomizer/Register.php

    r3021508 r3248039  
    2727            case 'compact':
    2828            case 'normal':
    29                 $css .= <<<CSS
     29                /* language=CSS */
     30                $css .= '
    3031    .ml-container #registerform {
    3132        height: unset;
    3233    }
    33 CSS;
     34';
    3435                break;
    3536            case 'invisible':
  • hcaptcha-for-forms-and-more/trunk/src/php/DelayedScript/DelayedScript.php

    r3215681 r3248039  
    1919     *
    2020     * @param string $js    js code to wrap in setTimeout().
    21      * @param int    $delay Delay in ms. Negative means no delay, just wait for user interaction.
     21     * @param int    $delay Delay in ms. Negative means no delay, wait for user interaction.
    2222     *
    2323     * @return string
     
    2525     */
    2626    public static function create( string $js, int $delay = -1 ): string {
    27         $js = <<<JS
     27        /* language=JS */
     28        $js = "
    2829    ( () => {
    2930        'use strict';
     
    7576        } );
    7677    } )();
    77 JS;
     78";
    7879
    7980        return "<script>\n" . HCaptcha::js_minify( $js ) . "\n</script>\n";
     
    8485     *
    8586     * @param array $args  Arguments.
    86      * @param int   $delay Delay in ms. Negative means no delay, just wait for user interaction.
     87     * @param int   $delay Delay in ms. Negative means no delay, wait for user interaction.
    8788     */
    8889    public static function launch( array $args, int $delay = -1 ): void {
    8990        unset( $args['id'], $args['async'] );
    9091
    91         $js = <<<JS
     92        /* language=JS */
     93        $js = "
    9294            const t = document.getElementsByTagName( 'script' )[0];
    9395            const s = document.createElement( 'script' );
    9496            s.type  = 'text/javascript';
    9597            s.id = 'hcaptcha-api';
    96 JS;
     98";
    9799
    98         $js = "$js\n";
     100        $js = trim( $js, " \n\r" );
    99101
    100102        // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     
    107109            }
    108110
    109             $js .= "\t\t\ts['$key'] = '$arg';\n";
     111            $js .= "\n\t\t\ts['$key'] = '$arg';";
    110112        }
    111113
    112         $js .= <<<JS
     114        /* language=JS */
     115        $js .= '
    113116            s.async = true;
    114117            t.parentNode.insertBefore( s, t );
    115 JS;
     118';
     119
     120        $js = trim( $js, " \n\r" );
    116121
    117122        echo self::create( $js, $delay );
  • hcaptcha-for-forms-and-more/trunk/src/php/DownloadManager/DownloadManager.php

    r3185570 r3248039  
    119119     */
    120120    public function print_inline_styles(): void {
    121         $css = <<<CSS
     121        /* language=CSS */
     122        $css = '
    122123    .wpdm-button-area + .h-captcha {
    123124        margin-bottom: 1rem;
     
    128129        color: #fff !important;
    129130    }
    130 CSS;
     131';
    131132
    132133        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/ElementorPro/HCaptchaHandler.php

    r3185570 r3248039  
    498498     */
    499499    public function print_inline_styles(): void {
    500         $css = <<<CSS
     500        /* language=CSS */
     501        $css = '
    501502    .elementor-field-type-hcaptcha .elementor-field {
    502503        background: transparent !important;
     
    506507        margin-bottom: unset;
    507508    }
    508 CSS;
     509';
    509510
    510511        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/ElementorPro/Login.php

    r3129246 r3248039  
    107107     */
    108108    public function print_inline_styles(): void {
    109         $css = <<<CSS
     109        /* language=CSS */
     110        $css = '
    110111    .elementor-widget-login .h-captcha {
    111112        margin-bottom: 0;
    112113    }
    113 CSS;
     114';
    114115
    115116        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/EssentialAddons/Register.php

    r3185570 r3248039  
    9090     */
    9191    public function print_inline_styles(): void {
    92         $css = <<<CSS
     92        /* language=CSS */
     93        $css = '
    9394    #eael-register-form .h-captcha {
    9495        margin-top: 1rem;
    9596        margin-bottom: 0;
    9697    }
    97 CSS;
     98';
    9899
    99100        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/EssentialBlocks/Form.php

    r3114572 r3248039  
    124124     */
    125125    public function print_inline_styles(): void {
    126         $css = <<<CSS
     126        /* language=CSS */
     127        $css = '
    127128    .wp-block-essential-blocks-form .h-captcha {
    128129        margin: 15px 0 0 0;
    129130    }
    130 CSS;
     131';
    131132
    132133        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/FluentForm/Form.php

    r3185570 r3248039  
    1515use FluentForm\App\Models\Form as FluentForm;
    1616use FluentForm\App\Modules\Form\FormFieldsParser;
     17use FluentForm\Framework\Helpers\ArrayHelper;
     18use HCaptcha\Abstracts\LoginBase;
    1719use HCaptcha\Helpers\HCaptcha;
    1820use HCaptcha\Main;
     
    2123/**
    2224 * Class Form
     25 *
     26 * Can be used as a login form also.
    2327 */
    24 class Form {
     28class Form extends LoginBase {
    2529
    2630    /**
    2731     * Nonce action.
    2832     */
    29     private const ACTION = 'hcaptcha_fluentform';
     33    protected const ACTION = 'hcaptcha_fluentform';
    3034
    3135    /**
    3236     * Nonce name.
    3337     */
    34     private const NONCE = 'hcaptcha_fluentform_nonce';
     38    protected const NONCE = 'hcaptcha_fluentform_nonce';
    3539
    3640    /**
     
    5761
    5862    /**
    59      * Constructor.
    60      */
    61     public function __construct() {
    62         $this->init_hooks();
    63     }
    64 
    65     /**
    6663     * Init hooks.
    6764     *
    6865     * @return void
    6966     */
    70     private function init_hooks(): void {
     67    protected function init_hooks(): void {
    7168        add_filter( 'fluentform/rendering_field_html_hcaptcha', [ $this, 'render_field_hcaptcha' ], 10, 3 );
    7269        add_action( 'fluentform/render_item_submit_button', [ $this, 'add_hcaptcha' ], 9, 2 );
     
    131128     */
    132129    public function verify( array $errors, array $data, FluentForm $form, array $fields ): array {
     130        if ( $this->is_login_form( $form ) ) {
     131            $email    = (string) ArrayHelper::get( $data, 'email' );
     132            $password = (string) ArrayHelper::get( $data, 'password' );
     133            $user     = get_user_by( 'email', $email );
     134
     135            if ( $user && wp_check_password( $password, $user->user_pass, $user->ID ) ) {
     136                $this->login( $email, $user );
     137            } else {
     138                $this->login_failed( $email );
     139            }
     140
     141            if ( ! $this->is_login_limit_exceeded() ) {
     142                return $errors;
     143            }
     144
     145            wp_send_json(
     146                __( 'Login failed. Please reload the page.', 'hcaptcha-for-forms-and-more' ),
     147                423
     148            );
     149
     150            // For testing purposes.
     151            return $errors;
     152        }
     153
    133154        remove_filter( 'pre_http_request', [ $this, 'pre_http_request' ] );
    134155
     
    202223        wp_deregister_script( $fluent_forms_conversational_script );
    203224
    204         $form = $this->get_captcha();
     225        $form = $this->get_hcaptcha();
    205226        $form = str_replace(
    206227            [
     
    307328    public function fluentform_has_hcaptcha(): bool {
    308329        add_filter( 'pre_http_request', [ $this, 'pre_http_request' ], 10, 3 );
     330
    309331        return false;
    310332    }
     
    349371     */
    350372    public function print_inline_styles(): void {
    351         $css = <<<CSS
     373        /* language=CSS */
     374        $css = '
    352375    .frm-fluent-form .h-captcha {
    353376        line-height: 0;
    354377        margin-bottom: 0;
    355378    }
    356 CSS;
     379';
    357380
    358381        HCaptcha::css_display( $css );
     
    368391     */
    369392    protected function has_own_hcaptcha( $form ): bool {
    370         FormFieldsParser::resetData();
    371 
    372         if ( FormFieldsParser::hasElement( $form, 'hcaptcha' ) ) {
    373             return true;
    374         }
    375 
    376         return false;
     393        return $this->has_element( $form, 'hcaptcha' );
    377394    }
    378395
     
    382399     * @return string
    383400     */
    384     private function get_captcha(): string {
     401    protected function get_hcaptcha(): string {
     402        $form = FluentForm::find( $this->form_id );
     403
     404        if ( $this->is_login_form( $form ) && ! $this->is_login_limit_exceeded() ) {
     405            return '';
     406        }
     407
    385408        $args = [
    386409            'action' => self::ACTION,
     
    396419
    397420    /**
     421     * Whether the form is a login form.
     422     *
     423     * @param FluentForm|stdClass $form Form.
     424     *
     425     * @return bool
     426     */
     427    private function is_login_form( $form ): bool {
     428
     429        return (
     430            has_action( 'fluentform/before_insert_submission' ) &&
     431            $this->has_element( $form, 'input_email' ) &&
     432            $this->has_element( $form, 'input_password' )
     433        );
     434    }
     435
     436    /**
     437     * Whether the form has an element.
     438     *
     439     * @param FluentForm|stdClass $form         Form.
     440     * @param string              $element_name Element name.
     441     *
     442     * @return bool
     443     */
     444    private function has_element( $form, string $element_name ): bool {
     445        FormFieldsParser::resetData();
     446
     447        return FormFieldsParser::hasElement( $form, $element_name );
     448    }
     449
     450    /**
    398451     * Get hCaptcha wrapped as Fluent Forms field.
    399452     *
     
    403456        ob_start();
    404457
     458        /* language=HTML */
    405459        ?>
    406460        <div class="ff-el-group">
     
    409463                    <?php
    410464                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    411                     echo $this->get_captcha();
     465                    echo $this->get_hcaptcha();
    412466                    ?>
    413467                </div>
  • hcaptcha-for-forms-and-more/trunk/src/php/GravityForms/Form.php

    r3233179 r3248039  
    252252     */
    253253    public function print_inline_styles(): void {
    254         $css = <<<CSS
     254        /* language=CSS */
     255        $css = '
    255256    .gform_previous_button + .h-captcha {
    256257        margin-top: 2rem;
     
    285286        margin: 1em 0 0 0 !important;
    286287    }
    287 CSS;
     288';
    288289
    289290        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/HTMLForms/Form.php

    r3114572 r3248039  
    197197     */
    198198    public function print_inline_styles(): void {
    199         $css = <<<CSS
     199        /* language=CSS */
     200        $css = '
    200201    #form-preview .h-captcha {
    201202        margin-bottom: 2rem;
     
    205206        margin-top: 2rem;
    206207    }
    207 CSS;
     208';
    208209
    209210        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Helpers/HCaptcha.php

    r3233179 r3248039  
    405405     */
    406406    public static function css_display( string $css, bool $wrap = true ): void {
     407        $css = trim( $css, " \n\r" );
     408
    407409        if ( $wrap ) {
    408410            echo "<style>\n";
     
    425427     */
    426428    public static function css_minify( string $css ): string {
     429        $css = trim( $css, " \n\r" );
     430
    427431        if ( defined( 'SCRIPT_DEBUG' ) && constant( 'SCRIPT_DEBUG' ) ) {
    428432            return $css;
     
    446450     */
    447451    public static function js_display( string $js, bool $wrap = true ): void {
     452        $js = trim( $js, " \n\r" );
     453
    448454        if ( $wrap ) {
    449455            echo "<script>\n";
     
    466472     */
    467473    public static function js_minify( string $js ): string {
     474        $js = trim( $js, " \n\r" );
     475
    468476        if ( defined( 'SCRIPT_DEBUG' ) && constant( 'SCRIPT_DEBUG' ) ) {
    469477            return $js;
  • hcaptcha-for-forms-and-more/trunk/src/php/Jetpack/Base.php

    r3215681 r3248039  
    143143        }
    144144
    145         $message = <<< HTML
     145        $message = '
    146146<div class="contact-form__input-error">
    147147    <span class="contact-form__warning-icon">
     
    149149        <i aria-hidden="true"></i>
    150150    </span>
    151     <span>$this->error_message</span>
     151    <span>' . $this->error_message . '</span>
    152152</div>
    153 HTML;
     153';
    154154
    155155        return $hcaptcha . $message;
     
    201201     */
    202202    public function print_inline_styles(): void {
    203         $css = <<<CSS
     203        /* language=CSS */
     204        $css = '
    204205    form.contact-form .grunion-field-hcaptcha-wrap.grunion-field-wrap {
    205206        flex-direction: row !important;
     
    210211        margin-bottom: 0;
    211212    }
    212 CSS;
     213';
    213214
    214215        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/LearnDash/Register.php

    r3215681 r3248039  
    107107     */
    108108    public function print_inline_styles(): void {
    109         $css = <<<CSS
     109        /* language=CSS */
     110        $css = '
    110111    #learndash_registerform .h-captcha {
    111112        margin-bottom: 0;
    112113    }
    113 CSS;
     114';
    114115
    115116        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/LoginSignupPopup/Login.php

    r3114572 r3248039  
    120120     */
    121121    public function print_inline_styles(): void {
    122         $css = <<<CSS
     122        /* language=CSS */
     123        $css = '
    123124    .xoo-el-form-container div[data-section="login"] .h-captcha {
    124125        margin-bottom: 25px;
    125126    }
    126 CSS;
     127';
    127128
    128129        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/LoginSignupPopup/Register.php

    r3114572 r3248039  
    141141     */
    142142    public function print_inline_styles(): void {
    143         $css = <<<CSS
     143        /* language=CSS */
     144        $css = '
    144145    .xoo-el-form-container div[data-section="register"] .h-captcha {
    145146        margin-bottom: 25px;
    146147    }
    147 CSS;
     148';
    148149
    149150        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Main.php

    r3233179 r3248039  
    2020use HCaptcha\CACSP\Compatibility;
    2121use HCaptcha\CF7\CF7;
     22use HCaptcha\CF7\ReallySimpleCaptcha;
    2223use HCaptcha\DelayedScript\DelayedScript;
    2324use HCaptcha\Divi\Fix;
     
    190191
    191192        add_action( 'plugins_loaded', [ $this, 'load_modules' ], self::LOAD_PRIORITY + 1 );
    192         add_filter( 'hcap_whitelist_ip', [ $this, 'whitelist_ip' ], -PHP_INT_MAX, 2 );
     193        add_filter( 'hcap_whitelist_ip', [ $this, 'allowlist_ip' ], -PHP_INT_MAX, 2 );
    193194        add_action( 'before_woocommerce_init', [ $this, 'declare_wc_compatibility' ] );
    194195
     
    252253         * Do not load hCaptcha functionality:
    253254         * - if a user is logged in and the option 'off_when_logged_in' is set;
    254          * - for whitelisted IPs;
     255         * - for allowlisted IPs;
    255256         * - when the site key or the secret key is empty (after first plugin activation).
    256257         */
     
    258259            ( is_user_logged_in() && $settings->is_on( 'off_when_logged_in' ) ) ||
    259260            /**
    260              * Filters the user IP to check whether it is whitelisted.
     261             * Filters the user IP to check whether it is allowlisted.
    261262             *
    262              * @param bool         $whitelisted IP is whitelisted.
     263             * @param bool         $allowlisted IP is allowlisted.
    263264             * @param string|false $ip          IP string or false for local addresses.
    264265             */
     
    438439     * @return void
    439440     * @noinspection CssUnusedSymbol
     441     * @noinspection CssUnknownTarget
    440442     */
    441443    public function print_inline_styles(): void {
     
    445447        $bg                 = $settings->get_custom_theme_background() ?: 'initial';
    446448
    447         $css = <<<CSS
     449        /* language=CSS */
     450        $css = '
    448451    .h-captcha {
    449452        position: relative;
     
    469472
    470473    .h-captcha::before {
    471         content: '';
     474        content: \'\';
    472475        display: block;
    473476        position: absolute;
    474477        top: 0;
    475478        left: 0;
    476         background: url( $div_logo_url ) no-repeat;
     479        background: url( ' . $div_logo_url . ' ) no-repeat;
    477480        border: 1px solid transparent;
    478481        border-radius: 4px;
     
    502505    html.wp-dark-mode-active .h-captcha[data-theme="auto"]::before,
    503506    html.drdt-dark-mode .h-captcha[data-theme="auto"]::before {
    504         background-image: url( $div_logo_white_url );
     507        background-image: url( ' . $div_logo_white_url . ' );
    505508        background-repeat: no-repeat;
    506509        background-color: #333;
     
    509512
    510513    .h-captcha[data-theme="custom"]::before {
    511         background-color: $bg;
     514        background-color: ' . $bg . ';
    512515    }
    513516
     
    523526        border-style: none;
    524527    }
    525 CSS;
     528';
    526529
    527530        HCaptcha::css_display( $css );
     
    535538     */
    536539    public function login_head(): void {
    537         $css = <<<'CSS'
     540        /* language=CSS */
     541        $css = '
    538542    @media (max-width: 349px) {
    539543        .h-captcha {
     
    553557        }
    554558    }
    555 CSS;
     559';
    556560
    557561        HCaptcha::css_display( $css );
     
    588592        $host = preg_replace( '#(http|https)://#', '', $host );
    589593
    590         // We need to add scheme here, otherwise wp_parse_url returns null.
     594        // We need to add a scheme here, otherwise wp_parse_url returns null.
    591595        $host = (string) wp_parse_url( 'https://' . $host, PHP_URL_HOST );
    592596
     
    753757        // @codeCoverageIgnoreStart
    754758        if ( class_exists( FeaturesUtil::class ) ) {
    755             FeaturesUtil::declare_compatibility( 'custom_order_tables', constant( 'HCAPTCHA_FILE' ), true );
     759            FeaturesUtil::declare_compatibility( 'custom_order_tables', constant( 'HCAPTCHA_FILE' ) );
    756760        }
    757761        // @codeCoverageIgnoreEnd
     
    759763
    760764    /**
    761      * Filter user IP to check if it is whitelisted.
    762      * For whitelisted IPs, hCaptcha will not be shown.
    763      *
    764      * @param bool|mixed   $whitelisted Whether IP is whitelisted.
     765     * Filter user IP to check if it is allowlisted.
     766     * For allowlisted IPs, hCaptcha will not be shown.
     767     *
     768     * @param bool|mixed   $allowlisted Whether IP is allowlisted.
    765769     * @param string|false $client_ip   Client IP.
    766770     *
    767771     * @return bool|mixed
    768772     */
    769     public function whitelist_ip( $whitelisted, $client_ip ) {
     773    public function allowlist_ip( $allowlisted, $client_ip ) {
    770774        $ips = explode(
    771775            "\n",
     
    802806        }
    803807
    804         return $whitelisted;
     808        return $allowlisted;
    805809    }
    806810
     
    973977                [ 'cf7_status', null ],
    974978                'contact-form-7/wp-contact-form-7.php',
    975                 [ CF7::class, Admin::class ],
     979                [ CF7::class, Admin::class, ReallySimpleCaptcha::class ],
    976980            ],
    977981            'Cookies and Content Security Policy'  => [
     
    14911495    /**
    14921496     * Is plugin active.
    1493      * When network wide activated, check if the plugin is network active.
     1497     * When network is widely activated, check if the plugin is network active.
    14941498     *
    14951499     * @param string $plugin_name Plugin name.
  • hcaptcha-for-forms-and-more/trunk/src/php/Maintenance/Login.php

    r3200161 r3248039  
    122122     */
    123123    public function print_inline_styles(): void {
    124         $css = <<<CSS
     124        /* language=CSS */
     125        $css = '
    125126    body.maintenance > .login-form-container {
    126127        min-width: 343px;
     
    136137        margin-top: 2em;
    137138    }
    138 CSS;
     139';
    139140
    140141        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Migrations/Migrations.php

    r3166267 r3248039  
    88namespace HCaptcha\Migrations;
    99
     10use ActionScheduler;
     11use ActionScheduler_Store;
    1012use HCaptcha\Admin\Events\Events;
    1113use HCaptcha\Settings\PluginSettingsBase;
     
    3739
    3840    /**
     41     * Migration completed status.
     42     */
     43    public const COMPLETED = - 3;
     44
     45    /**
    3946     * Priority of the plugins_loaded action to load Migrations.
    4047     */
     
    4552     */
    4653    private const PLUGIN_NAME = 'hCaptcha Plugin';
     54
     55    /**
     56     * Action Scheduler group name.
     57     */
     58    private const AS_GROUP = 'hcaptcha';
    4759
    4860    /**
     
    5870     * @return void
    5971     */
    60     public function init(): void {
     72    private function init(): void {
    6173        if ( ! $this->is_allowed() ) {
    6274            return;
     
    7385    private function init_hooks(): void {
    7486        add_action( 'plugins_loaded', [ $this, 'migrate' ], self::LOAD_PRIORITY );
     87        add_action( 'plugins_loaded', [ $this, 'load_action_scheduler' ], -10 );
     88
     89        add_action( 'async_migrate_4_11_0', [ $this, 'async_migrate_4_11_0' ] );
     90    }
     91
     92    /**
     93     * Load action scheduler.
     94     *
     95     * @return void
     96     */
     97    public function load_action_scheduler(): void {
     98        require_once HCAPTCHA_PATH . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
    7599    }
    76100
     
    88112            get_class_methods( $this ),
    89113            static function ( $migration ) {
    90                 return false !== strpos( $migration, 'migrate_' );
     114                return 0 === strpos( $migration, 'migrate_' );
    91115            }
    92116        );
     
    141165     * Determine if migration is allowed.
    142166     */
    143     public function is_allowed(): bool {
     167    private function is_allowed(): bool {
    144168        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    145169        if ( isset( $_GET['service-worker'] ) ) {
     
    148172
    149173        return (
    150             ( is_admin() && ! wp_doing_ajax() ) ||
     174            is_admin() ||
    151175            wp_doing_cron() ||
    152176            ( defined( 'WP_CLI' ) && constant( 'WP_CLI' ) )
     
    317341        }
    318342
    319         update_option( PluginSettingsBase::OPTION_NAME, $new_options );
     343        // This two lines is a precaution for a case if options in a new format already exist.
     344        $options = get_option( PluginSettingsBase::OPTION_NAME, [] );
     345        $options = array_merge( $new_options, $options );
     346
     347        update_option( PluginSettingsBase::OPTION_NAME, $options );
    320348
    321349        foreach ( array_keys( $options_map ) as $old_option_name ) {
     
    384412
    385413    /**
     414     * Migrate to 4.11.0
     415     *
     416     * @return bool|null
     417     * @noinspection PhpUnused
     418     */
     419    protected function migrate_4_11_0(): ?bool {
     420        return $this->run_async( __FUNCTION__ );
     421    }
     422
     423    /**
     424     * Async migration to 4.11.0.
     425     *
     426     * @return void
     427     */
     428    public function async_migrate_4_11_0(): void {
     429        global $wpdb;
     430
     431        $table_name = $wpdb->prefix . Events::TABLE_NAME;
     432
     433        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     434        // phpcs:disable WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     435        $result = $wpdb->query(
     436            "CREATE INDEX idx_date_source_form
     437                    ON $table_name
     438                    (date_gmt, source, form_id)"
     439        );
     440
     441        if ( $result ) {
     442            $wpdb->query( "DROP INDEX hcaptcha_id on $table_name" );
     443        }
     444        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     445        // phpcs:enable WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     446
     447        $this->mark_completed();
     448    }
     449
     450    /**
    386451     * Save license level in settings.
    387452     *
     
    404469        update_option( PluginSettingsBase::OPTION_NAME, $option );
    405470    }
     471
     472    /**
     473     * Run async action.
     474     *
     475     * @param string $method Method name.
     476     * @param array  $args   Arguments.
     477     *
     478     * @return bool|null
     479     * @noinspection PhpSameParameterValueInspection
     480     */
     481    private function run_async( string $method, array $args = [] ): ?bool {
     482        $hook      = 'async_' . $method;
     483        $group     = self::AS_GROUP;
     484        $transient = $group . '_' . $hook;
     485
     486        $status = (int) get_transient( $transient );
     487
     488        if ( self::COMPLETED === $status ) {
     489            delete_transient( $transient );
     490
     491            return true;
     492        }
     493
     494        if ( ! $status ) {
     495            set_transient( $transient, self::STARTED );
     496        }
     497
     498        add_action(
     499            'action_scheduler_init',
     500            function () use ( $hook, $args, $group ) {
     501                $transient = $group . '_' . $hook;
     502                $status    = $this->create_as_action( $hook, $args, $group );
     503
     504                if ( self::FAILED === $status ) {
     505                    set_transient( $transient, $status );
     506                }
     507            }
     508        );
     509
     510        return null;
     511    }
     512
     513    /**
     514     * Create an AS action.
     515     *
     516     * @param string $hook  Hook name.
     517     * @param array  $args  Hook arguments.
     518     * @param string $group Group name.
     519     *
     520     * @return int Started or failed.
     521     */
     522    private function create_as_action( string $hook, array $args, string $group ): int {
     523        $actions = as_get_scheduled_actions(
     524            [
     525                'hook'   => $hook,
     526                'args'   => $args,
     527                'group'  => $group,
     528                'status' => [ // All statuses except completed.
     529                    ActionScheduler_Store::STATUS_PENDING,
     530                    ActionScheduler_Store::STATUS_RUNNING,
     531                    ActionScheduler_Store::STATUS_FAILED,
     532                    ActionScheduler_Store::STATUS_CANCELED,
     533                ],
     534            ]
     535        );
     536
     537        if ( empty( $actions ) ) {
     538            // Plan the unique action.
     539            $action_id = as_enqueue_async_action( $hook, $args, $group, true );
     540
     541            return $action_id ? self::STARTED : self::FAILED;
     542        }
     543
     544        // Get the last action status.
     545        $last_action_id = max( array_map( 'intval', array_keys( $actions ) ) );
     546        $store          = ActionScheduler::store();
     547        $status         = $store ? $store->get_status( $last_action_id ) : ActionScheduler_Store::STATUS_FAILED;
     548
     549        $started = in_array(
     550            $status,
     551            [
     552                ActionScheduler_Store::STATUS_PENDING,
     553                ActionScheduler_Store::STATUS_RUNNING,
     554            ],
     555            true
     556        );
     557
     558        return $started ? self::STARTED : self::FAILED;
     559    }
     560
     561    /**
     562     * Mark async migration as completed.
     563     *
     564     * @return void
     565     */
     566    private function mark_completed(): void {
     567        $hook      = current_action();
     568        $group     = self::AS_GROUP;
     569        $transient = $group . '_' . $hook;
     570
     571        set_transient( $transient, self::COMPLETED );
     572    }
    406573}
  • hcaptcha-for-forms-and-more/trunk/src/php/Passster/Protect.php

    r3185570 r3248039  
    165165     */
    166166    public function print_inline_styles(): void {
    167         $css = <<<CSS
     167        /* language=CSS */
     168        $css = '
    168169    .passster-form .h-captcha {
    169170        margin-bottom: 5px;
    170171    }
    171 CSS;
     172';
    172173
    173174        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/ProfileBuilder/Login.php

    r3233179 r3248039  
    8686     */
    8787    public function print_inline_styles(): void {
    88         $css = <<<CSS
     88        /* language=CSS */
     89        $css = '
    8990    #wppb-loginform .h-captcha {
    9091        margin-bottom: 14px;
    9192    }
    92 CSS;
     93';
    9394
    9495        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/Abstracts/SettingsBase.php

    r3185570 r3248039  
    892892        }
    893893
    894         register_setting( $this->option_group(), $this->option_name() );
     894        $args = [
     895            'sanitize_callback' => [ $this, 'sanitize_option_callback' ],
     896        ];
     897
     898        register_setting( $this->option_group(), $this->option_name(), $args );
    895899
    896900        /**
     
    913917            );
    914918        }
     919    }
     920
     921    /**
     922     * Filters an option value following sanitization.
     923     *
     924     * @param array|mixed $value The sanitized option value.
     925     *
     926     * @return array
     927     */
     928    public function sanitize_option_callback( $value ): array {
     929        // Remove unexpected settings.
     930        $settings = array_intersect_key( (array) $value, $this->form_fields() );
     931
     932        foreach ( $settings as $key => $setting ) {
     933            $type = $this->form_fields[ $key ]['type'];
     934
     935            switch ( $type ) {
     936                case 'checkbox':
     937                    $settings[ $key ] = array_map( 'sanitize_text_field', $setting );
     938                    break;
     939                case 'textarea':
     940                    $settings[ $key ] = wp_kses_post( $setting );
     941                    break;
     942                default:
     943                    $settings[ $key ] = sanitize_text_field( $setting );
     944            }
     945        }
     946
     947        return $settings;
    915948    }
    916949
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/EventsPage.php

    r3233179 r3248039  
    88namespace HCaptcha\Settings;
    99
     10use HCaptcha\Admin\Events\Events;
    1011use HCaptcha\Admin\Events\EventsTable;
    1112use HCaptcha\Helpers\DB;
     
    5657
    5758    /**
    58      * Init class hooks.
    59      */
    60     protected function init_hooks(): void {
    61         parent::init_hooks();
    62 
    63         add_action( 'wp_ajax_' . self::BULK_ACTION, [ $this, 'bulk_action' ] );
    64     }
    65 
    66     /**
    6759     * Get page title.
    6860     *
     
    108100
    109101        $this->prepare_chart_data();
    110     }
    111 
    112     /**
    113      * Ajax callback for bulk actions.
    114      *
    115      * @return void
    116      */
    117     public function bulk_action(): void {
    118         $this->run_checks( self::BULK_ACTION );
    119 
    120         // Nonce is checked by check_ajax_referer() in run_checks().
    121         // phpcs:disable WordPress.Security.NonceVerification.Missing
    122         $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
    123         $ids  = isset( $_POST['ids'] )
    124             ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
    125             : [];
    126         // phpcs:enable WordPress.Security.NonceVerification.Missing
    127 
    128         if ( 'trash' === $bulk ) {
    129             if ( ! $this->delete_hcaptcha_events( $ids ) ) {
    130                 wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
    131             }
    132 
    133             wp_send_json_success();
    134 
    135             // For testing purposes.
    136             return;
    137         }
    138 
    139         wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
    140102    }
    141103
     
    174136                'bulkAction'   => self::BULK_ACTION,
    175137                'bulkNonce'    => wp_create_nonce( self::BULK_ACTION ),
     138                'bulkMessage'  => $this->get_clean_transient(),
    176139                'succeed'      => $this->succeed,
    177140                'failed'       => $this->failed,
     
    282245     * Delete hCaptcha events by IDs.
    283246     *
    284      * @param array $ids Array of event IDs to delete.
     247     * @param array $args Arguments.
    285248     *
    286249     * @return bool
    287250     */
    288     private function delete_hcaptcha_events( array $ids ): bool {
     251    protected function delete_events( array $args ): bool {
    289252        global $wpdb;
    290253
    291         $table_name = $wpdb->prefix . 'hcaptcha_events';
    292 
    293         $in = DB::prepare_in( $ids, '%d' );
     254        $ids = $args['ids'] ?? [];
     255
     256        $table_name = $wpdb->prefix . Events::TABLE_NAME;
     257        $in         = DB::prepare_in( $ids, '%d' );
    294258
    295259        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/FormsPage.php

    r3233179 r3248039  
    88namespace HCaptcha\Settings;
    99
     10use HCaptcha\Admin\Events\Events;
    1011use HCaptcha\Admin\Events\FormsTable;
    1112use KAGG\Settings\Abstracts\SettingsBase;
     
    4849
    4950    /**
    50      * Init class hooks.
    51      */
    52     protected function init_hooks(): void {
    53         parent::init_hooks();
    54 
    55         add_action( 'wp_ajax_' . self::BULK_ACTION, [ $this, 'bulk_action' ] );
    56     }
    57 
    58     /**
    5951     * Get page title.
    6052     *
     
    9890
    9991        $this->prepare_chart_data();
    100     }
    101 
    102     /**
    103      * Ajax callback for bulk actions.
    104      *
    105      * @return void
    106      */
    107     public function bulk_action(): void {
    108         $this->run_checks( self::BULK_ACTION );
    109 
    110         // Nonce is checked by check_ajax_referer() in run_checks().
    111         // phpcs:disable WordPress.Security.NonceVerification.Missing
    112         $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
    113         $ids  = isset( $_POST['ids'] )
    114             ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
    115             : [];
    116         // phpcs:enable WordPress.Security.NonceVerification.Missing
    117 
    118         if ( 'trash' === $bulk ) {
    119             if ( ! $this->delete_hcaptcha_events_by_forms( $ids ) ) {
    120                 wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
    121             }
    122 
    123             wp_send_json_success();
    124 
    125             // For testing purposes.
    126             return;
    127         }
    128 
    129         wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
    13092    }
    13193
     
    164126                'bulkAction'  => self::BULK_ACTION,
    165127                'bulkNonce'   => wp_create_nonce( self::BULK_ACTION ),
     128                'bulkMessage' => $this->get_clean_transient(),
    166129                'served'      => $this->served,
    167130                'servedLabel' => __( 'Served', 'hcaptcha-for-forms-and-more' ),
     
    219182                </p>
    220183            </canvas>
     184                <?php
     185                if ( count( $this->list_table->served ) >= Events::SERVED_LIMIT ) {
     186                    echo '<div id="hcaptcha-chart-message">';
     187                    printf(
     188                    /* translators: 1: Number of elements. */
     189                        esc_html__( 'The chart is limited to displaying a maximum of %1$s elements.', 'hcaptcha-for-forms-and-more' ),
     190                        esc_html( number_format_i18n( Events::SERVED_LIMIT ) )
     191                    );
     192                    echo '</div>';
     193                }
     194                ?>
    221195        </div>
    222196        <div id="hcaptcha-forms-wrap">
     
    257231     * Delete hCaptcha events by forms.
    258232     *
    259      * @param array $ids Array of event IDs to delete.
     233     * @param array $args Arguments.
    260234     *
    261235     * @return bool
    262236     */
    263     private function delete_hcaptcha_events_by_forms( array $ids ): bool {
     237    protected function delete_events( array $args ): bool {
    264238        global $wpdb;
    265239
    266         $table_name = $wpdb->prefix . 'hcaptcha_events';
     240        $ids   = $args['ids'] ?? [];
     241        $dates = $args['dates'] ?? [];
     242        $dates = $dates ?: Events::get_default_dates();
     243        $dates = Events::prepare_gmt_dates( $dates );
     244
     245        $table_name = $wpdb->prefix . Events::TABLE_NAME;
    267246        $conditions = [];
    268247        $values     = [];
    269248
     249        if ( ! $ids ) {
     250            return false;
     251        }
     252
    270253        foreach ( $ids as $item ) {
    271             $conditions[] = '(source = %s AND form_id = %d)';
     254            $conditions[] = '(source = %s AND form_id = %s)';
    272255            $values[]     = $item['source'];
    273256            $values[]     = $item['formId'];
     
    275258
    276259        $where_clause = implode( ' OR ', $conditions );
     260        $where_clause = "($where_clause) AND date_gmt BETWEEN %s AND %s";
    277261
    278262        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     
    281265            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
    282266                "DELETE FROM $table_name WHERE $where_clause",
    283                 ...$values
     267                ...$values,
     268                ...$dates
    284269            )
    285270        );
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/General.php

    r3233179 r3248039  
    535535            ],
    536536            'whitelisted_ips'      => [
    537                 'label'   => __( 'Whitelisted IPs', 'hcaptcha-for-forms-and-more' ),
     537                'label'   => __( 'Allowlisted IPs', 'hcaptcha-for-forms-and-more' ),
    538538                'type'    => 'textarea',
    539539                'section' => self::SECTION_OTHER,
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/Integrations.php

    r3233179 r3248039  
    1616use WP_Filesystem_Base;
    1717use WP_Theme;
    18 use WP_Upgrader;
    1918
    2019/**
     
    300299                'type'    => 'checkbox',
    301300                'options' => [
    302                     'form'  => __( 'Form Auto-Add', 'hcaptcha-for-forms-and-more' ),
    303                     'embed' => __( 'Form Embed', 'hcaptcha-for-forms-and-more' ),
    304                     'live'  => __( 'Live Form in Admin', 'hcaptcha-for-forms-and-more' ),
     301                    'form'        => __( 'Form Auto-Add', 'hcaptcha-for-forms-and-more' ),
     302                    'embed'       => __( 'Form Embed', 'hcaptcha-for-forms-and-more' ),
     303                    'live'        => __( 'Live Form in Admin', 'hcaptcha-for-forms-and-more' ),
     304                    'replace_rsc' => __( 'Replace Really Simple CAPTCHA', 'hcaptcha-for-forms-and-more' ),
    305305                ],
    306306            ],
     
    12481248     */
    12491249    protected function maybe_activate_plugin( string $plugin ) {
    1250 
    12511250        if ( hcaptcha()->is_plugin_active( $plugin ) ) {
    12521251            return true;
     
    12661265
    12671266        ob_start();
    1268 
    12691267        $result = $this->activate_plugin( $plugin );
    1270 
    12711268        ob_end_clean();
    12721269
     
    12821279     */
    12831280    protected function install_plugin( string $plugin ): ?WP_Error {
    1284 
    12851281        $plugin = trim( explode( '/', $plugin )[0] );
    12861282
     
    12961292        }
    12971293
    1298         require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    1299         require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
     1294        if ( ! class_exists( 'Plugin_Upgrader', false ) ) {
     1295            // @codeCoverageIgnoreStart
     1296            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     1297            require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
     1298            // @codeCoverageIgnoreEnd
     1299        }
    13001300
    13011301        $api = plugins_api(
     
    14571457     * @param string $theme Theme to activate.
    14581458     *
    1459      * @return null|WP_Error Null on success, WP_Error on failure.
    1460      */
    1461     protected function activate_theme( string $theme ): ?WP_Error {
    1462         if ( ! wp_get_theme( $theme )->exists() ) {
    1463             return new WP_Error(
    1464                 'theme_not_found',
    1465                 __( 'Theme not found.', 'hcaptcha-for-forms-and-more' )
    1466             );
     1459     * @return null|true|WP_Error Null on success, WP_Error on failure.
     1460     */
     1461    protected function activate_theme( string $theme ) {
     1462        if ( wp_get_theme()->get_stylesheet() === $theme ) {
     1463            return true;
    14671464        }
    14681465
     
    14931490     * @return null|WP_Error Null on success, WP_Error on failure.
    14941491     */
    1495     private function install_theme( string $theme ): ?WP_Error {
     1492    protected function install_theme( string $theme ): ?WP_Error {
    14961493        $theme = trim( $theme );
    14971494
     
    15101507        }
    15111508
    1512         require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    1513         require_once ABSPATH . 'wp-admin/includes/theme.php';
     1509        if ( ! class_exists( 'Theme_Upgrader', false ) ) {
     1510            // @codeCoverageIgnoreStart
     1511            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     1512            require_once ABSPATH . 'wp-admin/includes/theme.php';
     1513            // @codeCoverageIgnoreEnd
     1514        }
    15141515
    15151516        $api = themes_api(
     
    15221523
    15231524        if ( is_wp_error( $api ) ) {
    1524             return new WP_Error( $api->get_error_code(), $api->get_error_message() );
     1525            return $api;
    15251526        }
    15261527
     
    16111612     *
    16121613     * @return string
    1613      * @noinspection PhpVoidFunctionResultUsedInspection
    16141614     */
    16151615    protected function get_default_theme(): string {
     
    16781678     * Install entity (plugin or theme).
    16791679     *
    1680      * @param WP_Upgrader          $upgrader      Upgrader instance.
    1681      * @param WP_Ajax_Upgrader_Skin $skin          Upgrader skin instance.
    1682      * @param string                $download_link Download link.
     1680     * @param Plugin_Upgrader|Theme_Upgrader|object $upgrader      Upgrader instance.
     1681     * @param WP_Ajax_Upgrader_Skin|object          $skin          Upgrader skin instance.
     1682     * @param string                                $download_link Download link.
    16831683     *
    16841684     * @return WP_Error|null
    1685      * @noinspection PhpPossiblePolymorphicInvocationInspection
    1686      */
    1687     protected function install_entity( WP_Upgrader $upgrader, WP_Ajax_Upgrader_Skin $skin, string $download_link ): ?WP_Error {
     1685     */
     1686    protected function install_entity( object $upgrader, object $skin, string $download_link ): ?WP_Error {
    16881687        $result = $upgrader->install( $download_link );
    16891688
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/ListPageBase.php

    r3233179 r3248039  
    5050
    5151    /**
     52     * Transient name where to store a page bulk action message.
     53     */
     54    protected const TRANSIENT = 'hcaptcha_page_base';
     55
     56    /**
    5257     * Default date format.
    5358     */
     
    5560
    5661    /**
     62     * Bulk ajax action.
     63     * Must be overridden in child classes.
     64     * Here is for testing purposes.
     65     */
     66    public const BULK_ACTION = '';
     67
     68    /**
    5769     * Chart time unit.
    5870     *
     
    6779     */
    6880    protected $allowed = false;
     81
     82    /**
     83     * Delete hCaptcha events by IDs.
     84     *
     85     * @param array $args Arguments.
     86     *
     87     * @return bool
     88     */
     89    abstract protected function delete_events( array $args ): bool;
    6990
    7091    /**
     
    7697        add_action( 'admin_init', [ $this, 'admin_init' ] );
    7798        add_action( 'kagg_settings_header', [ $this, 'date_picker_display' ] );
     99        add_action( 'wp_ajax_' . static::BULK_ACTION, [ $this, 'bulk_action' ] );
    78100    }
    79101
     
    259281
    260282    /**
     283     * Ajax callback for bulk actions.
     284     *
     285     * @return void
     286     */
     287    public function bulk_action(): void {
     288        $this->run_checks( static::BULK_ACTION );
     289
     290        // Nonce is checked by check_ajax_referer() in run_checks().
     291        // phpcs:disable WordPress.Security.NonceVerification.Missing
     292        $bulk = isset( $_POST['bulk'] ) ? sanitize_text_field( wp_unslash( $_POST['bulk'] ) ) : '';
     293        $ids  = isset( $_POST['ids'] )
     294            ? (array) json_decode( sanitize_text_field( wp_unslash( $_POST['ids'] ) ), true )
     295            : [];
     296        $date = isset( $_POST['date'] )
     297            // We need filter_input here to keep the delimiter intact.
     298            ? filter_input( INPUT_POST, 'date', FILTER_SANITIZE_FULL_SPECIAL_CHARS )
     299            : '';
     300        // phpcs:enable WordPress.Security.NonceVerification.Missing
     301
     302        $dates = explode( self::TIMESPAN_DELIMITER, $date );
     303        $dates = array_filter( array_map( 'trim', $dates ) );
     304
     305        if ( 'trash' === $bulk ) {
     306            $args = [
     307                'ids'   => $ids,
     308                'dates' => $dates,
     309            ];
     310
     311            if ( ! $this->delete_events( $args ) ) {
     312                wp_send_json_error( __( 'Failed to delete the selected items.', 'hcaptcha-for-forms-and-more' ) );
     313
     314                // For testing purposes.
     315                return;
     316            }
     317
     318            set_transient(
     319                self::TRANSIENT,
     320                __( 'Selected items have been successfully deleted.', 'hcaptcha-for-forms-and-more' )
     321            );
     322
     323            wp_send_json_success();
     324
     325            // For testing purposes.
     326            return;
     327        }
     328
     329        wp_send_json_error( __( 'Invalid bulk action.', 'hcaptcha-for-forms-and-more' ) );
     330    }
     331
     332    /**
     333     * Get and clean the transient.
     334     *
     335     * @return string
     336     */
     337    protected function get_clean_transient(): string {
     338        $bulk_message = (string) get_transient( self::TRANSIENT );
     339
     340        if ( $bulk_message ) {
     341            delete_transient( self::TRANSIENT );
     342        }
     343
     344        return $bulk_message;
     345    }
     346
     347    /**
    261348     * Sets the timespan (or date range) for performing mysql queries.
    262349     *
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/Settings.php

    r3200161 r3248039  
    77
    88// phpcs:ignore Generic.Commenting.DocComment.MissingShort
    9 /** @noinspection ContractViolationInspection */
    109
    1110namespace HCaptcha\Settings;
  • hcaptcha-for-forms-and-more/trunk/src/php/Settings/SystemInfo.php

    r3114572 r3248039  
    187187        $data .= $this->data( 'Turn Off When Logged In', $this->is_on( 'off_when_logged_in' ) );
    188188        $data .= $this->data( 'Disable reCAPTCHA Compatibility', $this->is_on( 'recaptcha_compat_off' ) );
    189         $data .= $this->data( 'Whitelisted IPs', $this->is_empty( $settings->get( 'whitelisted_ips' ) ) );
     189        $data .= $this->data( 'Allowlisted IPs', $this->is_empty( $settings->get( 'whitelisted_ips' ) ) );
    190190        $data .= $this->data( 'Login attempts before hCaptcha', $settings->get( 'login_limit' ) );
    191191        $data .= $this->data( 'Failed login attempts interval, min', $settings->get( 'login_interval' ) );
  • hcaptcha-for-forms-and-more/trunk/src/php/SimpleMembership/Login.php

    r3166267 r3248039  
    9797     */
    9898    public function print_inline_styles(): void {
    99         $css = <<<CSS
     99        /* language=CSS */
     100        $css = '
    100101    #swpm-login-form .h-captcha {
    101102        margin: 10px 0;
    102103    }
    103 CSS;
     104';
    104105
    105106        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/SimpleMembership/LostPassword.php

    r3166267 r3248039  
    9898     */
    9999    public function print_inline_styles(): void {
    100         $css = <<<CSS
     100        /* language=CSS */
     101        $css = '
    101102    #swpm-pw-reset-form .h-captcha {
    102103        margin: 10px 0;
    103104    }
    104 CSS;
     105';
    105106
    106107        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/SimpleMembership/Register.php

    r3166267 r3248039  
    9898     */
    9999    public function print_inline_styles(): void {
    100         $css = <<<CSS
     100        /* language=CSS */
     101        $css = '
    101102    #swpm-registration-form .h-captcha {
    102103        margin: 10px 0;
    103104    }
    104 CSS;
     105';
    105106
    106107        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Spectra/Form.php

    r3143189 r3248039  
    155155        $style_shown = true;
    156156
    157         $css = <<<CSS
     157        /* language=CSS */
     158        $css = '
    158159    .uagb-forms-main-form .h-captcha {
    159160        margin-bottom: 20px;
    160161    }
    161 CSS;
     162';
    162163
    163164        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/SupportCandy/Base.php

    r3114572 r3248039  
    140140        $style_shown = true;
    141141
    142         $css = <<<CSS
     142        /* language=CSS */
     143        $css = '
    143144    form.wpsc-create-ticket .h-captcha {
    144145        margin: 0 15px 15px 15px;
    145146    }
    146 CSS;
     147';
    147148
    148149        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/UsersWP/Register.php

    r3114572 r3248039  
    8080        $template = (string) ob_get_clean();
    8181
    82         ob_start();
    83 
    84         $args = [
     82        $args     = [
    8583            'action' => static::ACTION,
    8684            'name'   => static::NONCE,
     
    9088            ],
    9189        ];
    92 
    93         HCaptcha::form_display( $args );
    94 
    95         $captcha = (string) ob_get_clean();
    96         $search  = '<input type="submit"';
     90        $hcaptcha = HCaptcha::form( $args );
     91        $search   = '/(<(?:input|button) type="submit")/';
    9792
    9893        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    99         echo str_replace( $search, $captcha . $search, $template );
     94        echo preg_replace( $search, $hcaptcha . '$1', $template );
    10095    }
    10196
  • hcaptcha-for-forms-and-more/trunk/src/php/WC/Login.php

    r3114572 r3248039  
    7171     */
    7272    public function print_inline_styles(): void {
    73         $css = <<<CSS
     73        /* language=CSS */
     74        $css = '
    7475    .woocommerce-form-login .h-captcha {
    7576        margin-top: 2rem;
    7677    }
    77 CSS;
     78';
    7879
    7980        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/WC/LostPassword.php

    r3114572 r3248039  
    6060     */
    6161    public function print_inline_styles(): void {
    62         $css = <<<CSS
     62        /* language=CSS */
     63        $css = '
    6364    .woocommerce-ResetPassword .h-captcha {
    6465        margin-top: 0.5rem;
    6566    }
    66 CSS;
     67';
    6768
    6869        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/WC/Register.php

    r3114572 r3248039  
    9494     */
    9595    public function print_inline_styles(): void {
    96         $css = <<<CSS
     96        /* language=CSS */
     97        $css = '
    9798    .woocommerce-form-register .h-captcha {
    9899        margin-top: 2rem;
    99100    }
    100 CSS;
     101';
    101102
    102103        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/WP/Base.php

    r3129246 r3248039  
    2323     *
    2424     * @return string
     25     * @noinspection PhpUndefinedFunctionInspection
    2526     */
    2627    private function get_login_url(): string {
     
    2829            // Integration with WPS Hide Login plugin.
    2930            return wp_parse_url( Plugin::get_instance()->new_login_url(), PHP_URL_PATH );
     31        }
     32
     33        if ( function_exists( 'perfmatters_login_url' ) ) {
     34            // Integration with Perfmatters plugin.
     35            return wp_parse_url( perfmatters_login_url(), PHP_URL_PATH );
    3036        }
    3137
  • hcaptcha-for-forms-and-more/trunk/src/php/WP/Comment.php

    r3233179 r3248039  
    115115        $comment_data = (array) $comment_data;
    116116
    117         if ( is_admin() ) {
     117        if ( is_admin() || wp_doing_ajax() ) {
    118118            return $comment_data;
    119119        }
  • hcaptcha-for-forms-and-more/trunk/src/php/WPDiscuz/Comment.php

    r3129246 r3248039  
    138138     */
    139139    public function print_inline_styles(): void {
    140         $css = <<<CSS
     140        /* language=CSS */
     141        $css = '
    141142    .wpd-field-hcaptcha .h-captcha {
    142143        margin-left: auto;
    143144    }
    144 CSS;
     145';
    145146
    146147        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/WPDiscuz/Subscribe.php

    r3114572 r3248039  
    7979     */
    8080    public function print_inline_styles(): void {
    81         $css = <<<CSS
     81        /* language=CSS */
     82        $css = '
    8283    #wpdiscuz-subscribe-form .h-captcha {
    8384        margin-top: 5px;
    8485        margin-left: auto;
    8586    }
    86 CSS;
     87';
    8788
    8889        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/WPForms/Form.php

    r3233179 r3248039  
    126126     */
    127127    public function print_inline_styles(): void {
    128         $css = <<<CSS
     128        /* language=CSS */
     129        $css = '
    129130    div.wpforms-container-full .wpforms-form .h-captcha {
    130131        position: relative;
     
    152153        position: relative;
    153154    }
    154 CSS;
     155';
    155156
    156157        HCaptcha::css_display( $css );
     
    197198
    198199        if ( isset( $fields['hcaptcha-heading'] ) ) {
    199             $notice_content = <<<HTML
     200            $notice_content = '
    200201<div
    201202        id="wpforms-setting-row-hcaptcha-heading"
     
    209210            </div>
    210211            <div class="wpforms-specific-note-content">
    211                 <p><strong>$label</strong></p>
    212                 <p>$description</p>
     212                <p><strong>' . $label . '</strong></p>
     213                <p>' . $description . '</p>
    213214            </div>
    214215        </div>
    215216    </span>
    216217</div>
    217 HTML;
     218';
    218219
    219220            $fields['hcaptcha-heading'] .= $notice_content;
  • hcaptcha-for-forms-and-more/trunk/src/php/WPForo/Base.php

    r3114572 r3248039  
    129129        $style_shown = true;
    130130
    131         $css = <<<CSS
     131        /* language=CSS */
     132        $css = '
    132133    #wpforo #wpforo-wrap div .h-captcha {
    133134        position: relative;
     
    142143        margin: 0 -20px;
    143144    }
    144 CSS;
     145';
    145146
    146147        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/Wordfence/General.php

    r3129246 r3248039  
    8585     */
    8686    public function print_inline_styles(): void {
    87         $css = <<<CSS
    88 #loginform[style="position: relative;"] > .h-captcha {
    89     visibility: hidden !important;
    90 }
    91 CSS;
     87        /* language=CSS */
     88        $css = '
     89    #loginform[style="position: relative;"] > .h-captcha {
     90        visibility: hidden !important;
     91    }
     92';
    9293
    9394        HCaptcha::css_display( $css );
  • hcaptcha-for-forms-and-more/trunk/src/php/includes/request.php

    r3233179 r3248039  
    320320}
    321321
    322 if ( ! function_exists( 'hcaptcha_get_verify_output' ) ) {
    323     /**
    324      * Get verify output.
    325      *
    326      * @param string $empty_message     Empty message.
    327      * @param string $fail_message      Fail message.
     322if ( ! function_exists( 'hcaptcha_get_verify_message' ) ) {
     323    /**
     324     * Get 'verify' message.
     325     *
    328326     * @param string $nonce_field_name  Nonce field name.
    329327     * @param string $nonce_action_name Nonce action name.
    330328     *
    331      * @deprecated 4.7.0
    332      *
    333329     * @return null|string Null on success, error message on failure.
    334330     */
    335     function hcaptcha_get_verify_output( string $empty_message, string $fail_message, string $nonce_field_name, string $nonce_action_name ): ?string {
    336         _deprecated_function( __FUNCTION__, '4.7.0', 'hcaptcha_verify_post' );
    337 
    338         if ( ! empty( $empty_message ) || ! empty( $fail_message ) ) {
    339             // @codeCoverageIgnoreStart
    340             _deprecated_argument( __FUNCTION__, '2.1.0' );
    341             // @codeCoverageIgnoreEnd
    342         }
    343 
     331    function hcaptcha_get_verify_message( string $nonce_field_name, string $nonce_action_name ): ?string {
    344332        return hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
    345333    }
    346334}
    347335
    348 if ( ! function_exists( 'hcaptcha_get_verify_message' ) ) {
    349     /**
    350      * Get 'verify' message.
     336if ( ! function_exists( 'hcaptcha_get_verify_message_html' ) ) {
     337    /**
     338     * Get verify message HTML.
    351339     *
    352340     * @param string $nonce_field_name  Nonce field name.
     
    355343     * @return null|string Null on success, error message on failure.
    356344     */
    357     function hcaptcha_get_verify_message( string $nonce_field_name, string $nonce_action_name ): ?string {
    358         return hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
    359     }
    360 }
    361 
    362 if ( ! function_exists( 'hcaptcha_get_verify_message_html' ) ) {
    363     /**
    364      * Get verify message HTML.
    365      *
    366      * @param string $nonce_field_name  Nonce field name.
    367      * @param string $nonce_action_name Nonce action name.
    368      *
    369      * @return null|string Null on success, error message on failure.
    370      */
    371345    function hcaptcha_get_verify_message_html( string $nonce_field_name, string $nonce_action_name ): ?string {
    372346        $message = hcaptcha_verify_post( $nonce_field_name, $nonce_action_name );
  • hcaptcha-for-forms-and-more/trunk/vendor/autoload.php

    r3233179 r3248039  
    2323require_once __DIR__ . '/composer/autoload_real.php';
    2424
    25 return ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18::getLoader();
     25return ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e::getLoader();
  • hcaptcha-for-forms-and-more/trunk/vendor/composer/autoload_classmap.php

    r3233179 r3248039  
    4141    'HCaptcha\\CF7\\Base' => $baseDir . '/src/php/CF7/Base.php',
    4242    'HCaptcha\\CF7\\CF7' => $baseDir . '/src/php/CF7/CF7.php',
     43    'HCaptcha\\CF7\\ReallySimpleCaptcha' => $baseDir . '/src/php/CF7/ReallySimpleCaptcha.php',
    4344    'HCaptcha\\ClassifiedListing\\Contact' => $baseDir . '/src/php/ClassifiedListing/Contact.php',
    4445    'HCaptcha\\ClassifiedListing\\Login' => $baseDir . '/src/php/ClassifiedListing/Login.php',
  • hcaptcha-for-forms-and-more/trunk/vendor/composer/autoload_real.php

    r3233179 r3248039  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18
     5class ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e
    66{
    77    private static $loader;
     
    2323        }
    2424
    25         spl_autoload_register(array('ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18', 'loadClassLoader'), true, true);
     25        require __DIR__ . '/platform_check.php';
     26
     27        spl_autoload_register(array('ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e', 'loadClassLoader'), true, true);
    2628        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    27         spl_autoload_unregister(array('ComposerAutoloaderInit5b9e71c5ecc4233f8a6f35918bdc1f18', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit3e48e8c03c5b5a02f16696bf1a21546e', 'loadClassLoader'));
    2830
    2931        require __DIR__ . '/autoload_static.php';
    30         call_user_func(\Composer\Autoload\ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::getInitializer($loader));
    3133
    3234        $loader->setClassMapAuthoritative(true);
  • hcaptcha-for-forms-and-more/trunk/vendor/composer/autoload_static.php

    r3233179 r3248039  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18
     7class ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e
    88{
    99    public static $prefixLengthsPsr4 = array (
     
    6969        'HCaptcha\\CF7\\Base' => __DIR__ . '/../..' . '/src/php/CF7/Base.php',
    7070        'HCaptcha\\CF7\\CF7' => __DIR__ . '/../..' . '/src/php/CF7/CF7.php',
     71        'HCaptcha\\CF7\\ReallySimpleCaptcha' => __DIR__ . '/../..' . '/src/php/CF7/ReallySimpleCaptcha.php',
    7172        'HCaptcha\\ClassifiedListing\\Contact' => __DIR__ . '/../..' . '/src/php/ClassifiedListing/Contact.php',
    7273        'HCaptcha\\ClassifiedListing\\Login' => __DIR__ . '/../..' . '/src/php/ClassifiedListing/Login.php',
     
    216217    {
    217218        return \Closure::bind(function () use ($loader) {
    218             $loader->prefixLengthsPsr4 = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$prefixLengthsPsr4;
    219             $loader->prefixDirsPsr4 = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$prefixDirsPsr4;
    220             $loader->classMap = ComposerStaticInit5b9e71c5ecc4233f8a6f35918bdc1f18::$classMap;
     219            $loader->prefixLengthsPsr4 = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$prefixLengthsPsr4;
     220            $loader->prefixDirsPsr4 = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$prefixDirsPsr4;
     221            $loader->classMap = ComposerStaticInit3e48e8c03c5b5a02f16696bf1a21546e::$classMap;
    221222
    222223        }, null, ClassLoader::class);
  • hcaptcha-for-forms-and-more/trunk/vendor/composer/installed.json

    r3064004 r3248039  
    130130            },
    131131            "install-path": "../matthiasmullie/path-converter"
     132        },
     133        {
     134            "name": "woocommerce/action-scheduler",
     135            "version": "3.9.2",
     136            "version_normalized": "3.9.2.0",
     137            "source": {
     138                "type": "git",
     139                "url": "https://github.com/woocommerce/action-scheduler.git",
     140                "reference": "efbb7953f72a433086335b249292f280dd43ddfe"
     141            },
     142            "dist": {
     143                "type": "zip",
     144                "url": "https://api.github.com/repos/woocommerce/action-scheduler/zipball/efbb7953f72a433086335b249292f280dd43ddfe",
     145                "reference": "efbb7953f72a433086335b249292f280dd43ddfe",
     146                "shasum": ""
     147            },
     148            "require": {
     149                "php": ">=7.1"
     150            },
     151            "require-dev": {
     152                "phpunit/phpunit": "^7.5",
     153                "woocommerce/woocommerce-sniffs": "0.1.0",
     154                "wp-cli/wp-cli": "~2.5.0",
     155                "yoast/phpunit-polyfills": "^2.0"
     156            },
     157            "time": "2025-02-03T09:09:30+00:00",
     158            "type": "wordpress-plugin",
     159            "extra": {
     160                "scripts-description": {
     161                    "test": "Run unit tests",
     162                    "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer",
     163                    "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier"
     164                }
     165            },
     166            "installation-source": "dist",
     167            "notification-url": "https://packagist.org/downloads/",
     168            "license": [
     169                "GPL-3.0-or-later"
     170            ],
     171            "description": "Action Scheduler for WordPress and WooCommerce",
     172            "homepage": "https://actionscheduler.org/",
     173            "support": {
     174                "issues": "https://github.com/woocommerce/action-scheduler/issues",
     175                "source": "https://github.com/woocommerce/action-scheduler/tree/3.9.2"
     176            },
     177            "install-path": "../woocommerce/action-scheduler"
    132178        }
    133179    ],
  • hcaptcha-for-forms-and-more/trunk/vendor/composer/installed.php

    r3233179 r3248039  
    22    'root' => array(
    33        'name' => 'hcaptcha/hcaptcha-wordpress-plugin',
    4         'pretty_version' => '4.10.0',
    5         'version' => '4.10.0.0',
    6         'reference' => '3f3d675e6a0c12404a0a7aa20b4472b5d37ea88d',
     4        'pretty_version' => '4.11.0',
     5        'version' => '4.11.0.0',
     6        'reference' => '83b1b3615b255290d2a5050750f078835392d129',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    1212    'versions' => array(
    1313        'hcaptcha/hcaptcha-wordpress-plugin' => array(
    14             'pretty_version' => '4.10.0',
    15             'version' => '4.10.0.0',
    16             'reference' => '3f3d675e6a0c12404a0a7aa20b4472b5d37ea88d',
     14            'pretty_version' => '4.11.0',
     15            'version' => '4.11.0.0',
     16            'reference' => '83b1b3615b255290d2a5050750f078835392d129',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
     
    3838            'dev_requirement' => false,
    3939        ),
     40        'woocommerce/action-scheduler' => array(
     41            'pretty_version' => '3.9.2',
     42            'version' => '3.9.2.0',
     43            'reference' => 'efbb7953f72a433086335b249292f280dd43ddfe',
     44            'type' => 'wordpress-plugin',
     45            'install_path' => __DIR__ . '/../woocommerce/action-scheduler',
     46            'aliases' => array(),
     47            'dev_requirement' => false,
     48        ),
    4049    ),
    4150);
Note: See TracChangeset for help on using the changeset viewer.