feat: caching, optimization, legal pages & footer

- WP Super Cache enabled (PHP mode, gzip, Nginx compatible)
- Autoptimize: CSS/HTML minification + deferred JS + Google Fonts optimization
- Cookie Notice: GDPR/LOPD banner styled with brand colors (navy/burgundy/gold)
- Legal pages: Aviso Legal, Política de Privacidad, Política de Cookies (ES)
- MU-plugin: custom footer with legal links + Cloud Host credit
- Footer: copyright, legal nav, Hosted & Maintained by Cloud Host (cloudhost.es)
- Security: X-Frame-Options, X-Content-Type, Referrer-Policy headers
- Security: XML-RPC disabled, REST user enumeration blocked
- Performance: emoji scripts removed, post revisions limited to 3
This commit is contained in:
Malin
2026-05-19 19:58:11 +02:00
parent 67241f537f
commit 6daabcab65
277 changed files with 96841 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,266 @@
/* -------------------------------------------------------------------
Microtip
Modern, lightweight css-only tooltips
Just 1kb minified and gzipped
@author Ghosh
@package Microtip
----------------------------------------------------------------------
1. Base Styles
2. Direction Modifiers
3. Position Modifiers
--------------------------------------------------------------------*/
/* ------------------------------------------------
[1] Base Styles
-------------------------------------------------*/
[aria-label][role~="tooltip"] {
position: relative;
}
[aria-label][role~="tooltip"]::before,
[aria-label][role~="tooltip"]::after {
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
will-change: transform;
opacity: 0;
pointer-events: none;
transition: all var(--microtip-transition-duration, .18s) var(--microtip-transition-easing, ease-in-out) var(--microtip-transition-delay, 0s);
position: absolute;
box-sizing: border-box;
z-index: 10;
transform-origin: top;
}
[aria-label][role~="tooltip"]::before {
background-size: 100% auto !important;
content: "";
}
[aria-label][role~="tooltip"]::after {
background: rgba(17, 17, 17, .9);
border-radius: 4px;
color: #ffffff;
content: attr(aria-label);
font-size: var(--microtip-font-size, 13px);
font-weight: var(--microtip-font-weight, normal);
text-transform: var(--microtip-text-transform, none);
padding: .5em 1em;
white-space: nowrap;
box-sizing: content-box;
}
[aria-label][role~="tooltip"]:hover::before,
[aria-label][role~="tooltip"]:hover::after,
[aria-label][role~="tooltip"]:focus::before,
[aria-label][role~="tooltip"]:focus::after {
opacity: 1;
pointer-events: auto;
}
/* ------------------------------------------------
[2] Position Modifiers
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position|="top"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%280%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 6px;
width: 18px;
margin-bottom: 5px;
}
[role~="tooltip"][data-microtip-position|="top"]::after {
margin-bottom: 11px;
}
[role~="tooltip"][data-microtip-position|="top"]::before {
transform: translate3d(-50%, 0, 0);
bottom: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position|="top"]:hover::before {
transform: translate3d(-50%, -5px, 0);
}
[role~="tooltip"][data-microtip-position|="top"]::after {
transform: translate3d(-50%, 0, 0);
bottom: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position="top"]:hover::after {
transform: translate3d(-50%, -5px, 0);
}
/* ------------------------------------------------
[2.1] Top Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="top-left"]::after {
transform: translate3d(calc(-100% + 16px), 0, 0);
bottom: 100%;
}
[role~="tooltip"][data-microtip-position="top-left"]:hover::after {
transform: translate3d(calc(-100% + 16px), -5px, 0);
}
/* ------------------------------------------------
[2.2] Top Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="top-right"]::after {
transform: translate3d(calc(0% + -16px), 0, 0);
bottom: 100%;
}
[role~="tooltip"][data-microtip-position="top-right"]:hover::after {
transform: translate3d(calc(0% + -16px), -5px, 0);
}
/* ------------------------------------------------
[2.3] Bottom
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position|="bottom"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2236px%22%20height%3D%2212px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28180%2018%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 6px;
width: 18px;
margin-top: 5px;
margin-bottom: 0;
}
[role~="tooltip"][data-microtip-position|="bottom"]::after {
margin-top: 11px;
}
[role~="tooltip"][data-microtip-position|="bottom"]::before {
transform: translate3d(-50%, -10px, 0);
bottom: auto;
left: 50%;
top: 100%;
}
[role~="tooltip"][data-microtip-position|="bottom"]:hover::before {
transform: translate3d(-50%, 0, 0);
}
[role~="tooltip"][data-microtip-position|="bottom"]::after {
transform: translate3d(-50%, -10px, 0);
top: 100%;
left: 50%;
}
[role~="tooltip"][data-microtip-position="bottom"]:hover::after {
transform: translate3d(-50%, 0, 0);
}
/* ------------------------------------------------
[2.4] Bottom Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="bottom-left"]::after {
transform: translate3d(calc(-100% + 16px), -10px, 0);
top: 100%;
}
[role~="tooltip"][data-microtip-position="bottom-left"]:hover::after {
transform: translate3d(calc(-100% + 16px), 0, 0);
}
/* ------------------------------------------------
[2.5] Bottom Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="bottom-right"]::after {
transform: translate3d(calc(0% + -16px), -10px, 0);
top: 100%;
}
[role~="tooltip"][data-microtip-position="bottom-right"]:hover::after {
transform: translate3d(calc(0% + -16px), 0, 0);
}
/* ------------------------------------------------
[2.6] Left
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="left"]::before,
[role~="tooltip"][data-microtip-position="left"]::after {
bottom: auto;
left: auto;
right: 100%;
top: 50%;
transform: translate3d(10px, -50%, 0);
}
[role~="tooltip"][data-microtip-position="left"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%28-90%2018%2018%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 18px;
width: 6px;
margin-right: 5px;
margin-bottom: 0;
}
[role~="tooltip"][data-microtip-position="left"]::after {
margin-right: 11px;
}
[role~="tooltip"][data-microtip-position="left"]:hover::before,
[role~="tooltip"][data-microtip-position="left"]:hover::after {
transform: translate3d(0, -50%, 0);
}
/* ------------------------------------------------
[2.7] Right
-------------------------------------------------*/
[role~="tooltip"][data-microtip-position="right"]::before,
[role~="tooltip"][data-microtip-position="right"]::after {
bottom: auto;
left: 100%;
top: 50%;
transform: translate3d(-10px, -50%, 0);
}
[role~="tooltip"][data-microtip-position="right"]::before {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2212px%22%20height%3D%2236px%22%3E%3Cpath%20fill%3D%22rgba%2817,%2017,%2017,%200.9%29%22%20transform%3D%22rotate%2890%206%206%29%22%20d%3D%22M2.658,0.000%20C-13.615,0.000%2050.938,0.000%2034.662,0.000%20C28.662,0.000%2023.035,12.002%2018.660,12.002%20C14.285,12.002%208.594,0.000%202.658,0.000%20Z%22/%3E%3C/svg%3E") no-repeat;
height: 18px;
width: 6px;
margin-bottom: 0;
margin-left: 5px;
}
[role~="tooltip"][data-microtip-position="right"]::after {
margin-left: 11px;
}
[role~="tooltip"][data-microtip-position="right"]:hover::before,
[role~="tooltip"][data-microtip-position="right"]:hover::after {
transform: translate3d(0, -50%, 0);
}
/* ------------------------------------------------
[3] Size
-------------------------------------------------*/
[role~="tooltip"][data-microtip-size="small"]::after {
white-space: initial;
width: 80px;
}
[role~="tooltip"][data-microtip-size="medium"]::after {
white-space: initial;
width: 150px;
}
[role~="tooltip"][data-microtip-size="large"]::after {
white-space: initial;
width: 260px;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,782 @@
/*!
Modaal - accessible modals - v0.4.4
by Humaan, for all humans.
http://humaan.com
*/
.modaal-noscroll {
overflow: hidden;
}
.modaal-accessible-hide {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0 !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
.modaal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
opacity: 0;
}
.modaal-wrapper {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
overflow: auto;
opacity: 1;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
-webkit-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.modaal-wrapper * {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-backface-visibility: hidden;
}
.modaal-wrapper .modaal-close {
border: none;
background: transparent;
padding: 0;
-webkit-appearance: none;
}
.modaal-wrapper.modaal-start_none {
display: none;
opacity: 1;
}
.modaal-wrapper.modaal-start_fade {
opacity: 0;
}
.modaal-wrapper *[tabindex="0"] {
outline: none !important;
}
.modaal-wrapper.modaal-fullscreen {
overflow: hidden;
}
.modaal-outer-wrapper {
display: table;
position: relative;
width: 100%;
height: 100%;
}
.modaal-fullscreen .modaal-outer-wrapper {
display: block;
}
.modaal-inner-wrapper {
display: table-cell;
width: 100%;
height: 100%;
position: relative;
vertical-align: middle;
text-align: center;
padding: 80px 25px;
}
.modaal-fullscreen .modaal-inner-wrapper {
padding: 0;
display: block;
vertical-align: top;
}
.modaal-container {
position: relative;
display: inline-block;
width: 100%;
margin: auto;
text-align: left;
color: #000;
max-width: 1000px;
border-radius: 0px;
background: #fff;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
cursor: auto;
}
.modaal-container.is_loading {
height: 100px;
width: 100px;
overflow: hidden;
}
.modaal-fullscreen .modaal-container {
max-width: none;
height: 100%;
overflow: auto;
}
.modaal-close {
position: fixed;
right: 20px;
top: 20px;
color: #fff;
cursor: pointer;
opacity: 1;
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0);
border-radius: 100%;
-webkit-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.modaal-close:focus,
.modaal-close:hover {
outline: none;
background: #fff;
}
.modaal-close:focus:before,
.modaal-close:focus:after,
.modaal-close:hover:before,
.modaal-close:hover:after {
background: #b93d0c;
}
.modaal-close span {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0 !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
.modaal-close:before,
.modaal-close:after {
display: block;
content: " ";
position: absolute;
top: 14px;
left: 23px;
width: 4px;
height: 22px;
border-radius: 4px;
background: #fff;
-webkit-transition: background 0.2s ease-in-out;
transition: background 0.2s ease-in-out;
}
.modaal-close:before {
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.modaal-close:after {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.modaal-fullscreen .modaal-close {
background: #afb7bc;
right: 10px;
top: 10px;
}
.modaal-content-container {
padding: 30px;
}
.modaal-confirm-wrap {
padding: 30px 0 0;
text-align: center;
font-size: 0;
}
.modaal-confirm-btn {
font-size: 14px;
display: inline-block;
margin: 0 10px;
vertical-align: middle;
cursor: pointer;
border: none;
background: transparent;
}
.modaal-confirm-btn.modaal-ok {
padding: 10px 15px;
color: #fff;
background: #555;
border-radius: 3px;
-webkit-transition: background 0.2s ease-in-out;
transition: background 0.2s ease-in-out;
}
.modaal-confirm-btn.modaal-ok:hover {
background: #2f2f2f;
}
.modaal-confirm-btn.modaal-cancel {
text-decoration: underline;
}
.modaal-confirm-btn.modaal-cancel:hover {
text-decoration: none;
color: #2f2f2f;
}
.modaal-instagram .modaal-container {
width: auto;
background: transparent;
box-shadow: none !important;
}
.modaal-instagram .modaal-content-container {
padding: 0;
background: transparent;
}
.modaal-instagram .modaal-content-container > blockquote {
width: 1px !important;
height: 1px !important;
opacity: 0 !important;
}
.modaal-instagram iframe {
opacity: 0;
margin: -6px !important;
border-radius: 0 !important;
width: 1000px !important;
max-width: 800px !important;
box-shadow: none !important;
-webkit-animation: instaReveal 1s linear forwards;
animation: instaReveal 1s linear forwards;
}
.modaal-image .modaal-inner-wrapper {
padding-left: 140px;
padding-right: 140px;
}
.modaal-image .modaal-container {
width: auto;
max-width: 100%;
}
.modaal-gallery-wrap {
position: relative;
color: #fff;
}
.modaal-gallery-item {
display: none;
}
.modaal-gallery-item img {
display: block;
}
.modaal-gallery-item.is_active {
display: block;
}
.modaal-gallery-label {
position: absolute;
left: 0;
width: 100%;
margin: 20px 0 0;
font-size: 18px;
text-align: center;
color: #fff;
}
.modaal-gallery-label:focus {
outline: none;
}
.modaal-gallery-control {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
opacity: 1;
cursor: pointer;
color: #fff;
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0);
border: none;
border-radius: 100%;
-webkit-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
}
.modaal-gallery-control.is_hidden {
opacity: 0;
cursor: default;
}
.modaal-gallery-control:focus,
.modaal-gallery-control:hover {
outline: none;
background: #fff;
}
.modaal-gallery-control:focus:before,
.modaal-gallery-control:focus:after,
.modaal-gallery-control:hover:before,
.modaal-gallery-control:hover:after {
background: #afb7bc;
}
.modaal-gallery-control span {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0 !important;
border: 0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
.modaal-gallery-control:before,
.modaal-gallery-control:after {
display: block;
content: " ";
position: absolute;
top: 16px;
left: 25px;
width: 4px;
height: 18px;
border-radius: 4px;
background: #fff;
-webkit-transition: background 0.2s ease-in-out;
transition: background 0.2s ease-in-out;
}
.modaal-gallery-control:before {
margin: -5px 0 0;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.modaal-gallery-control:after {
margin: 5px 0 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.modaal-gallery-next-inner {
left: 100%;
margin-left: 40px;
}
.modaal-gallery-next-outer {
right: 45px;
}
.modaal-gallery-prev:before,
.modaal-gallery-prev:after {
left: 22px;
}
.modaal-gallery-prev:before {
margin: 5px 0 0;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.modaal-gallery-prev:after {
margin: -5px 0 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.modaal-gallery-prev-inner {
right: 100%;
margin-right: 40px;
}
.modaal-gallery-prev-outer {
left: 45px;
}
.modaal-video-wrap {
margin: auto 50px;
position: relative;
}
.modaal-video-container {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
max-width: 100%;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
background: #000;
max-width: 1300px;
margin-left: auto;
margin-right: auto;
}
.modaal-video-container iframe,
.modaal-video-container object,
.modaal-video-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.modaal-iframe .modaal-content {
width: 100%;
height: 100%;
}
.modaal-iframe-elem {
width: 100%;
height: 100%;
display: block;
}
.modaal-loading-spinner {
background: none;
position: absolute;
width: 200px;
height: 200px;
top: 50%;
left: 50%;
margin: -100px 0 0 -100px;
-webkit-transform: scale(0.25);
-ms-transform: scale(0.25);
transform: scale(0.25);
}
.modaal-loading-spinner > div {
width: 24px;
height: 24px;
margin-left: 4px;
margin-top: 4px;
position: absolute;
}
.modaal-loading-spinner > div > div {
width: 100%;
height: 100%;
border-radius: 15px;
background: #fff;
}
.modaal-loading-spinner > div:nth-of-type(1) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: 0s;
animation-delay: 0s;
}
.modaal-loading-spinner > div:nth-of-type(2) > div,
.modaal-loading-spinner > div:nth-of-type(3) > div {
-ms-animation: modaal-loading-spinner 1s linear infinite;
-moz-animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation: modaal-loading-spinner 1s linear infinite;
-o-animation: modaal-loading-spinner 1s linear infinite;
}
.modaal-loading-spinner > div:nth-of-type(1) {
-ms-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(45deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(2) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .12s;
animation-delay: .12s;
}
.modaal-loading-spinner > div:nth-of-type(2) {
-ms-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(90deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(3) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .25s;
animation-delay: .25s;
}
.modaal-loading-spinner > div:nth-of-type(4) > div,
.modaal-loading-spinner > div:nth-of-type(5) > div {
-ms-animation: modaal-loading-spinner 1s linear infinite;
-moz-animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation: modaal-loading-spinner 1s linear infinite;
-o-animation: modaal-loading-spinner 1s linear infinite;
}
.modaal-loading-spinner > div:nth-of-type(3) {
-ms-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(135deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(4) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .37s;
animation-delay: .37s;
}
.modaal-loading-spinner > div:nth-of-type(4) {
-ms-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(180deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(5) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .5s;
animation-delay: .5s;
}
.modaal-loading-spinner > div:nth-of-type(6) > div,
.modaal-loading-spinner > div:nth-of-type(7) > div {
-ms-animation: modaal-loading-spinner 1s linear infinite;
-moz-animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation: modaal-loading-spinner 1s linear infinite;
-o-animation: modaal-loading-spinner 1s linear infinite;
}
.modaal-loading-spinner > div:nth-of-type(5) {
-ms-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(225deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(6) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .62s;
animation-delay: .62s;
}
.modaal-loading-spinner > div:nth-of-type(6) {
-ms-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(270deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(7) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .75s;
animation-delay: .75s;
}
.modaal-loading-spinner > div:nth-of-type(7) {
-ms-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(315deg) translate(70px, 0);
}
.modaal-loading-spinner > div:nth-of-type(8) > div {
-webkit-animation: modaal-loading-spinner 1s linear infinite;
animation: modaal-loading-spinner 1s linear infinite;
-webkit-animation-delay: .87s;
animation-delay: .87s;
}
.modaal-loading-spinner > div:nth-of-type(8) {
-ms-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
-webkit-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
transform: translate(84px, 84px) rotate(360deg) translate(70px, 0);
}
@media only screen and (min-width: 1400px) {
.modaal-video-container {
padding-bottom: 0;
height: 731px;
}
}
@media only screen and (max-width: 1140px) {
.modaal-image .modaal-inner-wrapper {
padding-left: 25px;
padding-right: 25px;
}
.modaal-gallery-control {
top: auto;
bottom: 20px;
-webkit-transform: none;
-ms-transform: none;
transform: none;
background: rgba(0, 0, 0, 0.7);
}
.modaal-gallery-control:before,
.modaal-gallery-control:after {
background: #fff;
}
.modaal-gallery-next {
left: auto;
right: 20px;
}
.modaal-gallery-prev {
left: 20px;
right: auto;
}
}
@media screen and (max-width: 900px) {
.modaal-instagram iframe {
width: 500px !important;
}
}
@media only screen and (max-width: 600px) {
.modaal-instagram iframe {
width: 280px !important;
}
}
@media screen and (max-height: 1100px) {
.modaal-instagram iframe {
width: 700px !important;
}
}
@media screen and (max-height: 1000px) {
.modaal-inner-wrapper {
padding-top: 60px;
padding-bottom: 60px;
}
.modaal-instagram iframe {
width: 600px !important;
}
}
@media screen and (max-height: 900px) {
.modaal-instagram iframe {
width: 500px !important;
}
.modaal-video-container {
max-width: 900px;
max-height: 510px;
}
}
@media only screen and (max-height: 820px) {
.modaal-gallery-label {
display: none;
}
}
@keyframes instaReveal {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes instaReveal {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes modaal-loading-spinner {
0% {
opacity: 1;
-ms-transform: scale(1.5);
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
opacity: .1;
-ms-transform: scale(1);
-webkit-transform: scale(1);
transform: scale(1);
}
}
@keyframes modaal-loading-spinner {
0% {
opacity: 1;
-ms-transform: scale(1.5);
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
100% {
opacity: .1;
-ms-transform: scale(1);
-webkit-transform: scale(1);
transform: scale(1);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,348 @@
.cn-dashboard-container {
min-height: 130px;
margin: 0 -4px;
text-align: center;
position: relative;
display: flex;
flex-direction: column;
}
.cn-dashboard-container .spinner {
position: absolute;
left: 50%;
top: 40%;
margin-left: -10px;
z-index: 10;
}
.cn-dashboard-container.loading {
pointer-events: none;
}
.cn-dashboard-container.loading:after {
position: absolute;
content: '';
display: block;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-color: rgba(255,255,255,0.8);
z-index: 1;
transition: all 0.2s;
}
.cn-dashboard_stats p.sub {
color: #8f8f8f;
font-size: 14px;
text-align: left;
padding-bottom: 3px;
border-bottom: 1px solid #ececec;
}
.cn-table-responsive {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.cn-table {
caption-side: bottom;
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
color: inherit;
vertical-align: top;
border-color: #dee2e6;
text-align: left;
}
.cn-table > thead {
vertical-align: bottom;
color: #212529;
}
.cn-table > tbody {
vertical-align: inherit;
}
.cn-table tbody,
.cn-table td,
.cn-table tfoot,
.cn-table th,
.cn-table thead,
.cn-table tr {
border-color: inherit;
border-style: solid;
border-width: 0;
}
.cn-table th,
.cn-table td {
text-align: inherit;
text-align: -webkit-match-parent;
}
.cn-table th:first-child,
.cn-table td:first-child {
width: 1px;
white-space: nowrap;
}
.cn-table th:last-child,
.cn-table td:last-child {
text-align: right;
}
.cn-table .no-posts :last-child {
text-align: left;
}
.cn-table > :not(caption) > * > * {
padding: .5rem .5rem;
background-color: transparent;
border-bottom-width: 1px;
box-shadow: inset 0 0 0 9999px transparent;
}
#cn_dashboard_stats .inside {
margin: 0;
padding: 0;
}
.cn-accordion-toggle {
cursor: pointer;
line-height: 1;
position: relative;
font-size: 14px;
font-weight: 400;
line-height: 1;
margin: 0;
padding: 15px 15px 0;
color: #23282c;
}
.cn-accordion-title {
display: inline-block;
padding-right: 10px;
}
.cn-accordion-actions {
position: absolute;
top: 0;
right: 0;
z-index: 1;
padding: 11px 30px 11px 0;
height: 14px;
line-height: 1;
}
.cn-accordion-actions .cn-accordion-action,
.cn-accordion-actions .cn-accordion-action::before {
font-size: 14px;
height: 14px;
width: 14px;
color: #72777c;
}
.cn-tooltip {
position: relative;
}
.cn-tooltip-icon {
display: inline-block;
width: 16px;
cursor: help;
}
.cn-tooltip-icon::before {
color: #b4b9be;
content: "\f14c";
display: inline-block;
font: normal 16px/1 dashicons;
position: absolute;
text-decoration: none !important;
speak: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
left: 0;
top: 2px;
}
.cn-according-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.cn-accordion-content {
padding: 20px 20px 15px;
height: 100%;
}
.cn-collapsed .cn-accordion-toggle::before {
transform: rotate(180deg);
}
.cn-collapsed .cn-accordion-content {
display: none;
}
.cn-infobox-container {
display: flex;
flex-wrap: wrap;
border: 1px solid #eee;
}
.cn-infobox-container:not(:first-child) {
border-top-color: transparent;
}
.cn-infobox {
width: 50%;
padding: 12px 10px 10px 15px;
position: relative;
text-align: left;
box-sizing: border-box;
border-left: 1px solid transparent;
min-height: 135px;
}
#cn-visits-infobox-consents {
border-left-color: #eee;
}
#cn-visits-infobox-limits,
#cn-visits-chart-limits {
border-top-color: #eee;
}
.cn-infobox-notice {
width: 100%;
margin: 5px 10px 15px 15px;
padding: 15px 12px;
position: relative;
text-align: left;
box-sizing: border-box;
background: rgba(255, 193, 7, 0.05);
border: 1px solid rgb(255, 193, 7);
}
.cn-infobox-notice p {
margin-top: 0;
}
.cn-infobox-notice p:last-child {
margin-bottom: 0;
}
.cn-infobox-notice p b {
font-size: 15px;
color: #222;
}
.cn-infobox-title {
font-size: 16px;
color: #393f4c;
font-weight: 700;
margin-top: 0;
padding-right: 18px;
text-overflow: ellipsis;
overflow: hidden;
white-space: pre;
line-height: 1.2;
}
.cn-infobox-number {
font-size: 36px;
float: none;
font-weight: 400;
display: inline-block;
line-height: 1;
margin-top: 11px;
color: rgb(32, 193, 158);
}
.cn-infobox-subtitle {
margin-top: 22px;
color: #a4a9ae;
}
.cn-infobox-subtitle p {
margin: 0 0 5px;
}
.cn-infobox-tooltip {
position: absolute;
top: 12px;
right: 15px;
}
.cn-widget-block {
position: relative;
overflow: hidden;
}
#cn-dashboard-upgrade {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: hidden;
box-sizing: border-box;
background: rgba(255,255,255,0.8);
min-height: 400px;
}
#cn-dashboard-modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 1.5em 3em;
box-shadow: 0 0 25px 10px rgba(0,0,0,0.1);
border-radius: 3px;
background-color: #fff;
text-align: center;
width: 22em;
}
#cn-dashboard-modal p {
margin: 0;
}
#cn-dashboard-modal h2 {
margin-bottom: 10px;
font-size: 21px;
}
.button.cn-button {
margin-top: 25px;
margin-bottom: 10px;
background-color: #20c19e;
border-color: #20c19e;
}
.button.cn-button:hover,
.button.cn-button:active,
.button.cn-button:focus {
background-color: #1ca98a;
border-color: #1ca98a;
}
.button.cn-button:focus {
box-shadow: 0 0 0 1px #fff, 0 0 0 3px #20c19e;
}
.cn-text-succcess {
color: #20c19e;
}
.cn-text-warning {
color: rgb(255, 193, 7);
}
.cn-text-danger {
color: rgb(200, 35, 51);
}

View File

@@ -0,0 +1,43 @@
#cn-admin-notice.cn-notice {
border-left-color: #20c19e;
}
.cn-notice .cn-notice-container {
padding: 1em;
display: flex;
justify-content: space-between;
align-items: center;
}
.cn-notice .cn-notice-actions {
margin-bottom: 0;
}
.cn-notice .cn-notice-actions .button {
display: inline-block;
margin: 0.5em 0 0;
}
.cn-notice .cn-notice-text h2 {
margin-top: 0;
margin-bottom: 0.5em;
}
.cn-notice .cn-notice-dismiss, .cn-notice .cn-notice-delay {
margin-left: 1em;
}
.cn-notice .cn-notice-text strong {
color: #000;
}
.cn-notice .cn-notice-text p:last-child {
margin-bottom: 0;
}
.cn-notice .cn-notice-icon svg path {
fill: #666 !important;
}
@media only screen and (max-width: 960px) {
.cn-notice .cn-notice-container {
flex-direction: column;
align-items: initial;
}
.cn-notice .cn-notice-container .cn-notice-text {
order: 1;
padding-top: 1em;
}
}

View File

@@ -0,0 +1,47 @@
.cn-deactivation-modal {
max-height: 500px;
overflow: hidden;
top: 50% !important;
transform: translateY(-50%);
}
.cn-deactivation-modal #TB_title {
padding: 13px 16px;
background: #f3f3f3;
}
.cn-deactivation-modal #TB_title > div {
padding: 0;
color: #000;
}
.cn-deactivation-modal #TB_ajaxContent {
width: auto !important;
height: calc(100% - 112px) !important;
padding: 0;
}
.cn-deactivation-modal #TB_closeAjaxWindow button {
right: 8px;
}
.cn-deactivation-options p:first-child {
margin-top: 0;
}
#cn-deactivation-container {
width: 100%;
}
#cn-deactivation-container textarea {
width: 100%;
min-height: 100px;
}
#cn-deactivation-body {
padding: 13px 16px;
}
#cn-deactivation-footer {
padding: 13px 16px;
position: absolute;
right: 0;
bottom: 0;
left: 0;
border-top: 1px solid #ddd;
background: #f3f3f3;
}
#cn-deactivation-footer .spinner {
float: none;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,833 @@
.cookie-notice-sidebar {
float: right;
width: 280px;
margin: 20px -300px 20px 20px;
position: relative;
}
.cookie-notice-sidebar .inner {
padding: 2em;
}
.cookie-notice-sidebar>div:not(:last-child) {
margin-bottom: 3em;
}
.cookie-notice-sidebar .inner img {
max-width: 80%;
height: auto;
display: block;
margin: 20px auto;
}
.cookie-notice-credits {
background: #fff;
box-shadow: 0 0 0 1px rgba(0,0,0,0.05);
}
.cookie-notice-credits .inner {
text-align: center;
margin: 0;
}
.button.cn-button {
background-color: #20c19e;
border-color: #20c19e;
}
.button.cn-button:active,.button.cn-button:focus,.button.cn-button:hover {
background-color: #1ca98a;
border-color: #1ca98a;
}
.button.cn-button:focus {
box-shadow: 0 0 0 1px #fff,0 0 0 3px #20c19e;
}
.button.button-secondary.cn-button {
background-color: #ffc107;
border-color: #ffc107;
color: #3c434a;
}
.button.button-secondary.cn-button:active,
.button.button-secondary.cn-button:focus,
.button.button-secondary.cn-button:hover {
background-color: #ffca2c;
border-color: #ffca2c;
}
.button.button-secondary.cn-button:focus {
box-shadow: 0 0 0 1px #fff,0 0 0 3px #ffc107;
}
.cookie-notice-settings .cookie-notice-credits h2 {
border: none;
padding-bottom: 0;
margin-top: 0;
}
.cookie-notice-credits h3 {
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0.66em 1.33em;
border-bottom: 1px solid #eee;
}
.cookie-notice-settings .df-credits form {
min-width: 260px;
margin-bottom: 1em;
}
.cookie-notice-settings .df-credits form input {
margin: 0;
padding: 0;
}
.cookie-notice-settings {
margin-right: 300px;
}
.cookie-notice-settings hr,.df-credits hr {
border: solid #eee;
border-width: 1px 0 0;
clear: both;
height: 0;
}
.cookie-notice-settings form {
float: left;
min-width: 463px;
width: 100%;
}
.cookie-notice-settings form.cn-options-disabled .cn-section-container.compliance-section,
.cookie-notice-settings form.cn-options-disabled .cn-section-container.misc-section,
.cookie-notice-settings form.cn-options-disabled .cn-section-container.notice-section,
.cookie-notice-settings form.cn-options-disabled .cn-section-container.design-section,
.cookie-notice-settings form.cn-options-disabled .cn-section-container.privacy-section,
.cookie-notice-settings form.cn-options-privacy-disabled .cn-section-container.privacy-section,
.cookie-notice-settings form.cn-options-compliance-disabled .cn-section-container.compliance-section,
form.cn-options-submit-disabled .submit {
opacity: 0.5;
pointer-events: none;
}
.cookie-notice-settings form .cn-options h2 {
margin: 1.5em 0;
}
.cookie-notice-settings .ui-button {
margin-bottom: 5px;
}
.cookie-notice-settings .description {
font-size: 13px;
margin-bottom: 8px;
}
.cookie-notice-settings .description strong {
color: #444;
}
.cookie-notice-settings .wp-list-table .column-more {
width: 80px;
}
.cookie-notice-settings .wp-list-table.cn-cookie-consent-logs {
margin-top: 30px;
}
.cookie-notice-settings .privacy-section table.wp-list-table {
position: relative;
}
.cookie-notice-settings .privacy-section table.wp-list-table {
margin-top: 12px;
}
.cookie-notice-settings .privacy-section table.wp-list-table th {
padding: 8px;
font-weight: normal;
}
.cookie-notice-settings .privacy-section table.wp-list-table th a {
padding: 0;
}
.cookie-notice-settings .privacy-section table.wp-list-table td.column-title {
font-weight: 600;
}
.cookie-notice-settings .privacy-section table.wp-list-table .title a {
pointer-events: none;
cursor: default;
}
.cookie-notice-settings .privacy-section table.wp-list-table.loading {
cursor: wait;
opacity: 0.5;
}
.cookie-notice-settings .privacy-section table.wp-list-table.loading a,
.cookie-notice-settings .privacy-section table.wp-list-table.loading input {
pointer-events: none;
}
.cookie-notice-settings .privacy-section .cn-unavailable label {
opacity: 0.7;
}
.cookie-notice-settings .privacy-section .cn-inactive .cn-privacy-consent-options-container {
opacity: 0.5;
filter: blur(3px);
pointer-events: none;
}
.cookie-notice-settings .privacy-section .search-box {
margin-bottom: 12px;
}
.cookie-notice-settings .privacy-section .spinner.inside, .cookie-notice-settings .logs-section .spinner.inside {
position: relative;
margin: 0;
padding: 0;
float: none;
left: calc( 50% - 10px );
}
#cn_colors label {
min-width: 10em;
display: inline-block;
}
#cn_colors div {
vertical-align: middle;
}
#cn_refuse_code .nav-tab-wrapper {
padding-top: 0;
}
#cn_refuse_code .refuse-code-tab {
display: none;
}
#cn_refuse_code .refuse-code-tab.active {
display: block;
}
#cn_refuse_code .refuse-code-tab .description {
margin-top: 10px;
}
.cn_compliance_status {
margin-right: 20px;
font-weight: 700;
display: inline-block;
}
#cn_app_status {
margin-bottom: 30px;
}
#cn_app_status .cn-status {
text-transform: uppercase;
font-weight: 700;
position: relative;
color: #999;
}
#cn_app_status .cn-status.cn-active {
color: #1ca98a;
}
#cn_app_status .cn-status.cn-inactive {
color: red;
}
#cn_colors_bar_opacity_range {
vertical-align: middle;
margin-right: 10px;
}
.cn-toggle-container .cn-toggle-item {
font-size: 14px;
display: block;
margin-bottom: 20px;
cursor: default;
}
.cn-toggle-container .cn-toggle-item input {
display: none;
}
.cn-toggle-container .cn-toggle-item span {
display: block;
}
.cn-toggle-container .cn-toggle-item .cn-toggle-heading {
color: #2271b1;
transition-property: border,background,color;
transition-duration: 0.05s;
transition-timing-function: ease-in-out;
text-decoration: underline;
font-weight: 600;
cursor: pointer;
position: relative;
padding-left: 20px;
}
.cn-toggle-container .cn-toggle-item .cn-toggle-heading:before {
border-style: solid;
border-width: 2px 2px 0 0;
content: '';
display: inline-block;
height: 6px;
width: 6px;
position: relative;
top: 5px;
left: 0;
vertical-align: top;
transform: rotate(45deg);
transition: transform 0.2s;
position: absolute;
}
.cn-toggle-container .cn-toggle-item .cn-toggle-body {
overflow: hidden;
transition: max-height 0.3s;
max-height: 0;
margin-top: 10px;
cursor: default;
padding-left: 20px;
}
.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-heading:before {
transform: rotate(135deg);
}
.cn-toggle-container .cn-toggle-item input:checked~.cn-toggle-body {
max-height: 100vh;
}
.cn-consent-log.disabled {
opacity: 0.5;
pointer-events: none;
}
.cn-consent-log .cn-consent-log-item {
font-size: 14px;
display: block;
cursor: pointer;
}
.cn-consent-log .cn-consent-log-item.disabled {
cursor: default;
pointer-events: none;
}
.cn-consent-log .cn-consent-log-item input {
display: none;
}
.cn-consent-log .cn-consent-log-item span {
display: block;
margin: 9px;
padding: 0;
vertical-align: text-top;
}
.cn-consent-log .cn-consent-log-item .cn-consent-log-head {
color: #2271b1;
transition-property: border,background,color;
transition-duration: 0.05s;
transition-timing-function: ease-in-out;
text-decoration: underline;
font-weight: 600;
position: relative;
}
.cn-consent-log .cn-consent-log-item .cn-consent-log-head:before {
border-style: solid;
border-width: 1px 1px 0 0;
content: '';
display: inline-block;
height: 6px;
width: 6px;
position: relative;
top: 4px;
left: 4px;
vertical-align: top;
transform: rotate(45deg);
transition: transform 0.2s;
position: absolute;
}
.cn-consent-log.disabled .cn-consent-log-item .cn-consent-log-head,
.cn-consent-log .cn-consent-log-item.disabled .cn-consent-log-head {
color: #bbb;
transition-property: none;
transition-duration: unset;
transition-timing-function: unset;
text-decoration: underline;
font-weight: 600;
position: relative;
pointer-events: none;
}
.cn-consent-log .cn-consent-log-item input:checked~.cn-consent-log-head:before {
transform: rotate(135deg);
}
.cn-consent-logs-row {
display: none;
}
.cn-consent-logs-data {
margin: 0 auto;
}
.cn-consent-logs-data.loading {
min-height: 100px;
}
.cn-consent-logs-data .spinner {
position: relative;
top: 38px;
margin: 0;
padding: 0;
float: none;
left: calc( 50% - 10px );
}
.cn-consent-logs-data p.description {
margin: 10px 0;
}
.cn-consent-logs-data .paginationjs {
justify-content: center;
margin-top: 10px;
}
.cn_fieldset_content {
margin-top: 10px;
}
.cn-asterix {
color: #ffc107;
}
@media only screen and (max-width:959px) {
.cookie-notice-sidebar {
width: 100%;
float:none;
margin: 20px 0;
}
.cookie-notice-settings {
margin-right: 0;
}
}
.cn-pricing-info .cn-pricing-head h2 {
font-size: 23px;
font-weight: normal;
margin: 1em 0;
}
.cn-pricing-info .cn-pricing-body {
padding-bottom: 0;
font-size: 14px;
text-align: left;
margin: 2em 0;
}
.cn-pricing-info .cn-pricing-footer {
margin: 1em 0;
}
.cn-pricing-info div.cn-pricing-body p {
padding-left: 30px;
margin: 0.75em 0;
}
.cn-pricing-info div.cn-pricing-body .cn-icon {
position: absolute;
top: 0;
left: 0;
}
.cn-active,
.cn-inactive,
.cn-pending {
position: relative;
}
.cn-active .cn-icon,
.cn-inactive .cn-icon,
.cn-pending .cn-icon {
box-sizing: border-box;
position: relative;
left: 0;
top: 5px;
display: inline-block;
transform: scale(1);
width: 22px;
height: 22px;
border: 2px solid;
border-radius: 44px;
}
.cn-active .cn-icon {
color: #20C19E;
}
.cn-active .cn-icon::after {
border-color: #20C19E;
}
.cn-pending .cn-icon::after {
border-color: #999;
}
.cn-active .cn-icon::after,
.cn-pending .cn-icon::after {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
left: 3px;
top: -1px;
width: 6px;
height: 10px;
border-width: 0 2px 2px 0;
border-style: solid;
transform-origin: bottom left;
transform: rotate(45deg);
}
.cn-inactive .cn-icon {
color: #FF0000;
}
.cn-inactive .cn-icon::after,
.cn-inactive .cn-icon::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
width: 12px;
height: 2px;
background: #FF0000;
transform: rotate(45deg);
border-radius: 5px;
top: 8px;
left: 3px;
}
.cn-inactive .cn-icon::after {
transform: rotate(-45deg);
}
.cn-option-disabled label {
opacity: 0.5;
pointer-events: none;
}
.cn-warning {
color: #ffc107;
}
#cookie-notice-conditions .inside {
padding: 0;
margin: 6px 0;
}
#cookie-notice-conditions .widefat {
border: none;
box-shadow: none;
background: none;
}
#cookie-notice-conditions .widefat td.label {
width: 25%;
}
#cookie-notice-conditions .widefat h4 {
margin: 8px 0;
}
#cookie-notice-conditions .widefat h4.or-rules {
margin: 0 5px 0 0;
}
#cookie-notice-conditions .widefat td, #cookie-notice-conditions .widefat th {
padding: 0;
}
#cookie-notice-conditions .widefat .widefat {
margin-bottom: 0;
}
#cookie-notice-conditions .widefat .widefat td {
padding: 5px;
}
#cookie-notice-conditions .widefat .widefat td.param {
width: 30%;
padding-left: 0;
}
#cookie-notice-conditions .widefat .widefat td.value {
width: 30%;
text-align: center;
}
#cookie-notice-conditions .widefat .widefat td.value .spinner {
float: none;
margin: 0;
}
#cookie-notice-conditions .widefat .widefat td.operator {
width: 20%;
}
#cookie-notice-conditions .widefat .widefat td.remove {
min-width: 40px;
text-align: left;
padding: 0;
}
#cookie-notice-conditions .widefat .widefat td.remove a {
vertical-align: middle;
}
#cookie-notice-conditions .widefat .widefat select {
width: 98.95%;
}
#cookie-notice-conditions #rules-groups {
margin-bottom: 10px;
}
#cookie-notice-conditions .rules-group:last-child .or-rules,
#cookie-notice-conditions .rules-group:only-child .or-rules {
display: none;
}
#cn-consent-logs-disabled {
position: relative;
}
.cn-section-container.compliance-section {
padding-bottom: 1em;
}
/* Sync Configuration Button */
#cn_sync_config .cn-button-container {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 8px;
}
#cn_sync_config .cn-sync-config-btn {
display: inline-flex;
align-items: center;
gap: 5px;
}
#cn_sync_config .cn-sync-config-btn .dashicons {
font-size: 16px;
width: 16px;
height: 16px;
transition: transform 0.3s ease;
}
#cn_sync_config .cn-sync-config-btn:hover .dashicons {
transform: rotate(180deg);
}
#cn_sync_config .cn-sync-spinner {
float: none;
margin: 0;
}
#cn_sync_config .cn-sync-spinner.is-active {
visibility: visible;
}
#cn_sync_config .cn-sync-status {
font-weight: 500;
color: #646970;
margin: 0 0 8px 0;
}
#cn_sync_config .cn-sync-message {
margin-top: 10px;
}
#cn_sync_config .cn-sync-message p {
margin: 0.5em 0;
}
#cn_sync_config .notice {
padding: 8px 12px;
margin: 0;
}
#cn_sync_config .notice-success {
border-left-color: #00a32a;
}
#cn_sync_config .notice-error {
border-left-color: #d63638;
}
.cn-section-container.compliance-section .form-table {
display: block;
padding-left: 1em;
padding-right: 1em;
background-color: rgba(32,193,158,0.05);
box-shadow: 0 0 0 1px rgba(32, 193, 158, 0.5);
}
form .cn-options .cn-section-container.logs-section > h2 {
margin-bottom: 0;
}
.cn-section-container.logs-section > .subsubsub {
margin-bottom: 1em;
}
#cn-consent-logs-upgrade {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: hidden;
box-sizing: border-box;
min-height: 400px;
}
#cn-consent-logs-bg {
width: 100%;
height: auto;
opacity: 0.8;
}
#cn-consent-logs-modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 1.5em 3em;
box-shadow: 0 0 25px 10px rgba(0,0,0,0.1);
border-radius: 3px;
background-color: #fff;
text-align: center;
width: 24em;
}
#cn-consent-logs-modal p {
margin: 0;
}
#cn-consent-logs-modal h2 {
font-size: 21px;
font-weight: 400;
margin: 0 0 10px 0;
padding: 9px 0 4px;
line-height: 1.3;
}
#cn-consent-logs-modal .button {
margin-top: 25px;
margin-bottom: 10px;
}
input[type="checkbox"].cn-privacy-consent-form-status {
position: relative;
height: 1.2rem;
width: 2.4rem;
cursor: pointer;
appearance: none;
-webkit-appearance: none;
border-radius: 9999px;
background-color: rgba(100, 116, 139, 0.377);
transition: all .3s ease;
border: none;
box-shadow: none;
opacity: 1;
}
.apply-all input[type="checkbox"].cn-privacy-consent-form-status {
pointer-events: none;
opacity: 0.3;
}
.apply-all input[type="checkbox"].cn-privacy-consent-form-status,
input[type="checkbox"].cn-privacy-consent-form-status:checked {
background-color: rgba(32, 193, 158, 1);
}
input[type="checkbox"].cn-privacy-consent-form-status:focus {
border-color: inherit;
box-shadow: none;
}
input[type="checkbox"].cn-privacy-consent-form-status::before {
position: absolute;
content: "";
left: calc(1.2rem - 1.3rem);
top: calc(1.2rem - 1.3rem);
display: block;
height: 1.3rem;
width: 1.3rem;
cursor: pointer;
border: 1px solid rgba(100, 116, 139, 0.5);
border-radius: 9999px;
background-color: rgba(255, 255, 255, 1);
box-shadow: 0 2px 6px rgba(100, 116, 139, 0.2);
transition: all .3s ease;
margin: 0;
}
input[type="checkbox"].cn-privacy-consent-form-status:hover::before {
box-shadow: 0 0 0px 5px rgba(0, 0, 0, .1)
}
.apply-all input[type="checkbox"].cn-privacy-consent-form-status:hover::before,
input[type="checkbox"].cn-privacy-consent-form-status:checked:hover::before {
box-shadow: 0 0 0px 5px rgba(32, 193, 158, .2)
}
.apply-all input[type="checkbox"].cn-privacy-consent-form-status:before,
input[type="checkbox"].cn-privacy-consent-form-status:checked:before {
transform: translateX(100%);
border-color: rgba(32, 193, 158, 1);
}
/* R1 US-3: Pro features locked callout */
.cn-pro-feature-item {
margin-bottom: 12px;
opacity: 0.6;
}
.cn-pro-lock {
display: inline-block;
background: #3c434a;
color: #fff;
font-size: 10px;
font-weight: 700;
padding: 2px 6px;
border-radius: 3px;
vertical-align: middle;
margin-left: 6px;
letter-spacing: 0.4px;
text-transform: uppercase;
}
#cn_pro_features_locked .cn-pro-upgrade-btn {
margin-top: 4px;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,343 @@
#cookie-notice {
position: fixed;
min-width: 100%;
height: auto;
z-index: 100000;
font-size: 13px;
letter-spacing: 0;
line-height: 20px;
left: 0;
text-align: center;
/* border-top: 2px solid #fbb03b; */
font-weight: normal;
font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
}
#cookie-notice,
#cookie-notice * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#cookie-notice.cn-animated {
-webkit-animation-duration: 0.5s !important;
animation-duration: 0.5s !important;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
#cookie-notice.cn-animated.cn-effect-none {
-webkit-animation-duration: 0.001s !important;
animation-duration: 0.001s !important;
}
#cookie-notice .cookie-notice-container {
display: block;
}
#cookie-notice.cookie-notice-hidden .cookie-notice-container {
display: none;
}
#cookie-notice .cookie-revoke-container {
display: block;
}
#cookie-notice.cookie-revoke-hidden .cookie-revoke-container {
display: none;
}
.cn-position-top {
top: 0;
}
.cn-position-bottom {
bottom: 0;
}
.cookie-notice-container {
padding: 15px 30px;
text-align: center;
width: 100%;
z-index: 2;
}
.cookie-revoke-container {
padding: 15px 30px;
width: 100%;
z-index: 1;
}
.cn-close-icon {
position: absolute;
right: 15px;
top: 50%;
margin: -10px 0 0 0;
width: 15px;
height: 15px;
opacity: 0.5;
padding: 10px;
border: none;
outline: none;
background: none;
box-shadow: none;
cursor: pointer;
}
.cn-close-icon:focus,
.cn-close-icon:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
.cn-close-icon:hover {
opacity: 1;
}
.cn-close-icon:before,
.cn-close-icon:after {
position: absolute;
content: ' ';
height: 15px;
width: 2px;
top: 3px;
background-color: rgba(128,128,128,1);
}
.cn-close-icon:before {
transform: rotate(45deg);
}
.cn-close-icon:after {
transform: rotate(-45deg);
}
#cookie-notice .cn-revoke-cookie {
margin: 0;
}
#cookie-notice .cn-button {
margin: 0 0 0 10px;
display: inline-block;
}
#cookie-notice .cn-button:not(.cn-button-custom) {
font-family: -apple-system,BlinkMacSystemFont,Arial,Roboto,"Helvetica Neue",sans-serif;
font-weight: normal;
font-size: 13px;
letter-spacing: 0.25px;
line-height: 20px;
margin: 0 0 0 10px;
text-align: center;
text-transform: none;
display: inline-block;
cursor: pointer;
touch-action: manipulation;
white-space: nowrap;
outline: none;
box-shadow: none;
text-shadow: none;
border: none;
-webkit-border-radius: 2rem;
-moz-border-radius: 2rem;
border-radius: 2rem;
text-decoration: none;
padding: 8.5px 10px;
line-height: 1;
color: inherit;
}
.cn-text-container {
margin: 0 0 6px 0;
}
.cn-text-container,
.cn-buttons-container {
display: inline-block;
}
/* Non-compliance warning styles */
.cn-compliance-warning {
display: block;
color: #f5a623 !important;
font-size: 12px;
line-height: 18px;
margin: 4px 0 8px 0;
}
.cn-compliance-warning .cn-warning-icon {
color: #f5a623 !important;
margin-right: 4px;
}
.cn-compliance-warning strong {
color: #f5a623 !important;
}
.cn-compliance-warning a {
color: #f5a623 !important;
text-decoration: underline;
}
.cn-compliance-warning a:hover {
color: #ffb84d !important;
}
#cookie-notice.cookie-notice-visible.cn-effect-none,
#cookie-notice.cookie-revoke-visible.cn-effect-none {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
#cookie-notice.cn-effect-none {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
}
#cookie-notice.cookie-notice-visible.cn-effect-fade,
#cookie-notice.cookie-revoke-visible.cn-effect-fade {
-webkit-animation-name: fadeIn;
animation-name: fadeIn;
}
#cookie-notice.cn-effect-fade {
-webkit-animation-name: fadeOut;
animation-name: fadeOut;
}
#cookie-notice.cookie-notice-visible.cn-effect-slide,
#cookie-notice.cookie-revoke-visible.cn-effect-slide{
-webkit-animation-name: slideInUp;
animation-name: slideInUp;
}
#cookie-notice.cn-effect-slide {
-webkit-animation-name: slideOutDown;
animation-name: slideOutDown;
}
#cookie-notice.cookie-notice-visible.cn-position-top.cn-effect-slide,
#cookie-notice.cookie-revoke-visible.cn-position-top.cn-effect-slide {
-webkit-animation-name: slideInDown;
animation-name: slideInDown;
}
#cookie-notice.cn-position-top.cn-effect-slide {
-webkit-animation-name: slideOutUp;
animation-name: slideOutUp;
}
@-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-webkit-keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@-webkit-keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes slideOutDown {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@keyframes slideOutDown {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
}
}
@-webkit-keyframes slideInDown {
from {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes slideInDown {
from {
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
visibility: visible;
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes slideOutUp {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@keyframes slideOutUp {
from {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
to {
visibility: hidden;
-webkit-transform: translate3d(0, -100%, 0);
transform: translate3d(0, -100%, 0);
}
}
@media all and (max-width: 900px) {
.cookie-notice-container #cn-notice-text {
display: block;
}
.cookie-notice-container #cn-notice-buttons {
display: block;
}
#cookie-notice .cn-button {
margin: 0 5px 5px 5px;
}
}
@media all and (max-width: 480px) {
.cookie-notice-container,
.cookie-revoke-container {
padding: 15px 25px;
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.732" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><path d="M8.75,96.232l122.5,0" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/></g></svg>

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.733" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><rect x="39.375" y="39.349" width="61.25" height="61.268" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.8px;"/></g></svg>

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" viewBox="0 0 140 140" width="140" height="140"><g transform="matrix(5.833333333333333,0,0,5.833333333333333,0,0)"><path d="M1.500 1.497 L22.500 1.497 L22.500 22.497 L1.500 22.497 Z" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M7.5 1.497L7.5 22.497" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></g></svg>

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 140 140" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;"><g><rect x="8.75" y="8.733" width="122.5" height="122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/><path d="M96.25,8.733l0,122.5" style="fill:none;fill-rule:nonzero;stroke:#000;stroke-width:8.75px;"/></g></svg>

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" viewBox="0 0 140 140" width="140" height="140"><g transform="matrix(5.833333333333333,0,0,5.833333333333333,0,0)"><path d="M1.500 1.497 L22.500 1.497 L22.500 22.497 L1.500 22.497 Z" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path><path d="M1.5 7.497L22.5 7.497" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></path></g></svg>

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Consent_Logs_Date_List_Table class.
*
* @class Cookie_Notice_Consent_Logs_Date_List_Table
*/
class Cookie_Notice_Consent_Logs_Date_List_Table extends WP_List_Table {
/**
* Display content.
*
* @return void
*/
public function views() {
// get main instance
$cn = Cookie_Notice();
$login_url = esc_url( $cn->get_url( 'login', '?utm_campaign=consentlogs&utm_source=wordpress&utm_medium=link' ) );
$message = __( 'The table below shows the consent records from your website accumulated from the last thirty days.', 'cookie-notice' );
$message .= ' ' . sprintf( __( 'View individual records by expanding a single row of data or log in to the <a href="%s" target="_blank">Compliance by Hu-manity.co</a> dashboard to export proof of consent.', 'cookie-notice' ), $login_url );
// disable if basic plan and data older than 7 days
if ( $cn->get_subscription() === 'basic' )
$message .= '<br/><span class="cn-asterix">*</span> ' . __( 'Note: sites on the Compliance by Hu-manity.co Free Plan can view consent records from the last 7 days and store data only for 30 days.', 'cookie-notice' );
echo '<p class="description">' . wp_kses_post( $message ) . '</p>';
}
/**
* Prepare the items for the table to process.
*
* @return void
*/
public function prepare_items() {
// get main instance
$cn = Cookie_Notice();
// get consent logs
if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
$analytics = get_site_option( 'cookie_notice_app_analytics', [] );
else
$analytics = get_option( 'cookie_notice_app_analytics', [] );
// get date format
$format = get_option( 'date_format' );
// get 30 days of default data
$logs = $this->fill_missing_dates( $format );
// get last day
$today = array_key_last( $logs );
// any data?
if ( ! empty( $analytics['consentActivities'] ) && is_array( $analytics['consentActivities'] ) ) {
foreach ( $analytics['consentActivities'] as $index => $entry ) {
// get date in digits only
$digits = (int) str_replace( '-', '', substr( $entry->eventdt, 0, 10 ) );
// current data?
if ( array_key_exists( $digits, $logs ) ) {
$logs[$digits]['level_' . (int) $entry->consentlevel] = (int) $entry->totalrecd;
$logs[$digits]['total'] += (int) $entry->totalrecd;
}
}
krsort( $logs, SORT_NUMERIC );
}
// remove last day
unset( $logs[$today] );
$this->_column_headers = [ $this->get_columns(), [], $this->get_sortable_columns(), '' ];
usort( $logs, [ $this, 'usort_reorder' ] );
$this->items = $logs;
}
/**
* Fill missing dates.
*
* @param string $format
*
* @return array
*/
private function fill_missing_dates( $format ) {
$empty_logs = [];
// get current date
$d = new DateTime();
// go back 30 days
$d->modify( '-30 days' );
// update dates for last 30 days
for ( $i = 1; $i <= 31; $i++ ) {
$date = $d->format( 'Y-m-d' );
$digits = (int) str_replace( '-', '', $date );
$empty_logs[$digits] = [
'slug' => $digits,
'date' => date_i18n( $format, strtotime( $date ) ),
'date_iso' => $date,
'level_1' => 0,
'level_2' => 0,
'level_3' => 0,
'total' => 0
];
$d->modify( '+1 days' );
}
return $empty_logs;
}
/**
* Sort consent logs.
*
* @param int $first
* @param int $second
*
* @return array
*/
public function usort_reorder( $first, $second ) {
// get orderby
$orderby = ( ! empty( $_GET['orderby'] ) ) ? sanitize_key( $_GET['orderby'] ) : 'date';
// skip invalid orderby
if ( ! array_key_exists( $orderby, $this->get_sortable_columns() ) )
return 0;
// get order
$order = ( ! empty( $_GET['order'] ) ) ? sanitize_key( $_GET['order'] ) : 'desc';
// use numeric value for dates
if ( $orderby === 'date' )
$orderby = 'slug';
// determine sort order
if ( $first[$orderby] === $second[$orderby] )
$result = 0;
else
$result = ( $first[$orderby] < $second[$orderby] ) ? -1 : 1;
return ( $order === 'asc' ) ? $result : -$result;
}
/**
* Define columns in listing table.
*
* @return array
*/
public function get_columns() {
$columns = [
'cb' => '',
'date' => __( 'Date', 'cookie-notice' ),
'level_1' => __( 'Level 1', 'cookie-notice' ),
'level_2' => __( 'Level 2', 'cookie-notice' ),
'level_3' => __( 'Level 3', 'cookie-notice' ),
'total' => __( 'Total', 'cookie-notice' )
];
return $columns;
}
/**
* Define sortable columns.
*
* @return array
*/
public function get_sortable_columns() {
return [
'date' => [ 'date', false ],
'level_1' => [ 'level_1', true ],
'level_2' => [ 'level_2', true ],
'level_3' => [ 'level_3', true ],
'total' => [ 'total', true ]
];
}
/**
* Display single row.
*
* @param array $item
*
* @return void
*/
public function single_row( $item ) {
$disabled = false;
// disable if basic plan and data older than 7 days
if ( Cookie_Notice()->get_subscription() === 'basic' ) {
// get current date
$last_date = new DateTime();
// go back 7 days
$last_date->modify( '-7 days' );
// get event date
$event_date = new DateTime( $item[ 'date_iso' ] );
if ( $event_date->getTimestamp() < $last_date->getTimestamp() )
$disabled = true;
}
echo '
<tr id="cn_consent_log_' . esc_attr( $item['slug'] ) . '" class="cn-consent-log' . ( $disabled ? ' disabled' : '' ) . '" data-date="' . esc_attr( $item['date_iso'] ) . '">';
$this->single_row_columns( $item );
echo '
</tr>';
}
/**
* Define what data to show on each column of the table.
*
* @param array $item
* @param string $column_name
*
* @return string
*/
public function column_default( $item, $column_name ) {
return esc_html( $item[$column_name] );
}
/**
* Define what data to show on cb column of the table.
*
* @param array $item
*
* @return string
*/
function column_cb( $item ) {
$disabled = false;
// disable if no data
if ( $item['total'] === 0 )
$disabled = true;
return '
<label for="cn-consent-log-' . esc_attr( $item['slug'] ) . '" class="cn-consent-log-item' . ( $disabled ? ' disabled' : '' ) . '">
<input id="cn-consent-log-' . esc_attr( $item['slug'] ) . '" type="checkbox">
<span class="cn-consent-log-head"></span>
</label>';
}
/**
* Generate table navigation.
*
* @param string $which
*
* @return void
*/
protected function display_tablenav( $which ) {
// do nothing
}
/**
* Display bulk actions.
*
* @return array
*/
public function get_bulk_actions() {
return [];
}
/**
* Display empty result.
*
* @return void
*/
public function no_items() {
echo __( 'No cookie consent logs found.', 'cookie-notice' );
}
}

View File

@@ -0,0 +1,299 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Consent_Logs_List_Table class.
*
* @class Cookie_Notice_Consent_Logs_List_Table
*/
class Cookie_Notice_Consent_Logs_List_Table extends WP_List_Table {
private $cn_data = [];
private $cn_item_number = 0;
/**
* Set data.
*
* @param array $data
*
* @return void
*/
public function cn_set_data( $data ) {
$this->cn_data = $data;
}
/**
* Prepare the items for the table to process.
*
* @return void
*/
public function prepare_items() {
// prepare items
$items = [];
// no data?
if ( ! empty( $this->cn_data ) ) {
foreach ( $this->cn_data as $no => $consent_log ) {
$categories = [];
if ( $consent_log->ev_essential )
$categories[] = esc_html__( 'Basic Operations', 'cookie-notice' );
if ( $consent_log->ev_functional )
$categories[] = esc_html__( 'Content Personalization', 'cookie-notice' );
if ( $consent_log->ev_analytics )
$categories[] = esc_html__( 'Site Optimization', 'cookie-notice' );
if ( $consent_log->ev_marketing )
$categories[] = esc_html__( 'Ad Personalization', 'cookie-notice' );
// get current date
$timestamp = new DateTime( $consent_log->timestamp );
// get deuration in days
$duration = (int) $consent_log->ev_eventdetails_expiry;
if ( $duration === 30 )
$duration = __( '1 month', 'cookie-notice' );
elseif ( $duration === 90 )
$duration = __( '3 months', 'cookie-notice' );
elseif ( $duration === 182 )
$duration = __( '6 months', 'cookie-notice' );
elseif ( $duration === 365 )
$duration = __( '1 year', 'cookie-notice' );
elseif ( $duration === 730 )
$duration = __( '2 years', 'cookie-notice' );
$items[] = [
'consent_id' => $consent_log->ev_eventdetails_consentid,
'consent_level' => sprintf( __( 'Level %d', 'cookie-notice' ), $consent_log->ev_consentlevel ),
'consent_categories' => implode( ', ', $categories ),
'consent_duration' => $duration,
'consent_time' => $timestamp->format( get_option( 'time_format' ) ) . ' ' . __( 'GMT', 'cookie-notice' ),
'consent_ip_address' => $consent_log->rj_ip
];
}
}
// count items
$noi = count( $items );
$per_page = 10;
$this->set_pagination_args(
[
'total_items' => $noi,
'total_pages' => (int) ceil( $noi / $per_page ),
'per_page' => $per_page
]
);
$this->_column_headers = [ $this->get_columns(), [], $this->get_sortable_columns(), '' ];
$this->items = $items;
}
/**
* Define columns in listing table.
*
* @return array
*/
public function get_columns() {
$columns = [
'consent_id' => __( 'Consent ID', 'cookie-notice' ),
'consent_level' => __( 'Consent Level', 'cookie-notice' ),
'consent_categories' => __( 'Categories', 'cookie-notice' ),
'consent_duration' => __( 'Duration', 'cookie-notice' ),
'consent_time' => __( 'Time', 'cookie-notice' ),
'consent_ip_address' => __( 'IP address', 'cookie-notice' )
];
return $columns;
}
/**
* Define sortable columns.
*
* @return array
*/
public function get_sortable_columns() {
return [];
}
/**
* Define what data to show on each column of the table.
*
* @param array $item
* @param string $column_name
*
* @return string
*/
public function column_default( $item, $column_name ) {
return esc_html( $item[$column_name] );
}
/**
* Generate table navigation.
*
* @param string $which
*
* @return void
*/
protected function display_tablenav( $which ) {
parent::display_tablenav( $which );
}
/**
* Generate content for a single row of the table.
*
* @param array $item
*
* @return void
*/
public function single_row( $item ) {
$this->cn_item_number++;
echo '<tr' . ( $this->cn_item_number > $this->_pagination_args['per_page'] ? ' style="display: none"' : '' ) . '>';
$this->single_row_columns( $item );
echo '</tr>';
}
/**
* Display the pagination.
*
* @param string $which
*
* @return void
*/
protected function pagination( $which ) {
if ( empty( $this->_pagination_args ) )
return;
$total_items = $this->_pagination_args['total_items'];
$total_pages = $this->_pagination_args['total_pages'];
$output = '<span class="displaying-num">' . sprintf(
/* translators: %s: Number of items. */
_n( '%s item', '%s items', $total_items ),
number_format_i18n( $total_items )
) . '</span>';
$page_links = array();
$total_pages_before = '<span class="paging-input">';
$total_pages_after = '</span></span>';
// first page
$page_links[] = sprintf(
"<a class='first-page button disabled' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'First page' ),
'&laquo;'
);
// previous page
$page_links[] = sprintf(
"<a class='prev-page button disabled' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Previous page' ),
'&lsaquo;'
);
$html_current_page = '<span class="current-page">' . (int) $this->get_pagenum() . '</span>';
$total_pages_before = sprintf(
'<span class="screen-reader-text">%s</span>' .
'<span id="table-paging-' . $which . '" class="paging-input">' .
'<span class="tablenav-paging-text">',
/* translators: Hidden accessibility text. */
__( 'Current Page' )
);
$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
$page_links[] = $total_pages_before . sprintf(
/* translators: 1: Current page, 2: Total pages. */
_x( '%1$s of %2$s', 'paging' ),
$html_current_page,
$html_total_pages
) . $total_pages_after;
// next page
$page_links[] = sprintf(
"<a class='next-page button' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Next page' ),
'&rsaquo;'
);
// last page
$page_links[] = sprintf(
"<a class='last-page button' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Last page' ),
'&raquo;'
);
$pagination_links_class = 'pagination-links';
if ( ! empty( $infinite_scroll ) )
$pagination_links_class .= ' hide-if-js';
$output .= "\n<span class='$pagination_links_class' data-total=" . (int) $total_pages . ">" . implode( "\n", $page_links ) . '</span>';
if ( $total_pages )
$page_class = $total_pages < 2 ? ' one-page' : '';
else
$page_class = ' no-pages';
$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
echo $this->_pagination;
}
/**
* Print column headers.
*
* @param bool $with_id
*
* @return void
*/
public function print_column_headers( $with_id = true ) {
// do not print column ids
parent::print_column_headers( false );
}
/**
* Display bulk actions.
*
* @return array
*/
public function get_bulk_actions() {
return [];
}
/**
* Display empty result.
*
* @return void
*/
public function no_items() {
echo __( 'No cookie consent logs found.', 'cookie-notice' );
}
}

View File

@@ -0,0 +1,120 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Consent_Logs class.
*
* @class Cookie_Notice_Consent_Logs
*/
class Cookie_Notice_Consent_Logs {
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'wp_ajax_cn_get_cookie_consent_logs', [ $this, 'get_cookie_consent_logs' ] );
}
/**
* Get cookie consent logs via AJAX request.
*
* @return void
*/
public function get_cookie_consent_logs() {
// check data
if ( ! isset( $_POST['action'], $_POST['date'], $_POST['nonce'] ) )
wp_send_json_error();
// valid nonce?
if ( ! check_ajax_referer( 'cn-get-cookie-consent-logs', 'nonce' ) )
wp_send_json_error();
// check capability
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
wp_send_json_error();
// sanitize date
$date = preg_replace( '[^\d-]', '', $_POST['date'] );
// get datetime
$dt = DateTime::createFromFormat( 'Y-m-d', $date );
// valid date?
if ( $dt && $dt->format( 'Y-m-d' ) === $date ) {
$data = Cookie_Notice()->welcome_api->get_cookie_consent_logs( $date );
if ( is_array( $data ) )
wp_send_json_success( $this->get_cookie_consent_logs_table( $data ) );
else
wp_send_json_error( $data );
}
wp_send_json_error();
}
/**
* Get consent logs from specific date.
*
* @param array $data
*
* @return string
*/
public function get_cookie_consent_logs_table( $data ) {
// include wp list table class if needed
if ( ! class_exists( 'WP_List_Table' ) )
include_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
// include consent logs list table
include_once( COOKIE_NOTICE_PATH . '/includes/consent-logs-list-table.php' );
// initialize list table
$list_table = new Cookie_Notice_Consent_Logs_List_Table( [
'plural' => 'cn-cookie-consent-day-logs',
'singular' => 'cn-cookie-consent-day-log',
'ajax' => false
] );
// prepare data
$list_table->cn_set_data( $data );
// prepare items
$list_table->prepare_items();
ob_start();
$list_table->display();
$html = ob_get_clean();
return $html;
}
/**
* Get single row template.
*
* @return string
*/
public function get_single_row_template() {
return '
<tr id="" class="cn-consent-log-details">
<th></th>
<td colspan="5">
<div class="cn-consent-logs-data loading">
<span class="spinner is-active"></span>
</div>
</td>
</tr>';
}
/**
* Get error template.
*
* @return string
*/
public function get_error_template() {
return '<p class="description">' . esc_html__( 'We were unable to download consent logs due to an error. Please try again later.', 'cookie-notice' ) . '</p>';
}
}

View File

@@ -0,0 +1,782 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Evaluate notification rules from notifications.json for the wpDashboard slot.
*
* @param float $threshold_used Usage percentage (0-100).
* @param string $tier Current tier: 'basic', 'free', or 'pro'.
* @return array|null Highest-priority matching rule, or null.
*/
function cn_get_dashboard_notification( $threshold_used, $tier ) {
$rules_json = file_get_contents( COOKIE_NOTICE_PATH . 'includes/notifications.json' );
$rules_data = $rules_json !== false ? json_decode( $rules_json, true ) : null;
if ( ! is_array( $rules_data ) || empty( $rules_data['rules'] ) ) {
return null;
}
$best = null;
foreach ( $rules_data['rules'] as $rule ) {
if ( ( $rule['slot'] ?? '' ) !== 'wpDashboard' ) {
continue;
}
// Tier check.
if ( isset( $rule['condition']['tier'] ) && $rule['condition']['tier'] !== $tier ) {
continue;
}
// Usage range check: [inclusive, exclusive).
if ( isset( $rule['condition']['usagePercent'] ) ) {
$min = $rule['condition']['usagePercent'][0];
$max = $rule['condition']['usagePercent'][1];
if ( $min !== null && $threshold_used < $min ) {
continue;
}
if ( $max !== null && $threshold_used >= $max ) {
continue;
}
}
if ( ! $best || $rule['priority'] > $best['priority'] ) {
$best = $rule;
}
}
return $best;
}
/**
* Cookie_Notice_Dashboard class.
*
* @class Cookie_Notice_Dashboard
*/
class Cookie_Notice_Dashboard {
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'wp_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
add_action( 'wp_network_dashboard_setup', [ $this, 'wp_dashboard_setup' ], 11 );
add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts_styles' ] );
// site status
add_filter( 'site_status_tests', [ $this, 'add_tests' ] );
}
/**
* Initialize widget.
*
* @global array $wp_meta_boxes
*
* @return void
*/
public function wp_dashboard_setup() {
// filter user_can_see_stats
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
return;
// get main instance
$cn = Cookie_Notice();
// check when to hide widget
if ( is_multisite() ) {
// site dashboard
if ( current_action() === 'wp_dashboard_setup' && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
return;
// network dashboard
if ( current_action() === 'wp_network_dashboard_setup' ) {
if ( $cn->is_plugin_network_active() ) {
if ( ! $cn->network_options['general']['global_override'] )
return;
} else
return;
}
}
// check is it network admin
if ( $cn->is_network_admin() )
$dashboard_key = 'dashboard-network';
else
$dashboard_key = 'dashboard';
global $wp_meta_boxes;
// set widget key
$widget_key = 'cn_dashboard_stats';
// add dashboard chart widget
wp_add_dashboard_widget( $widget_key, __( 'Compliance by Hu-manity.co', 'cookie-notice' ), [ $this, 'dashboard_widget' ] );
// get widgets
$normal_dashboard = $wp_meta_boxes[$dashboard_key]['normal']['core'];
// attempt to place the widget at the top
$widget_instance = [
$widget_key => $normal_dashboard[ $widget_key ]
];
// remove new widget
unset( $normal_dashboard[ $widget_key ] );
// merge widgets
$sorted_dashboard = array_merge( $widget_instance, $normal_dashboard );
// update widgets
$wp_meta_boxes[$dashboard_key]['normal']['core'] = $sorted_dashboard;
}
/**
* Enqueue admin scripts and styles.
*
* @param string $pagenow
* @return void
*/
public function admin_scripts_styles( $pagenow ) {
if ( $pagenow !== 'index.php' )
return;
// filter user_can_see_stats
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
return;
// get main instance
$cn = Cookie_Notice();
$date_format = get_option( 'date_format' );
if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
$analytics = get_site_option( 'cookie_notice_app_analytics', [] );
else
$analytics = get_option( 'cookie_notice_app_analytics', [] );
// styles
wp_enqueue_style( 'cookie-notice-admin-dashboard', COOKIE_NOTICE_URL . '/css/admin-dashboard.css', [], $cn->defaults['version'] );
wp_enqueue_style( 'cookie-notice-microtip', COOKIE_NOTICE_URL . '/assets/microtip/microtip.min.css', [], $cn->defaults['version'] );
// bail if compliance is not active
if ( $cn->get_status() !== 'active' )
return;
// scripts
wp_register_script( 'cookie-notice-admin-chartjs', COOKIE_NOTICE_URL . '/assets/chartjs/chart.min.js', [ 'jquery' ], '4.5.1', true );
wp_enqueue_script( 'cookie-notice-admin-dashboard', COOKIE_NOTICE_URL . '/js/admin-dashboard.js', [ 'jquery', 'cookie-notice-admin-chartjs' ], $cn->defaults['version'], true );
// cycle usage data
$cycle_usage = [
'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0
];
// no more than threshold available
$cycle_usage['visits'] = $cycle_usage['visits'] > $cycle_usage['threshold'] ? $cycle_usage['threshold'] : $cycle_usage['visits'];
// available visits, -1 for no pro plans
$cycle_usage['visits_available'] = $cycle_usage['threshold'] ? $cycle_usage['threshold'] - $cycle_usage['visits'] : -1;
// get used threshold info
if ( $cycle_usage['threshold'] > 0 ) {
$threshold_used = ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100;
if ( $threshold_used > 100 )
$threshold_used = 100;
} else
$threshold_used = 0;
// CN_DEV_MODE: override usage % for testing. Param: ?cn_usage=0-100
if ( defined( 'CN_DEV_MODE' ) && CN_DEV_MODE && current_user_can( 'manage_options' ) && isset( $_GET['cn_usage'] ) ) {
$cn_usage_override = (int) $_GET['cn_usage'];
if ( $cn_usage_override >= 0 && $cn_usage_override <= 100 ) {
$threshold_used = $cn_usage_override;
if ( $cycle_usage['threshold'] <= 0 )
$cycle_usage['threshold'] = 10000;
$cycle_usage['visits'] = (int) round( $cycle_usage['threshold'] * ( $threshold_used / 100 ) );
$cycle_usage['visits_available'] = $cycle_usage['threshold'] - $cycle_usage['visits'];
}
}
$chartdata = [
'usage' => [
'type' => 'doughnut',
'options' => [
'responsive' => true,
'plugins' => [
'legend' => [
'position' => 'top'
]
],
'hover' => [
'mode' => 'label'
],
'layout' => [
'padding' => 0
]
],
'data' => [
'labels' => [
_x( 'Used', 'threshold limit', 'cookie-notice' ),
_x( 'Free', 'threshold limit', 'cookie-notice' )
],
'datasets' => [
[
'data' => [ $cycle_usage['visits'], $cycle_usage['visits_available'] ],
'backgroundColor' => [
'rgb(32, 193, 158)',
'rgb(235, 233, 235)'
]
]
]
]
],
'consent-activity' => [
'type' => 'line',
'options' => [
'maintainAspectRatio' => false,
'responsive' => true,
'scales' => [
'x' => [
'display' => true,
'title' => [
'display' => false
]
],
'y' => [
'display' => true,
'grace' => 0,
'beginAtZero' => true,
'title' => [
'display' => false
],
'ticks' => [
'precision' => 0,
'maxTicksLimit' => 12
]
]
]
]
],
'privacy-consent-logs-activity' => [
'type' => 'line',
'options' => [
'maintainAspectRatio' => false,
'responsive' => true,
'scales' => [
'x' => [
'display' => true,
'title' => [
'display' => false
]
],
'y' => [
'display' => true,
'grace' => 0,
'beginAtZero' => true,
'title' => [
'display' => false
],
'ticks' => [
'precision' => 0,
'maxTicksLimit' => 12
]
]
],
'plugins' => [
'legend' => [
'display' => false
]
]
]
]
];
// warning usage color
if ( $threshold_used > 80 && $threshold_used < 100 )
$chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(255, 193, 7)';
// danger usage color
elseif ( $threshold_used == 100 )
$chartdata['usage']['data']['datasets'][0]['backgroundColor'][0] = 'rgb(220, 53, 69)';
$consent_activity_data = [
'labels' => [],
'datasets' => [
0 => [
'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 1 ),
'data' => [],
'fill' => true,
'backgroundColor' => 'rgba(196, 196, 196, 0.3)',
'borderColor' => 'rgba(196, 196, 196, 1)',
'borderWidth' => 1.2,
'borderDash' => [],
'pointBorderColor' => 'rgba(196, 196, 196, 1)',
'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
'pointBorderWidth' => 1.2
],
1 => [
'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 2 ),
'data' => [],
'fill' => true,
'backgroundColor' => 'rgba(213, 181, 101, 0.3)',
'borderColor' => 'rgba(213, 181, 101, 1)',
'borderWidth' => 1.2,
'borderDash' => [],
'pointBorderColor' => 'rgba(213, 181, 101, 1)',
'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
'pointBorderWidth' => 1.2
],
2 => [
'label' => sprintf( __( 'Level %s', 'cookie-notice' ), 3 ),
'data' => [],
'fill' => true,
'backgroundColor' => 'rgba(152, 145, 177, 0.3)',
'borderColor' => 'rgba(152, 145, 177, 1)',
'borderWidth' => 1.2,
'borderDash' => [],
'pointBorderColor' => 'rgba(152, 145, 177, 1)',
'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
'pointBorderWidth' => 1.2
]
]
];
// generate chart days
$chart_date_format = 'j/m';
for ( $i = 29; $i >= 0; $i-- ) {
// set label
$consent_activity_data['labels'][] = date( $chart_date_format, strtotime( '-'. ( $i + 1 ) .' days' ) );
// reset datasets
$consent_activity_data['datasets'][0]['data'][] = 0;
$consent_activity_data['datasets'][1]['data'][] = 0;
$consent_activity_data['datasets'][2]['data'][] = 0;
}
if ( ! empty( $analytics['consentActivities'] ) && is_array( $analytics['consentActivities'] ) ) {
// set consent records in charts days
foreach ( $analytics['consentActivities'] as $index => $entry ) {
$time = date_i18n( $chart_date_format, strtotime( $entry->eventdt ) );
$i = array_search( $time, $consent_activity_data['labels'] );
if ( $i !== false )
$consent_activity_data['datasets'][(int) $entry->consentlevel - 1]['data'][$i] = (int) $entry->totalrecd;
}
}
$chartdata['consent-activity']['data'] = $consent_activity_data;
$privacy_consent_logs_activity_data = [
'labels' => [],
'datasets' => [
0 => [
'label' => __( 'Privacy Content Logs', 'cookie-notice' ),
'data' => [],
'fill' => true,
'backgroundColor' => 'rgba(32, 193, 158, 0.3)',
'borderColor' => 'rgba(32, 193, 158, 1)',
'borderWidth' => 1.2,
'borderDash' => [],
'pointBorderColor' => 'rgba(32, 193, 158, 1)',
'pointBackgroundColor' => 'rgba(255, 255, 255, 1)',
'pointBorderWidth' => 1.2
]
]
];
for ( $i = 29; $i >= 0; $i-- ) {
// set label
$privacy_consent_logs_activity_data['labels'][] = date( $chart_date_format, strtotime( '-'. ( $i + 1 ) .' days' ) );
// reset dataset
$privacy_consent_logs_activity_data['datasets'][0]['data'][] = 0;
}
if ( ! empty( $analytics['privacyActivities'] ) && is_array( $analytics['privacyActivities'] ) ) {
// set consent records in charts days
foreach ( $analytics['privacyActivities'] as $index => $entry ) {
$time = date_i18n( $chart_date_format, strtotime( $entry->date ) );
$i = array_search( $time, $privacy_consent_logs_activity_data['labels'] );
if ( $i !== false )
$privacy_consent_logs_activity_data['datasets'][0]['data'][$i] = (int) $entry->count;
}
}
$chartdata['privacy-consent-logs-activity']['data'] = $privacy_consent_logs_activity_data;
// prepare script data
$script_data = [
'ajaxURL' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'cn-dashboard-widget' ),
'nonceUser' => wp_create_nonce( 'cn-dashboard-user-options' ),
'charts' => $chartdata
];
wp_add_inline_script( 'cookie-notice-admin-dashboard', 'var cnDashboardArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
}
/**
* Render dashboard widget.
*
* @return void
*/
public function dashboard_widget() {
// get main instance
$cn = Cookie_Notice();
if ( $cn->is_network_admin() )
$upgrade_url = network_admin_url( 'admin.php?page=cookie-notice&welcome=1' );
else
$upgrade_url = admin_url( 'admin.php?page=cookie-notice&welcome=1' );
$html = '';
// compliance active, display chart
if ( $cn->get_status() === 'active' ) {
// get user options
$user_options = get_user_meta( get_current_user_id(), 'pvc_dashboard', true );
// empty options?
if ( empty( $user_options ) || ! is_array( $user_options ) )
$user_options = [];
// sanitize options
$user_options = map_deep( $user_options, 'sanitize_text_field' );
// get menu items
$menu_items = ! empty( $user_options['menu_items'] ) ? $user_options['menu_items'] : [];
$items = [
[
'id' => 'visits',
'title' => esc_html__( 'Traffic Overview', 'cookie-notice' ),
'description' => esc_html__( 'Displays the general visits information for your domain.', 'cookie-notice' )
],
[
'id' => 'consent-activity',
'title' => esc_html__( 'Cookie Consent Activity', 'cookie-notice' ),
'description' => esc_html__( 'Displays the chart of the domain cookie consent activity in the last 30 days.', 'cookie-notice' )
],
[
'id' => 'privacy-consent-logs-activity',
'title' => esc_html__( 'Privacy Consent Activity', 'cookie-notice' ),
'description' => esc_html__( 'Displays the chart of the domain privacy consent activity in the last 30 days.', 'cookie-notice' )
]
];
$html .= '
<div id="cn-dashboard-accordion" class="cn-accordion">';
foreach ( $items as $item ) {
$html .= $this->widget_item( $item, $menu_items );
}
$html .= '
</div>';
// compliance inactive, display image
} else {
$html .= '
<div id="cn-dashboard-accordion" class="cn-accordion cn-widget-block">
<img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-widget.png" alt="Compliance by Hu-manity.co widget" />
<div id="cn-dashboard-upgrade">
<div id="cn-dashboard-modal">
<h2>' . esc_html__( 'View consent activity inside WordPress Dashboard', 'cookie-notice' ) . '</h2>
<p>' . esc_html__( 'Display information about the visits.', 'cookie-notice' ) . '</p>
<p>' . esc_html__( 'Get Consent logs data for the last 30 days.', 'cookie-notice' ) . '</p>
<p>' . esc_html__( 'Enable consent purpose categories, automatic cookie blocking and more.', 'cookie-notice' ) . '</p>
<p><a href="' . esc_url( $upgrade_url ) . '" class="button button-primary button-hero cn-button">' . esc_html__( 'Try Compliance by Hu-manity.co free', 'cookie-notice' ) . '</a></p>
</div>
</div>
</div>';
}
// allows a list of html entities such as
$allowed_html = wp_kses_allowed_html( 'post' );
$allowed_html['canvas'] = [
'id' => true,
'height' => true
];
echo wp_kses( $html, $allowed_html );
}
/**
* Generate dashboard widget item HTML.
*
* @param array $item
* @param array $menu_items
* @return string
*/
public function widget_item( $item, $menu_items ) {
return '
<div id="cn-' . esc_attr( $item['id'] ) . '" class="cn-accordion-item' . ( in_array( $item['id'], $menu_items, true ) ? ' cn-collapsed' : '' ) . '">
<div class="cn-accordion-header">
<div class="cn-accordion-toggle"><span class="cn-accordion-title">' . esc_html( $item['title'] ) . '</span><span class="cn-tooltip" aria-label="' . esc_attr( $item['description'] ) . '" data-microtip-position="top" data-microtip-size="large" role="tooltip"><span class="cn-tooltip-icon"></span></span></div>
</div>
<div class="cn-accordion-content">
<div class="cn-dashboard-container">
<div class="cn-data-container">
' . $this->widget_item_content( $item['id'] ) . '
<span class="spinner"></span>
</div>
</div>
</div>
</div>';
}
/**
* Generate dashboard widget item content HTML.
*
* @param array $item
* @return void
*/
public function widget_item_content( $item ) {
$html = '';
switch ( $item ) {
case 'visits':
// get main instance
$cn = Cookie_Notice();
$date_format = get_option( 'date_format' );
// get analytics data options
if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
$analytics = get_site_option( 'cookie_notice_app_analytics', [] );
else
$analytics = get_option( 'cookie_notice_app_analytics', [] );
// thirty days data
$thirty_days_usage = [
'visits' => ! empty( $analytics['thirtyDaysUsage']->visits ) ? (int) $analytics['thirtyDaysUsage']->visits : 0,
'consents' => 0,
'consents_updated' => ! empty( $analytics['lastUpdated'] ) ? date_create_from_format( 'Y-m-d H:i:s', $analytics['lastUpdated'] ) : date_create_from_format( 'Y-m-d H:i:s', current_time( 'mysql', true ) )
];
// set current timezone
$current_timezone = new DateTimeZone( $this->timezone_string() );
// update date
$thirty_days_usage['consents_updated']->setTimezone( $current_timezone );
if ( ! empty( $analytics['consentActivities'] ) ) {
foreach ( $analytics['consentActivities'] as $index => $entry ) {
$thirty_days_usage['consents'] += (int) $entry->totalrecd;
}
}
// cycle usage data
$cycle_usage = [
'threshold' => ! empty( $analytics['cycleUsage']->threshold ) ? (int) $analytics['cycleUsage']->threshold : 0,
'visits' => ! empty( $analytics['cycleUsage']->visits ) ? (int) $analytics['cycleUsage']->visits : 0,
'days_to_go' => ! empty( $analytics['cycleUsage']->daysToGo ) ? (int) $analytics['cycleUsage']->daysToGo : 0,
'start_date' => ! empty( $analytics['cycleUsage']->startDate ) ? date_create_from_format( '!Y-m-d', $analytics['cycleUsage']->startDate ) : ''
];
// get used threshold info
if ( $cycle_usage['threshold'] > 0 ) {
$threshold_used = ( $cycle_usage['visits'] / $cycle_usage['threshold'] ) * 100;
if ( $threshold_used > 100 )
$threshold_used = 100;
} else
$threshold_used = 0;
// CN_DEV_MODE: override usage % for testing. Param: ?cn_usage=0-100
if ( defined( 'CN_DEV_MODE' ) && CN_DEV_MODE && current_user_can( 'manage_options' ) && isset( $_GET['cn_usage'] ) ) {
$cn_usage_override = (int) $_GET['cn_usage'];
if ( $cn_usage_override >= 0 && $cn_usage_override <= 100 ) {
$threshold_used = $cn_usage_override;
if ( $cycle_usage['threshold'] <= 0 )
$cycle_usage['threshold'] = 10000;
$cycle_usage['visits'] = (int) round( $cycle_usage['threshold'] * ( $threshold_used / 100 ) );
$cycle_usage['visits_available'] = $cycle_usage['threshold'] - $cycle_usage['visits'];
}
}
$html .= '
<div id="cn-dashboard-' . esc_attr( $item ) . '">
<div id="cn-' . esc_attr( $item ) . '-infobox-traffic-overview" class="cn-infobox-container">
<div id="cn-' . esc_attr( $item ) . '-infobox-visits" class="cn-infobox">
<div class="cn-infobox-title">' . esc_html__( 'Total Visits', 'cookie-notice' ) . '</div>
<div class="cn-infobox-number">' . esc_html( number_format_i18n( $thirty_days_usage['visits'], 0 ) ) . '</div>
<div class="cn-infobox-subtitle">' . esc_html__( 'Last 30 days', 'cookie-notice' ) . '</div>
</div>
<div id="cn-' . esc_attr( $item ) . '-infobox-consents" class="cn-infobox">
<div class="cn-infobox-title">' . esc_html__( 'Consent Logs', 'cookie-notice' ) . '</div>
<div class="cn-infobox-number">' . esc_html( number_format_i18n( $thirty_days_usage['consents'], 0 ) ) . '</div>
<div class="cn-infobox-subtitle">' . esc_html( sprintf( __( 'Updated %s', 'cookie-notice' ), date_i18n( $date_format, $thirty_days_usage['consents_updated']->getTimestamp() ) ) ) . '</div>
</div>
</div>';
if ( $cycle_usage['threshold'] ) {
$usage_class = 'success';
// warning usage color
if ( $threshold_used > 80 && $threshold_used < 100 )
$usage_class = 'warning';
// danger usage color
elseif ( $threshold_used === 100 )
$usage_class = 'danger';
$html .= '
<div id="cn-' . esc_attr( $item ) . '-infobox-traffic-usage" class="cn-infobox-container">
<div id="cn-' . esc_attr( $item ) . '-infobox-limits" class="cn-infobox">
<div class="cn-infobox-title">' . esc_html__( 'Traffic Usage', 'cookie-notice' ) . '</div>
<div class="cn-infobox-number cn-text-' . esc_attr( $usage_class ) . '">' . esc_html( number_format_i18n( $threshold_used, 1 ) ) . ' %</div>
<div class="cn-infobox-subtitle">
<p>' . esc_html( sprintf( __( 'Visits usage: %1$s / %2$s', 'cookie-notice' ), $cycle_usage['visits'], $cycle_usage['threshold'] ) ) . '</p>
<p>' . esc_html( sprintf( __( 'Cycle started: %s', 'cookie-notice' ), date_i18n( $date_format, $cycle_usage['start_date']->getTimestamp() ) ) ) . '</p>
<p>' . esc_html( sprintf( __( 'Days to go: %s', 'cookie-notice' ), $cycle_usage['days_to_go'] ) ) . '</p>
</div>
</div>
<div id="cn-' . esc_attr( $item ) . '-chart-limits" class="cn-infobox cn-chart-container">
<canvas id="cn-usage-chart" style="height: 100px"></canvas>
</div>';
// Near-limit nudge — reads copy from shared notifications.json.
$cn_dash_tier = 'basic';
if ( ! empty( $cn->options['general']['app_id'] ) ) {
$cn_dash_tier = ( $cn->get_subscription() === 'pro' ) ? 'pro' : 'free';
}
$cn_dash_notification = cn_get_dashboard_notification( $threshold_used, $cn_dash_tier );
if ( $cn_dash_notification ) {
$react_welcome_url = $cn->is_network_admin()
? network_admin_url( 'admin.php?page=cookie-notice&cn_react_welcome=1' )
: admin_url( 'admin.php?page=cookie-notice&cn_react_welcome=1' );
$cn_dash_desc = str_replace(
[ '{usagePercent}', '{sessionTotal}', '{sessionUsed}' ],
[ number_format_i18n( $threshold_used, 0 ), number_format_i18n( $cycle_usage['threshold'] ), number_format_i18n( $cycle_usage['visits'] ) ],
$cn_dash_notification['description'] ?? ''
);
$cn_dash_cta_label = $cn_dash_notification['cta']['label'] ?? 'Upgrade &rarr;';
$html .= '
<div id="cn-' . esc_attr( $item ) . '-traffic-notice" class="cn-infobox-notice">
<p><b>' . esc_html( $cn_dash_desc ) . '</b></p>
<p><a href="' . esc_url( $react_welcome_url ) . '">' . esc_html( $cn_dash_cta_label ) . '</a></p>
</div>';
}
$html .= '
</div>';
}
$html .= '
</div>';
break;
case 'consent-activity':
$html .= '
<div id="cn-dashboard-' . esc_attr( $item ) . '">
<div id="cn-' . esc_attr( $item ) . '-chart-container cn-chart-container">
<canvas id="cn-' . esc_attr( $item ) . '-chart" style="height: 300px"></canvas>
</div>
</div>';
break;
case 'privacy-consent-logs-activity':
$html .= '
<div id="cn-dashboard-' . esc_attr( $item ) . '">
<div id="cn-' . esc_attr( $item ) . '-chart-container cn-chart-container">
<canvas id="cn-' . esc_attr( $item ) . '-chart" style="height: 300px"></canvas>
</div>
</div>';
break;
}
return $html;
}
/**
* Add site test.
*
* @param array $tests
* @return array
*/
public function add_tests( $tests ) {
$tests['direct']['cookie_compliance_status'] = [
'label' => esc_html__( 'Compliance by Hu-manity.co Status', 'cookie-notice' ),
'test' => [ $this, 'test_cookie_compliance' ]
];
return $tests;
}
/**
* Test for Cookie Compliance.
*
* @return array|void
*/
public function test_cookie_compliance() {
if ( Cookie_Notice()->get_status() !== 'active' ) {
return [
'label' => esc_html__( 'Your site does not have Compliance by Hu-manity.co', 'cookie-notice' ),
'status' => 'recommended',
'description' => esc_html__( "Run Compliance Check to determine your site's compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.", 'cookie-notice' ),
'actions' => sprintf( '<p><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></p>', admin_url( 'admin.php?page=cookie-notice&welcome=1' ), esc_html__( 'Run Compliance Check', 'cookie-notice' ) ),
'test' => 'cookie_compliance_status',
'badge' => [
'label' => esc_html__( 'Compliance', 'cookie-notice' ),
'color' => 'blue'
]
];
} else {
return [
'label' => esc_html__( 'Compliance by Hu-manity.co is active', 'cookie-notice' ),
'status' => 'good',
'description' => esc_html__( 'Compliance by Hu-manity.co is configured with active Compliance by Hu-manity.co protection. Your site is collecting consent in accordance with GDPR, CCPA, and other applicable privacy laws.', 'cookie-notice' ),
'actions' => sprintf( '<p><a href="%s">%s</a></p>', admin_url( 'admin.php?page=cookie-notice' ), esc_html__( 'View compliance dashboard', 'cookie-notice' ) ),
'test' => 'cookie_compliance_status',
'badge' => [
'label' => esc_html__( 'Compliance', 'cookie-notice' ),
'color' => 'green'
]
];
}
}
/**
* Retrieve the timezone of the site as a string.
*
* @return string
*/
public function timezone_string() {
if ( function_exists( 'wp_timezone_string' ) )
return wp_timezone_string();
$timezone_string = get_option( 'timezone_string' );
if ( $timezone_string )
return $timezone_string;
$offset = (float) get_option( 'gmt_offset' );
$hours = (int) $offset;
$minutes = ( $offset - $hours );
$sign = ( $offset < 0 ) ? '-' : '+';
$abs_hour = abs( $hours );
$abs_mins = abs( $minutes * 60 );
$tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
return $tz_offset;
}
}

View File

@@ -0,0 +1,902 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Frontend class.
*
* @class Cookie_Notice_Frontend
*/
class Cookie_Notice_Frontend {
private $compliance = false;
private $matched_handles = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// general actions
add_action( 'init', [ $this, 'early_init' ], 9 );
add_action( 'wp', [ $this, 'init' ] );
add_action( 'wp_head', [ $this, 'wp_print_header_scripts' ] );
add_action( 'wp_print_footer_scripts', [ $this, 'wp_print_footer_scripts' ] );
// compliance actions
add_action( 'wp_head', [ $this, 'add_dns_prefetch' ], -1 );
add_action( 'wp_head', [ $this, 'add_cookie_compliance' ], 0 );
add_action( 'login_head', [ $this, 'add_cookie_compliance' ], 0 );
// notice actions
add_action( 'wp_footer', [ $this, 'add_cookie_notice' ], 1000 );
add_action( 'login_footer', [ $this, 'add_cookie_notice' ], 1000 );
add_action( 'wp_enqueue_scripts', [ $this, 'wp_enqueue_notice_scripts' ] );
add_action( 'login_enqueue_scripts', [ $this, 'wp_enqueue_notice_scripts' ] );
// filters
add_filter( 'body_class', [ $this, 'change_body_class' ] );
add_filter( 'cn_is_bot', [ $this, 'wp_cache_check' ] );
}
/**
* Early initialization.
*
* @return void
*/
public function early_init() {
// get main instance
$cn = Cookie_Notice();
// set compliance status
$this->compliance = ( $cn->get_status() === 'active' );
// cookie compliance initialization
if ( $this->compliance ) {
// amp compatibility
if ( $cn->options['general']['amp_support'] && cn_is_plugin_active( 'amp' ) )
include_once( COOKIE_NOTICE_PATH . 'includes/modules/amp/amp.php' );
// excluded script handles — stamp data-hu-category="1" so the widget never blocks them
if ( $cn->options['general']['app_blocking'] && ! empty( $cn->options['general']['excluded_handles'] ) ) {
add_filter( 'script_loader_tag', [ $this, 'exclude_handles_from_blocking' ], 10, 2 );
if ( $cn->options['general']['debug_mode'] )
add_action( 'wp_footer', [ $this, 'debug_excluded_handles' ], 999 );
}
}
}
/**
* Stamp excluded script handles with data-hu-category="1" (Essential).
*
* @param string $tag Full <script> tag HTML.
* @param string $handle WordPress script handle.
* @return string
*/
public function exclude_handles_from_blocking( $tag, $handle ) {
$excluded = Cookie_Notice()->options['general']['excluded_handles'];
if ( in_array( $handle, $excluded, true ) && strpos( $tag, 'data-hu-category' ) === false ) {
$tag = str_replace( ' src=', ' data-hu-category="1" src=', $tag );
$this->matched_handles[] = $handle;
}
return $tag;
}
/**
* Output debug console.warn lines listing matched / unmatched excluded handles.
*
* @return void
*/
public function debug_excluded_handles() {
$configured = Cookie_Notice()->options['general']['excluded_handles'];
$matched = $this->matched_handles;
$unmatched = array_values( array_diff( $configured, $matched ) );
echo '<script>' .
'console.warn("CC Banner: Excluded script handles — stamped (' . count( $matched ) . '): " + ' . wp_json_encode( $matched ) . ');' .
( ! empty( $unmatched ) ? 'console.warn("CC Banner: Excluded script handles — not found on this page (' . count( $unmatched ) . '): " + ' . wp_json_encode( $unmatched ) . ');' : '' ) .
'</script>' . "\n";
}
/**
* Initialize plugin.
*
* @return void
*/
public function init() {
if ( is_admin() )
return;
// purge cache
if (
isset( $_GET['hu_purge_cache'], $_GET['_wpnonce'] )
&& current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) )
&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'cn-purge-cache' )
) {
$this->purge_cache();
}
// get main instance
$cn = Cookie_Notice();
// compatibility fixes
if ( $this->compliance ) {
// is blocking active?
if ( $cn->options['general']['app_blocking'] ) {
// contact form 7 compatibility
if ( cn_is_plugin_active( 'contactform7', 'captcha' ) )
include_once( COOKIE_NOTICE_PATH . 'includes/modules/contact-form-7/contact-form-7.php' );
}
}
}
/**
* Whether banner is allowed to display.
*
* @param array $args
* @return bool
*/
public function maybe_display_banner( $args = [] ) {
$defaults = [
'skip_amp' => false
];
if ( is_array( $args ) )
$args = wp_parse_args( $args, $defaults );
else
$args = $defaults;
// get main instance
$cn = Cookie_Notice();
// is cookie compliance active?
if ( $this->compliance ) {
// elementor compatibility, needed early for is_preview_mode
if ( cn_is_plugin_active( 'elementor' ) )
include_once( COOKIE_NOTICE_PATH . 'includes/modules/elementor/elementor.php' );
// divi builder compatibility
if ( cn_is_plugin_active( 'divi', 'theme' ) )
include_once( COOKIE_NOTICE_PATH . 'includes/modules/divi/divi.php' );
}
// is it preview mode?
if ( $this->is_preview_mode() )
return false;
// is bot detection enabled and it's a bot?
if ( $cn->options['general']['bot_detection'] && apply_filters( 'cn_is_bot', $cn->bot_detect->is_crawler() ) )
return false;
// check amp
if ( ! $args['skip_amp'] ) {
if ( $cn->options['general']['amp_support'] && cn_is_plugin_active( 'amp' ) && function_exists( 'amp_is_request' ) && amp_is_request() )
return false;
}
// final check for conditional display
return $this->check_conditions();
}
/**
* Check if WP_CACHE is active.
*
* @return bool
*/
public function wp_cache_check( $result ) {
if ( defined( 'WP_CACHE' ) && WP_CACHE === true )
$result = false;
return $result;
}
/**
* Whether preview mode is active.
*
* @return bool
*/
public function is_preview_mode() {
return isset( $_GET['cn_preview_mode'] ) || is_preview() || is_customize_preview() || defined( 'IFRAME_REQUEST' ) || ( function_exists( 'wp_is_json_request' ) && wp_is_json_request() ) || isset( $_GET[ 'fl_builder' ] ) || apply_filters( 'cn_is_preview_mode', false );
}
/**
* Check whether banner should be displayed based on specified conditions.
*
* @return bool
*/
public function check_conditions() {
// get main instance
$cn = Cookie_Notice();
if ( ! $cn->options['general']['conditional_active'] )
return true;
// get conditions
$rules = $cn->options['general']['conditional_rules'];
// set access type
$access_type = $cn->options['general']['conditional_display'] === 'show';
// get object
$object = get_queried_object();
// no rules?
if ( empty( $rules ) )
$final_access = true;
else {
// check the rules
foreach( $rules as $index => $group ) {
$give_group_access = true;
foreach ( $group as $rule ) {
$give_rule_access = false;
switch ( $rule['param'] ) {
case 'page_type':
if ( ( $rule['operator'] === 'equal' && $rule['value'] === 'front' && is_front_page() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'front' && ! is_front_page() ) || ( $rule['operator'] === 'equal' && $rule['value'] === 'home' && is_home() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'home' && ! is_home() ) || ( $rule['operator'] === 'equal' && $rule['value'] === 'login' && $this->is_login() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'login' && ! $this->is_login() ) )
$give_rule_access = true;
break;
case 'page':
if ( ( $rule['operator'] === 'equal' && ! empty( $object ) && is_a( $object, 'WP_Post' ) && property_exists( $object, 'ID' ) && is_page( $object->ID ) && (int) $object->ID === (int) $rule['value'] ) || ( $rule['operator'] === 'not_equal' && ( empty( $object ) || ! is_page() || ( is_page() && ! empty( $object ) && is_a( $object, 'WP_Post' ) && property_exists( $object, 'ID' ) && $object->ID !== (int) $rule['value'] ) ) ) )
$give_rule_access = true;
break;
case 'post_type':
if ( ( $rule['operator'] === 'equal' && is_singular( $rule['value'] ) ) || ( $rule['operator'] === 'not_equal' && ! is_singular( $rule['value'] ) ) )
$give_rule_access = true;
break;
case 'post_type_archive':
if ( ( $rule['operator'] === 'equal' && is_post_type_archive( $rule['value'] ) ) || ( $rule['operator'] === 'not_equal' && ! is_post_type_archive( $rule['value'] ) ) )
$give_rule_access = true;
break;
case 'user_type':
if ( ( $rule['operator'] === 'equal' && $rule['value'] === 'logged_in' && is_user_logged_in() ) || ( $rule['operator'] === 'equal' && $rule['value'] === 'guest' && ! is_user_logged_in() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'logged_in' && ! is_user_logged_in() ) || ( $rule['operator'] === 'not_equal' && $rule['value'] === 'guest' && is_user_logged_in() ) )
$give_rule_access = true;
break;
case 'taxonomy_archive':
// check value
if ( strpos( $rule['value'], '|' ) !== false ) {
// explode it
$values = explode( '|', $rule['value'] );
// 2 chunks?
if ( count( $values ) === 2 ) {
$term_id = (int) $values[0];
if ( $values[1] === 'category' && ( ( $rule['operator'] === 'equal' && is_category( $term_id ) ) || ( $rule['operator'] === 'not_equal' && ! is_category( $term_id ) ) ) )
$give_rule_access = true;
elseif ( $values[1] === 'post_tag' && ( ( $rule['operator'] === 'equal' && is_tag( $term_id ) ) || ( $rule['operator'] === 'not_equal' && ! is_tag( $term_id ) ) ) )
$give_rule_access = true;
elseif ( ( $rule['operator'] === 'equal' && is_tax( $values[1], $term_id ) ) || ( $rule['operator'] === 'not_equal' && ! is_tax( $values[1], $term_id ) ) )
$give_rule_access = true;
}
}
break;
}
// condition failed?
if ( ! $give_rule_access ) {
// group failed
$give_group_access = false;
// finish group checking
break;
}
}
// whole group successful?
if ( $give_group_access ) {
// set final access
$final_access = $access_type;
// finish rules checking
break;
} else
$final_access = ! $access_type;
}
}
return (bool) apply_filters( 'cn_conditional_display', $final_access, $object );
}
/**
* Determine whether the current request is for the login screen.
*
* @return bool
*/
public function is_login() {
return ( function_exists( 'is_login' ) ? is_login() : ( stripos( wp_login_url(), $_SERVER['SCRIPT_NAME'] ) !== false ) );
}
/**
* Get Cookie Compliance options.
*
* @return array
*/
public function get_cc_options() {
// get main instance
$cn = Cookie_Notice();
// get site language
$locale = get_locale();
$locale_code = explode( '_', $locale );
// exceptions, norwegian
if ( is_array( $locale_code ) && in_array( $locale_code[0], [ 'nb', 'nn' ] ) )
$locale_code[0] = 'no';
// get active sources
$sources = $cn->privacy_consent->get_active_sources();
// prepare huOptions
$options = [
'appID' => $cn->options['general']['app_id'],
'currentLanguage' => $locale_code[0],
'blocking' => ! is_user_logged_in() ? $cn->options['general']['app_blocking'] : false,
'globalCookie' => is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install(),
'isAdmin' => current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ),
'privacyConsent' => ! empty( $sources )
];
// any active source?
if ( ! empty( $sources ) )
$options['forms'] = [];
// filter options
$options = apply_filters( 'cn_cookie_compliance_args', $options );
// get config timestamp
if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
$timestamp = (int) get_site_transient( 'cookie_notice_config_update' );
else
$timestamp = (int) get_transient( 'cookie_notice_config_update' );
// update config?
if ( $timestamp > 0 ) {
$options['cachePurge'] = true;
$options['cacheTimestamp'] = $timestamp;
}
// debug mode
if ( $cn->options['general']['debug_mode'] )
$options['debugMode'] = true;
// blocking data (custom patterns, providers, consent mode defaults)
// always include in huOptions so the widget has the full configuration;
// the huOptions.blocking flag controls whether scripts are actually blocked
if ( $cn->is_network_options() )
$blocking = get_site_option( 'cookie_notice_app_blocking' );
else
$blocking = get_option( 'cookie_notice_app_blocking' );
if ( ! empty( $blocking ) && is_array( $blocking ) ) {
$options['customProviders'] = ! empty( $blocking['providers'] ) && is_array( $blocking['providers'] ) ? $blocking['providers'] : [];
$options['customPatterns'] = ! empty( $blocking['patterns'] ) && is_array( $blocking['patterns'] ) ? $blocking['patterns'] : [];
// google consent mode default categories
if ( ! empty( $blocking['google_consent_default'] ) && is_array( $blocking['google_consent_default'] ) ) {
$gcd = [];
foreach ( $blocking['google_consent_default'] as $storage => $category ) {
if ( in_array( $storage, ['ad_storage', 'analytics_storage', 'functionality_storage', 'personalization_storage', 'security_storage', 'ad_personalization', 'ad_user_data'], true ) )
$gcd[$storage] = (int) $category;
}
if ( ! empty( $gcd ) )
$options['googleConsentDefault'] = $gcd;
}
// facebook consent mode default categories
if ( ! empty( $blocking['facebook_consent_default'] ) && is_array( $blocking['facebook_consent_default'] ) ) {
$fcd = [];
foreach ( $blocking['facebook_consent_default'] as $storage => $category ) {
if ( in_array( $storage, ['consent'], true ) )
$fcd[$storage] = (int) $category;
}
if ( ! empty( $fcd ) )
$options['facebookConsentDefault'] = $fcd;
}
// microsoft consent mode default categories
if ( ! empty( $blocking['microsoft_consent_default'] ) && is_array( $blocking['microsoft_consent_default'] ) ) {
$mcd = [];
foreach ( $blocking['microsoft_consent_default'] as $storage => $category ) {
if ( in_array( $storage, ['ad_storage', 'analytics_storage'], true ) )
$mcd[$storage] = (int) $category;
}
if ( ! empty( $mcd ) )
$options['microsoftConsentDefault'] = $mcd;
}
}
if ( isset( $_GET['cn_preview'] ) && $_GET['cn_preview'] === '1' && current_user_can( 'manage_options' ) ) {
$options['forceShow'] = true;
}
return $options;
}
/**
* Get Cookie Compliance output.
*
* @param array $options
* @return string
*/
public function get_cc_output( $options ) {
$output = '
<!-- Cookie Compliance -->
<script type="text/javascript" id="hu-banner-options" data-nowprocket data-noptimize="1" data-no-optimize="1" nitro-exclude data-jetpack-boost="ignore">var huOptions = ' . wp_json_encode( $options, JSON_UNESCAPED_SLASHES ) . '; // nowprocket</script>
<script type="text/javascript" id="hu-banner-js" data-cfasync="false" data-nowprocket data-noptimize="1" data-no-optimize="1" nitro-exclude data-jetpack-boost="ignore" src="' . esc_url( ( is_ssl() ? 'https:' : 'http:' ) . Cookie_Notice()->get_url( 'widget' ) ) . '"></script>';
return apply_filters( 'cn_cookie_compliance_output', $output, $options );
}
/**
* Add DNS Prefetch.
*
* @return void
*/
public function add_dns_prefetch() {
if ( ! $this->compliance )
return;
// is banner allowed to display?
if ( ! $this->maybe_display_banner() )
return;
// Derive prefetch host from widget URL so CN_APP_WIDGET_URL overrides are honoured.
$widget_url = Cookie_Notice()->get_url( 'widget' );
$prefetch_host = '//' . wp_parse_url( 'https:' . $widget_url, PHP_URL_HOST );
echo '<link rel="dns-prefetch" href="' . esc_attr( $prefetch_host ) . '" />';
}
/**
* Run Cookie Compliance.
*
* @return void
*/
public function add_cookie_compliance() {
// skip modal login iframe
if ( current_filter() === 'login_head' && ! empty( $_REQUEST['interim-login'] ) )
return;
// allow only for compliance
if ( ! $this->compliance )
return;
// is banner allowed to display?
if ( ! $this->maybe_display_banner() )
return;
// get options
$options = $this->get_cc_options();
// display output
echo $this->get_cc_output( $options );
}
/**
* Cookie notice output.
*
* @return void
*/
public function add_cookie_notice() {
// skip modal login iframe
if ( current_filter() === 'login_footer' && ! empty( $_REQUEST['interim-login'] ) )
return;
if ( $this->compliance )
return;
// is banner allowed to display?
if ( ! $this->maybe_display_banner() )
return;
// get main instance
$cn = Cookie_Notice();
// WPML >= 3.2
if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '3.2', '>=' ) ) {
$cn->options['general']['message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['message_text'], 'Cookie Notice', 'Message in the notice' );
$cn->options['general']['accept_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['accept_text'], 'Cookie Notice', 'Button text' );
$cn->options['general']['refuse_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['refuse_text'], 'Cookie Notice', 'Refuse button text' );
$cn->options['general']['revoke_message_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_message_text'], 'Cookie Notice', 'Revoke message text' );
$cn->options['general']['revoke_text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['revoke_text'], 'Cookie Notice', 'Revoke button text' );
$cn->options['general']['see_more_opt']['text'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['text'], 'Cookie Notice', 'Privacy policy text' );
$cn->options['general']['see_more_opt']['link'] = apply_filters( 'wpml_translate_single_string', $cn->options['general']['see_more_opt']['link'], 'Cookie Notice', 'Custom link' );
// WPML and Polylang compatibility
} elseif ( function_exists( 'icl_t' ) ) {
$cn->options['general']['message_text'] = icl_t( 'Cookie Notice', 'Message in the notice', $cn->options['general']['message_text'] );
$cn->options['general']['accept_text'] = icl_t( 'Cookie Notice', 'Button text', $cn->options['general']['accept_text'] );
$cn->options['general']['refuse_text'] = icl_t( 'Cookie Notice', 'Refuse button text', $cn->options['general']['refuse_text'] );
$cn->options['general']['revoke_message_text'] = icl_t( 'Cookie Notice', 'Revoke message text', $cn->options['general']['revoke_message_text'] );
$cn->options['general']['revoke_text'] = icl_t( 'Cookie Notice', 'Revoke button text', $cn->options['general']['revoke_text'] );
$cn->options['general']['see_more_opt']['text'] = icl_t( 'Cookie Notice', 'Privacy policy text', $cn->options['general']['see_more_opt']['text'] );
$cn->options['general']['see_more_opt']['link'] = icl_t( 'Cookie Notice', 'Custom link', $cn->options['general']['see_more_opt']['link'] );
}
if ( $cn->options['general']['see_more_opt']['link_type'] === 'page' ) {
// multisite with global override?
if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] ) {
// get main site id
$main_site_id = get_main_site_id();
// switch to main site
switch_to_blog( $main_site_id );
// update page id for current language if needed
if ( function_exists( 'icl_object_id' ) )
$cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
// get main site privacy policy link
$permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
// restore current site
restore_current_blog();
} else {
// update page id for current language if needed
if ( function_exists( 'icl_object_id' ) )
$cn->options['general']['see_more_opt']['id'] = icl_object_id( $cn->options['general']['see_more_opt']['id'], 'page', true );
// get privacy policy link
$permalink = get_permalink( $cn->options['general']['see_more_opt']['id'] );
}
}
// #2266: position is API-owned — read from cookie_notice_app_design for connected sites.
// Falls back to cookie_notice_options["general"]["position"] for disconnected/legacy-only installs.
$app_design = $cn->is_network_options()
? get_site_option( 'cookie_notice_app_design', [] )
: get_option( 'cookie_notice_app_design', [] );
$banner_position = ! empty( $app_design['position'] )
? sanitize_key( $app_design['position'] )
: ( $cn->options['general']['position'] ?? 'bottom' );
// get cookie container args
$options = apply_filters( 'cn_cookie_notice_args', [
'position' => $banner_position,
'css_class' => $cn->options['general']['css_class'],
'button_class' => 'cn-button',
'colors' => $cn->options['general']['colors'],
'message_text' => $cn->options['general']['message_text'],
'accept_text' => $cn->options['general']['accept_text'],
'refuse_text' => $cn->options['general']['refuse_text'],
'revoke_message_text' => $cn->options['general']['revoke_message_text'],
'revoke_text' => $cn->options['general']['revoke_text'],
'refuse_opt' => $cn->options['general']['refuse_opt'],
'revoke_cookies' => $cn->options['general']['revoke_cookies'],
'see_more' => $cn->options['general']['see_more'],
'see_more_opt' => $cn->options['general']['see_more_opt'],
'link_target' => $cn->options['general']['link_target'],
'link_position' => $cn->options['general']['link_position'],
'aria_label' => 'Compliance by Hu-manity.co'
] );
// message output
$output = '
<!-- Compliance by Hu-manity.co plugin v' . esc_attr( $cn->defaults['version'] ) . ' https://hu-manity.co/ -->
<div id="cookie-notice" role="dialog" class="cookie-notice-hidden cookie-revoke-hidden cn-position-' . esc_attr( $options['position'] ) . '" aria-label="' . esc_attr( $options['aria_label'] ) . '" style="background-color: __CN_BG_COLOR__">'
. '<div class="cookie-notice-container" style="color: ' . esc_attr( $options['colors']['text'] ) . '">'
. '<span id="cn-notice-text" class="cn-text-container">'. ( $options['see_more'] ? do_shortcode( $options['message_text'] ) : $options['message_text'] ) . '</span>'
. '<span id="cn-notice-buttons" class="cn-buttons-container"><button id="cn-accept-cookie" data-cookie-set="accept" class="cn-set-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['accept_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['accept_text'] ) . '</button>'
. ( $options['refuse_opt'] ? '<button id="cn-refuse-cookie" data-cookie-set="refuse" class="cn-set-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['refuse_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['refuse_text'] ) . '</button>' : '' )
. ( $options['see_more'] && $options['link_position'] === 'banner' ? '<button data-link-url="' . esc_url( $options['see_more_opt']['link_type'] === 'custom' ? $options['see_more_opt']['link'] : $permalink ) . '" data-link-target="' . esc_attr( $options['link_target'] ) . '" id="cn-more-info" class="cn-more-info ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['see_more_opt']['text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['see_more_opt']['text'] ) . '</button>' : '' )
. '</span><button type="button" id="cn-close-notice" data-cookie-set="accept" class="cn-close-icon" aria-label="' . esc_attr( $options['refuse_text'] ) . '" tabindex="0"></button>'
. '</div>
' . ( $options['refuse_opt'] && $options['revoke_cookies'] ?
'<div class="cookie-revoke-container" style="color: ' . esc_attr( $options['colors']['text'] ) . '">'
. ( ! empty( $options['revoke_message_text'] ) ? '<span id="cn-revoke-text" class="cn-text-container">' . $options['revoke_message_text'] . '</span>' : '' )
. '<span id="cn-revoke-buttons" class="cn-buttons-container"><button id="cn-revoke-cookie" class="cn-revoke-cookie ' . esc_attr( $options['button_class'] ) . ( $options['css_class'] !== '' ? ' cn-button-custom ' . esc_attr( $options['css_class'] ) : '' ) . '" aria-label="' . esc_attr( $options['revoke_text'] ) . '"' . ( $options['css_class'] == '' ? ' style="background-color: ' . esc_attr( $options['colors']['button'] ) . '"' : '' ) . '>' . esc_html( $options['revoke_text'] ) . '</button></span>
</div>' : '' ) . '
</div>
<!-- / Compliance by Hu-manity.co plugin -->';
add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
$output = apply_filters( 'cn_cookie_notice_output', wp_kses_post( $output ), $options );
remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
// convert rgb color to hex
$bg_rgb_color = $this->hex2rgb( $options['colors']['bar'] );
// invalid color? use default
if ( $bg_rgb_color === false )
$bg_rgb_color = $this->hex2rgb( $cn->defaults['general']['colors']['bar'] );
// allow rgba background
echo str_replace( '__CN_BG_COLOR__', esc_attr( 'rgba(' . implode( ',', $bg_rgb_color ) . ',' . ( (int) $options['colors']['bar_opacity'] ) * 0.01 . ');' ), $output );
}
/**
* Add new properties to style safe list.
*
* @param array $styles
* @return array
*/
public function allow_style_attributes( $styles ) {
$styles[] = 'display';
return $styles;
}
/**
* Convert HEX to RGB color.
*
* @param string $color
* @return bool|array
*/
public function hex2rgb( $color ) {
if ( ! is_string( $color ) )
return false;
// with hash?
if ( $color[0] === '#' )
$color = substr( $color, 1 );
if ( sanitize_hex_color_no_hash( $color ) !== $color )
return false;
// 6 hex digits?
if ( strlen( $color ) === 6 )
list( $r, $g, $b ) = [ $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] ];
// 3 hex digits?
elseif ( strlen( $color ) === 3 )
list( $r, $g, $b ) = [ $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] ];
else
return false;
return [ 'r' => hexdec( $r ), 'g' => hexdec( $g ), 'b' => hexdec( $b ) ];
}
/**
* Add blocking class to scripts, iframes and links.
*
* @param string $type
* @param string $code
* @return string
*/
public function add_block_class( $type, $code ) {
// clear and disable libxml errors and allow user to fetch error information as needed
libxml_use_internal_errors( true );
// create new dom object
$document = new DOMDocument( '1.0', 'UTF-8' );
// set attributes
$document->formatOutput = true;
$document->preserveWhiteSpace = false;
// load code
$document->loadHTML( '<div>' . wp_kses( trim( $code ), Cookie_Notice()->get_allowed_html( $type ) ) . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
$container = $document->getElementsByTagName( 'div' )->item( 0 );
$container = $container->parentNode->removeChild( $container );
while ( $document->firstChild ) {
$document->removeChild( $document->firstChild );
}
while ( $container->firstChild ) {
$document->appendChild( $container->firstChild );
}
// set blocked tags
if ( $type === 'body' )
$blocked_tags = [ 'script', 'iframe' ];
elseif ( $type === 'head' )
$blocked_tags = [ 'script', 'link' ];
foreach ( $blocked_tags as $blocked_tag ) {
$tags = $document->getElementsByTagName( $blocked_tag );
// any tags?
if ( ! empty( $tags ) && is_object( $tags ) ) {
foreach ( $tags as $tag ) {
$tag->setAttribute( 'class', 'hu-block' );
}
}
}
// save new HTML
$output = $document->saveHTML();
// reenable libxml errors
libxml_use_internal_errors( false );
return $output;
}
/**
* Load notice scripts and styles - frontend.
*
* @return void
*/
public function wp_enqueue_notice_scripts() {
// skip modal login iframe
if ( current_filter() === 'login_enqueue_scripts' && ! empty( $_REQUEST['interim-login'] ) )
return;
// force script if a reopen shortcode is present on the page
$force_enqueue = $this->has_reopen_shortcode();
if ( $this->compliance && ! $force_enqueue )
return;
// is banner allowed to display?
if ( ! $force_enqueue && ! $this->maybe_display_banner() )
return;
// get main instance
$cn = Cookie_Notice();
wp_enqueue_script( 'cookie-notice-front', COOKIE_NOTICE_URL . '/js/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $cn->defaults['version'], isset( $cn->options['general']['script_placement'] ) && $cn->options['general']['script_placement'] === 'footer' );
// not array? changeable by cn_cookie_expiry filter
if ( is_array( $cn->settings->times ) ) {
// check cookie expiration time
if ( array_key_exists( $cn->options['general']['time'], $cn->settings->times ) && array_key_exists( 1, $cn->settings->times[$cn->options['general']['time']] ) )
$cookie_time = (int) $cn->settings->times[$cn->options['general']['time']][1];
else {
// fallback to default length of month
$cookie_time = MONTH_IN_SECONDS;
}
// check cookie rejection expiration time
if ( array_key_exists( $cn->options['general']['time_rejected'], $cn->settings->times ) && array_key_exists( 1, $cn->settings->times[$cn->options['general']['time_rejected']] ) )
$cookie_time_rejected = (int) $cn->settings->times[$cn->options['general']['time_rejected']][1];
else {
// fallback to default length of month
$cookie_time_rejected = MONTH_IN_SECONDS;
}
} else {
// fallback to default length of month
$cookie_time = $cookie_time_rejected = MONTH_IN_SECONDS;
}
// #2266: position is API-owned — read from cookie_notice_app_design for connected sites.
// Falls back to cookie_notice_options["general"]["position"] for disconnected/legacy-only installs.
// (Same resolution as add_cookie_notice() — duplicated here because this is a separate WP hook.)
$app_design = $cn->is_network_options()
? get_site_option( 'cookie_notice_app_design', [] )
: get_option( 'cookie_notice_app_design', [] );
$banner_position = ! empty( $app_design['position'] )
? sanitize_key( $app_design['position'] )
: ( $cn->options['general']['position'] ?? 'bottom' );
// prepare script data
$script_data = [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'cn_save_cases' ),
'hideEffect' => $cn->options['general']['hide_effect'],
'position' => $banner_position,
'onScroll' => $cn->options['general']['on_scroll'],
'onScrollOffset' => (int) $cn->options['general']['on_scroll_offset'],
'onClick' => $cn->options['general']['on_click'],
'cookieName' => 'cookie_notice_accepted',
'cookieTime' => $cookie_time,
'cookieTimeRejected' => $cookie_time_rejected,
'globalCookie' => is_multisite() && $cn->options['general']['global_cookie'] && is_subdomain_install(),
'redirection' => $cn->options['general']['redirection'],
'cache' => defined( 'WP_CACHE' ) && WP_CACHE,
'revokeCookies' => $cn->options['general']['revoke_cookies'],
'revokeCookiesOpt' => $cn->options['general']['revoke_cookies_opt']
];
wp_add_inline_script( 'cookie-notice-front', 'var cnArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
wp_enqueue_style( 'cookie-notice-front', COOKIE_NOTICE_URL . '/css/front' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], $cn->defaults['version'] );
}
/**
* Print non functional JavaScript in body.
*
* @return void
*/
public function wp_print_footer_scripts() {
// get main instance
$cn = Cookie_Notice();
if ( $cn->cookies_accepted() || $this->compliance ) {
$scripts = apply_filters( 'cn_refuse_code_scripts_html', $cn->options['general']['refuse_code'], 'body' );
if ( ! empty( $scripts ) )
echo html_entity_decode( wp_kses( $scripts, $cn->get_allowed_html( 'body' ) ) );
}
}
/**
* Print non functional JavaScript in header.
*
* @return void
*/
public function wp_print_header_scripts() {
// get main instance
$cn = Cookie_Notice();
if ( $cn->cookies_accepted() || $this->compliance ) {
$scripts = apply_filters( 'cn_refuse_code_scripts_html', $cn->options['general']['refuse_code_head'], 'head' );
if ( ! empty( $scripts ) )
echo html_entity_decode( wp_kses( $scripts, $cn->get_allowed_html( 'head' ) ) );
}
}
/**
* Add new body classes.
*
* @param array $classes Body classes
* @return array
*/
public function change_body_class( $classes ) {
if ( is_admin() )
return $classes;
if ( Cookie_Notice()->cookies_set() ) {
$classes[] = 'cookies-set';
if ( Cookie_Notice()->cookies_accepted() )
$classes[] = 'cookies-accepted';
else
$classes[] = 'cookies-refused';
} else
$classes[] = 'cookies-not-set';
return $classes;
}
/**
* Detect if reopen shortcode is present on the current singular content.
*
* @return bool
*/
private function has_reopen_shortcode() {
if ( ! is_singular() )
return false;
global $post;
if ( empty( $post ) || ! property_exists( $post, 'post_content' ) )
return false;
return has_shortcode( $post->post_content, 'cookies_revoke' );
}
/**
* Purge config cache.
*
* @return void
*/
public function purge_cache() {
// get main instance
$cn = Cookie_Notice();
if ( is_multisite() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] ) {
$app_id = $cn->network_options['general']['app_id'];
$app_key = $cn->network_options['general']['app_key'];
} else {
$app_id = $cn->options['general']['app_id'];
$app_key = $cn->options['general']['app_key'];
}
// compliance active only
if ( $app_id !== '' && $app_key !== '' ) {
// request for new config data too
$cn->welcome_api->get_app_config( $app_id, true );
}
}
}

View File

@@ -0,0 +1,329 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Check if cookies are accepted.
*
* @return bool Whether cookies are accepted
*/
if ( ! function_exists( 'cn_cookies_accepted' ) ) {
function cn_cookies_accepted() {
return (bool) Cookie_Notice::cookies_accepted();
}
}
/**
* Check if cookies are set.
*
* @return bool Whether cookies are set
*/
if ( ! function_exists( 'cn_cookies_set' ) ) {
function cn_cookies_set() {
return (bool) Cookie_Notice::cookies_set();
}
}
/**
* Get active caching plugins.
*
* @param array $args
* @return array
*/
function cn_get_active_caching_plugins( $args = [] ) {
if ( isset( $args['versions'] ) && $args['versions'] === true )
$version = true;
else
$version = false;
$active_plugins = [];
// autoptimize
if ( cn_is_plugin_active( 'autoptimize' ) ) {
if ( $version )
$active_plugins['Autoptimize'] = '2.4.0';
else
$active_plugins[] = 'Autoptimize';
}
// wp-optimize
if ( cn_is_plugin_active( 'wpoptimize' ) ) {
if ( $version )
$active_plugins['WP-Optimize'] = '3.0.12';
else
$active_plugins[] = 'WP-Optimize';
}
// litespeed
if ( cn_is_plugin_active( 'litespeed' ) ) {
if ( $version )
$active_plugins['LiteSpeed Cache'] = '3.0.0';
else
$active_plugins[] = 'LiteSpeed Cache';
}
// speed optimizer
if ( cn_is_plugin_active( 'speedoptimizer' ) ) {
if ( $version )
$active_plugins['Speed Optimizer'] = '5.5.0';
else
$active_plugins[] = 'Speed Optimizer';
}
// wp fastest cache
if ( cn_is_plugin_active( 'wpfastestcache' ) ) {
if ( $version )
$active_plugins['WP Fastest Cache'] = '1.0.0';
else
$active_plugins[] = 'WP Fastest Cache';
}
// wp rocket
if ( cn_is_plugin_active( 'wprocket' ) ) {
if ( $version )
$active_plugins['WP Rocket'] = '3.8.0';
else
$active_plugins[] = 'WP Rocket';
}
// hummingbird
if ( cn_is_plugin_active( 'hummingbird' ) ) {
if ( $version )
$active_plugins['Hummingbird'] = '2.1.0';
else
$active_plugins[] = 'Hummingbird';
}
// wp super cache
if ( cn_is_plugin_active( 'wpsupercache' ) ) {
if ( $version )
$active_plugins['WP Super Cache'] = '1.6.9';
else
$active_plugins[] = 'WP Super Cache';
}
// breeze
if ( cn_is_plugin_active( 'breeze' ) ) {
if ( $version )
$active_plugins['Breeze'] = '1.1.0';
else
$active_plugins[] = 'Breeze';
}
// speedycache
if ( cn_is_plugin_active( 'speedycache' ) ) {
if ( $version )
$active_plugins['SpeedyCache'] = '1.0.0';
else
$active_plugins[] = 'SpeedyCache';
}
return $active_plugins;
}
/**
* Check whether specified plugin is active.
*
* @global object $siteground_optimizer_loader
* @global int $wpsc_version
*
* @param string $plugin
* @param string $module
* @return bool
*/
function cn_is_plugin_active( $plugin = '', $module = 'caching' ) {
// no valid plugin?
if ( ! in_array( $plugin, [
'amp',
'autoptimize',
'breeze',
'contactform7',
'divi',
'easydigitaldownloads',
'elementor',
'formidableforms',
'hummingbird',
'litespeed',
'mailchimp',
'speedoptimizer',
'speedycache',
'woocommerce',
'wpfastestcache',
'wpforms',
'wpoptimize',
'wprocket',
'wpsupercache'
], true ) )
return false;
// set default flag
$is_plugin_active = false;
switch ( $plugin ) {
// amp
case 'amp':
if ( $module === 'caching' && function_exists( 'amp_is_enabled' ) && defined( 'AMP__VERSION' ) && version_compare( AMP__VERSION, '2.0', '>=' ) )
$is_plugin_active = true;
break;
// autoptimize
case 'autoptimize':
if ( $module === 'caching' && function_exists( 'autoptimize' ) && defined( 'AUTOPTIMIZE_PLUGIN_VERSION' ) && version_compare( AUTOPTIMIZE_PLUGIN_VERSION, '2.4', '>=' ) )
$is_plugin_active = true;
break;
// breeze
case 'breeze':
if ( $module === 'caching' && class_exists( 'Breeze_PurgeCache' ) && class_exists( 'Breeze_Options_Reader' ) && function_exists( 'breeze_get_option' ) && function_exists( 'breeze_update_option' ) && defined( 'BREEZE_VERSION' ) && version_compare( BREEZE_VERSION, '1.1.0', '>=' ) )
$is_plugin_active = true;
break;
// contact form 7
case 'contactform7':
if ( $module === 'captcha' && class_exists( 'WPCF7' ) && class_exists( 'WPCF7_RECAPTCHA' ) && defined( 'WPCF7_VERSION' ) && version_compare( WPCF7_VERSION, '5.1', '>=' ) )
$is_plugin_active = true;
elseif ( $module === 'privacy-consent' && class_exists( 'WPCF7' ) && defined( 'WPCF7_VERSION' ) && version_compare( WPCF7_VERSION, '5.3', '>=' ) )
$is_plugin_active = true;
break;
// divi
case 'divi':
if ( $module === 'theme' && function_exists( 'is_et_pb_preview' ) && defined( 'ET_CORE_VERSION' ) )
$is_plugin_active = true;
break;
// easy digital downloads
case 'easydigitaldownloads':
if ( $module === 'privacy-consent' && class_exists( 'Easy_Digital_Downloads' ) && function_exists( 'EDD' ) && defined( 'EDD_VERSION' ) && version_compare( EDD_VERSION, '3.0.0', '>=' ) )
$is_plugin_active = true;
break;
// elementor
case 'elementor':
if ( $module === 'caching' && did_action( 'elementor/loaded' ) && defined( 'ELEMENTOR_VERSION' ) && version_compare( ELEMENTOR_VERSION, '1.3', '>=' ) )
$is_plugin_active = true;
break;
// formidable forms
case 'formidableforms':
if ( $module === 'privacy-consent' && class_exists( 'FrmAppHelper' ) && method_exists( 'FrmAppHelper', 'plugin_version' ) && version_compare( FrmAppHelper::plugin_version(), '2.0', '>=' ) )
$is_plugin_active = true;
break;
// hummingbird
case 'hummingbird':
if ( $module === 'caching' && class_exists( 'Hummingbird\\WP_Hummingbird' ) && defined( 'WPHB_VERSION' ) && version_compare( WPHB_VERSION, '2.1.0', '>=' ) )
$is_plugin_active = true;
break;
// litespeed
case 'litespeed':
if ( $module === 'caching' && class_exists( 'LiteSpeed\Core' ) && defined( 'LSCWP_CUR_V' ) && version_compare( LSCWP_CUR_V, '3.0', '>=' ) )
$is_plugin_active = true;
break;
// mailchimp
case 'mailchimp':
if ( $module === 'privacy-consent' && class_exists( 'MC4WP_Form_Manager' ) && defined( 'MC4WP_VERSION' ) && version_compare( MC4WP_VERSION, '4.0', '>=' ) )
$is_plugin_active = true;
break;
// speed optimizer
case 'speedoptimizer':
global $siteground_optimizer_loader;
if ( $module === 'caching' && ! empty( $siteground_optimizer_loader ) && is_object( $siteground_optimizer_loader ) && is_a( $siteground_optimizer_loader, 'SiteGround_Optimizer\Loader\Loader' ) && defined( '\SiteGround_Optimizer\VERSION' ) && version_compare( \SiteGround_Optimizer\VERSION, '5.5', '>=' ) )
$is_plugin_active = true;
break;
// speedycache
case 'speedycache':
if ( $module === 'caching' && class_exists( 'SpeedyCache' ) && defined( 'SPEEDYCACHE_VERSION' ) && function_exists( 'speedycache_delete_cache' ) && version_compare( SPEEDYCACHE_VERSION, '1.0.0', '>=' ) )
$is_plugin_active = true;
break;
// woocommerce
case 'woocommerce':
if ( $module === 'privacy-consent' && class_exists( 'WooCommerce' ) && defined( 'WOOCOMMERCE_VERSION' ) && version_compare( WOOCOMMERCE_VERSION, '4.0.4', '>=' ) )
$is_plugin_active = true;
break;
// wp fastest cache
case 'wpfastestcache':
if ( $module === 'caching' && function_exists( 'wpfc_clear_all_cache' ) )
$is_plugin_active = true;
break;
// wpforms
case 'wpforms':
if ( $module === 'privacy-consent' && function_exists( 'wpforms' ) && defined( 'WPFORMS_VERSION' ) && version_compare( WPFORMS_VERSION, '1.6.0', '>=' ) )
$is_plugin_active = true;
break;
// wp-optimize
case 'wpoptimize':
if ( $module === 'caching' && function_exists( 'WP_Optimize' ) && defined( 'WPO_VERSION' ) && version_compare( WPO_VERSION, '3.0.12', '>=' ) )
$is_plugin_active = true;
break;
// wp rocket
case 'wprocket':
if ( $module === 'caching' && function_exists( 'rocket_init' ) && defined( 'WP_ROCKET_VERSION' ) && version_compare( WP_ROCKET_VERSION, '3.8', '>=' ) )
$is_plugin_active = true;
break;
// wp super cache
case 'wpsupercache':
if ( $module === 'caching' ) {
$plugin_name = 'wp-super-cache/wp-cache.php';
$plugin_path = WP_PLUGIN_DIR . '/' . $plugin_name;
if ( file_exists( $plugin_path ) && is_plugin_active( $plugin_name ) ) {
$plugin = get_plugin_data( $plugin_path, false, false );
if ( version_compare( $plugin['Version'], '1.6.3', '>=' ) && function_exists( 'wp_cache_is_enabled' ) && function_exists( 'wp_cache_clean_cache' ) && function_exists( 'wpsc_add_cookie' ) && function_exists( 'wpsc_delete_cookie' ) )
$is_plugin_active = true;
}
}
break;
}
return $is_plugin_active;
}
/**
* Detect active analytics/tracking plugins for consent mode suggestions.
*
* @return array List of detected plugin categories: 'google', 'facebook', 'microsoft'.
*/
function cn_detect_active_plugins() {
$checks = [
'google' => [
'google-analytics-for-wordpress/googleanalytics.php',
'google-site-kit/google-site-kit.php',
'wp-google-analytics/wp-google-analytics.php',
'gtm4wp/gtm4wp.php',
],
'facebook' => [
'official-facebook-pixel/facebook-for-wordpress.php',
'pixel-caffeine/pixel-caffeine.php',
],
'microsoft' => [
'clarity-analytics/clarity-analytics.php',
],
];
$detected = [];
foreach ( $checks as $mode => $plugins ) {
foreach ( $plugins as $plugin ) {
if ( is_plugin_active( $plugin ) ) {
$detected[] = $mode;
break;
}
}
}
return array_values( array_unique( $detected ) );
}

View File

@@ -0,0 +1,172 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules AMP class.
*
* Compatibility since: 2.0.0
*
* @class Cookie_Notice_Modules_AMP
*/
class Cookie_Notice_Modules_AMP {
private $nonce = '';
/**
* Constructor.
*
* @return void
*/
public function __construct() {
$this->nonce = wp_create_nonce( 'cookie-compliance-amp-consent' );
add_action( 'init', [ $this, 'handle_iframe' ] );
add_action( 'wp_head', [ $this, 'load_amp_consent' ] );
}
/**
* Load AMP consent module.
*
* @return void
*/
public function load_amp_consent() {
// is banner allowed to display?
if ( ! Cookie_Notice()->frontend->maybe_display_banner( [ 'skip_amp' => true ] ) )
return;
if ( function_exists( 'amp_is_request' ) && amp_is_request() ) {
// load styles
echo '
<style amp-custom>
#cnConsentContainer {
background: none;
border: none;
box-shadow: none;
border-radius: 0;
height: 100vh;
width: 100%;
}
#cnConsentContainer amp-iframe {
height: 100vh;
width: 100%;
}
#cnConsentWidget {
height: 100vh;
width: 100%;
}
</style>';
// load scripts
echo '
<script async custom-element="amp-script" src="https://cdn.ampproject.org/v0/amp-script-0.1.js"></script>
<script async custom-element="amp-consent" src="https://cdn.ampproject.org/v0/amp-consent-0.1.js"></script>
<script async custom-element="amp-iframe" src="https://cdn.ampproject.org/v0/amp-iframe-0.1.js"></script>';
// get iframe url
$url = apply_filters( 'cn_cookie_compliance_amp_iframe_url', $this->add_subdomain_to_url( get_site_url(), 'www' ) );
// load consent iframe
echo '
<amp-consent id="cnConsentContainer" layout="nodisplay">
<script type="application/json">
{
"consentInstanceId": "cnConsent",
"consentRequired": true,
"purposeConsentRequired": [ "basic_operations", "content_personalization", "site_optimization", "ad_personalization" ],
"promptUI": "cnConsentWidget"
}
</script>
<div id="cnConsentWidget">
<amp-iframe layout="fill" sandbox="allow-scripts allow-same-origin" src="' . esc_url( $url . '/?cn-amp-consent-iframe=' . $this->nonce ) . '">
<div placeholder></div>
</amp-iframe>
</div>
</amp-consent>';
}
}
/**
* Add subdomain to url.
*
* @param string $url
* @param string $subdomain
* @return string
*/
public function add_subdomain_to_url( $url, $subdomain ) {
// parse url
$parts = parse_url( $url );
// subdomain does not exist?
if ( substr( $parts['host'], 0, strlen( $subdomain ) + 1 ) !== $subdomain . '.' ) {
// find host
$pos = strpos( $url, $parts['host'] );
// update url and add subdomain
$url = substr_replace( $url, $subdomain . '.' . $parts['host'], $pos, strlen( $parts['host'] ) );
}
return $url;
}
/**
* Generate consent iframe.
*
* @return void
*/
public function handle_iframe() {
if ( isset( $_GET['cn-amp-consent-iframe'] ) && $_GET['cn-amp-consent-iframe'] === $this->nonce ) {
wp_ob_end_flush_all();
// display iframe
echo $this->generate_iframe_html();
exit;
}
}
/**
* Generate consent iframe.
*
* @return string
*/
public function generate_iframe_html() {
// get main instance
$cn = Cookie_Notice();
// get options
$options = $cn->frontend->get_cc_options();
// get output
$cc_output = $cn->frontend->get_cc_output( $options );
// get allowed html for cookie compliance html output
$allowed_html = array_merge(
wp_kses_allowed_html( 'post' ),
[
'script' => [
'type' => true,
'src' => true
]
]
);
$html = '
<!DOCTYPE html>
<html ' . get_language_attributes( 'html' ) . '>
<head>
<meta charset="' . esc_attr( get_bloginfo( 'charset', 'display' ) ) . '">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<title>' . esc_html__( 'Cookie Compliance AMP Consent', 'cookie-notice' ) . '</title>
' . wp_kses( $cc_output, $allowed_html ) . '
<script type="text/javascript" src="' . esc_url( COOKIE_NOTICE_URL . '/includes/modules/amp/iframe.js' ) . '"></script>
</head>
<body></body>
</html>';
return $html;
}
}
new Cookie_Notice_Modules_AMP();

View File

@@ -0,0 +1,58 @@
function cnDisableRevoke() {
var huObject = null;
// get valid hu object
for ( const object of [ '__hu', 'hu' ] ) {
// check global variable
if ( typeof window[object] !== 'undefined' && window[object].hasOwnProperty( 'earlyInit' ) && typeof window[object].earlyInit === 'function' ) {
huObject = window[object];
// no need to check again
break;
}
}
// force revoke button to be disabled
huObject.options.config.revokeConsent = false;
}
function cnConsentResponse( event ) {
// allow this event to run only once
if ( event.type === 'set-consent.hu' )
document.removeEventListener( 'hide.hu', cnConsentResponse );
document.addEventListener( 'save-consent-response.hu', cnConsentSet( event.detail.categories ) );
}
function cnConsentSet( categories ) {
// it has to use return function to wait for save-consent-response event
return function cnRequestFinished( event ) {
var action = 'accept';
// only basic operations?
if ( categories[1] && ! categories[2] && ! categories[3] && ! categories[4] )
action = 'reject';
// inform amp to save consent
window.parent.postMessage(
{
type: 'consent-response',
action: action,
purposeConsents: {
'basic_operations': categories[1],
'content_personalization': categories[2],
'site_optimization': categories[3],
'ad_personalization': categories[4]
}
},
'*'
);
}
}
// set consent
document.addEventListener( 'hide.hu', cnConsentResponse );
document.addEventListener( 'set-consent.hu', cnConsentResponse );
// disable revoke button
document.addEventListener( 'load.hu', cnDisableRevoke );

View File

@@ -0,0 +1,72 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Autoptimize class.
*
* Compatibility since: 2.4.0
*
* @class Cookie_Notice_Modules_Autoptimize
*/
class Cookie_Notice_Modules_Autoptimize {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to Autoptimize plugin.
*
* @return void
*/
public function load_module() {
add_filter( 'autoptimize_filter_js_exclude', [ $this, 'exclude' ] );
}
/**
* Exclude JavaScript files or inline code.
*
* @param string $excludes
* @return string
*/
function exclude( $excludes ) {
if ( empty( $excludes ) )
$new_excludes = [];
else {
$new_excludes = explode( ',', $excludes );
$new_excludes = array_filter( $new_excludes );
$new_excludes = array_map( 'trim', $new_excludes );
}
// not found huOptions?
if ( strpos( $excludes, 'huOptions' ) === false )
$new_excludes[] = 'huOptions';
// get widget url
$widget_url = basename( Cookie_Notice()->get_url( 'widget' ) );
// not found widget url?
if ( strpos( $excludes, $widget_url ) === false )
$new_excludes[] = $widget_url;
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
// Keeps Autoptimize off our IIFE bundle if its "optimize admin" toggle is on.
if ( strpos( $excludes, Cookie_Notice::REACT_ADMIN_BUNDLE_BASENAME ) === false )
$new_excludes[] = Cookie_Notice::REACT_ADMIN_BUNDLE_BASENAME;
if ( strpos( $excludes, Cookie_Notice::REACT_ADMIN_INLINE_KEYWORD ) === false )
$new_excludes[] = Cookie_Notice::REACT_ADMIN_INLINE_KEYWORD;
return implode( ', ', $new_excludes );
}
}
new Cookie_Notice_Modules_Autoptimize();

View File

@@ -0,0 +1,100 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Breeze class.
*
* Compatibility since: 2.0.30
*
* @class Cookie_Notice_Modules_Breeze
*/
class Cookie_Notice_Modules_Breeze {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to Breeze plugin.
*
* @return void
*/
public function load_module() {
// get main instance
$cn = Cookie_Notice();
// update 2.5.7+
if ( version_compare( $cn->db_version, '2.5.7', '<=' ) )
$this->remove_excluded_external_script();
// is caching active?
if ( (int) Breeze_Options_Reader::get_option_value( 'breeze-active' ) === 1 ) {
// update 2.4.16+
if ( version_compare( $cn->db_version, '2.4.16', '<=' ) ) {
// clear cache
$this->delete_cache();
}
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
// is js minification active?
if ( (int) Breeze_Options_Reader::get_option_value( 'breeze-minify-js' ) === 1 ) {
// filters
add_filter( 'cn_cookie_compliance_output', [ $this, 'update_cc_output' ] );
}
}
}
/**
* Update Cookie Compliance output.
*
* @param string $output
*
* @return string
*/
public function update_cc_output( $output ) {
// add special /breeze-extra/ comment
return preg_replace( '/<script(.*)var huOptions(.*)<\/script>/', "<script$1var huOptions$2\n//breeze-extra/</script>", $output, 1 );
}
/**
* Remove previously excluded external script from being minified/combined.
*
* @return void
*/
public function remove_excluded_external_script() {
$pattern = '(.*)/js/hu-options.js(.*)';
// get breeze file options
$file_options = breeze_get_option( 'file_settings' );
// find pattern
$key = array_search( $pattern, $file_options['breeze-exclude-js'], true );
// found pattern? remove it
if ( $key !== false )
unset( $file_options['breeze-exclude-js'][$key] );
// update breeze file options
breeze_update_option( 'file_settings', $file_options, true );
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
do_action( 'breeze_clear_all_cache' );
}
}
new Cookie_Notice_Modules_Breeze();

View File

@@ -0,0 +1,69 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Contact Form 7 class.
*
* Compatibility since: 5.1.0 (recaptcha v3 only)
*
* @class Cookie_Notice_Modules_ContactForm7
*/
class Cookie_Notice_Modules_ContactForm7 {
private $service;
/**
* Constructor.
*
* @return void
*/
public function __construct() {
$this->service = WPCF7_RECAPTCHA::get_instance();
if ( $this->service->is_active() )
add_action( 'wp_enqueue_scripts', [ $this, 'contact_form_7_recaptcha' ], 21 );
}
/**
* Replace original recaptcha script from Contact Form 7.
*
* @return void
*/
public function contact_form_7_recaptcha() {
// deregister original script
wp_deregister_script( 'wpcf7-recaptcha' );
// register new script
wp_register_script(
'wpcf7-recaptcha',
COOKIE_NOTICE_URL . '/includes/modules/contact-form-7/recaptcha.js',
[
'google-recaptcha',
'wp-polyfill'
],
WPCF7_VERSION,
true
);
wp_enqueue_script( 'wpcf7-recaptcha' );
wp_localize_script(
'wpcf7-recaptcha',
'wpcf7_recaptcha',
[
'sitekey' => $this->service->get_sitekey(),
'actions' => apply_filters(
'wpcf7_recaptcha_actions',
[
'homepage' => 'homepage',
'contactform' => 'contactform'
]
)
]
);
}
}
new Cookie_Notice_Modules_ContactForm7();

View File

@@ -0,0 +1,246 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Contact Form 7 Privacy Consent class.
*
* Compatibility since: 5.3.0
*
* @class Cookie_Notice_Modules_ContactForm7_Privacy_Consent
*/
class Cookie_Notice_Modules_ContactForm7_Privacy_Consent {
private $defaults = [];
private $source = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'Contact Form 7', 'cookie-notice' ),
'id' => 'contactform7',
'id_type' => 'integer',
'type' => 'dynamic',
'availability' => cn_is_plugin_active( 'contactform7', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['contactform7_active'],
'status_type' => $cn->options['privacy_consent']['contactform7_active_type'],
'forms' => []
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// forms
add_filter( 'do_shortcode_tag', [ $this, 'shortcode' ], 10, 3 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_contactform7',
'cookie_notice_privacy_consent_contactform7',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['contactform7_active'] = isset( $input['contactform7_active'] );
$input['contactform7_active_type'] = isset( $input['contactform7_active_type'] ) && array_key_exists( $input['contactform7_active_type'], $cn->privacy_consent->form_active_types ) ? $input['contactform7_active_type'] : $cn->defaults['privacy_consent']['contactform7_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param int $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
$query = new WP_Query( [
'p' => $form_id,
'post_status' => 'publish',
'post_type' => 'wpcf7_contact_form',
'fields' => 'ids',
'no_found_rows' => true
] );
return $query->have_posts();
}
/**
* Get forms.
*
* @param array $args
*
* @return array
*/
public function get_forms( $args ) {
// get only published forms
$query = new WP_Query( [
'post_status' => 'publish',
'post_type' => 'wpcf7_contact_form',
'order' => $args['order'],
'orderby' => $args['orderby'],
'fields' => 'all',
'posts_per_page' => 10,
'no_found_rows' => false,
'paged' => $args['page'],
's' => $args['search']
] );
$forms = [];
// any forms?
if ( ! empty( $query->posts ) ) {
foreach ( $query->posts as $post ) {
$forms[] = [
'id' => $post->ID,
'title' => $post->post_title,
'date' => $post->post_date,
'fields' => []
];
}
}
return [
'forms' => $forms,
'total' => $query->found_posts,
'max_pages' => $query->max_num_pages
];
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// get only one form
$query = new WP_Query( [
'p' => (int) $args['form_id'],
'post_status' => 'publish',
'post_type' => 'wpcf7_contact_form',
'fields' => 'all',
'no_found_rows' => true
] );
// any forms?
if ( ! empty( $query->posts[0] ) ) {
$form = [
'source' => $this->source['id'],
'id' => $query->posts[0]->ID,
'title' => Cookie_Notice()->privacy_consent->strcut( sanitize_text_field( $query->posts[0]->post_title ), 100 ),
'fields' => [
'subject' => [
'first_name' => 'your-name',
'email' => 'your-email'
],
'preferences' => [
'terms' => 'your-consent'
]
]
];
} else
$form = [];
return $form;
}
/**
* Contact Form 7 shortcode output.
*
* @param string $output
* @param string $tag
* @param array $attr
*
* @return string
*/
public function shortcode( $output, $tag, $attr ) {
if ( $tag !== 'contact-form-7' )
return $output;
// check form id
$form_id = isset( $attr['id'] ) ? trim( $attr['id'] ) : '';
if ( empty( $form_id ) )
return $output;
$form = null;
// sanitize form id
$form_id = preg_replace( '/[^a-z0-9]/i', '', $form_id );
// get form by hash, since cf7 5.8
if ( function_exists( 'wpcf7_get_contact_form_by_hash' ) )
$form = wpcf7_get_contact_form_by_hash( $form_id );
// get form by integer id
if ( ! $form && function_exists( 'wpcf7_contact_form' ) )
$form = wpcf7_contact_form( $form_id );
// valid form?
if ( $form && is_a( $form, 'WPCF7_ContactForm' ) ) {
// get id
$form_id = (int) $form->id();
// active form?
if ( $form_id && Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id
] );
$output = (string) $output;
$output .= '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'[id^="wpcf7-f' . (int) $form_id . '-"] form\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
return $output;
}
}
new Cookie_Notice_Modules_ContactForm7_Privacy_Consent();

View File

@@ -0,0 +1,89 @@
( function( window, document, undefined ) {
'use strict';
/**
* Initialize recaptcha.
*
* @return {void}
*/
function initRecaptcha() {
wpcf7_recaptcha = {
...( wpcf7_recaptcha ?? {} )
};
const siteKey = wpcf7_recaptcha.sitekey;
const { homepage, contactform } = wpcf7_recaptcha.actions;
const execute = options => {
const { action, func, params } = options;
grecaptcha.execute( siteKey, {
action,
} ).then( token => {
const event = new CustomEvent( 'wpcf7grecaptchaexecuted', {
detail: {
action,
token
}
} );
document.dispatchEvent( event );
} ).then( () => {
if ( typeof func === 'function' ) {
func( ...params );
}
} ).catch( error => console.error( error ) );
};
grecaptcha.ready( () => {
execute( {
action: homepage
} );
} );
document.addEventListener( 'change', event => {
execute( {
action: contactform
} );
} );
if ( typeof wpcf7 !== 'undefined' && typeof wpcf7.submit === 'function' ) {
const submit = wpcf7.submit;
wpcf7.submit = ( form, options = {} ) => {
execute( {
action: contactform,
func: submit,
params: [ form, options ]
} );
};
}
document.addEventListener( 'wpcf7grecaptchaexecuted', event => {
const fields = document.querySelectorAll( 'form.wpcf7-form input[name="_wpcf7_recaptcha_response"]' );
for ( let i = 0; i < fields.length; i++ ) {
let field = fields[ i ];
field.setAttribute( 'value', event.detail.token );
}
} );
}
/**
* Handle cookies-unblocked event.
*
* @return {void}
*/
document.addEventListener( 'cookies-unblocked.hu', function( e ) {
e.detail.data.scripts.forEach( function( script ) {
// find google recaptcha in valid category
if ( script.id === 'google-recaptcha-js' && e.detail.categories[script.dataset.huCategory] === true ) {
script.onload = initRecaptcha;
script.onreadystatechange = initRecaptcha;
}
} );
}, false );
} )( window, document );

View File

@@ -0,0 +1,34 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Divi class.
*
* Compatibility since: 2.4.19
*
* @class Cookie_Notice_Modules_Divi
*/
class Cookie_Notice_Modules_Divi {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
add_filter( 'cn_is_preview_mode', [ $this, 'is_preview_mode' ] );
}
/**
* Whether Divi builder is active.
*
* @return bool
*/
function is_preview_mode() {
return is_et_pb_preview() || isset( $_GET[ 'et_fb' ] );
}
}
new Cookie_Notice_Modules_Divi();

View File

@@ -0,0 +1,397 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Easy Digital Downloads Privacy Consent class.
*
* Compatibility since: 3.0.0
*
* @class Cookie_Notice_Modules_EasyDigitalDownloads_Privacy_Consent
*/
class Cookie_Notice_Modules_EasyDigitalDownloads_Privacy_Consent {
private $defaults = [
'edd_registration_form' => [
'status' => false
],
'edd_checkout_form' => [
'status' => false
]
];
private $source = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'Easy Digital Downloads', 'cookie-notice' ),
'id' => 'easydigitaldownloads',
'id_type' => 'string',
'type' => 'static',
'availability' => cn_is_plugin_active( 'easydigitaldownloads', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['easydigitaldownloads_active'],
'status_type' => $cn->options['privacy_consent']['easydigitaldownloads_active_type'],
'forms' => [
'edd_registration_form' => [
'name' => __( 'Registration Form', 'cookie-notice' ),
'id' => 'edd_registration_form',
'type' => 'static',
'mode' => 'automatic',
'status' => false,
'logged_out_only' => true,
'fields' => [
'username' => '',
'email' => ''
],
'subject' => [
'email' => '#edd-user-email'
],
'preferences' => [],
'excluded' => []
],
'edd_checkout_form' => [
'name' => __( 'Checkout Form', 'cookie-notice' ),
'id' => 'edd_checkout_form',
'type' => 'static',
'mode' => 'automatic',
'status' => true,
'logged_out_only' => true,
'fields' => [
'email' => '',
'first_name' => '',
'last_name' => '',
'country' => '',
'address' => '',
'city' => '',
'postal_code' => '',
'phone' => ''
],
'subject' => [
'email' => '#edd-email',
'first_name' => '#edd-first',
'last_name' => '#edd-last'
],
'preferences' => [
'terms' => '#edd_agree_to_terms',
'privacy' => '#edd-agree-to-privacy-policy'
],
'excluded' => []
]
]
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// registration
add_action( 'edd_register_form_fields_after', [ $this, 'registration_form_classic' ] );
add_filter( 'render_block', [ $this, 'registration_form_blocks' ], 10, 2 );
add_filter( 'edd_errors', [ $this, 'errors' ] );
// checkout
add_action( 'edd_checkout_form_bottom', [ $this, 'checkout_form_classic' ] );
add_filter( 'render_block', [ $this, 'checkout_form_blocks' ], 10, 2 );
add_action( 'edd_built_order', [ $this, 'checkout_new_order' ], 10, 2 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_easydigitaldownloads',
'cookie_notice_privacy_consent_easydigitaldownloads',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['easydigitaldownloads_active'] = isset( $input['easydigitaldownloads_active'] );
$input['easydigitaldownloads_active_type'] = isset( $input['easydigitaldownloads_active_type'] ) && array_key_exists( $input['easydigitaldownloads_active_type'], $cn->privacy_consent->form_active_types ) ? $input['easydigitaldownloads_active_type'] : $cn->defaults['privacy_consent']['easydigitaldownloads_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param string $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
return array_key_exists( $form_id, $this->source['forms'] );
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// invalid form?
if ( ! $this->form_exists( $args['form_id'] ) )
return [];
$form_data = $this->source['forms'][$args['form_id']];
$form = [
'source' => $this->source['id'],
'id' => $form_data['id'],
'title' => $form_data['name'],
'fields' => [
'subject' => $form_data['subject'],
'preferences' => $form_data['preferences']
]
];
return $form;
}
/**
* Registration classic form.
*
* @return void
*/
public function registration_form_classic() {
$form_id = 'edd_registration_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
if ( $this->source['forms'][ $form_id ]['logged_out_only'] && is_user_logged_in() )
return;
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'classic'
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.getElementById( \'edd_register_form\' );';
// edd 3.2.3+ uses different id for registration form in blocks
if ( defined( 'EDD_VERSION' ) && version_compare( EDD_VERSION, '3.2.3', '>=' ) ) {
echo '
if ( huFormNode === null )
huFormNode = document.getElementById( \'edd-blocks-form__register\' );';
}
echo '
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
/**
* Registration blocks form.
*
* @param string|mixed $block_content
* @param array $block
*
* @return string
*/
public function registration_form_blocks( $block_content, $block ) {
// edd version 3.2.3+ has native support of edd_checkout_form_bottom in blocks
if ( defined( 'EDD_VERSION' ) && version_compare( EDD_VERSION, '3.2.3', '>=' ) )
return $block_content;
// not edd checkout block?
if ( $block['blockName'] !== 'edd/register' )
return $block_content;
$form_id = 'edd_registration_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
if ( $this->source['forms'][ $form_id ]['logged_out_only'] && is_user_logged_in() )
return;
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'blocks'
] );
$block_content = '
<div class="wp-block" data-blockType="' . esc_attr( $block['blockName'] ) . '">
' . $block_content . '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.getElementById( \'edd-blocks-form__register\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>
</div>';
}
return $block_content;
}
/**
* Registration errors.
*
* @param array $errors
*
* @return array
*/
public function errors( $errors ) {
if ( isset( $_POST['edd_action'] ) && $_POST['edd_action'] === 'user_register' ) {
// prevent headers already sent
if ( headers_sent() )
return $errors;
// get main instance
$cn = Cookie_Notice();
// active registration form?
if ( $cn->privacy_consent->is_form_active( 'edd_registration_form', $this->source['id'] ) )
$cn->privacy_consent->set_cookie( empty( $errors ) ? 'true' : 'false' );
}
return $errors;
}
/**
* Checkout blocks form.
*
* @param string|mixed $block_content
* @param array $block
*
* @return string
*/
public function checkout_form_blocks( $block_content, $block ) {
// edd version 3.6.0+ has native support of edd_checkout_form_bottom in blocks
if ( defined( 'EDD_VERSION' ) && version_compare( EDD_VERSION, '3.6.0', '>=' ) )
return $block_content;
// not edd checkout block?
if ( $block['blockName'] !== 'edd/checkout' )
return $block_content;
$form_id = 'edd_checkout_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
if ( $this->source['forms'][ $form_id ]['logged_out_only'] && is_user_logged_in() )
return;
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'blocks'
] );
$block_content = '
<div class="wp-block" data-blockType="' . esc_attr( $block['blockName'] ) . '">
' . $block_content . '
' . $this->checkout_form_script( $form_data ) . '
</div>';
}
return $block_content;
}
/**
* Checkout classic form.
*
* @return void
*/
public function checkout_form_classic() {
$form_id = 'edd_checkout_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
if ( $this->source['forms'][ $form_id ]['logged_out_only'] && is_user_logged_in() )
return;
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'classic'
] );
echo $this->checkout_form_script( $form_data );
}
}
/**
* Add form script.
*
* @param array $form_data
*
* @return string
*/
public function checkout_form_script( $form_data ) {
return '<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.getElementById( \'edd_purchase_form\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
/**
* Checkout new order.
*
* @param int $order_id
* @param array $order_data
*
* @return void
*/
public function checkout_new_order( $order_id, $order_data ) {
// get main instance
$cn = Cookie_Notice();
// active checkout form?
if ( $cn->privacy_consent->is_form_active( 'edd_checkout_form', $this->source['id'] ) ) {
if ( ! empty( $order_data['user_email'] ) || ! empty( $order_data['user_info']['email'] ) )
$cn->privacy_consent->set_cookie( 'true' );
else
$cn->privacy_consent->set_cookie( 'false' );
}
}
}
new Cookie_Notice_Modules_EasyDigitalDownloads_Privacy_Consent();

View File

@@ -0,0 +1,34 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Elementor class.
*
* Compatibility since: 1.3.0
*
* @class Cookie_Notice_Modules_Elementor
*/
class Cookie_Notice_Modules_Elementor {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
add_filter( 'cn_is_preview_mode', [ $this, 'is_preview_mode' ] );
}
/**
* Whether elementor editor is active.
*
* @return bool
*/
function is_preview_mode() {
return \Elementor\Plugin::$instance->preview->is_preview_mode();
}
}
new Cookie_Notice_Modules_Elementor();

View File

@@ -0,0 +1,254 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Formidable Forms Privacy Consent class.
*
* Compatibility since: 2.0.0
*
* @class Cookie_Notice_Modules_FormidableForms_Privacy_Consent
*/
class Cookie_Notice_Modules_FormidableForms_Privacy_Consent {
private $defaults = [];
private $source = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'Formidable Forms', 'cookie-notice' ),
'id' => 'formidableforms',
'id_type' => 'integer',
'type' => 'dynamic',
'availability' => cn_is_plugin_active( 'formidableforms', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['formidableforms_active'],
'status_type' => $cn->options['privacy_consent']['formidableforms_active_type'],
'forms' => []
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// forms
add_filter( 'do_shortcode_tag', [ $this, 'shortcode' ], 10, 3 );
add_filter( 'frm_validate_entry', [ $this, 'handle_form' ], PHP_INT_MAX, 2 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_formidableforms',
'cookie_notice_privacy_consent_formidableforms',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['formidableforms_active'] = isset( $input['formidableforms_active'] );
$input['formidableforms_active_type'] = isset( $input['formidableforms_active_type'] ) && array_key_exists( $input['formidableforms_active_type'], $cn->privacy_consent->form_active_types ) ? $input['formidableforms_active_type'] : $cn->defaults['privacy_consent']['formidableforms_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param int $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
$form = FrmForm::get_published_forms( [ 'id' => $form_id ], 1, 'exclude' );
return ! empty( $form );
}
/**
* Get forms.
*
* @param array $args
*
* @return array
*/
public function get_forms( $args ) {
// default query args
$query = [
'is_template' => 0,
'parent_form_id' => array( null, 0 ),
'status' => array( null, '', 'published' )
];
// searching?
if ( $args['search'] !== '' ) {
$query[] = [
'or' => true,
'name LIKE' => $args['search'],
'description LIKE' => $args['search'],
'form_key LIKE' => $args['search']
];
}
// check orderby
if ( $args['orderby'] === 'title' )
$orderby = 'name';
elseif ( $args['orderby'] === 'date' )
$orderby = 'created_at';
// get only published forms
$frm_forms = FrmForm::getAll( $query, $orderby . ' ' . $args['order'], '10 OFFSET ' . ( ( $args['page'] - 1 ) * 10 ) );
$forms = [];
// any forms?
if ( ! empty( $frm_forms ) ) {
$total_items = FrmDb::get_count( 'frm_forms', $query );
foreach ( $frm_forms as $form ) {
$forms[] = [
'id' => $form->id,
'title' => $form->name,
'date' => $form->created_at,
'fields' => []
];
}
} else
$total_items = 0;
return [
'forms' => $forms,
'total' => $total_items,
'max_pages' => (int) ceil( $total_items / 10 )
];
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// get only one form
$frm_form = FrmForm::get_published_forms( [ 'id' => (int) $args['form_id'] ], 1, 'exclude' );
// any forms?
if ( ! empty( $frm_form ) ) {
$form = [
'source' => $this->source['id'],
'id' => $frm_form->id,
'title' => Cookie_Notice()->privacy_consent->strcut( sanitize_text_field( $frm_form->name ), 100 ),
'fields' => [
'subject' => [],
'preferences' => []
]
];
} else
$form = [];
return $form;
}
/**
* Formidable Forms shortcode output.
*
* @param string $output
* @param string $tag
* @param array $attr
*
* @return string
*/
public function shortcode( $output, $tag, $attr ) {
if ( $tag !== 'formidable' )
return $output;
// check form id
$form_id = isset( $attr['id'] ) ? trim( $attr['id'] ) : '';
if ( empty( $form_id ) )
return $output;
// cast form id
$form_id = (int) $form_id;
// get form
// $form = FrmForm::getOne( $form_id );
$form = FrmForm::get_published_forms( [ 'id' => $form_id ], 1, 'exclude' );
// valid abd active form?
if ( $form && Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id
] );
$output = (string) $output;
$output .= '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'#frm_form_' . $form_id . '_container form\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
return $output;
}
/**
* Handle form submission.
*
* @param array $errors
* @param array $values
*
* @return array
*/
public function handle_form( $errors, $values ) {
// get main instance
$cn = Cookie_Notice();
// active registration form?
if ( $cn->privacy_consent->is_form_active( $values['form_id'], $this->source['id'] ) )
$cn->privacy_consent->set_cookie( empty( $errors ) ? 'true' : 'false' );
return $errors;
}
}
new Cookie_Notice_Modules_FormidableForms_Privacy_Consent();

View File

@@ -0,0 +1,60 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
use Hummingbird\Core\Utils;
/**
* Cookie Notice Modules Hummingbird class.
*
* Compatibility since: 2.1.0
*
* @class Cookie_Notice_Modules_Hummingbird
*/
class Cookie_Notice_Modules_Hummingbird {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'init', [ $this, 'load_module' ] );
}
/**
* Add compatibility to Hummingbird plugin.
*
* @return void
*/
public function load_module() {
// bail if options class is not available
if ( ! class_exists( 'Hummingbird\Core\Utils' ) )
return;
// get caching module
$mod = Utils::get_module( 'page_cache' );
// valid object?
if ( is_a( $mod, 'Hummingbird\Core\Modules\Page_Cache' ) && method_exists( $mod, 'is_active' ) ) {
// is caching enabled?
if ( $mod->is_active() ) {
// delete cache files after updating settings or status
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
}
}
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
do_action( 'wphb_clear_page_cache' );
}
}
new Cookie_Notice_Modules_Hummingbird();

View File

@@ -0,0 +1,57 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules LiteSpeed Cache class.
*
* Compatibility since: 3.0.0
*
* @class Cookie_Notice_Modules_LiteSpeedCache
*/
class Cookie_Notice_Modules_LiteSpeedCache {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'init', [ $this, 'load_module' ], 9 );
}
/**
* Add compatibility to LiteSpeed Cache plugin.
*
* @return void
*/
public function load_module() {
add_filter( 'litespeed_optimize_js_excludes', [ $this, 'exclude_js' ] );
add_filter( 'litespeed_optm_js_defer_exc ', [ $this, 'exclude_js' ] );
}
/**
* Exclude JavaScript external file and inline code.
*
* @param array $excludes
* @return array
*/
function exclude_js( $excludes ) {
// add widget url
$excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
// add widget inline code
$excludes[] = 'huOptions';
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
// Defense-in-depth if LiteSpeed's JS combine / defer touches admin pages.
$excludes[] = Cookie_Notice::REACT_ADMIN_BUNDLE_BASENAME;
$excludes[] = Cookie_Notice::REACT_ADMIN_INLINE_KEYWORD;
return $excludes;
}
}
new Cookie_Notice_Modules_LiteSpeedCache();

View File

@@ -0,0 +1,233 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules Mailchimp Privacy Consent class.
*
* Compatibility since: 4.0.0
*
* @class Cookie_Notice_Modules_Mailchimp_Privacy_Consent
*/
class Cookie_Notice_Modules_Mailchimp_Privacy_Consent {
private $defaults = [];
private $source = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'Mailchimp for WP', 'cookie-notice' ),
'id' => 'mailchimp',
'id_type' => 'integer',
'type' => 'dynamic',
'availability' => cn_is_plugin_active( 'mailchimp', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['mailchimp_active'],
'status_type' => $cn->options['privacy_consent']['mailchimp_active_type'],
'forms' => []
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// forms
add_filter( 'mc4wp_form_after_fields', [ $this, 'form_html' ], 10, 2 );
add_action( 'mc4wp_form_success', [ $this, 'handle_form' ] );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_mailchimp',
'cookie_notice_privacy_consent_mailchimp',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['mailchimp_active'] = isset( $input['mailchimp_active'] );
$input['mailchimp_active_type'] = isset( $input['mailchimp_active_type'] ) && array_key_exists( $input['mailchimp_active_type'], $cn->privacy_consent->form_active_types ) ? $input['mailchimp_active_type'] : $cn->defaults['privacy_consent']['mailchimp_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param int $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
$query = new WP_Query( [
'p' => $form_id,
'post_status' => 'publish',
'post_type' => 'mc4wp-form',
'fields' => 'ids',
'no_found_rows' => true
] );
return $query->have_posts();
}
/**
* Get forms.
*
* @param array $args
*
* @return array
*/
public function get_forms( $args ) {
// get only published forms
$query = new WP_Query( [
'post_status' => 'publish',
'post_type' => 'mc4wp-form',
'order' => $args['order'],
'orderby' => $args['orderby'],
'fields' => 'all',
'posts_per_page' => 10,
'no_found_rows' => false,
'paged' => $args['page'],
's' => $args['search']
] );
$forms = [];
// any forms?
if ( ! empty( $query->posts ) ) {
foreach ( $query->posts as $post ) {
$forms[] = [
'id' => $post->ID,
'title' => $post->post_title,
'date' => $post->post_date,
'fields' => []
];
}
}
return [
'forms' => $forms,
'total' => $query->found_posts,
'max_pages' => $query->max_num_pages
];
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// get only one form
$query = new WP_Query( [
'p' => (int) $args['form_id'],
'post_status' => 'publish',
'post_type' => 'mc4wp-form',
'fields' => 'all',
'no_found_rows' => true
] );
// any forms?
if ( ! empty( $query->posts[0] ) ) {
$form = [
'source' => $this->source['id'],
'id' => $query->posts[0]->ID,
'title' => Cookie_Notice()->privacy_consent->strcut( sanitize_text_field( $query->posts[0]->post_title ), 100 ),
'fields' => [
'subject' => [
'first_name' => 'FNAME',
'last_name' => 'LNAME',
'email' => 'EMAIL'
],
'preferences' => [
'terms' => 'AGREE_TO_TERMS'
]
]
];
} else
$form = [];
return $form;
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function form_html( $html, $form ) {
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form->ID, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form->ID
] );
$html .= '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'form[class*="mc4wp-form-' . (int) $form->ID . '"]\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
return $html;
}
/**
* Handle form submission.
*
* @param object $form
*
* @return void
*/
public function handle_form( $form ) {
// get main instance
$cn = Cookie_Notice();
// active registration form?
if ( $cn->privacy_consent->is_form_active( $form->ID, $this->source['id'] ) )
$cn->privacy_consent->set_cookie( 'true' );
}
}
new Cookie_Notice_Modules_Mailchimp_Privacy_Consent();

View File

@@ -0,0 +1,104 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
use SiteGround_Optimizer\Options\Options;
/**
* Cookie Notice Modules Speed Optimizer class.
*
* Compatibility since: 5.5.0
*
* @class Cookie_Notice_Modules_SpeedOptimizer
*/
class Cookie_Notice_Modules_SpeedOptimizer {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to Speed Optimizer plugin.
*
* @return void
*/
public function load_module() {
// bail if options class is not available
if ( ! class_exists( 'SiteGround_Optimizer\Options\Options' ) )
return;
// check caching status
$cache_active = Options::is_enabled( 'siteground_optimizer_enable_cache' ) || Options::is_enabled( 'siteground_optimizer_file_caching' );
// update 2.4.17
if ( version_compare( Cookie_Notice()->db_version, '2.4.16', '<=' ) ) {
if ( $cache_active ) {
// clear cache
$this->delete_cache();
}
}
if ( $cache_active ) {
// actions
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
// filters
add_filter( 'sgo_js_minify_exclude', [ $this, 'exclude_script' ] );
add_filter( 'sgo_javascript_combine_exclude', [ $this, 'exclude_script' ] );
add_filter( 'sgo_javascript_combine_excluded_external_paths', [ $this, 'exclude_script' ] );
add_filter( 'sgo_javascript_combine_excluded_inline_content', [ $this, 'exclude_code' ] );
}
}
/**
* Exclude JavaScript file.
*
* @param array $excludes
* @return array
*/
function exclude_script( $excludes ) {
// add widget url
$excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
// Defense-in-depth if SG Optimizer's JS minify / combine touches admin pages.
$excludes[] = Cookie_Notice::REACT_ADMIN_BUNDLE_BASENAME;
return $excludes;
}
/**
* Exclude JavaScript inline code.
*
* @param array $excludes
* @return array
*/
function exclude_code( $excludes ) {
// add widget inline code
$excludes[] = 'huOptions';
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
$excludes[] = Cookie_Notice::REACT_ADMIN_INLINE_KEYWORD;
return $excludes;
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
if ( function_exists( 'sg_cachepress_purge_cache' ) )
sg_cachepress_purge_cache();
}
}
new Cookie_Notice_Modules_SpeedOptimizer();

View File

@@ -0,0 +1,64 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules SpeedyCache class.
*
* Compatibility since: 1.0.0
*
* @class Cookie_Notice_Modules_SpeedyCache
*/
class Cookie_Notice_Modules_SpeedyCache {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to SpeedyCache plugin.
*
* @global object $speedycache
*
* @return void
*/
public function load_module() {
global $speedycache;
// check caching status
$cache_active = ! empty( $speedycache->options['status'] );
// update 2.4.17
if ( version_compare( Cookie_Notice()->db_version, '2.4.16', '<=' ) ) {
if ( $cache_active ) {
// clear cache
$this->delete_cache();
}
}
if ( $cache_active ) {
// delete cache files after updating settings or status
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
}
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
// clear cache
if ( function_exists( 'speedycache_delete_cache' ) )
speedycache_delete_cache( true );
}
}
new Cookie_Notice_Modules_SpeedyCache();

View File

@@ -0,0 +1,382 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WooCommerce Privacy Consent class.
*
* Compatibility since: 4.0.4
*
* @class Cookie_Notice_Modules_WooCommerce_Privacy_Consent
*/
class Cookie_Notice_Modules_WooCommerce_Privacy_Consent {
private $defaults = [
'wc_registration_form' => [
'status' => false
],
'wc_checkout_form' => [
'status' => false
]
];
private $source = [];
private $registration_started = false;
private $registration_ended = false;
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'WooCommerce', 'cookie-notice' ),
'id' => 'woocommerce',
'id_type' => 'string',
'type' => 'static',
'availability' => cn_is_plugin_active( 'woocommerce', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['woocommerce_active'],
'status_type' => $cn->options['privacy_consent']['woocommerce_active_type'],
'forms' => [
'wc_registration_form' => [
'name' => __( 'Registration Form', 'cookie-notice' ),
'id' => 'wc_registration_form',
'type' => 'static',
'mode' => 'automatic',
'status' => false,
'logged_out_only' => true,
'fields' => [
'email' => ''
],
'subject' => [
'email' => 'email'
],
'preferences' => [],
'excluded' => []
],
'wc_checkout_form' => [
'name' => __( 'Checkout Form', 'cookie-notice' ),
'id' => 'wc_checkout_form',
'type' => 'static',
'mode' => 'automatic',
'status' => true,
'logged_out_only' => true,
'fields' => [
'email' => '',
'country' => '',
'first_name' => '',
'last_name' => '',
'address_1' => '',
'address_2' => '',
'postal_code' => '',
'city' => '',
'phone' => '',
'note' => ''
],
'subject' => [
'email' => '#email',
'first_name' => '#shipping-first_name',
'last_name' => '#shipping-last_name'
],
'preferences' => [
'terms' => '#terms-and-conditions'
],
'excluded' => []
]
]
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// registration
add_action( 'woocommerce_register_form', [ $this, 'register_form' ] );
add_action( 'wp_loaded', [ $this, 'registration_end' ], 21 );
add_filter( 'woocommerce_process_registration_errors', [ $this, 'registration_start' ], PHP_INT_MAX );
add_filter( 'woocommerce_registration_auth_new_customer', [ $this, 'registration_auth_new_customer' ], PHP_INT_MAX );
// checkout
add_action( 'woocommerce_new_order', [ $this, 'checkout_new_order' ], 10, 2 );
add_action( 'woocommerce_checkout_after_order_review', [ $this, 'checkout_form_classic' ] );
add_filter( 'render_block', [ $this, 'checkout_form_blocks' ], 10, 2 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_woocommerce',
'cookie_notice_privacy_consent_woocommerce',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['woocommerce_active'] = isset( $input['woocommerce_active'] );
$input['woocommerce_active_type'] = isset( $input['woocommerce_active_type'] ) && array_key_exists( $input['woocommerce_active_type'], $cn->privacy_consent->form_active_types ) ? $input['woocommerce_active_type'] : $cn->defaults['privacy_consent']['woocommerce_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param string $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
return array_key_exists( $form_id, $this->source['forms'] );
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// invalid form?
if ( ! $this->form_exists( $args['form_id'] ) )
return [];
$form_data = $this->source['forms'][$args['form_id']];
$form = [
'source' => $this->source['id'],
'id' => $form_data['id'],
'title' => $form_data['name'],
'fields' => [
'subject' => $form_data['subject'],
'preferences' => $form_data['preferences']
]
];
if ( $args['form_id'] === 'wc_checkout_form' ) {
if ( $args['form_type'] === 'blocks' ) {
// force preferences
$form['preferences']['privacy'] = true;
} elseif ( $args['form_type'] === 'classic' ) {
// set default input names
$form['fields']['subject']['email'] = 'billing_email';
$form['fields']['subject']['first_name'] = 'billing_first_name';
$form['fields']['subject']['last_name'] = 'billing_last_name';
// add terms and conditions input name if needed
if ( wc_terms_and_conditions_checkbox_enabled() )
$form['fields']['preferences']['terms'] = 'terms';
else
unset( $form['fields']['preferences']['terms'] );
// force privacy policy
if ( wc_privacy_policy_page_id() && wc_get_privacy_policy_text( 'checkout' ) !== '' )
$form['preferences']['privacy'] = true;
}
} elseif ( $args['form_id'] === 'wc_registration_form' ) {
// force privacy policy
if ( wc_privacy_policy_page_id() && wc_get_privacy_policy_text( 'registration' ) !== '' )
$form['preferences']['privacy'] = true;
}
return $form;
}
/**
* Registration form.
*
* @return void
*/
public function register_form() {
$form_id = 'wc_registration_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'.woocommerce-form-register\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
/**
* Registration start point.
*
* @param object $error
*
* @return object
*/
public function registration_start( $error ) {
if ( Cookie_Notice()->privacy_consent->is_form_active( 'wc_registration_form', $this->source['id'] ) ) {
// begin registration process
$this->registration_started = true;
}
return $error;
}
/**
* Registration end point #1.
*
* @param bool $force_login
*
* @return bool
*/
public function registration_auth_new_customer( $force_login ) {
if ( $this->registration_started ) {
$this->registration_ended = true;
Cookie_Notice()->privacy_consent->set_cookie( 'true' );
}
// if $force_login is true registration_end() will not be executed
return $force_login;
}
/**
* Registration end point #2.
*
* @return void
*/
public function registration_end() {
if ( $this->registration_started && ! $this->registration_ended )
Cookie_Notice()->privacy_consent->set_cookie( 'false' );
}
/**
* Checkout form.
*
* @return void
*/
public function checkout_form_classic() {
$form_id = 'wc_checkout_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'classic'
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
jQuery( document.body ).on( \'init_checkout\', function() {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'form.woocommerce-checkout\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
} );
}
</script>';
}
}
/**
* Add captcha to the checkout block.
*
* @param string|mixed $block_content
* @param array $block
*
* @return string
*/
public function checkout_form_blocks( $block_content, $block ) {
$block_content = (string) $block_content;
if ( $block['blockName'] !== 'woocommerce/checkout' )
return $block_content;
$form_id = 'wc_checkout_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id,
'form_type' => 'blocks'
] );
$block_content = '
<div class="wp-block" data-blockType="' . esc_attr( $block['blockName'] ) . '">
' . $block_content . '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = null;
// set empty node
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>
</div>';
}
return $block_content;
}
/**
* Checkout new order.
*
* @param int $order_id
* @param object $order
*
* @return void
*/
public function checkout_new_order( $order_id, $order ) {
// skip new admin area orders
if ( isset( $_REQUEST[ '_wpnonce' ] ) && wp_verify_nonce( $_REQUEST[ '_wpnonce' ], 'update-order_' . $order_id ) )
return;
// get main instance
$cn = Cookie_Notice();
// is checkout enabled?
if ( $cn->privacy_consent->is_form_active( 'wc_checkout_form', $this->source['id'] ) ) {
if ( $order->get_billing_email() !== '' )
$cn->privacy_consent->set_cookie( 'true' );
}
}
}
new Cookie_Notice_Modules_WooCommerce_Privacy_Consent();

View File

@@ -0,0 +1,313 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WordPress Privacy Consent class.
*
* Compatibility since: ?
*
* @class Cookie_Notice_Modules_WordPress_Privacy_Consent
*/
class Cookie_Notice_Modules_WordPress_Privacy_Consent {
private $defaults = [
'wp_registration_form' => [
'status' => true
],
'wp_comment_form' => [
'status' => true
]
];
private $source = [];
private $comment_form_active = false;
private $comment_passed_validation = false;
private $comment_validation = false;
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'WordPress', 'cookie-notice' ),
'id' => 'wordpress',
'id_type' => 'string',
'type' => 'static',
'availability' => true,
'status' => $cn->options['privacy_consent']['wordpress_active'],
'status_type' => $cn->options['privacy_consent']['wordpress_active_type'],
'forms' => [
'wp_registration_form' => [
'name' => __( 'Registration Form', 'cookie-notice' ),
'id' => 'wp_registration_form',
'type' => 'static',
'mode' => 'automatic',
'status' => false,
'logged_out_only' => true,
'fields' => [
'username' => '',
'email' => ''
],
'subject' => [
'email' => 'user_email',
'first_name' => 'user_login'
],
'preferences' => [],
'excluded' => []
],
'wp_comment_form' => [
'name' => __( 'Comment Form', 'cookie-notice' ),
'id' => 'wp_comment_form',
'type' => 'static',
'mode' => 'automatic',
'status' => false,
'logged_out_only' => true,
'fields' => [
'comment' => '',
'name' => '',
'email' => '',
'website' => ''
],
'subject' => [
'email' => 'email',
'first_name' => 'author'
],
'preferences' => [
'privacy' => 'wp-comment-cookies-consent'
],
'excluded' => []
]
]
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// comments
add_action( 'comment_form', [ $this, 'comment_form' ] );
add_action( 'comment_post', [ $this, 'comment_post' ], 10, 3 );
add_action( 'init', [ $this, 'comment_submission_start' ] );
add_action( 'shutdown', [ $this, 'comment_submission_end' ] );
// registration
add_action( 'register_form', [ $this, 'register_form' ] );
add_filter( 'registration_errors', [ $this, 'registration_errors' ], PHP_INT_MAX, 3 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_wordpress',
'cookie_notice_privacy_consent_wordpress',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['wordpress_active'] = isset( $input['wordpress_active'] );
$input['wordpress_active_type'] = isset( $input['wordpress_active_type'] ) && array_key_exists( $input['wordpress_active_type'], $cn->privacy_consent->form_active_types ) ? $input['wordpress_active_type'] : $cn->defaults['privacy_consent']['wordpress_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param string $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
return array_key_exists( $form_id, $this->source['forms'] );
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// invalid form?
if ( ! $this->form_exists( $args['form_id'] ) )
return [];
$form_data = $this->source['forms'][$args['form_id']];
return [
'source' => $this->source['id'],
'id' => $form_data['id'],
'title' => $form_data['name'],
'fields' => [
'subject' => $form_data['subject'],
'preferences' => $form_data['preferences']
]
];
}
/**
* Comment form.
*
* @return void
*/
public function comment_form() {
$form_id = 'wp_comment_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'[id="commentform"]\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
/**
* Mark comment as valid.
*
* @param array $comment_data
*
* @return array
*/
public function comment_post( $comment_id, $comment_approved, $comment_data ) {
if ( is_admin() )
return;
if ( ! $this->comment_form_active )
return;
if ( $this->comment_validation )
$this->comment_passed_validation = true;
}
/**
* Comment validation start process.
*
* @return void
*/
public function comment_submission_start() {
if ( is_admin() )
return;
$this->comment_form_active = Cookie_Notice()->privacy_consent->is_form_active( 'wp_comment_form', $this->source['id'] );
if ( ! $this->comment_form_active )
return;
// adding comment?
if ( basename( $_SERVER['PHP_SELF'] ) === 'wp-comments-post.php' ) {
$this->comment_validation = true;
$this->comment_passed_validation = false;
Cookie_Notice()->privacy_consent->set_cookie( 'false' );
}
}
/**
* Comment validation end process.
*
* @return void
*/
public function comment_submission_end() {
if ( is_admin() )
return;
if ( ! $this->comment_form_active )
return;
// adding comment?
if ( $this->comment_validation && $this->comment_passed_validation )
Cookie_Notice()->privacy_consent->set_cookie( 'true' );
}
/**
* Registration form.
*
* @return void
*/
public function register_form() {
$form_id = 'wp_registration_form';
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $form_id, $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $form_id
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'[id="registerform"]\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
/**
* Verify registration.
*
* @param object $errors
* @param string $user_login
* @param string $user_email
*
* @return object
*/
public function registration_errors( $errors, $user_login, $user_email ) {
// get main instance
$cn = Cookie_Notice();
// active registration form?
if ( $cn->privacy_consent->is_form_active( 'wp_registration_form', $this->source['id'] ) )
$cn->privacy_consent->set_cookie( $errors->has_errors() ? 'false' : 'true' );
return $errors;
}
}
new Cookie_Notice_Modules_WordPress_Privacy_Consent();

View File

@@ -0,0 +1,53 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WP Fastest Cache class.
*
* Compatibility since: 1.0.0
*
* @class Cookie_Notice_Modules_WPFastestCache
*/
class Cookie_Notice_Modules_WPFastestCache {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to WP Fastest Cache plugin.
*
* @return void
*/
public function load_module() {
// is caching enabled?
if ( isset( $GLOBALS['wp_fastest_cache_options']->wpFastestCacheStatus ) ) {
// update 2.4.10
if ( version_compare( Cookie_Notice()->db_version, '2.4.9', '<=' ) )
$this->delete_cache();
// delete cache files after updating settings or status
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
}
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) )
$GLOBALS['wp_fastest_cache']->deleteCache( false );
}
}
new Cookie_Notice_Modules_WPFastestCache();

View File

@@ -0,0 +1,54 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WP-Optimize class.
*
* Compatibility since: 3.0.12
*
* @class Cookie_Notice_Modules_WPOptimize
*/
class Cookie_Notice_Modules_WPOptimize {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// has to be executed on plugins_loaded with priority 0
$this->load_module();
}
/**
* Add compatibility to WP-Optimize plugin.
*
* @return void
*/
public function load_module() {
// get wp-optimize configuration
if ( class_exists( 'WPO_Cache_Config' ) ) {
$options = WPO_Cache_Config::instance()->get();
// is caching enabled?
if ( ! empty( $options['enable_page_caching'] ) )
add_filter( 'wpo_purge_cache_hooks', [ $this, 'add_purge_cache' ] );
}
}
/**
* Add action when cache is purged.
*
* @param array $actions
* @return array
*/
public function add_purge_cache( $actions ) {
$actions[] = 'cn_configuration_updated';
return $actions;
}
}
new Cookie_Notice_Modules_WPOptimize();

View File

@@ -0,0 +1,97 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WP Rocket class.
*
* Compatibility since: 3.8.0
*
* @class Cookie_Notice_Modules_WPRocket
*/
class Cookie_Notice_Modules_WPRocket {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'load_module' ], 11 );
}
/**
* Add compatibility to WP Rocket plugin.
*
* @return void
*/
public function load_module() {
// update 2.4.17
if ( version_compare( Cookie_Notice()->db_version, '2.4.16', '<=' ) )
$this->delete_cache();
// delete cache files after updating settings or status
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
// filters
add_filter( 'rocket_exclude_defer_js', [ $this, 'exclude_script' ] );
add_filter( 'rocket_exclude_js', [ $this, 'exclude_script' ] );
add_filter( 'rocket_delay_js_exclusions', [ $this, 'exclude_script' ] );
add_filter( 'rocket_delay_js_exclusions', [ $this, 'exclude_code' ] );
add_filter( 'rocket_defer_inline_exclusions', [ $this, 'exclude_code' ] );
add_filter( 'rocket_excluded_inline_js_content', [ $this, 'exclude_code' ] );
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
// clear cache
if ( function_exists( 'rocket_clean_domain' ) )
rocket_clean_domain();
// clear minified css and js files
if ( function_exists( 'rocket_clean_minify' ) )
rocket_clean_minify( [ 'js', 'css' ] );
}
/**
* Exclude JavaScript file.
*
* @param array $excludes
* @return array
*/
function exclude_script( $excludes ) {
// add widget url
$excludes[] = basename( Cookie_Notice()->get_url( 'widget' ) );
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
// Defense-in-depth if Rocket's delay-JS / minify touches admin pages
// (e.g. via Cloudflare APO integrations).
$excludes[] = Cookie_Notice::REACT_ADMIN_BUNDLE_BASENAME;
return $excludes;
}
/**
* Exclude JavaScript inline code.
*
* @param array $excludes
* @return array
*/
function exclude_code( $excludes ) {
// add widget inline code
$excludes[] = 'huOptions';
// React admin asset exclusions — see Cookie_Notice::REACT_ADMIN_*.
$excludes[] = Cookie_Notice::REACT_ADMIN_INLINE_KEYWORD;
return $excludes;
}
}
new Cookie_Notice_Modules_WPRocket();

View File

@@ -0,0 +1,76 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WP Super Cache class.
*
* Compatibility since: 1.6.3
*
* @class Cookie_Notice_Modules_WPSuperCache
*/
class Cookie_Notice_Modules_WPSuperCache {
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'init', [ $this, 'add_cookie' ] );
add_action( 'admin_init', [ $this, 'load_module' ] );
add_action( 'deactivated_cookie-notice/cookie-notice.php', [ $this, 'delete_cookie' ] );
}
/**
* Add compatibility to WP Super Cache plugin.
*
* @return void
*/
public function load_module() {
// bail if function is not available
if ( ! function_exists( 'wp_cache_is_enabled' ) )
return;
// is caching enabled?
if ( wp_cache_is_enabled() ) {
// delete cache files after updating settings or status
add_action( 'cn_configuration_updated', [ $this, 'delete_cache' ] );
}
}
/**
* Add hu-consent cookie.
*
* @return void
*/
public function add_cookie() {
do_action( 'wpsc_add_cookie', 'hu-consent' );
}
/**
* Delete hu-consent cookie.
*
* @return void
*/
public function delete_cookie() {
do_action( 'wpsc_delete_cookie', 'hu-consent' );
}
/**
* Delete all cache files.
*
* @return void
*/
public function delete_cache() {
if ( function_exists( 'wp_cache_clean_cache' ) ) {
global $file_prefix;
wp_cache_clean_cache( $file_prefix, true );
}
}
}
new Cookie_Notice_Modules_WPSuperCache();

View File

@@ -0,0 +1,225 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie Notice Modules WPForms Privacy Consent class.
*
* Compatibility since: 1.6.0
*
* @class Cookie_Notice_Modules_WPForms_Privacy_Consent
*/
class Cookie_Notice_Modules_WPForms_Privacy_Consent {
private $defaults = [];
private $source = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// get main instance
$cn = Cookie_Notice();
$this->source = [
'name' => __( 'WPForms', 'cookie-notice' ),
'id' => 'wpforms',
'id_type' => 'integer',
'type' => 'dynamic',
'availability' => cn_is_plugin_active( 'wpforms', 'privacy-consent' ),
'status' => $cn->options['privacy_consent']['wpforms_active'],
'status_type' => $cn->options['privacy_consent']['wpforms_active_type'],
'forms' => []
];
// register source
$cn->privacy_consent->add_instance( $this, $this->source['id'] );
$cn->privacy_consent->add_source( $this->source );
add_action( 'admin_init', [ $this, 'register_source' ] );
// check compliance status
if ( $cn->get_status() !== 'active' )
return;
// forms
add_action( 'wpforms_frontend_output', [ $this, 'wpforms_shortcode' ], 19, 5 );
}
/**
* Register source.
*
* @return void
*/
public function register_source() {
register_setting(
'cookie_notice_privacy_consent_wpforms',
'cookie_notice_privacy_consent_wpforms',
[
'type' => 'array'
]
);
}
/**
* Validate source.
*
* @param array $input
*
* @return array
*/
public function validate( $input ) {
// get main instance
$cn = Cookie_Notice();
$input['wpforms_active'] = isset( $input['wpforms_active'] );
$input['wpforms_active_type'] = isset( $input['wpforms_active_type'] ) && array_key_exists( $input['wpforms_active_type'], $cn->privacy_consent->form_active_types ) ? $input['wpforms_active_type'] : $cn->defaults['privacy_consent']['wpforms_active_type'];
return $input;
}
/**
* Check whether form exists.
*
* @param int $form_id
*
* @return bool
*/
public function form_exists( $form_id ) {
$query = new WP_Query( [
'p' => $form_id,
'post_status' => 'publish',
'post_type' => 'wpforms',
'fields' => 'ids',
'no_found_rows' => true
] );
return $query->have_posts();
}
/**
* Get forms.
*
* @param array $args
*
* @return array
*/
public function get_forms( $args ) {
// get only published forms
$query = new WP_Query( [
'post_status' => 'publish',
'post_type' => 'wpforms',
'order' => $args['order'],
'orderby' => $args['orderby'],
'fields' => 'all',
'posts_per_page' => 10,
'no_found_rows' => false,
'paged' => $args['page'],
's' => $args['search']
] );
$forms = [];
// any forms?
if ( ! empty( $query->posts ) ) {
foreach ( $query->posts as $post ) {
$forms[] = [
'id' => $post->ID,
'title' => $post->post_title,
'date' => $post->post_date,
'fields' => []
];
}
}
return [
'forms' => $forms,
'total' => $query->found_posts,
'max_pages' => $query->max_num_pages
];
}
/**
* Get form.
*
* @param array $args
*
* @return array
*/
public function get_form( $args ) {
// get only one form
$query = new WP_Query( [
'p' => (int) $args['form_id'],
'post_status' => 'publish',
'post_type' => 'wpforms',
'fields' => 'all',
'no_found_rows' => true
] );
// any forms?
if ( ! empty( $query->posts[0] ) ) {
$form = [
'source' => $this->source['id'],
'id' => $query->posts[0]->ID,
'title' => Cookie_Notice()->privacy_consent->strcut( sanitize_text_field( $query->posts[0]->post_title ), 100 ),
'fields' => [
'subject' => [
'first_name' => '',
'last_name' => ''
]
]
];
} else
$form = [];
return $form;
}
/**
* WPForms shortcode output.
*
* @param array|mixed $data
* @param null $deprecated
* @param bool $title
* @param bool $description
* @param array $errors
*
* @return void
*/
public function wpforms_shortcode( $data, $deprecated, $title, $description, $errors ) {
$data = (array) $data;
// active form?
if ( Cookie_Notice()->privacy_consent->is_form_active( $data['id'], $this->source['id'] ) ) {
// get form data
$form_data = $this->get_form( [
'form_id' => $data['id']
] );
echo '
<script>
if ( typeof huOptions !== \'undefined\' ) {
var huFormData = ' . wp_json_encode( $form_data ) . ';
var huFormNode = document.querySelector( \'[id="wpforms-' . (int) $data['id'] . '"] form\' );
var firstName = huFormNode.querySelector( \'input.wpforms-field-name-first\' );
var lastName = huFormNode.querySelector( \'input.wpforms-field-name-last\' );
if ( firstName )
huFormData[\'fields\'][\'subject\'][\'first_name\'] = firstName.getAttribute( \'name\' );
if ( lastName )
huFormData[\'fields\'][\'subject\'][\'last_name\'] = lastName.getAttribute( \'name\' );
huFormData[\'node\'] = huFormNode;
huOptions[\'forms\'].push( huFormData );
}
</script>';
}
}
}
new Cookie_Notice_Modules_WPForms_Privacy_Consent();

View File

@@ -0,0 +1,83 @@
{
"_meta": {
"version": 1,
"rangeConvention": "usagePercent ranges are [inclusive, exclusive). null = unbounded. Example: [70, 100] means >= 70% AND < 100%.",
"templateVariables": "{sessionTotal}, {sessionUsed}, {usagePercent} — interpolated at render time with locale-formatted numbers."
},
"rules": [
{
"id": "threshold-locked",
"type": "critical",
"priority": 100,
"slot": "topBar",
"condition": { "tier": "free", "usagePercent": [ 100, null ] },
"title": "Action Required: Visit limit reached",
"description": "Your site has exceeded its free monthly limit of {sessionTotal} visits. Cookie autoblocking is now disabled, which means tracking scripts may fire before visitors consent. Upgrade to Pro immediately to restore full compliance protection.",
"cta": { "label": "Upgrade to Pro \u2192", "action": "openPricingModal" },
"dismissible": false,
"icon": "error"
},
{
"id": "threshold-warning",
"type": "warning",
"priority": 80,
"slot": "topBar",
"condition": { "tier": "free", "usagePercent": [ 70, 100 ] },
"title": "Approaching your visit limit",
"description": "Your site is nearing its free monthly limit ({sessionUsed} / {sessionTotal} visits). If you exceed the limit, cookie autoblocking will be disabled. Upgrade to Pro now for unlimited coverage.",
"cta": { "label": "Upgrade to Pro \u2192", "action": "openPricingModal" },
"dismissible": true,
"icon": "warning"
},
{
"id": "generic-upsell",
"type": "info",
"priority": 20,
"slot": "topBar",
"condition": { "tier": "free" },
"title": "Upgrade for unlimited coverage",
"description": "Free protects up to {sessionTotal} visits/month. Upgrade to Pro for unlimited visits, geo-targeting, and extended consent logs.",
"cta": { "label": "Upgrade to Pro \u2192", "action": "openPricingModal" },
"dismissible": true,
"icon": "info"
},
{
"id": "sidebar-threshold",
"type": "warning",
"priority": 90,
"slot": "sidebar",
"condition": { "tier": "free", "usagePercent": [ 70, null ] },
"headline": "Restore protection",
"features": [
"Remove the visit limit",
"Geo-targeted consent",
"Extended consent logs"
],
"cta": { "label": "Upgrade to Pro \u2192", "action": "openPricingModal" }
},
{
"id": "sidebar-generic",
"type": "info",
"priority": 10,
"slot": "sidebar",
"condition": { "tier": "free" },
"headline": "Unlock unlimited compliance",
"features": [
"Unlimited visits",
"Geo-targeted consent",
"Extended consent logs"
],
"cta": { "label": "Upgrade to Pro \u2192", "action": "openPricingModal" }
},
{
"id": "dashboard-near-limit",
"type": "warning",
"priority": 80,
"slot": "wpDashboard",
"condition": { "tier": "free", "usagePercent": [ 70, null ] },
"title": "Approaching your visit limit",
"description": "You\u2019ve used {usagePercent}% of your monthly limit. Autoblocking will be disabled and consent records will not be stored once you reach your limit.",
"cta": { "label": "Upgrade to Professional \u2192", "action": "openPricingModal" }
}
]
}

View File

@@ -0,0 +1,332 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Privacy_Consent_List_Table class.
*
* @class Cookie_Notice_Privacy_Consent_List_Table
*/
class Cookie_Notice_Privacy_Consent_List_Table extends WP_List_Table {
private $cn_empty_init = false;
private $cn_source = [];
private $cn_forms = [];
/**
* Set source.
*
* @param array $source
*
* @return void
*/
public function cn_set_source( $source ) {
$this->cn_source = $source;
}
/**
* Set source forms.
*
* @param array $forms
*
* @return void
*/
public function cn_set_forms( $forms ) {
$this->cn_forms = $forms;
}
/**
* Set empty init.
*
* @return void
*/
public function cn_empty_init() {
$this->cn_empty_init = true;
}
/**
* Display extra controls between bulk actions and pagination.
*
* @param string $which
*
* @return void
*/
protected function extra_tablenav( $which ) {
// skip top navigation
if ( $which === 'top' )
return;
echo '<span class="spinner"></span>';
}
/**
* Generate table navigation.
*
* @param string $which
*
* @return void
*/
protected function display_tablenav( $which ) {
// avoid different nonce and skip top navigation
if ( $which === 'top' )
return;
// skip static source and sources with less than 11 forms
if ( $this->cn_source['type'] === 'static' || $this->get_pagination_arg( 'total_items' ) < 11 )
return;
echo '
<div class="tablenav bottom">';
if ( $this->has_items() ) {
echo '
<div class="alignleft actions bulkactions">';
$this->bulk_actions( $which );
echo '
</div>';
}
$this->pagination( $which );
$this->extra_tablenav( $which );
echo '
<br class="clear" />
</div>';
}
/**
* Get a list of CSS classes.
*
* @return array
*/
protected function get_table_classes() {
if ( $this->cn_source['type'] === 'static' )
return parent::get_table_classes();
return [ 'widefat', 'fixed', 'striped', esc_attr( 'table-view-' . get_user_setting( 'posts_list_mode', 'list' ) ), $this->_args['plural'], 'loading' ];
}
/**
* Display search box.
*
* @param string $text
* @param string $input_id
*
* @return void
*/
public function search_box( $text, $input_id ) {
if ( empty( $_REQUEST['s'] ) && ! $this->has_items() )
return;
/* update input id
$input_id .= '-search-input';
echo '
<p class="search-box">
<label class="screen-reader-text" for="' . esc_attr( $input_id ) . '">' . esc_html( $text ) . ':</label>
<input type="search" id="' . esc_attr( $input_id ) . '" name="s" value="" />
<a id="' . esc_attr( $this->cn_source['id'] . '-search-submit' ) . '" class="button" href="' .esc_url( remove_query_arg( wp_removable_query_args(), set_url_scheme( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) ) . '">' . esc_html( $text ) . '</a>
</p>';
*/
}
/**
* Print column headers.
*
* @param bool $with_id
*
* @return void
*/
public function print_column_headers( $with_id = true ) {
// do not print column ids
parent::print_column_headers( false );
}
/**
* Handle AJAX request.
*
* @return void
*/
function ajax_response() {
check_ajax_referer( 'cn-privacy-consent-list-table-nonce', 'nonce' );
$this->prepare_items();
ob_start();
if ( ! empty( $_REQUEST['no_placeholder'] ) )
$this->display_rows();
else
$this->display_rows_or_placeholder();
$rows = ob_get_clean();
ob_start();
$this->print_column_headers();
$headers = ob_get_clean();
ob_start();
$this->pagination( 'bottom' );
$pagination = ob_get_clean();
$response = [
'rows' => $rows,
'column_headers' => $headers,
'pagination' => $pagination
];
// get pagination data
$total_items = $this->get_pagination_arg( 'total_items' );
$total_pages = $this->get_pagination_arg( 'total_pages' );
if ( isset( $total_items ) )
$response['total_items_i18n'] = sprintf( _n( '1 form', '%s forms', $total_items ), number_format_i18n( $total_items ) );
if ( isset( $total_pages ) ) {
$response['total_pages'] = $total_pages;
$response['total_pages_i18n'] = number_format_i18n( $total_pages );
}
wp_send_json_success( $response );
}
/**
* Prepare items for table.
*
* @return void
*/
public function prepare_items() {
// get main instance
$cn = Cookie_Notice();
// get consent logs
if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() && $cn->network_options['general']['global_override'] )
$privacy_consent = get_site_option( 'cookie_notice_privacy_consent_' . $this->cn_source['id'], [] );
else
$privacy_consent = get_option( 'cookie_notice_privacy_consent_' . $this->cn_source['id'], [] );
$items = [];
$data = $this->cn_forms;
foreach ( $data['forms'] as $form ) {
$items[] = [
'title' => $this->cn_source['type'] === 'dynamic' ? $form['title'] : $form['name'],
'id' => $form['id'],
'fields' => count( $form['fields'] ),
'date' => $this->cn_source['type'] === 'dynamic' ? $form['date'] : '-',
'status' => array_key_exists( $form['id'], $privacy_consent ) && array_key_exists( 'status', $privacy_consent[$form['id']] ) ? $privacy_consent[$form['id']]['status'] : false
];
}
if ( $this->cn_source['type'] === 'dynamic' ) {
$this->set_pagination_args(
[
'total_items' => empty( $data['total'] ) ? 0 : (int) $data['total'],
'total_pages' => empty( $data['max_pages'] ) ? 0 : (int) $data['max_pages'],
// 'per_page' => $per_page,
'orderby' => ! empty( $_POST['orderby'] ) ? sanitize_key( $_POST['orderby'] ) : 'title',
'order' => ! empty( $_POST['order'] ) ? sanitize_key( $_POST['order'] ) : 'asc'
]
);
}
$this->_column_headers = [ $this->get_columns(), [ 'date' ], $this->get_sortable_columns(), '' ];
$this->items = $items;
}
/**
* Define columns in listing table.
*
* @return array
*/
public function get_columns() {
$columns = [
'title' => __( 'Form Title', 'cookie-notice' ),
'id' => __( 'Form ID', 'cookie-notice' ),
'fields' => __( 'Fields', 'cookie-notice' ),
'date' => __( 'Date', 'cookie-notice' ),
'status' => __( 'Status', 'cookie-notice' )
];
return $columns;
}
/**
* Define sortable columns.
*
* @return array
*/
public function get_sortable_columns() {
if ( $this->cn_source['type'] === 'static' )
return [];
else
return [
'title' => [ 'title', false ]
// 'date' => [ 'date', true ]
];
}
/**
* Define what data to show on each column of the table.
*
* @param array $item
* @param string $column_name
*
* @return string
*/
public function column_default( $item, $column_name ) {
return esc_html( $item[$column_name] );
}
/**
* Display form title.
*
* @param array $item
*
* @return string
*/
public function column_title( $item ) {
return '<a href="#">' . esc_html( $item['title'] ) . '</a>';
}
/**
* Display status.
*
* @param array $item
*
* @return string
*/
public function column_status( $item ) {
return '<input type="checkbox" name="" value="1" class="cn-privacy-consent-form-status" data-source="' . esc_attr( $this->cn_source['id'] ) . '" data-form_id="' . esc_attr( $item['id'] ) . '" ' . checked( $item['status'], true, false ) . ' />';
}
/**
* Display bulk actions.
*
* @return array
*/
public function get_bulk_actions() {
return [];
}
/**
* Display empty result.
*
* @return void
*/
public function no_items() {
// display spinner for the first visit for dynamic source
if ( $this->cn_source['type'] === 'dynamic' && $this->cn_empty_init ) {
$this->cn_empty_init = false;
echo '<span class="spinner inside is-active"></span>';
} else
echo __( 'No forms found.', 'cookie-notice' );
}
}

View File

@@ -0,0 +1,382 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Privacy_Consent_Logs_List_Table class.
*
* @class Cookie_Notice_Privacy_Consent_Logs_List_Table
*/
class Cookie_Notice_Privacy_Consent_Logs_List_Table extends WP_List_Table {
private $cn_data = [];
private $cn_item_number = 0;
private $cn_empty_init = false;
/**
* Set empty init.
*
* @return void
*/
public function cn_empty_init() {
$this->cn_empty_init = true;
}
/**
* Set data.
*
* @param array $data
*
* @return void
*/
public function cn_set_data( $data ) {
$this->cn_data = $data;
}
/**
* Display content.
*
* @return void
*/
public function views() {
// get main instance
$cn = Cookie_Notice();
$login_url = esc_url( $cn->get_url( 'login', '?utm_campaign=consentlogs&utm_source=wordpress&utm_medium=link' ) );
$message = __( 'The table below shows the latest privacy consent records collected from the forms on your website.', 'cookie-notice' );
$message .= ' ' . sprintf( __( 'Log in to the <a href="%s" target="_blank">Compliance by Hu-manity.co</a> dashboard to view details or export proof of consent.', 'cookie-notice' ), $login_url );
// disable if basic plan and data older than 7 days
if ( $cn->get_subscription() === 'basic' )
$message .= '<br/><span class="cn-asterix">*</span> ' . __( 'Note: sites on the Compliance by Hu-manity.co Free Plan can collect up to 100 records.', 'cookie-notice' );
echo '<p class="description">' . wp_kses_post( $message ) . '</p>';
}
/**
* Prepare items for table.
*
* @return void
*/
public function prepare_items() {
// prepare items
$items = [];
// no data?
if ( ! empty( $this->cn_data ) ) {
foreach ( $this->cn_data as $consent ) {
$items[] = [
'subject' => $consent->subject_id,
'preferences' => $consent->preferences,
'form_id' => $consent->form_id,
'form_title' => ! empty( $consent->form_title ) ? $consent->form_title : __( '—', 'cookie-notice' ),
'source' => ! empty( $consent->source ) ? $consent->source : 'unknown',
'date' => $consent->created_at,
'ip_address' => $consent->ip_address
];
}
}
// count items
$noi = count( $items );
$per_page = 20;
$this->set_pagination_args(
[
'total_items' => $noi,
'total_pages' => (int) ceil( $noi / $per_page ),
'per_page' => $per_page
]
);
$this->_column_headers = [ $this->get_columns(), [], $this->get_sortable_columns(), '' ];
$this->items = $items;
}
/**
* Generate table navigation.
*
* @param string $which
*
* @return void
*/
protected function display_tablenav( $which ) {
// avoid different nonce and skip top navigation
if ( $which === 'top' ) {
echo '
<div class="tablenav top">';
$this->pagination( $which );
echo '
<br class="clear" />
</div>';
} else {
echo '
<div class="tablenav bottom">';
if ( $this->has_items() ) {
echo '
<div class="alignleft actions bulkactions">';
$this->bulk_actions( $which );
echo '
</div>';
}
$this->pagination( $which );
$this->extra_tablenav( $which );
echo '
<br class="clear" />
</div>';
}
}
/**
* Generate content for a single row of the table.
*
* @param array $item
*
* @return void
*/
public function single_row( $item ) {
$this->cn_item_number++;
echo '<tr' . ( $this->cn_item_number > $this->_pagination_args['per_page'] ? ' style="display: none"' : '' ) . '>';
$this->single_row_columns( $item );
echo '</tr>';
}
/**
* Display the pagination.
*
* @param string $which
*
* @return void
*/
protected function pagination( $which ) {
if ( empty( $this->_pagination_args ) )
return;
$total_items = $this->_pagination_args['total_items'];
$total_pages = $this->_pagination_args['total_pages'];
$output = '<span class="displaying-num">' . sprintf(
/* translators: %s: Number of items. */
_n( '%s item', '%s items', $total_items ),
number_format_i18n( $total_items )
) . '</span>';
$page_links = array();
$total_pages_before = '<span class="paging-input">';
$total_pages_after = '</span></span>';
// first page
$page_links[] = sprintf(
"<a class='first-page button disabled' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'First page' ),
'&laquo;'
);
// previous page
$page_links[] = sprintf(
"<a class='prev-page button disabled' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Previous page' ),
'&lsaquo;'
);
$html_current_page = '<span class="current-page">' . (int) $this->get_pagenum() . '</span>';
$total_pages_before = sprintf(
'<span class="screen-reader-text">%s</span>' .
'<span id="table-paging-' . $which . '" class="paging-input">' .
'<span class="tablenav-paging-text">',
/* translators: Hidden accessibility text. */
__( 'Current Page' )
);
$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
$page_links[] = $total_pages_before . sprintf(
/* translators: 1: Current page, 2: Total pages. */
_x( '%1$s of %2$s', 'paging' ),
$html_current_page,
$html_total_pages
) . $total_pages_after;
// next page
$page_links[] = sprintf(
"<a class='next-page button' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Next page' ),
'&rsaquo;'
);
// last page
$page_links[] = sprintf(
"<a class='last-page button' href='#'>" .
"<span class='screen-reader-text'>%s</span>" .
"<span aria-hidden='true'>%s</span>" .
'</a>',
/* translators: Hidden accessibility text. */
__( 'Last page' ),
'&raquo;'
);
$pagination_links_class = 'pagination-links';
if ( ! empty( $infinite_scroll ) )
$pagination_links_class .= ' hide-if-js';
$output .= "\n<span class='$pagination_links_class' data-total=" . (int) $total_pages . ">" . implode( "\n", $page_links ) . '</span>';
if ( $total_pages )
$page_class = $total_pages < 2 ? ' one-page' : '';
else
$page_class = ' no-pages';
$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
echo $this->_pagination;
}
/**
* Get a list of CSS classes.
*
* @return array
*/
protected function get_table_classes() {
return [ 'widefat', 'fixed', 'striped', esc_attr( 'table-view-' . get_user_setting( 'posts_list_mode', 'list' ) ), $this->_args['plural'], 'loading' ];
}
/**
* Define columns in listing table.
*
* @return array
*/
public function get_columns() {
$columns = [
'subject' => __( 'Subject', 'cookie-notice' ),
'preferences' => __( 'Preferences', 'cookie-notice' ),
'source' => __( 'Source', 'cookie-notice' ),
'form_title' => __( 'Form', 'cookie-notice' ),
'date' => __( 'Date', 'cookie-notice' ),
'ip_address' => __( 'IP address', 'cookie-notice' )
];
return $columns;
}
/**
* Define sortable columns.
*
* @return array
*/
public function get_sortable_columns() {
return [];
}
/**
* Define what data to show on each column of the table.
*
* @param array $item
* @param string $column_name
*
* @return string
*/
public function column_default( $item, $column_name ) {
return esc_html( $item[$column_name] );
}
/**
* Display source.
*
* @param array $item
*
* @return string
*/
public function column_source( $item ) {
if ( $item['source'] === 'unknown' )
$label = __( '—', 'cookie-notice' );
else {
$source = Cookie_Notice()->privacy_consent->get_source( $item['source'] );
if ( ! empty( $source ) )
$label = $source['name'];
else
$label = __( '—', 'cookie-notice' );
}
return esc_html( $label );
}
/**
* Display date.
*
* @param array $item
*
* @return string
*/
public function column_date( $item ) {
// get current date
$datetime = new DateTime( $item['date'] );
return esc_html( $datetime->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) . ' ' . __( 'GMT', 'cookie-notice' ) );
}
/**
* Display preferences.
*
* @param array $item
*
* @return string
*/
public function column_preferences( $item ) {
$preferences = (array) $item['preferences'];
return esc_html( empty( $preferences ) ? '—' : implode( ', ', array_keys( $preferences ) ) );
}
/**
* Display bulk actions.
*
* @return array
*/
public function get_bulk_actions() {
return [];
}
/**
* Display empty result.
*
* @return void
*/
public function no_items() {
// display spinner for the first visit
if ( $this->cn_empty_init ) {
$this->cn_empty_init = false;
echo '<span class="spinner inside is-active"></span>';
} else
echo __( 'No privacy consent logs found.', 'cookie-notice' );
}
}

View File

@@ -0,0 +1,83 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Privacy_Consent_logs class.
*
* @class Cookie_Notice_Privacy_Consent_logs
*/
class Cookie_Notice_Privacy_Consent_logs {
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'wp_ajax_cn_get_privacy_consent_logs', [ $this, 'get_privacy_consent_logs' ] );
}
/**
* Get privacy consent logs via AJAX request.
*
* @return void
*/
public function get_privacy_consent_logs() {
// check data
if ( ! isset( $_POST['action'], $_POST['nonce'] ) )
wp_send_json_error();
// valid nonce?
if ( check_ajax_referer( 'cn-get-privacy-consent-logs', 'nonce' ) === false )
wp_send_json_error();
// check capability
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
wp_send_json_error();
$data = Cookie_Notice()->welcome_api->get_privacy_consent_logs();
if ( is_array( $data ) )
wp_send_json_success( $this->get_privacy_consent_logs_table( $data ) );
else
wp_send_json_error( $data );
}
/**
* Get consent logs from specific date.
*
* @param array $data
*
* @return string
*/
public function get_privacy_consent_logs_table( $data ) {
// include wp list table class if needed
if ( ! class_exists( 'WP_List_Table' ) )
include_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
// include consent logs list table
include_once( COOKIE_NOTICE_PATH . '/includes/privacy-consent-logs-list-table.php' );
// initialize list table
$list_table = new Cookie_Notice_Privacy_Consent_Logs_List_Table( [
'plural' => 'cn-privacy-consent-logs',
'singular' => 'cn-privacy-consent-log',
'ajax' => false
] );
// prepare data
$list_table->cn_set_data( $data );
// prepare items
$list_table->prepare_items();
ob_start();
$list_table->display();
$html = ob_get_clean();
return $html;
}
}

View File

@@ -0,0 +1,673 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Privacy_Consent class.
*
* @class Cookie_Notice_Privacy_Consent
*/
class Cookie_Notice_Privacy_Consent {
private $sources = [];
private $instances = [];
public $form_active_types = [];
/**
* Class constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'add_settings' ] );
add_action( 'init', [ $this, 'init_privacy_consent' ], 5 );
add_action( 'init', [ $this, 'load_defaults' ] );
add_action( 'admin_init', [ $this, 'register_settings' ] );
}
/**
* Get all sources data.
*
* @return array
*/
public function get_sources() {
return $this->sources;
}
/**
* Get single source data.
*
* @param array $source_id
*
* @return array
*/
public function get_source( $source_id ) {
return array_key_exists( $source_id, $this->sources ) ? $this->sources[$source_id] : [];
}
/**
* Get active sources.
*
* @return array
*/
public function get_active_sources() {
$sources = [];
foreach ( $this->sources as $source_id => $source ) {
if ( $source['availability'] && $source['status'] )
$sources[] = $source_id;
}
return $sources;
}
/**
* Get available sources.
*
* @return array
*/
public function get_available_sources() {
$sources = [];
foreach ( $this->sources as $source_id => $source ) {
if ( $source['availability'] )
$sources[] = $source_id;
}
return $sources;
}
/**
* Check whether source is available.
*
* @param string $source_id
*
* @return bool
*/
public function is_source_available( $source_id ) {
}
/**
* Add source.
*
* @param array $source
*
* @return array
*/
public function add_source( $source ) {
$this->sources[$source['id']] = $source;
}
/**
* Strip string to specified length removing multibyte character from the end if needed.
*
* @param string $str
* @param int $length
*
* @return string
*/
public function strcut( $str = '', $length = 100 ) {
if ( function_exists( 'mb_strcut' ) )
return mb_strcut( $str, 0, $length );
// get length
$str_length = strlen( $str );
// smaller string?
if ( $str_length <= $length )
return $str;
// check any multibyte characters
preg_match_all( '/./u', $str, $chars );
if ( ! empty( $chars[0] ) ) {
// no multibyte characters
if ( count( $chars[0] ) === $str_length )
return $str;
$mb_str_length = 0;
// check every character
foreach ( $chars[0] as $char ) {
// get character length
$mb_char_length = strlen( $char );
// length with new character
$new_str_length = $mb_str_length + $mb_char_length;
// longer then expected? cut just before new character
if ( $new_str_length > $length )
return substr( $str, 0, $mb_str_length );
// perfect length? cut without stripping
elseif ( $new_str_length === $length )
return substr( $str, 0, $new_str_length );
$mb_str_length += $mb_char_length;
}
} else
return substr( $str, 0, 100 );
}
/**
* Add instance.
*
* @param object $instance
* @param array $source
*
* @return array
*/
public function add_instance( $instance, $source ) {
$this->instances[$source] = $instance;
}
/**
* Initialize privacy consent.
*
* @return void
*/
public function init_privacy_consent() {
// get main instance
$cn = Cookie_Notice();
if ( is_admin() ) {
// handle ajax requests
add_action( 'wp_ajax_cn_privacy_consent_form_status', [ $this, 'set_form_status' ] );
add_action( 'wp_ajax_cn_privacy_consent_get_forms', [ $this, 'query_forms' ] );
add_action( 'wp_ajax_cn_privacy_consent_display_table', [ $this, 'display_table' ] );
// include wp list table class if needed
if ( ! class_exists( 'WP_List_Table' ) )
include_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
// include privacy consent list table
include_once( COOKIE_NOTICE_PATH . '/includes/privacy-consent-list-table.php' );
}
// include modules
include_once( COOKIE_NOTICE_PATH . '/includes/modules/wordpress/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/contact-form-7/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/mailchimp/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/woocommerce/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/wpforms/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/formidable-forms/privacy-consent.php' );
include_once( COOKIE_NOTICE_PATH . '/includes/modules/easy-digital-downloads/privacy-consent.php' );
// update 2.5.0
if ( version_compare( $cn->db_version, '2.4.18', '<=' ) ) {
// $sources = get_available_sources()
$sources = $cn->defaults['privacy_consent'];
// check all available sources
foreach ( $this->sources as $source_id => $source ) {
if ( $source['availability'] )
$sources[$source_id . '_active'] = true;
}
if ( is_multisite() )
update_site_option( 'cookie_notice_privacy_consent', $sources );
else
update_option( 'cookie_notice_privacy_consent', $sources, null, false );
}
}
/**
* Load default data.
*
* @return void
*/
public function load_defaults() {
$this->form_active_types = [
'all' => __( 'Apply to all forms', 'cookie-notice' ),
'selected' => __( 'Apply to selected forms', 'cookie-notice' )
];
}
/**
* Add settings.
*
* @return void
*/
public function add_settings() {
if ( ! is_admin() )
return;
// get main instance
$cn = Cookie_Notice();
// update 2.5.0
if ( version_compare( $cn->db_version, '2.4.18', '<=' ) ) {
if ( is_multisite() )
add_site_option( 'cookie_notice_privacy_consent', $cn->defaults['privacy_consent'] );
else
add_option( 'cookie_notice_privacy_consent', $cn->defaults['privacy_consent'], null, false );
}
}
/**
* Register settings.
*
* @return void
*/
public function register_settings() {
// register privacy consent settings
register_setting( 'cookie_notice_privacy_consent', 'cookie_notice_privacy_consent', [ $this, 'validate_options' ] );
add_settings_section( 'cookie_notice_privacy_consent_status', esc_html__( 'Compliance Integration', 'cookie-notice' ), '', 'cookie_notice_privacy_consent', [ 'before_section' => '<div class="%s">', 'after_section' => '</div>', 'section_class' => 'cn-section-container compliance-section' ] );
add_settings_field( 'cn_privacy_consent_status', esc_html__( 'Compliance Status', 'cookie-notice' ), [ $this, 'cn_privacy_consent_status' ], 'cookie_notice_privacy_consent', 'cookie_notice_privacy_consent_status' );
// add section
add_settings_section( 'cookie_notice_privacy_consent_settings', esc_html__( 'Privacy Consent Settings', 'cookie-notice' ), [ $this, 'display_section' ], 'cookie_notice_privacy_consent', [ 'before_section' => '<div class="%s">', 'after_section' => '</div>', 'section_class' => 'cn-section-container privacy-section' ] );
foreach ( $this->sources as $source ) {
add_settings_field( 'cn_privacy_consent_' . esc_attr( $source['id'] ), esc_html( $source['name'] ), [ $this, 'option' ], 'cookie_notice_privacy_consent', 'cookie_notice_privacy_consent_settings', $source );
}
}
/**
* Display section.
*
* @return void
*/
public function display_section() {
wp_nonce_field( 'cn-privacy-consent-list-table-nonce', 'cn_privacy_consent_nonce' );
}
/**
* Compliance status.
*
* @return void
*/
public function cn_privacy_consent_status() {
// get main instance
$cn = Cookie_Notice();
// get cookie compliance status
$app_status = $cn->get_status();
if ( $cn->is_network_admin() )
$url = network_admin_url( 'admin.php?page=cookie-notice' );
else
$url = admin_url( 'admin.php?page=cookie-notice' );
switch ( $app_status ) {
case 'active':
echo '
<div id="cn_app_status">
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Privacy Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Privacy Consent Storage', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-active"><span class="cn-icon"></span> ' . esc_html__( 'Active', 'cookie-notice' ) . '</span></div>
</div>
<div id="cn_app_actions">
<a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/dashboard' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '</a>
<p class="description">' . esc_html__( 'Log in to the Compliance by Hu-manity.co dashboard to explore, configure and manage its functionalities.', 'cookie-notice' ) . '</p>
</div>';
break;
case 'pending':
echo '
<div id="cn_app_status">
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Privacy Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Privacy Consent Storage', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-pending"><span class="cn-icon"></span> ' . esc_html__( 'Pending', 'cookie-notice' ) . '</span></div>
</div>
<div id="cn_app_actions">
<a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/dashboard' ) ) . '" class="button button-primary button-hero cn-button" target="_blank">' . esc_html__( 'Log in & Configure', 'cookie-notice' ) . '</a>
<p class="description">' . esc_html__( 'Log in to the Compliance by Hu-manity.co web application and complete the setup process.', 'cookie-notice' ) . '</p>
</div>';
break;
default:
echo '
<div id="cn_app_status">
<div class="cn_compliance_status"><span class="cn-status-label">' . '<span class="cn-status-label">' . esc_html__( 'Privacy Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . '<span class="cn-status-label">' . esc_html__( 'Privacy Consent Storage', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
<div class="cn_compliance_status"><span class="cn-status-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . '</span>: <span class="cn-status cn-inactive"><span class="cn-icon"></span> ' . esc_html__( 'Inactive', 'cookie-notice' ) . '</span></div>
</div>
<div id="cn_app_actions">
<a href="' . esc_url( $url ) . '" class="button button-primary button-hero cn-button cn-run-welcome">' . esc_html__( 'Try Compliance by Hu-manity.co free', 'cookie-notice' ) . '</a>
<p class="description">' . sprintf( esc_html__( 'Sign up to %s and enable Privacy Consent support.', 'cookie-notice' ), '<a href="https://cookie-compliance.co/?utm_campaign=sign-up&utm_source=wordpress&utm_medium=textlink" target="_blank">Compliance by Hu-manity.co</a>' ) . '</p>
</div>';
}
}
/**
* Display source options.
*
* @return void
*/
public function option( $source ) {
// get main instance
$cn = Cookie_Notice();
// get cookie compliance status
$status = $cn->get_status();
// disable source for network area
if ( is_multisite() && $cn->is_network_admin() && $cn->is_plugin_network_active() )
$source['status'] = false;
echo '
<fieldset id="cn_privacy_consent_' . esc_attr( $source['id'] ) . '" class="cn-' . ( $source['availability'] ? '' : 'un' ) . 'available cn-' . ( $status === 'active' ? 'active' : 'inactive' ) . '">
<div>
<label><input class="cn-privacy-consent-status" type="checkbox" name="' . esc_attr( 'cookie_notice_privacy_consent[' . $source['id'] . '_active]' ) . '" value="1" data-source="' . esc_attr( $source['id'] ) . '" ' . checked( true, $source['status'] && $source['availability'], false ) . ' ' . disabled( $status === 'active' && $source['availability'], false, false ) . ' />' . sprintf( esc_html__( 'Enable to apply privacy consent support for %s forms.', 'cookie-notice' ), '<strong>' . $source['name'] . '</strong>' ) . '</label>
</div>
<div class="cn-privacy-consent-options-container"' . ( $source['status'] && $source['availability'] ? '' : ' style="display: none"' ) . '>
<div>';
foreach ( $this->form_active_types as $active_type => $label ) {
echo '
<label><input class="cn-privacy-consent-active-type" type="radio" name="' . esc_attr( 'cookie_notice_privacy_consent[' . $source['id'] . '_active_type]' ) . '" value="' . esc_attr( $active_type ) . '" ' . checked( $active_type, $source['status_type'], false ) . ' />' . esc_html( $label ) . '</label>';
}
echo '
</div>
<div class="cn-privacy-consent-list-table-container apply-' . esc_attr( $source['status_type'] ) . '">';
if ( $source['availability'] ) {
// initialize list table
$list_table = new Cookie_Notice_Privacy_Consent_List_Table( [
'plural' => 'cn-source-' . esc_attr( $source['name'] ) . '-forms',
'singular' => 'cn-source-' . esc_attr( $source['name'] ) . '-form',
'ajax' => false
] );
// set source
$list_table->cn_set_source( $source );
// set source forms
$list_table->cn_set_forms( [ 'forms' => $source['forms'] ] );
// set empty init for dynamic sources
if ( $source['type'] === 'dynamic' )
$list_table->cn_empty_init();
// prepare items
$list_table->prepare_items();
// display table
$list_table->display();
}
echo '
</div>
</div>
</fieldset>';
}
/**
* Source forms query to get data.
*
* @return void
*/
function query_forms() {
// valid nonce?
if ( check_ajax_referer( 'cn-privacy-consent-list-table-nonce', 'nonce' ) === false )
wp_send_json_error();
// check data
if ( ! isset( $_REQUEST['action'], $_REQUEST['nonce'], $_REQUEST['source'], $_REQUEST['paged'], $_REQUEST['order'], $_REQUEST['orderby'], $_REQUEST['search'] ) )
wp_send_json_error();
// check capability
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
wp_send_json_error();
// sanitize data
$source = sanitize_key( $_REQUEST['source'] );
$order = sanitize_key( $_REQUEST['order'] );
$orderby = sanitize_key( $_REQUEST['orderby'] );
$search = trim( sanitize_text_field( wp_unslash( $_REQUEST['search'] ) ) );
$page = (int) $_REQUEST['paged'];
// validate order
if ( ! in_array( $order, [ 'asc', 'desc' ], true ) )
$order = 'asc';
// validate orderby
if ( ! in_array( $orderby, [ 'title', 'date' ], true ) )
$orderby = 'title';
if ( ! array_key_exists( $source, $this->sources ) || ! $this->sources[$source]['availability'] )
wp_send_json_error();
// initialize list table
$list_table = new Cookie_Notice_Privacy_Consent_List_Table( [
'plural' => 'cn-source-' . esc_attr( $this->sources[$source]['name'] ) . '-forms',
'singular' => 'cn-source-' . esc_attr( $this->sources[$source]['name'] ) . '-form',
'ajax' => true
] );
// set source
$list_table->cn_set_source( $this->sources[$source] );
$args = [
'source' => $source,
'order' => $order,
'orderby' => $orderby,
'page' => max( $page, $list_table->get_pagenum() ),
'search' => $search
];
// set source forms
$list_table->cn_set_forms( $this->instances[$source]->get_forms( $args ) );
// handle ajax request
$list_table->ajax_response();
}
/**
* Display initial (first page) source table.
*
* @return void
*/
function display_table() {
// valid nonce?
if ( check_ajax_referer( 'cn-privacy-consent-list-table-nonce', 'nonce' ) === false )
wp_send_json_error();
// check data
if ( ! isset( $_REQUEST['action'], $_REQUEST['nonce'], $_REQUEST['source'] ) )
wp_send_json_error();
// check capability
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
wp_send_json_error();
// sanitize source
$source = sanitize_key( $_REQUEST['source'] );
if ( ! array_key_exists( $source, $this->sources ) || ! $this->sources[$source]['availability'] )
wp_send_json_error();
// make title column sorted
if ( empty( $_GET['orderby'] ) )
$_GET['orderby'] = 'title';
if ( empty( $_GET['order'] ) )
$_GET['order'] = 'asc';
// initialize list table
$list_table = new Cookie_Notice_Privacy_Consent_List_Table( [
'plural' => 'cn-source-' . esc_attr( $this->sources[$source]['name'] ) . '-forms',
'singular' => 'cn-source-' . esc_attr( $this->sources[$source]['name'] ) . '-form',
'ajax' => true
] );
// set source
$list_table->cn_set_source( $this->sources[$source] );
$args = [
'source' => $source,
'order' => 'asc',
'orderby' => 'title',
'page' => 1,
'search' => ''
];
// set source forms
$list_table->cn_set_forms( $this->instances[$source]->get_forms( $args ) );
// prepare items
$list_table->prepare_items();
ob_start();
// $list_table->search_box( __( 'Search', 'cookie-notice' ), $source );
$list_table->display();
$display = ob_get_clean();
wp_send_json_success( $display );
}
/**
* Set form status.
*
* @return void
*/
public function set_form_status() {
if ( ! isset( $_POST['source'], $_POST['form_id'], $_POST['status'] ) || wp_verify_nonce( $_POST['nonce'], 'cn-privacy-consent-set-form-status' ) === false )
wp_send_json_error();
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
wp_send_json_error();
// sanitize source
$source = sanitize_key( $_POST['source'] );
// active source?
if ( array_key_exists( $source, $this->sources ) && $this->sources[$source]['availability'] ) {
// sanitize form id
if ( $this->sources[$source]['id_type'] === 'integer' )
$form_id = (int) $_POST['form_id'];
elseif ( $this->sources[$source]['id_type'] === 'string' )
$form_id = (string) sanitize_key( $_POST['form_id'] );
// valid form?
if ( $this->instances[$source]->form_exists( $form_id ) ) {
// inactive source?
if ( ! $this->sources[$source]['status'] ) {
// get privacy consent data
$data = get_option( 'cookie_notice_privacy_consent' );
// activate source
$data[$source . '_active'] = true;
// update privacy consent
update_option( 'cookie_notice_privacy_consent', $data );
}
// get source data
$data = get_option( 'cookie_notice_privacy_consent_' . $source );
// update status of specified form
$data[$form_id]['status'] = (bool) (int) $_POST['status'];
// update source
update_option( 'cookie_notice_privacy_consent_' . $source, $data );
wp_send_json_success();
}
}
wp_send_json_error();
}
/**
* Check whether form is active.
*
* @param int|string $form_id
* @param string $source
*
* @return bool
*/
public function is_form_active( $form_id, $source ) {
// sanitize source
$source = sanitize_key( $source );
// unavailable source?
if ( ! array_key_exists( $source, $this->sources ) )
return false;
// inactive source?
if ( ! $this->sources[$source]['availability'] )
return false;
// disabled source?
if ( ! $this->sources[$source]['status'] )
return false;
// allow all forms?
if ( $this->sources[$source]['status_type'] === 'all' )
return true;
// sanitize form id
if ( $this->sources[$source]['id_type'] === 'integer' )
$form_id = (int) $form_id;
elseif ( $this->sources[$source]['id_type'] === 'string' )
$form_id = (string) sanitize_key( $form_id );
// get source data
$data = get_option( 'cookie_notice_privacy_consent_' . $source, [] );
// valid form?
if ( array_key_exists( $form_id, $data ) && array_key_exists( 'status', $data[$form_id] ) )
return $data[$form_id]['status'];
else
return false;
}
/**
* Set cookie.
*
* @param string $value
*
* @return void
*/
public function set_cookie( $value ) {
// set cookie
setcookie(
'hu-form',
$value,
[
'expires' => current_time( 'timestamp', true ) + 5 * MINUTE_IN_SECONDS,
'path' => COOKIEPATH,
'domain' => COOKIE_DOMAIN,
'secure' => is_ssl(),
'httponly' => false,
'samesite' => 'LAX'
]
);
}
/**
* Validate options.
*
* @param array $input
*
* @return array
*/
public function validate_options( $input ) {
if ( ! current_user_can( apply_filters( 'cn_manage_cookie_notice_cap', 'manage_options' ) ) )
return $input;
if ( isset( $_POST['save_cookie_notice_privacy_consent'] ) ) {
// validate every source
foreach ( $this->sources as $source ) {
$input = $this->instances[$source['id']]->validate( $input );
}
add_settings_error( 'cn_cookie_notice_options', 'save_cookie_notice_privacy_consent', esc_html__( 'Settings saved.', 'cookie-notice' ), 'updated' );
} elseif ( isset( $_POST['reset_cookie_notice_privacy_consent'] ) ) {
$input = Cookie_Notice()->defaults['privacy_consent'];
add_settings_error( 'cn_cookie_notice_options', 'reset_cookie_notice_privacy_consent', esc_html__( 'Settings restored to defaults.', 'cookie-notice' ), 'updated' );
}
do_action( 'cn_configuration_updated', 'privacy-consent', $input );
return $input;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Welcome_Frontend class.
*
* @class Cookie_Notice_Welcome_Frontend
*/
class Cookie_Notice_Welcome_Frontend {
private $preview_mode = false;
/**
* Constructor.
*
* @return void
*/
public function __construct() {
add_action( 'after_setup_theme', [ $this, 'preview_init' ], 1 );
}
/**
* Initialize preview mode.
*
* @return void
*/
public function preview_init() {
// check preview mode
$this->preview_mode = isset( $_GET['cn_preview_mode'] ) ? (int) $_GET['cn_preview_mode'] : false;
if ( $this->preview_mode !== false ) {
// filters
add_filter( 'show_admin_bar', '__return_false' );
add_filter( 'cn_cookie_notice_output', '__return_false', 1000 );
// actions
add_action( 'wp_enqueue_scripts', [ $this, 'wp_dequeue_scripts' ] );
// only in live preview
if ( $this->preview_mode === 1 ) {
add_action( 'wp_enqueue_scripts', [ $this, 'wp_enqueue_scripts' ] );
add_action( 'wp_head', [ $this, 'wp_head_scripts' ], 0 );
}
}
}
/**
* Load scripts and styles.
*
* @return void
*/
public function wp_enqueue_scripts() {
// get main instance
$cn = Cookie_Notice();
// show only in live preview
if ( $this->preview_mode === 1 ) {
wp_enqueue_script( 'cookie-notice-welcome-frontend', COOKIE_NOTICE_URL . '/js/front-welcome.js', [ 'jquery', 'underscore' ], $cn->defaults['version'] );
// prepare script data
$script_data = [
'previewMode' => $this->preview_mode,
'allowedURLs' => $this->get_allowed_urls(),
'levelNames' => $cn->settings->level_names,
'textStrings' => $cn->settings->text_strings
];
wp_add_inline_script( 'cookie-notice-welcome-frontend', 'var cnFrontWelcome = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
}
}
/**
* Unload scripts and styles.
*
* @return void
*/
public function wp_dequeue_scripts() {
// deregister native cookie notice script
wp_dequeue_script( 'cookie-notice-front' );
}
/**
* Load cookie compliance script.
*
* @return void
*/
public function wp_head_scripts() {
$options = [
'currentLanguage' => 'en',
'previewMode' => true,
'debugMode' => true
];
echo '
<!-- Cookie Compliance -->
<script type="text/javascript" id="hu-banner-options" data-nowprocket data-noptimize="1" data-no-optimize="1" nitro-exclude data-jetpack-boost="ignore">var huOptions = ' . wp_json_encode( $options, JSON_UNESCAPED_SLASHES ) . '; // nowprocket</script>
<script type="text/javascript" id="hu-banner-js" data-cfasync="false" data-nowprocket data-noptimize="1" data-no-optimize="1" nitro-exclude data-jetpack-boost="ignore" src="' . esc_url( ( is_ssl() ? 'https:' : 'http:' ) . Cookie_Notice()->get_url( 'widget' ) ) . '"></script>
<style>.hu-preview-mode #hu::after {content: "";position: fixed;width: 100%;height: 100%;display: block;top: 0;left: 0}</style>';
}
/**
* Get URLs allowed to be previewed.
*
* @return array
*/
public function get_allowed_urls() {
$allowed_urls = [ home_url( '/' ) ];
if ( is_ssl() && ! $this->is_cross_domain() )
$allowed_urls[] = home_url( '/', 'https' );
return $allowed_urls;
}
/**
* Determines whether the admin and the frontend are on different domains.
*
* @return bool
*/
public function is_cross_domain() {
$admin_origin = wp_parse_url( admin_url() );
$home_origin = wp_parse_url( home_url() );
return ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
}
}

View File

@@ -0,0 +1,865 @@
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
exit;
/**
* Cookie_Notice_Welcome class.
*
* @class Cookie_Notice_Welcome
*/
class Cookie_Notice_Welcome {
private $pricing_monthly = [];
private $pricing_yearly = [];
/**
* Constructor.
*
* @return void
*/
public function __construct() {
// actions
add_action( 'plugins_loaded', [ $this, 'allow_protocols' ] );
add_action( 'admin_init', [ $this, 'init' ] );
add_action( 'admin_init', [ $this, 'welcome' ] );
add_action( 'wp_ajax_cn_welcome_screen', [ $this, 'welcome_screen' ] );
add_action( 'wp_ajax_cn_dismiss_welcome', [ $this, 'dismiss_welcome' ] );
}
/**
* Allow new protocols.
*
* @return void
*/
function allow_protocols() {
// allow only ajax calls
if ( ! wp_doing_ajax() )
return;
// get action
$action = isset( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : '';
// welcome screen?
if ( $action === 'cn_welcome_screen' )
add_filter( 'kses_allowed_protocols', [ $this, 'allow_data_protocol' ] );
}
/**
* Add new properties to style safe list.
*
* @param array $styles
* @return array
*/
public function allow_style_attributes( $styles ) {
$styles[] = 'display';
return $styles;
}
/**
* Add data protocol to image source.
*
* @param array $protocols
* @return array
*/
public function allow_data_protocol( $protocols ) {
$protocols[] = 'data';
return $protocols;
}
/**
* Load defaults.
*
* @return void
*/
public function init() {
$this->pricing_monthly = [
'compliance_monthly_notrial' => '14.95',
'compliance_monthly_5' => '29.95',
'compliance_monthly_10' => '49.95',
'compliance_monthly_20' => '69.95'
];
$this->pricing_yearly = [
'compliance_yearly_notrial' => '149.50',
'compliance_yearly_5' => '299.50',
'compliance_yearly_10' => '499.50',
'compliance_yearly_20' => '699.50'
];
}
/**
* Load scripts and styles - admin.
*
* @return void
*/
public function admin_enqueue_scripts( $page ) {
// get main instance
$cn = Cookie_Notice();
if ( $cn->check_status( $cn->get_status() ) )
return;
// Legacy welcome scripts only load when ui_mode is explicitly set to legacy.
if ( $cn->options['general']['ui_mode'] !== 'legacy' )
return;
// styles
wp_enqueue_style( 'dashicons' );
wp_enqueue_style( 'cookie-notice-modaal', COOKIE_NOTICE_URL . '/assets/modaal/css/modaal.min.css', [], $cn->defaults['version'] );
wp_enqueue_style( 'cookie-notice-spectrum', COOKIE_NOTICE_URL . '/assets/spectrum/spectrum.min.css', [], $cn->defaults['version'] );
wp_enqueue_style( 'cookie-notice-microtip', COOKIE_NOTICE_URL . '/assets/microtip/microtip.min.css', [], $cn->defaults['version'] );
// scripts
wp_enqueue_script( 'cookie-notice-modaal', COOKIE_NOTICE_URL . '/assets/modaal/js/modaal.min.js', [], $cn->defaults['version'] );
wp_enqueue_script( 'cookie-notice-spectrum', COOKIE_NOTICE_URL . '/assets/spectrum/spectrum.min.js', [], $cn->defaults['version'] );
wp_enqueue_script( 'cookie-notice-welcome', COOKIE_NOTICE_URL . '/js/admin-welcome.js', [ 'jquery', 'jquery-ui-core', 'jquery-ui-progressbar' ], $cn->defaults['version'] );
wp_enqueue_script( 'cookie-notice-braintree-client', 'https://js.braintreegateway.com/web/3.71.0/js/client.min.js', [], null, false );
wp_enqueue_script( 'cookie-notice-braintree-hostedfields', 'https://js.braintreegateway.com/web/3.71.0/js/hosted-fields.min.js', [], null, false );
wp_enqueue_script( 'cookie-notice-braintree-paypal', 'https://js.braintreegateway.com/web/3.71.0/js/paypal-checkout.min.js', [], null, false );
// check network
$network = $cn->is_network_admin();
// prepare script data
$script_data = [
'ajaxURL' => admin_url( 'admin-ajax.php' ),
'network' => $network,
'nonce' => wp_create_nonce( 'cookie-notice-welcome' ),
'cnNonce' => wp_create_nonce( 'cookie-notice-welcome' ),
'initModal' => $network ? get_site_transient( 'cn_show_welcome' ) : get_transient( 'cn_show_welcome' ), // welcome modal
'error' => esc_html__( 'Unexpected error occurred. Please try again later.', 'cookie-notice' ),
'statusPassed' => esc_html__( 'Passed', 'cookie-notice' ),
'statusFailed' => esc_html__( 'Failed', 'cookie-notice' ),
'paidMonth' => esc_html__( 'monthly', 'cookie-notice' ),
'paidYear' => esc_html__( 'yearly', 'cookie-notice' ),
'pricingMonthly' => $this->pricing_monthly,
'pricingYearly' => $this->pricing_yearly,
'complianceStatus' => $cn->get_status(),
'complianceFailed' => sprintf( esc_html__( '%sCompliance Failed!%sYour website does not achieve minimum viable compliance. %sSign up to Compliance by Hu-manity.co%s to bring your site into compliance with the latest data privacy rules and regulations.', 'cookie-notice' ), '<em>', '</em>', '<b><a href="#" class="cn-sign-up">', '</a></b>' ),
'compliancePassed' => sprintf( esc_html__( '%sCompliance Passed!%sCongratulations. Your website meets minimum viable compliance.', 'cookie-notice' ), '<em>', '</em>' ),
'licensesAvailable' => esc_html__( 'available', 'cookie-notice' ),
'invalidFields' => esc_html__( 'Please fill all the required fields.', 'cookie-notice' ),
'dismissed' => (bool) get_option( 'cookie_notice_welcome_dismissed', false )
];
// delete the show modal transient
if ( $network )
delete_site_transient( 'cn_show_welcome' );
else
delete_transient( 'cn_show_welcome' );
wp_add_inline_script( 'cookie-notice-welcome', 'var cnWelcomeArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );
wp_enqueue_style( 'cookie-notice-welcome', COOKIE_NOTICE_URL . '/css/admin-welcome.css', [], $cn->defaults['version'] );
}
/**
* Send user to the welcome page on first activation.
*
* @global string $pagenow
*
* @return void
*/
public function welcome() {
global $pagenow;
if ( $pagenow !== 'admin.php' )
return;
// get page
$page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : '';
if ( $page !== 'cookie-notice' )
return;
// bail if bulk activating or within an iframe
if ( isset( $_GET['activate-multi'] ) || defined( 'IFRAME_REQUEST' ) )
return;
// get action
$action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : '';
// get plugin
$plugin = isset( $_GET['plugin'] ) ? sanitize_file_name( $_GET['plugin'] ) : '';
if ( $action === 'upgrade-plugin' && strpos( $plugin, 'cookie-notice.php' ) !== false )
return;
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
add_action( 'admin_footer', [ $this, 'admin_footer' ] );
}
/**
* Welcome modal container.
*
* @return void
*/
public function admin_footer() {
echo '<button id="cn-modal-trigger" style="display:none"></button>';
}
/**
* Dismiss the welcome modal — AJAX handler.
* Sets cookie_notice_welcome_dismissed option so the modal won't auto-fire again
* when user navigates to ?welcome=1 after closing without completing.
*
* @return void
*/
public function dismiss_welcome() {
if ( ! check_ajax_referer( 'cookie-notice-welcome', 'nonce', false ) )
wp_die( -1 );
if ( ! current_user_can( 'manage_options' ) )
wp_die( -1 );
update_option( 'cookie_notice_welcome_dismissed', true, false );
wp_die( 1 );
}
/**
* Render welcome screen sidebar step.
*
* @param int|string $screen
* @param bool $echo
* @return string|void
*/
public function welcome_screen( $screen, $echo = true ) {
if ( ! current_user_can( 'install_plugins' ) )
wp_die( __( 'You do not have permission to access this page.', 'cookie-notice' ) );
$sidebars = [ 'about', 'login', 'register', 'configure', 'success' ];
$steps = [ 1, 2, 3, 4 ];
$screens = array_merge( $sidebars, $steps );
if ( ! empty( $screen ) ) {
if ( is_numeric( $screen ) )
$screen = (int) $screen;
else
$screen = sanitize_key( $screen );
} else
$screen = '';
if ( empty( $screen ) || ! in_array( $screen, $screens, true ) ) {
if ( isset( $_REQUEST['screen'] ) ) {
if ( is_numeric( $_REQUEST['screen'] ) )
$screen = (int) $_REQUEST['screen'];
else
$screen = sanitize_key( $_REQUEST['screen'] );
} else
$screen = '';
if ( ! in_array( $screen, $screens, true ) )
$screen = '';
}
if ( empty( $screen ) )
wp_die( __( 'You do not have permission to access this page.', 'cookie-notice' ) );
if ( wp_doing_ajax() && ! check_ajax_referer( 'cookie-notice-welcome', 'nonce' ) )
wp_die( __( 'You do not have permission to access this page.', 'cookie-notice' ) );
// step screens
if ( in_array( $screen, $steps ) ) {
$html = '
<div class="wrap full-width-layout cn-welcome-wrap cn-welcome-step-' . esc_attr( $screen ) . ' has-loader">';
if ( $screen == 1 ) {
$html .= $this->welcome_screen( 'about', false );
$html .= '
<div class="cn-content cn-sidebar-visible">
<div class="cn-inner">
<div class="cn-content-full">
<h1><b>Compliance by Hu-manity.co</b></h1>
<h2>' . esc_html__( 'Simple cookie & privacy compliance solution for your business.', 'cookie-notice' ) . '</h2>
<div class="cn-lead">
<div class="cn-hero-image">
<div class="cn-flex-item">
<img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/screen-compliance.png" alt="Compliance by Hu-manity.co dashboard" />
</div>
</div>
<p>' . sprintf( esc_html__( 'Protect your business and take a proactive approach to data privacy laws with Compliance by Hu-manity.co. Build trust by giving your website visitors a beautiful, multi-level consent experience that complies with the latest cookie regulations in 100+ countries.', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
</div>';
$html .= '
<div class="cn-buttons">
<button type="button" class="cn-btn cn-btn-lg cn-screen-button" data-screen="2"><span class="cn-spinner"></span>' . esc_html__( 'Sign up to Compliance by Hu-manity.co', 'cookie-notice' ) . '</button><br />
<button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . esc_html__( 'Skip for now', 'cookie-notice' ) . '</button>
</div>
';
$html .= '
</div>
</div>
</div>';
} elseif ( $screen == 2 ) {
$html .= $this->welcome_screen( 'configure', false );
$html .= '
<div id="cn_upgrade_iframe" class="cn-content cn-sidebar-visible has-loader cn-loading"><span class="cn-spinner"></span>
<iframe id="cn_iframe_id" src="' . esc_url( home_url( '/?cn_preview_mode=1' ) ) . '"></iframe>
</div>';
} elseif ( $screen == 3 ) {
$html .= $this->welcome_screen( 'register', false );
$html .= '
<div class="cn-content cn-sidebar-visible">
<div class="cn-inner">
<div class="cn-content-full">
<h1><b>Compliance by Hu-manity.co</b></h1>
<h2>' . esc_html__( 'Consent Management Platform with simple, transparent pricing.', 'cookie-notice' ) . '</h2>
<div class="cn-lead">
<p>' . esc_html__( 'Choose monthly or yearly payment and number of domains for the fully featured, Professional plan. Or start with limited, Basic plan for free.', 'cookie-notice' ) . '</p>
</div>';
$html .= '
<h3 class="cn-pricing-select">' . esc_html__( 'Select plan', 'cookie-notice' ) . ':</h3>
<div class="cn-pricing-type cn-checkmark-wrapper">
<label for="pricing-type-monthly"><input id="pricing-type-monthly" type="radio" name="cn_pricing_type" value="monthly" checked><span class="cn-pricing-toggle toggle-left"><span class="cn-checkmark-container"><span class="cn-checkmark"></span></span><span class="cn-label">' . esc_html__( 'Monthly', 'cookie-notice' ) . '</span></span></label>
<label for="pricing-type-yearly"><input id="pricing-type-yearly" type="radio" name="cn_pricing_type" value="yearly"><span class="cn-pricing-toggle toggle-right"><span class="cn-checkmark-container"><span class="cn-checkmark"></span></span><span class="cn-label">' . esc_html__( 'Yearly', 'cookie-notice' ) . '<span class="cn-badge">' . esc_html__( 'Save 12%', 'cookie-notice' ) . '</span></span></span></label>
</div>
<div class="cn-pricing-table">
<label class="cn-pricing-item cn-pricing-plan-free" for="cn-pricing-plan-free">
<input id="cn-pricing-plan-free" type="radio" name="cn_pricing" value="free">
<div class="cn-pricing-info">
<div class="cn-pricing-head">
<h4>' . esc_html__( 'Basic', 'cookie-notice' ) . '</h4>
<span class="cn-plan-pricing"><span class="cn-plan-price">' . esc_html__( 'Free', 'cookie-notice' ) . '</span></span>
</div>
<div class="cn-pricing-body">
<p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'GDPR, CCPA, LGPD, PECR requirements', 'cookie-notice' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s1,000%s visits / month', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s100%s privacy consents', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s30 days%s consent storage', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGoogle & Facebook%s consent modes', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGeolocation%s support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%s1 additional%s language', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-excluded"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sBasic%s Support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
</div>
<div class="cn-pricing-footer">
<button type="button" class="cn-btn cn-btn-outline">' . esc_html__( 'Start Basic', 'cookie-notice' ) . '</button>
<span class="cn-trust-badge">' . esc_html__( 'No credit card · Free to start', 'cookie-notice' ) . '</span>
</div>
</div>
</label>
<label class="cn-pricing-item cn-pricing-plan-pro" for="cn-pricing-plan-pro">
<input id="cn-pricing-plan-pro" type="radio" name="cn_pricing" value="pro">
<div class="cn-pricing-info">
<div class="cn-pricing-head">
<h4>' . esc_html__( 'Professional', 'cookie-notice' ) . '</h4>
<span class="cn-plan-pricing"><span class="cn-plan-price"><sup>$ </sup><span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span><sub> / <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></sub></span></span>
<span class="cn-plan-promo">' . esc_html__( 'Recommended', 'cookie-notice' ) . '</span>
<div class="cn-select-wrapper">
<select name="cn_pricing_plan" class="form-select" aria-label="' . esc_html__( 'Pricing options', 'cookie-notice' ) . '" id="cn-pricing-plans">
<option value="compliance_monthly_notrial" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 1, 'cookie-notice' ), 1 ) ) . '</option>
<option value="compliance_monthly_5" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_5'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 5, 'cookie-notice' ), 5 ) ) . '</option>
<option value="compliance_monthly_10" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_10'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 10, 'cookie-notice' ), 10 ) ) . '</option>
<option value="compliance_monthly_20" data-price="' . esc_attr( $this->pricing_monthly['compliance_monthly_20'] ) . '">' . esc_html( sprintf( _n( '%s domain license', '%s domains license', 20, 'cookie-notice' ), 20 ) ) . '</option>
</select>
</div>
</div>
<div class="cn-pricing-body">
<p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'GDPR, CCPA, LGPD, PECR requirements', 'cookie-notice' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . esc_html__( 'Consent Analytics Dashboard', 'cookie-notice' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s visits', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s privacy consents', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sLifetime%s consent storage', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGoogle & Facebook%s consent modes', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sGeolocation%s support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sUnlimited%s languages', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
<p class="cn-included"><span class="cn-icon"></span>' . sprintf( esc_html__( '%sPriority%s Support', 'cookie-notice' ), '<b>', '</b>' ) . '</p>
</div>
<div class="cn-pricing-footer">
<button type="button" class="cn-btn cn-btn-secondary">' . esc_html__( 'Start Professional', 'cookie-notice' ) . '</button>
</div>
</div>
</label>
</div>
<div class="cn-buttons">
<button type="button" class="cn-btn cn-btn-lg cn-btn-transparent cn-skip-button">' . esc_html__( "I dont want to create an account now", 'cookie-notice' ) . '</button>
</div>';
$html .= '
</div>
</div>
</div>';
} elseif ( $screen == 4 ) {
$html .= $this->welcome_screen( 'success', false );
// get main instance
$cn = Cookie_Notice();
$subscription = $cn->get_subscription();
$html .= '
<div class="cn-content cn-sidebar-visible">
<div class="cn-inner">
<div class="cn-content-full">
<h1><b>' . esc_html__( 'Congratulations', 'cookie-notice' ) . '</b></h1>
<h2>' . esc_html__( 'You have successfully signed up to Compliance by Hu-manity.co.', 'cookie-notice' ) . '</h2>
<div class="cn-lead">
<p>' . esc_html__( 'Log in to your account and continue configuring your website.', 'cookie-notice' ) . '</p>
</div>
<div class="cn-buttons">
<a href="' . esc_url( $cn->get_url( 'host', '?utm_campaign=configure&utm_source=wordpress&utm_medium=button#/login' ) ) . '" class="cn-btn cn-btn-lg" target="_blank">' . esc_html__( 'Go to Application', 'cookie-notice' ) . '</a>
</div>
</div>
</div>
</div>';
}
$html .= '
</div>';
// sidebar screens
} elseif ( in_array( $screen, $sidebars ) ) {
$html = '';
if ( $screen === 'about' ) {
$theme = wp_get_theme();
$html .= '
<div class="cn-sidebar cn-sidebar-left has-loader">
<div class="cn-inner">
<div class="cn-header">
<div class="cn-top-bar">
<div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-logo.png" alt="Compliance by Hu-manity.co" /></div>
</div>
</div>
<div class="cn-body">
<h2>' . esc_html__( 'Compliance check', 'cookie-notice' ) . '</h2>
<div class="cn-lead"><p>' . esc_html__( 'This is a Compliance Check to determine your sites compliance with updated data processing and consent rules under GDPR, CCPA and other international data privacy laws.', 'cookie-notice' ) . '</p></div>
<div id="cn_preview_about">
<p>' . esc_html__( 'Site URL', 'cookie-notice' ) . ': <b>' . esc_url( home_url() ) . '</b></p>
<p>' . esc_html__( 'Site Name', 'cookie-notice' ) . ': <b>' . esc_html( get_bloginfo( 'name' ) ) . '</b></p>
</div>
<div class="cn-compliance-check">
<div class="cn-progressbar"><div class="cn-progress-label">' . esc_html__( 'Checking...', 'cookie-notice' ) . '</div></div>
<div class="cn-compliance-feedback cn-hidden"></div>
<div class="cn-compliance-results">
<div class="cn-compliance-item"><p><span class="cn-compliance-label">' . esc_html__( 'Consent Banner', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Notify visitors to the site that it uses cookies or similar technologies.', 'cookie-notice' ) . '</span></p></div>
<div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Autoblocking', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Block non-essential 3rd party services until consent is registered.', 'cookie-notice' ) . '</span></p></div>
<div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Cookie Categories', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Allow to customize the consent requested per purpose of use.', 'cookie-notice' ) . '</span></p></div>
<div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Cookie Consent Logs', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( "Save the website visitor's cookie consent preferences.", 'cookie-notice' ) . '</span></p></div>
<div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Privacy Consent Logs', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( "Record the website user's consent to the processing of personal data.", 'cookie-notice' ) . '</span></p></div>
<div class="cn-compliance-item" style="display: none"><p><span class="cn-compliance-label">' . esc_html__( 'Proof-of-Consent', 'cookie-notice' ) . ' </span><span class="cn-compliance-status"></span></p><p><span class="cn-compliance-desc">' . esc_html__( 'Store and export a Proof-of-consent in secure audit format.', 'cookie-notice' ) . '</span></p></div>
</div>
</div>
' /* <div id="cn_preview_frame"><img src=" ' . esc_url( $theme->get_screenshot() ) . '" /></div>
. '<div id="cn_preview_frame"><div id="cn_preview_frame_wrapper"><iframe id="cn_iframe_id" src="' . home_url( '/?cn_preview_mode=0' ) . '" scrolling="no" frameborder="0"></iframe></div></div> */ . '
</div>';
} elseif ( $screen === 'configure' ) {
$html .= '
<div class="cn-sidebar cn-sidebar-left has-loader cn-theme-light">
<div class="cn-inner">
<div class="cn-header">
<div class="cn-top-bar">
<div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-logo.png" alt="Compliance by Hu-manity.co" /></div>
</div>
</div>
<div class="cn-body">
<h2>' . esc_html__( 'Live Setup', 'cookie-notice' ) . '</h2>
<div class="cn-lead"><p>' . esc_html__( 'Configure your Compliance by Hu-manity.co design and compliance features through the options below. Click Apply Setup to save the configuration and go to selecting your preferred cookie solution.', 'cookie-notice' ) . '</p></div>
<form method="post" id="cn-form-configure" class="cn-form" action="" data-action="configure">
<div class="cn-accordion">
<div class="cn-accordion-item cn-form-container" tabindex="-1">
<div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">' . esc_html__( 'Banner Compliance', 'cookie-notice' ) . '</button></div>
<div class="cn-accordion-collapse cn-form">
<div class="cn-form-feedback cn-hidden"></div>' .
/*
<div class="cn-field cn-field-select">
<label for="cn_location">' . __( 'What is the location of your business/organization?', 'cookie-notice' ) . '</label>
<div class="cn-select-wrapper">
<select id="cn_location" name="cn_location">
<option value="0">' . __( 'Select location', 'cookie-notice' ) . '</option>';
foreach ( Cookie_Notice()->settings->countries as $country_code => $country_name ) {
$html .= '<option value="' . $country_code . '">' . $country_name . '</option>';
}
$html .= '
</select>
</div>
</div>
*/
'
<div id="cn_laws" class="cn-field cn-field-checkbox">
<label>' . esc_html__( 'Select the laws that apply to your business', 'cookie-notice' ) . ':</label>
<div class="cn-checkbox-wrapper">
<label for="cn_laws_gdpr"><input id="cn_laws_gdpr" type="checkbox" name="cn_laws" value="gdpr" title="' . esc_attr__( 'GDPR', 'cookie-notice' ) . '" checked><span>' . esc_html__( 'GDPR', 'cookie-notice' ) . '<span class="cn-tooltip" aria-label="' . esc_html__( 'European Union and Switzerland', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_ccpa"><input id="cn_laws_ccpa" type="checkbox" name="cn_laws" value="ccpa" title="' . esc_attr__( 'CCPA', 'cookie-notice' ) . '"><span>' . esc_html__( 'CCPA/CPRA', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'California', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_otherus"><input id="cn_laws_otherus" type="checkbox" name="cn_laws" value="otherus" title="' . esc_attr__( 'Other U.S. State Laws', 'cookie-notice' ) . '"><span>' . esc_html__( 'Other U.S. State Laws', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'Virginia, Colorado, Connecticut, Utah, etc.', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_ukpecr"><input id="cn_laws_ukpecr" type="checkbox" name="cn_laws" value="ukpecr" title="' . esc_attr__( 'UK PECR', 'cookie-notice' ) . '"><span>' . esc_html__( 'UK PECR', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'United Kingdom', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_lgpd"><input id="cn_laws_lgpd" type="checkbox" name="cn_laws" value="lgpd" title="' . esc_attr__( 'LGPD', 'cookie-notice' ) . '"><span>' . esc_html__( 'LGPD', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'Brazil', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_pipeda"><input id="cn_laws_pipeda" type="checkbox" name="cn_laws" value="pipeda" title="' . esc_attr__( 'PIPEDA', 'cookie-notice' ) . '"><span>' . esc_html__( 'PIPEDA', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'Canada', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_popia"><input id="cn_laws_popia" type="checkbox" name="cn_laws" value="popia" title="' . esc_attr__( 'POPIA', 'cookie-notice' ) . '"><span>' . esc_html__( 'POPIA', 'cookie-notice' ) . '<span class="tooltip" aria-label="' . esc_html__( 'South Africa', 'cookie-notice' ) . '" data-microtip-position="right" data-microtip-size="small" role="tooltip"><i class="cn-tooltip-icon"></i></span></span></label>
<label for="cn_laws_other"><input id="cn_laws_other" type="checkbox" name="cn_laws" value="other" title="' . esc_attr__( 'Other', 'cookie-notice' ) . '"><span>' . esc_html__( 'Other', 'cookie-notice' ) . '</span></label>
</div>
</div>
<div id="cn_naming" class="cn-field cn-field-radio">
<label class="cn-asterix">' . esc_html__( 'Select a naming style for the consent choices', 'cookie-notice' ) . ':</label>
<div class="cn-radio-wrapper">
<label for="cn_naming_1"><input id="cn_naming_1" type="radio" name="cn_naming" value="1" checked><span>' . esc_html__( 'Private, Balanced, Personalized', 'cookie-notice' ) . '</span></label>
<label for="cn_naming_2"><input id="cn_naming_2" type="radio" name="cn_naming" value="2"><span>' . esc_html__( 'Silver, Gold, Platinum', 'cookie-notice' ) . '</span></label>
<label for="cn_naming_3"><input id="cn_naming_3" type="radio" name="cn_naming" value="3"><span>' . esc_html__( 'Reject All, Accept Some, Accept All', 'cookie-notice' ) . '</span></label>
</div>
</div>
<div class="cn-field cn-field-checkbox">
<label>' . esc_html__( 'Select basic consent options:', 'cookie-notice' ) . '</label>
<div class="cn-checkbox-wrapper">
<label for="cn_on_scroll"><input id="cn_on_scroll" type="checkbox" name="cn_on_scroll" value="1"><span>' . esc_html__( 'Consent on Scroll', 'cookie-notice' ) . '</span></label>
<label for="cn_on_click"><input id="cn_on_click" type="checkbox" name="cn_on_click" value="1"><span>' . esc_html__( 'Consent on Click', 'cookie-notice' ) . '</span></label>
<label for="cn_ui_blocking"><input id="cn_ui_blocking" type="checkbox" name="cn_ui_blocking" value="1"><span>' . esc_html__( 'UI Blocking', 'cookie-notice' ) . '</span></label>
<label for="cn_revoke_consent"><input id="cn_revoke_consent" type="checkbox" name="cn_revoke_consent" value="1" checked><span>' . esc_html__( 'Revoke Consent', 'cookie-notice' ) . '</span></label>
</div>
</div>' .
// <div class="cn-small">* ' . esc_html__( 'available for Cookie Compliance&trade; Pro plans only', 'cookie-notice' ) . '</div>
'</div>
</div>
<div class="cn-accordion-item cn-form-container cn-collapsed" tabindex="-1">
<div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">' . esc_html__( 'Banner Design', 'cookie-notice' ) . '</button></div>
<div class="cn-accordion-collapse cn-form">
<div class="cn-form-feedback cn-hidden"></div>
<div class="cn-field cn-field-radio-image">
<label>' . esc_html__( 'Select your preferred display position', 'cookie-notice' ) . ':</label>
<div class="cn-radio-image-wrapper">
<label for="cn_position_bottom"><input id="cn_position_bottom" type="radio" name="cn_position" value="bottom" title="' . esc_attr__( 'Bottom', 'cookie-notice' ) . '" checked><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-bottom.png" width="24" height="24"></label>
<label for="cn_position_top"><input id="cn_position_top" type="radio" name="cn_position" value="top" title="' . esc_attr__( 'Top', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-top.png" width="24" height="24"></label>
<label for="cn_position_left"><input id="cn_position_left" type="radio" name="cn_position" value="left" title="' . esc_attr__( 'Left', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-left.png" width="24" height="24"></label>
<label for="cn_position_right"><input id="cn_position_right" type="radio" name="cn_position" value="right" title="' . esc_attr__( 'Right', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-right.png" width="24" height="24"></label>
<label for="cn_position_center"><input id="cn_position_center" type="radio" name="cn_position" value="center" title="' . esc_attr__( 'Center', 'cookie-notice' ) . '"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/layout-center.png" width="24" height="24"></label>
</div>
</div>
<div class="cn-field cn-fieldset">
<label>' . esc_html__( 'Adjust the banner color scheme', 'cookie-notice' ) . ':</label>
<div class="cn-checkbox-wrapper cn-color-picker-wrapper">
<label for="cn_color_primary"><input id="cn_color_primary" class="cn-color-picker" type="checkbox" name="cn_color_primary" value="#20c19e"><span>' . esc_html__( 'Color of the buttons and interactive elements.', 'cookie-notice' ) . '</span></label>
<label for="cn_color_background"><input id="cn_color_background" class="cn-color-picker" type="checkbox" name="cn_color_background" value="#ffffff"><span>' . esc_html__( 'Color of the banner background.', 'cookie-notice' ) . '</span></label>
<label for="cn_color_text"><input id="cn_color_text" class="cn-color-picker" type="checkbox" name="cn_color_text" value="#434f58"><span>' . esc_html__( 'Color of the body text.', 'cookie-notice' ) . '</span></label>
<label for="cn_color_border"><input id="cn_color_border" class="cn-color-picker" type="checkbox" name="cn_color_border" value="#5e6a74"><span>' . esc_html__( 'Color of the borders and inactive elements.', 'cookie-notice' ) . '</span></label>
<label for="cn_color_heading"><input id="cn_color_heading" class="cn-color-picker" type="checkbox" name="cn_color_heading" value="#434f58"><span>' . esc_html__( 'Color of the heading text.', 'cookie-notice' ) . '</span></label>
<label for="cn_color_button_text"><input id="cn_color_button_text" class="cn-color-picker" type="checkbox" name="cn_color_button_text" value="#ffffff"><span>' . esc_html__( 'Color of the button text.', 'cookie-notice' ) . '</span></label>
</div>
</div>' .
// <div class="cn-small">* ' . esc_html__( 'available for Cookie Compliance&trade; Pro plans only', 'cookie-notice' ) . '</div>
'</div>
</div>
</div>
<div class="cn-field cn-field-submit cn-nav">
<button type="button" class="cn-btn cn-screen-button" data-screen="3"><span class="cn-spinner"></span>' . esc_html__( 'Apply Setup', 'cookie-notice' ) . '</button>
</div>';
$html .= wp_nonce_field( 'cn_api_configure', 'cn_nonce', true, false );
$html .= '
</form>
</div>';
} elseif ( $screen === 'register' ) {
$html .= '
<div class="cn-sidebar cn-sidebar-left has-loader">
<div class="cn-inner">
<div class="cn-header">
<div class="cn-top-bar">
<div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-logo.png" alt="Compliance by Hu-manity.co" /></div>
</div>
</div>
<div class="cn-body">
<h2>' . esc_html__( 'Compliance account', 'cookie-notice' ) . '</h2>
<div class="cn-lead">
<p>' . esc_html__( 'Create a Compliance by Hu-manity.co account and select your preferred plan.', 'cookie-notice' ) . '</p>
</div>
<div class="cn-accordion">
<div id="cn-accordion-account" class="cn-accordion-item cn-form-container" tabindex="-1">
<div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">1. ' . esc_html__( 'Create Account', 'cookie-notice' ) . '</button></div>
<div class="cn-accordion-collapse">
<form method="post" class="cn-form" action="" data-action="register">
<div class="cn-form-feedback cn-hidden"></div>
<div class="cn-field cn-field-text">
<input type="text" name="email" value="" tabindex="1" placeholder="' . esc_attr__( 'Email address', 'cookie-notice' ) . '">
</div>
<div class="cn-field cn-field-text">
<input type="password" name="pass" value="" tabindex="2" autocomplete="off" placeholder="' . esc_attr__( 'Password', 'cookie-notice' ) . '">
<span>' . esc_html( 'Minimum eight characters, at least one capital letter and one number are required.', 'cookie-notice' ) . '</span>
</div>
<div class="cn-field cn-field-text">
<input type="password" name="pass2" value="" tabindex="3" autocomplete="off" placeholder="' . esc_attr__( 'Confirm Password', 'cookie-notice' ) . '">
</div>
<div class="cn-field cn-field-checkbox">
<div class="cn-checkbox-wrapper">
<label for="cn_terms"><input id="cn_terms" type="checkbox" name="terms" value="1"><span>' . sprintf( esc_html__( 'I have read and agree to the %sTerms of Service%s', 'cookie-notice' ), '<a href="https://cookie-compliance.co/terms-of-service/?utm_campaign=accept-terms&utm_source=wordpress&utm_medium=link" target="_blank">', '</a>' ) . '</span></label>
</div>
</div>
<div class="cn-field cn-field-submit cn-nav">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Sign Up', 'cookie-notice' ) . '</button>
</div>';
// get site language
$locale = get_locale();
$locale_code = explode( '_', $locale );
$html .= '
<input type="hidden" name="language" value="' . esc_attr( $locale_code[0] ) . '" />';
$html .= wp_nonce_field( 'cn_api_register', 'cn_nonce', true, false );
$html .= '
</form>
<p>' . esc_html__( 'Already have an account?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="login">' . esc_html__( 'Sign in', 'cookie-notice' ). '</a></p>
</div>
</div>';
$html .= '
<div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
<div class="cn-accordion-header cn-form-header">
<button class="cn-accordion-button" type="button">2. ' . esc_html__( 'Select Plan', 'cookie-notice' ) . '</button>
</div>
<form method="post" class="cn-accordion-collapse cn-form cn-form-disabled" action="" data-action="payment">
<div class="cn-form-feedback cn-hidden"></div>
<div class="cn-field cn-field-radio">
<div class="cn-radio-wrapper cn-plan-wrapper">
<label for="cn-field-plan-free" class="cn-pricing-plan-free"><input id="cn-field-plan-free" type="radio" name="plan" value="free" checked><span><span class="cn-plan-description">' . esc_html__( 'Basic', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price">Free</span></span><span class="cn-plan-overlay"></span></span></label>
<label for="cn-field-plan-pro" class="cn-pricing-plan-pro"><input id="cn-field-plan-pro" type="radio" name="plan" value="compliance_monthly_notrial"><span><span class="cn-plan-description">' . sprintf( esc_html__( '%sProfessional%s', 'cookie-notice' ), '<b>', '</b>' ) . ' - <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></span><span class="cn-plan-pricing"><span class="cn-plan-price">$<span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span></span></span><span class="cn-plan-overlay"></span></span></label>
</div>
</div>
<div class="cn-field cn-fieldset" id="cn_submit_free">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
</div>
<div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
<input type="hidden" name="cn_payment_identifier" value="" />
<div class="cn-field cn-field-radio">
<label>' . esc_html__( 'Payment Method', 'cookie-notice' ) . '</label>
<div class="cn-radio-wrapper cn-horizontal-wrapper">
<label for="cn_field_method_credit_card"><input id="cn_field_method_credit_card" type="radio" name="method" value="credit_card" checked><span>' . esc_html__( 'Credit Card', 'cookie-notice' ) . '</span></label>
<label for="cn_field_method_paypal"><input id="cn_field_method_paypal" type="radio" name="method" value="paypal"><span>' . esc_html__( 'PayPal', 'cookie-notice' ) . '</span></label>
</div>
</div>
<div class="cn-fieldset" id="cn_payment_method_credit_card">
<input type="hidden" name="payment_nonce" value="" />
<div class="cn-field cn-field-text">
<label for="cn_card_number">' . esc_html__( 'Card Number', 'cookie-notice' ) . '</label>
<div id="cn_card_number"></div>
</div>
<div class="cn-field cn-field-text cn-field-half cn-field-first">
<label for="cn_expiration_date">' . esc_html__( 'Expiration Date', 'cookie-notice' ) . '</label>
<div id="cn_expiration_date"></div>
</div>
<div class="cn-field cn-field-text cn-field-half cn-field-last">
<label for="cn_cvv">' . esc_html__( 'CVC/CVV', 'cookie-notice' ) . '</label>
<div id="cn_cvv"></div>
</div>
<div class="cn-field cn-field-submit cn-nav">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Submit', 'cookie-notice' ) . '</button>
</div>
</div>
<div class="cn-fieldset" id="cn_payment_method_paypal" style="display: none">
<div id="cn_paypal_button"></div>
</div>
</div>';
$html .= wp_nonce_field( 'cn_api_payment', 'cn_payment_nonce', true, false );
$html .= '
</form>
</div>
</div>
</div>';
} elseif ( $screen === 'login' ) {
$html .= '
<div class="cn-sidebar cn-sidebar-left has-loader">
<div class="cn-inner">
<div class="cn-header">
<div class="cn-top-bar">
<div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-logo.png" alt="Compliance by Hu-manity.co" /></div>
</div>
</div>
<div class="cn-body">
<h2>' . esc_html__( 'Compliance Sign in', 'cookie-notice' ) . '</h2>
<div class="cn-lead">
<p>' . esc_html__( 'Sign in to your existing Compliance by Hu-manity.co account and select your preferred plan.', 'cookie-notice' ) . '</p>
</div>
<div class="cn-accordion">
<div id="cn-accordion-account" class="cn-accordion-item cn-form-container" tabindex="-1">
<div class="cn-accordion-header cn-form-header"><button class="cn-accordion-button" type="button">1. ' . esc_html__( 'Account Login', 'cookie-notice' ) . '</button></div>
<div class="cn-accordion-collapse">
<form method="post" class="cn-form" action="" data-action="login">
<div class="cn-form-feedback cn-hidden"></div>
<div class="cn-field cn-field-text">
<input type="text" name="email" value="" tabindex="1" placeholder="' . esc_attr__( 'Email address', 'cookie-notice' ) . '">
</div>
<div class="cn-field cn-field-text">
<input type="password" name="pass" value="" tabindex="2" autocomplete="off" placeholder="' . esc_attr__( 'Password', 'cookie-notice' ) . '">
</div>
<div class="cn-field cn-field-submit cn-nav">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" ' . /* data-screen="4" */ '><span class="cn-spinner"></span>' . esc_html__( 'Sign in', 'cookie-notice' ) . '</button>
</div>';
// get site language
$locale = get_locale();
$locale_code = explode( '_', $locale );
$html .= '
<input type="hidden" name="language" value="' . esc_attr( $locale_code[0] ) . '" />';
$html .= wp_nonce_field( 'cn_api_login', 'cn_nonce', true, false );
$html .= '
</form>
<p>' . esc_html__( 'Don\'t have an account yet?', 'cookie-notice' ) . ' <a href="#" class="cn-screen-button" data-screen="register">' . esc_html__( 'Sign up', 'cookie-notice' ) . '</a></p>
</div>
</div>
<div id="cn-accordion-billing" class="cn-accordion-item cn-form-container cn-collapsed cn-disabled" tabindex="-1">
<div class="cn-accordion-header cn-form-header">
<button class="cn-accordion-button" type="button">2. ' . esc_html__( 'Select Plan', 'cookie-notice' ) . '</button>
</div>
<form method="post" class="cn-accordion-collapse cn-form cn-form-disabled" action="" data-action="payment">
<div class="cn-form-feedback cn-hidden"></div>
<div class="cn-field cn-field-radio">
<div class="cn-radio-wrapper cn-plan-wrapper">
<label for="cn-field-plan-free" class="cn-pricing-plan-free"><input id="cn-field-plan-free" type="radio" name="plan" value="free" checked><span><span class="cn-plan-description">' . esc_html__( 'Basic', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price">Free</span></span><span class="cn-plan-overlay"></span></span></label>
<label for="cn-field-plan-pro" class="cn-pricing-plan-pro"><input id="cn-field-plan-pro" type="radio" name="plan" value="compliance_monthly_notrial"><span><span class="cn-plan-description">' . sprintf( esc_html__( '%sProfessional%s', 'cookie-notice' ), '<b>', '</b>' ) . ' - <span class="cn-plan-period">' . esc_html__( 'monthly', 'cookie-notice' ) . '</span></span><span class="cn-plan-pricing"><span class="cn-plan-price">$<span class="cn-plan-amount">' . esc_attr( $this->pricing_monthly['compliance_monthly_notrial'] ) . '</span></span></span><span class="cn-plan-overlay"></span></span></label>
<label for="cn-field-plan-license" class="cn-pricing-plan-license cn-disabled">
<input id="cn-field-plan-license" type="radio" name="plan" value="license"><span><span class="cn-plan-description">' . esc_html__( 'Use License', 'cookie-notice' ) . '</span><span class="cn-plan-pricing"><span class="cn-plan-price"><span class="cn-plan-amount">0</span> ' . esc_html__( 'available', 'cookie-notice' ) . '</span></span><span class="cn-plan-overlay"></span></span>
</label>
</div>
</div>
<div class="cn-field cn-fieldset" id="cn_submit_free">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
</div>
<div class="cn-field cn-fieldset cn-hidden" id="cn_submit_pro">
<input type="hidden" name="cn_payment_identifier" value="" />
<div class="cn-field cn-field-radio">
<label>' . esc_html__( 'Payment Method', 'cookie-notice' ) . '</label>
<div class="cn-radio-wrapper cn-horizontal-wrapper">
<label for="cn_field_method_credit_card"><input id="cn_field_method_credit_card" type="radio" name="method" value="credit_card" checked><span>' . esc_html__( 'Credit Card', 'cookie-notice' ) . '</span></label>
<label for="cn_field_method_paypal"><input id="cn_field_method_paypal" type="radio" name="method" value="paypal"><span>' . esc_html__( 'PayPal', 'cookie-notice' ) . '</span></label>
</div>
</div>
<div class="cn-fieldset" id="cn_payment_method_credit_card">
<input type="hidden" name="payment_nonce" value="" />
<div class="cn-field cn-field-text">
<label for="cn_card_number">' . esc_html__( 'Card Number', 'cookie-notice' ) . '</label>
<div id="cn_card_number"></div>
</div>
<div class="cn-field cn-field-text cn-field-half cn-field-first">
<label for="cn_expiration_date">' . esc_html__( 'Expiration Date', 'cookie-notice' ) . '</label>
<div id="cn_expiration_date"></div>
</div>
<div class="cn-field cn-field-text cn-field-half cn-field-last">
<label for="cn_cvv">' . esc_html__( 'CVC/CVV', 'cookie-notice' ) . '</label>
<div id="cn_cvv"></div>
</div>
<div class="cn-field cn-field-submit cn-nav">
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Submit', 'cookie-notice' ) . '</button>
</div>
</div>
<div class="cn-fieldset" id="cn_payment_method_paypal" style="display: none">
<div id="cn_paypal_button"></div>
</div>
</div>
<div class="cn-field cn-fieldset cn-hidden" id="cn_submit_license">
<div class="cn-field cn-field-select" id="cn-subscriptions-list">
<label for="cn-subscription-select">' . esc_html__( 'Select subscription', 'cookie-notice' ) . '</label>
<select name="cn_subscription_id" class="form-select" aria-label="' . esc_attr__( 'Licenses', 'cookie-notice' ) . '" id="cn-subscription-select">
</select>
</div><br>
<button type="submit" class="cn-btn cn-screen-button" tabindex="4" data-screen="4"><span class="cn-spinner"></span>' . esc_html__( 'Confirm', 'cookie-notice' ) . '</button>
</div>';
$html .= wp_nonce_field( 'cn_api_payment', 'cn_payment_nonce', true, false );
$html .= '
</form>
</div>
</div>
</div>';
} elseif ( $screen === 'success' ) {
$html .= '
<div class="cn-sidebar cn-sidebar-left has-loader">
<div class="cn-inner">
<div class="cn-header">
<div class="cn-top-bar">
<div class="cn-logo"><img src="' . esc_url( COOKIE_NOTICE_URL ) . '/img/cookie-compliance-logo.png" alt="Compliance by Hu-manity.co" /></div>
</div>
</div>
<div class="cn-body">
<h2>' . esc_html__( 'Success!', 'cookie-notice' ) . '</h2>
<div class="cn-lead"><p><b>' . esc_html__( 'You have successfully integrated your website with Compliance by Hu-manity.co.', 'cookie-notice' ) . '</b></p><p>' . sprintf( esc_html__( 'Go to Compliance by Hu-manity.co now. Or access it anytime from your %sCompliance settings page%s.', 'cookie-notice' ), '<a href="' . esc_url( Cookie_Notice()->is_network_admin() ? network_admin_url( 'admin.php?page=cookie-notice' ) : admin_url( 'admin.php?page=cookie-notice' ) ) . '">', '</a>' ) . '</p></div>
</div>';
}
$html .= '
<div class="cn-footer">';
/*
switch ( $screen ) {
case 'about':
$html .= '<a href="' . esc_url( admin_url( 'admin.php?page=cookie-notice' ) ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'Skip Live Setup', 'cookie-notice' ) . '</a>';
break;
case 'success':
$html .= '<a href="' . esc_url( get_dashboard_url() ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'WordPress Dashboard', 'cookie-notice' ) . '</a>';
break;
default:
$html .= '<a href="' . esc_url( admin_url( 'admin.php?page=cookie-notice' ) ) . '" class="cn-btn cn-btn-link cn-skip-button">' . __( 'Skip for now', 'cookie-notice' ) . '</a>';
break;
}
*/
$html .= '
</div>
</div>
</div>';
}
if ( $echo ) {
// get allowed html
$allowed_html = wp_kses_allowed_html( 'post' );
$allowed_html['div']['tabindex'] = true;
$allowed_html['button']['tabindex'] = true;
$allowed_html['iframe'] = [
'id' => true,
'src' => true
];
$allowed_html['form'] = [
'id' => true,
'class' => true,
'action' => true,
'data-action' => true
];
$allowed_html['select'] = [
'name' => true,
'class' => true,
'id' => true,
'aria-label' => true
];
$allowed_html['option'] = [
'value' => true,
'data-price' => true
];
$allowed_html['input'] = [
'id' => true,
'type' => true,
'name' => true,
'class' => true,
'value' => true,
'tabindex' => true,
'autocomplete' => true,
'checked' => true,
'placeholder' => true,
'title' => true
];
add_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
// echo wp_kses( $html, $allowed_html );
echo $html;
remove_filter( 'safe_style_css', [ $this, 'allow_style_attributes' ] );
} else
return $html;
if ( wp_doing_ajax() )
exit();
}
}

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden.

View File

@@ -0,0 +1,19 @@
( function( $ ) {
// ready event
$( function() {
// get charts
var charts = cnDashboardArgs.charts;
if ( Object.entries( charts ).length > 0 ) {
for ( const [key, config] of Object.entries( charts ) ) {
// create canvas
var canvas = document.getElementById( 'cn-' + key + '-chart' );
if ( canvas )
new Chart( canvas, config );
}
}
} );
} )( jQuery );

View File

@@ -0,0 +1,149 @@
( function() {
'use strict';
/**
* Build a form-encoded payload and send it without relying on jQuery.
*
* @param {string} action
* @param {Object} data
* @returns {void}
*/
const postNoticeAction = function( action, data ) {
if ( ! window.cnArgsNotice || ! cnArgsNotice.ajaxURL ) {
return;
}
const bodyParams = {
action: action,
notice_action: data.noticeAction,
nonce: data.nonce,
cn_network: cnArgsNotice.network ? 1 : 0
};
if ( typeof data.param !== 'undefined' ) {
bodyParams.param = data.param;
}
const encodeBody = function( params ) {
return Object.keys( params )
.map( function( key ) {
return encodeURIComponent( key ) + '=' + encodeURIComponent( params[ key ] );
} )
.join( '&' );
};
const body = encodeBody( bodyParams );
if ( window.fetch ) {
fetch( cnArgsNotice.ajaxURL, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: body
} ).catch( function() {
// fail silently notice still closes
} );
} else {
// XHR fallback for older browsers.
var xhr = new XMLHttpRequest();
xhr.open( 'POST', cnArgsNotice.ajaxURL, true );
xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' );
xhr.send( body );
}
};
const hideNotice = function( notice ) {
if ( notice ) {
notice.style.display = 'none';
}
};
document.addEventListener( 'DOMContentLoaded', function() {
// No cookie compliance notice.
document.addEventListener( 'click', function( event ) {
const target = event.target;
if ( ! target || typeof target.closest !== 'function' ) {
return;
}
const dismissButton = target.closest( '.cn-notice .cn-no-compliance .cn-notice-dismiss' );
if ( ! dismissButton ) {
return;
}
const notice = dismissButton.closest( '.cn-notice' );
if ( ! notice ) {
return;
}
event.preventDefault();
let noticeAction = 'dismiss';
let param = '';
if ( dismissButton.classList.contains( 'cn-approve' ) ) {
noticeAction = 'approve';
} else if ( dismissButton.classList.contains( 'cn-delay' ) ) {
noticeAction = 'delay';
} else if ( notice.classList.contains( 'cn-threshold' ) ) {
noticeAction = 'threshold';
const noticeText = notice.querySelector( '.cn-notice-text' );
const delay = noticeText && noticeText.dataset ? parseInt( noticeText.dataset.delay, 10 ) : NaN;
param = ! isNaN( delay ) && isFinite( delay ) ? delay : '';
}
postNoticeAction( 'cn_dismiss_notice', {
noticeAction: noticeAction,
nonce: cnArgsNotice.nonce,
param: param
} );
hideNotice( notice );
} );
// Review notice.
document.addEventListener( 'click', function( event ) {
const target = event.target;
if ( ! target || typeof target.closest !== 'function' ) {
return;
}
const link = target.closest( '.cn-notice .cn-review .button-link' );
if ( ! link ) {
return;
}
const notice = link.closest( '.cn-notice' );
if ( ! notice ) {
return;
}
event.preventDefault();
let noticeAction = 'dismiss';
if ( link.classList.contains( 'cn-notice-review' ) ) {
noticeAction = 'review';
} else if ( link.classList.contains( 'cn-notice-delay' ) ) {
noticeAction = 'delay';
}
postNoticeAction( 'cn_review_notice', {
noticeAction: noticeAction,
nonce: cnArgsNotice.reviewNonce
} );
hideNotice( notice );
} );
} );
} )();

View File

@@ -0,0 +1,71 @@
( function( $ ) {
// ready event
$( function() {
// cancel deactivation
$( document ).on( 'click', '.cn-deactivate-plugin-cancel', function( e ) {
tb_remove();
return false;
} );
// simple deactivation
$( document ).on( 'click', '.cn-deactivate-plugin-simple', function( e ) {
// display spinner
$( '#cn-deactivation-footer .spinner' ).addClass( 'is-active' );
} );
// deactivation with sending data
$( document ).on( 'click', '.cn-deactivate-plugin-data', function( e ) {
var spinner = $( '#cn-deactivation-footer .spinner' );
var url = $( this ).attr( 'href' );
// display spinner
spinner.addClass( 'is-active' );
// submit data
$.post( ajaxurl, {
action: 'cn-deactivate-plugin',
option_id: $( 'input[name="cn_deactivation_option"]:checked' ).val(),
other: $( 'textarea[name="cn_deactivation_other"]' ).val(),
nonce: cnArgsPlugins.nonce
} ).done( function( response ) {
// deactivate plugin
window.location.href = url;
} ).fail( function() {
// deactivate plugin
window.location.href = url;
} );
return false;
} );
// click on deactivation link
$( document ).on( 'click', '.cn-deactivate-plugin-modal', function( e ) {
tb_show( cnArgsPlugins.deactivate, '#TB_inline?inlineId=cn-deactivation-modal&modal=false' );
setTimeout( function() {
var modalBox = $( '#cn-deactivation-container' ).closest( '#TB_window' );
if ( modalBox.length > 0 ) {
$( modalBox ).addClass( 'cn-deactivation-modal' );
}
}, 0 );
return false;
} );
// change radio
$( document ).on( 'change', 'input[name="cn_deactivation_option"]', function( e ) {
var last = $( 'input[name="cn_deactivation_option"]' ).last().get( 0 );
// last element?
if ( $( this ).get( 0 ) === last )
$( '.cn-deactivation-textarea textarea' ).prop( 'disabled', false );
else
$( '.cn-deactivation-textarea textarea' ).prop( 'disabled', true );
} );
} );
} )( jQuery );

Some files were not shown because too many files have changed in this diff Show More