Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
.advads-buttonset .advads-button {
margin-left: 0;
margin-right: -.3em;
}
.advads-buttonset .advads-button.advads-ui-state-active {
/*border-color: #0074a2 !important;*/
border-color: #2ea2cc !important;
background: #2ea2cc !important;
color: #fff !important;
box-shadow: none;
border-width: 1px;
}
.advads-button {
text-decoration: none;
display: inline-block;
position: relative;
padding: 0;
line-height: normal;
margin-right: .1em;
cursor: pointer;
vertical-align: middle;
text-align: center;
overflow: visible;
color: #555;
border: 1px solid #d3d3d3;
background: #e6e6e6;
font-weight: normal;
font-family: Verdana,Arial,sans-serif;
font-size: 1.1em;
}
.advads-button .advads-button-text {
display: block;
line-height: normal;
padding: .4em 1em;
}
.advads-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.advads-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 300px;
box-shadow: 0 0 5px #aaa;
border-radius: 4px;
border: 2px solid #aaa;
background: #fff;
color: #222;
font-family: Verdana,Arial,sans-serif;
font-size: 14px;
font-weight: normal;
}
.advads-tooltip h4 {
margin: 0;
}
/* jQueryUI autocomplete */
.ui-menu-item:hover {
border: 1px solid #999;
background: #dadada;
color: #212121;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="70" viewBox="4.312 5.25 70 70" overflow="visible" xmlns:v="https://vecta.io/nano"><linearGradient id="A" gradientUnits="userSpaceOnUse" x1="39.856" y1="81.911" x2="57.095" y2="52.05"><stop offset="0" stop-color="#8c2100"/><stop offset="1" stop-color="#8c2100" stop-opacity="0"/></linearGradient><path fill="url(#A)" d="M46.392 45.871L35.33 65.031c-3.412 5.911-8.94 9.101-12.354 7.135 1.368.788 3.436 1.295 4.87 1L73.971 61.8 46.392 45.871z"/><path fill="#fff" d="M52.296 7.117l-1.759-1.016c-.976-.564-2.076-.85-3.271-.85-1.574 0-3.224.49-4.901 1.458l-12.356 7.134c-2.636 1.523-5.089 4.1-6.909 7.256L7.13 48.751c-4.023 6.971-3.701 14.436.732 16.995l12.353 7.134 1.762 1.018c.978.562 2.077.848 3.269.848 4.123 0 8.761-3.421 11.817-8.715L53.03 38.374c1.823-3.154 2.828-6.567 2.828-9.608V14.503c-.001-3.439-1.265-6.062-3.562-7.386z"/><path d="M8.862 64.014c-3.41-1.969-3.41-8.354 0-14.263l15.971-27.654c1.704-2.956 3.939-5.23 6.176-6.523l12.355-7.133c2.234-1.288 4.47-1.593 6.173-.608s2.561 3.073 2.561 5.654V27.75c0 2.583-.854 5.654-2.561 8.608L33.569 64.014c-2.729 4.729-6.812 7.715-10.084 7.715-.818 0-1.586-.187-2.269-.58L8.862 64.014zM54.695 29.25c0 2.583-.854 5.654-2.561 8.608L36.167 65.514c-3.373 5.845-8.812 9.02-12.234 7.19 3.615-.25 7.779-3.472 10.502-8.19l15.968-27.656c1.737-3.009 2.694-6.244 2.694-9.108V13.487c0-1.574-.291-2.945-.837-4.066 1.618 1.015 2.435 3.053 2.435 5.566V29.25z" fill="#cc3000"/><path d="M46.449 13.182c-.341-.197-.725-.291-1.134-.291-.613 0-1.283.21-1.951.596-1.117.645-2.235 1.782-3.087 3.261-1.706 2.954-1.709 6.148-.003 7.133.341.197.725.291 1.134.291 1.635 0 3.677-1.495 5.041-3.858.855-1.478 1.28-3.013 1.28-4.304s-.424-2.336-1.28-2.828zm-.865 6.63c-1.274 2.206-3.064 3.359-4.176 3.359a1.23 1.23 0 0 1-.634-.157c-.235-.136-.414-.379-.547-.686a5.47 5.47 0 0 0 .879-.472c-.211-.632-.194-2.208.903-4.109.641-1.114 1.499-2.035 2.354-2.529.326-.188.566-.264.734-.299l.032-.411c0-.213-.038-.4-.062-.597l.247-.022c.24 0 .454.053.633.157.497.286.781 1.001.781 1.962.001 1.16-.416 2.547-1.144 3.804zM30.138 49.288c-1.521-.883-3.996.547-5.521 3.189-1.521 2.637-1.521 5.492 0 6.369 1.525.883 3.996-.544 5.521-3.186s1.525-5.495 0-6.372zm-4.139 7.17c-.759-.438-.759-1.868 0-3.187.766-1.321 1.998-2.033 2.76-1.595s.76 1.868 0 3.186-1.997 2.034-2.76 1.596zm4.142-22.946c-1.524-.88-3.996.548-5.518 3.188-1.528 2.641-1.524 5.494 0 6.374s3.993-.548 5.518-3.188 1.525-5.493 0-6.374zm-4.139 7.171c-.762-.438-.762-1.868 0-3.186s1.999-2.033 2.76-1.595.763 1.868-.003 3.186-1.994 2.035-2.757 1.595zm12.764.06L16.019 53.881l-.003-2.252 22.75-13.138z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" overflow="visible"><path fill="#fff" d="M19.878 99C9.469 99 1 90.532 1 80.123V2a1 1 0 0 1 1-1h78.122C90.531 1 99 9.469 99 19.878V98a1 1 0 0 1-1 1H19.878z"/><path d="M80.122 2C89.98 2 98 10.02 98 19.878V98H19.878C10.019 98 2 89.98 2 80.123V2h78.122m0-2H2a2 2 0 0 0-2 2v78.123C0 91.083 8.917 100 19.878 100H98a2 2 0 0 0 2-2V19.878C100 8.917 91.083 0 80.122 0h0zM34.065 47.149H19.381c-.811 0-1.467-.657-1.467-1.467V31c0-.81.656-1.467 1.467-1.467h14.685c.811 0 1.467.657 1.467 1.467v14.683a1.47 1.47 0 0 1-1.468 1.466zm46.637 0H66.019c-.811 0-1.467-.657-1.467-1.467V31c0-.81.656-1.467 1.467-1.467h14.684c.811 0 1.467.657 1.467 1.467v14.683a1.47 1.47 0 0 1-1.468 1.466zm-23.318 0H42.699c-.811 0-1.467-.657-1.467-1.467V31c0-.81.656-1.467 1.467-1.467h14.685c.811 0 1.467.657 1.467 1.467v14.683c0 .81-.657 1.466-1.467 1.466zM34.065 70.467H19.381c-.811 0-1.467-.656-1.467-1.467V54.317c0-.811.656-1.467 1.467-1.467h14.685c.811 0 1.467.656 1.467 1.467V69a1.47 1.47 0 0 1-1.468 1.467zm46.637 0H66.019c-.811 0-1.467-.656-1.467-1.467V54.317c0-.811.656-1.467 1.467-1.467h14.684c.811 0 1.467.656 1.467 1.467V69a1.47 1.47 0 0 1-1.468 1.467zm-23.318 0H42.699c-.811 0-1.467-.656-1.467-1.467V54.317c0-.811.656-1.467 1.467-1.467h14.685c.811 0 1.467.656 1.467 1.467V69c0 .811-.657 1.467-1.467 1.467z" fill="#0074a2"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" overflow="visible"><path fill="#fff" d="M19.878 99C9.469 99 1 90.532 1 80.123V2a1 1 0 0 1 1-1h78.122C90.531 1 99 9.469 99 19.878V98a1 1 0 0 1-1 1H19.878z"/><path d="M80.122 2C89.98 2 98 10.02 98 19.878V98H19.878C10.019 98 2 89.98 2 80.123V2h78.122m0-2H2a2 2 0 0 0-2 2v78.123C0 91.083 8.917 100 19.878 100H98a2 2 0 0 0 2-2V19.878C100 8.917 91.083 0 80.122 0h0zM34.064 45.483H19.38c-.811 0-1.467-.657-1.467-1.467V29.333c0-.81.656-1.467 1.467-1.467h14.685c.811 0 1.467.657 1.467 1.467v14.683a1.47 1.47 0 0 1-1.468 1.467zm46.638 0H66.017c-.811 0-1.467-.657-1.467-1.467V29.333c0-.81.656-1.467 1.467-1.467h14.686c.811 0 1.467.657 1.467 1.467v14.683a1.47 1.47 0 0 1-1.468 1.467zM67.483 42.55h11.752V30.8H67.483v11.75zm-10.1 2.933H42.698c-.811 0-1.467-.657-1.467-1.467V29.333c0-.81.656-1.467 1.467-1.467h14.685c.811 0 1.467.657 1.467 1.467v14.683c0 .811-.657 1.467-1.467 1.467zM44.165 42.55h11.751V30.8H44.165v11.75zm-1.901 11.877c-.23 0-.461.06-.667.179-.412.238-.667.679-.667 1.155v14.682c0 .477.255.917.667 1.155.206.119.437.179.667.179s.46-.06.667-.179l12.718-7.34c.412-.238.667-.679.667-1.155s-.255-.917-.667-1.155l-12.718-7.342c-.206-.12-.437-.179-.667-.179h0zm15.553 17.482c-.811 0-1.467-.656-1.467-1.467V55.761c0-.811.656-1.467 1.467-1.467s1.467.656 1.467 1.467v14.682c0 .81-.656 1.466-1.467 1.466z" fill="#0074a2"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" overflow="visible"><path fill="#fff" d="M19.878 99C9.469 99 1 90.532 1 80.123V2a1 1 0 0 1 1-1h78.122C90.531 1 99 9.469 99 19.878V98a1 1 0 0 1-1 1H19.878z"/><path d="M80.122 2C89.98 2 98 10.02 98 19.878V98H19.878C10.019 98 2 89.98 2 80.123V2h78.122m0-2H2a2 2 0 0 0-2 2v78.123C0 91.083 8.917 100 19.878 100H98a2 2 0 0 0 2-2V19.878C100 8.917 91.083 0 80.122 0h0zM34.064 45.483H19.38a1.47 1.47 0 0 1-1.467-1.467V29.333a1.47 1.47 0 0 1 1.467-1.467h14.684a1.47 1.47 0 0 1 1.467 1.467v14.683c0 .811-.657 1.467-1.467 1.467zM20.847 42.55h11.75V30.8h-11.75v11.75zm59.854 2.933H66.018c-.811 0-1.467-.657-1.467-1.467V29.333c0-.81.656-1.467 1.467-1.467h14.684c.811 0 1.467.657 1.467 1.467v14.683a1.47 1.47 0 0 1-1.468 1.467zm-23.318 0H42.699a1.47 1.47 0 0 1-1.467-1.467V29.333a1.47 1.47 0 0 1 1.467-1.467h14.684c.811 0 1.467.657 1.467 1.467v14.683c0 .811-.657 1.467-1.467 1.467zM44.166 42.55h11.75V30.8h-11.75v11.75zm22.896 27.259l-8.193-4.729c-.227-.133-.505-.133-.733 0a.73.73 0 0 0-.366.635v3.263h-1.016c-1.571-.002-3.046-.613-4.154-1.721l-4.154-4.154 4.154-4.154c1.109-1.109 2.584-1.72 4.152-1.72h1.018v3.263c0 .262.14.504.366.635a.73.73 0 0 0 .367.099c.127 0 .253-.032.366-.099l8.193-4.729a.73.73 0 0 0 .367-.635c0-.262-.14-.504-.367-.635l-8.193-4.73c-.227-.131-.505-.131-.733 0a.73.73 0 0 0-.366.635v3.263h-1.018a8.75 8.75 0 0 0-6.227 2.578l-4.154 4.154-4.155-4.155a8.75 8.75 0 0 0-6.225-2.577h-1.688c-.81 0-1.467.656-1.467 1.467s.657 1.467 1.467 1.467h1.688a5.83 5.83 0 0 1 4.15 1.719l4.155 4.155-4.154 4.154c-1.108 1.107-2.583 1.719-4.15 1.721h-1.688c-.81 0-1.467.656-1.467 1.467s.657 1.467 1.467 1.467h1.689c2.352-.002 4.562-.919 6.223-2.58l4.154-4.154 4.154 4.154c1.661 1.661 3.872 2.578 6.227 2.58h1.018v3.263c0 .262.14.504.366.635a.73.73 0 0 0 .367.099c.127 0 .253-.032.366-.099l8.193-4.729a.73.73 0 0 0 .367-.635c0-.262-.139-.508-.366-.638z" fill="#0074a2"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" overflow="visible"><path fill="#fff" d="M19.878 99C9.469 99 1 90.532 1 80.123V2a1 1 0 0 1 1-1h78.122C90.531 1 99 9.469 99 19.878V98a1 1 0 0 1-1 1H19.878z"/><path d="M80.122 2C89.98 2 98 10.02 98 19.878V98H19.878C10.019 98 2 89.98 2 80.123V2h78.122m0-2H2a2 2 0 0 0-2 2v78.123C0 91.083 8.917 100 19.878 100H98a2 2 0 0 0 2-2V19.878C100 8.917 91.083 0 80.122 0h0zm.579 31.367H67.484V24.2c0-.81-.656-1.467-1.467-1.467H34.064c-.811 0-1.467.657-1.467 1.467v7.167H19.38c-.811 0-1.467.657-1.467 1.467v14.683c0 .81.656 1.467 1.467 1.467h13.218v7.167c0 .811.656 1.467 1.467 1.467h31.953c.811 0 1.467-.656 1.467-1.467v-7.167h13.217c.811 0 1.467-.657 1.467-1.467V32.834a1.47 1.47 0 0 0-1.468-1.467zM20.847 46.05V34.3h11.751v11.75H20.847zm58.387 0h-11.75V34.3h11.75v11.75zM50 65.25c-3.235 0-5.867 2.632-5.867 5.867s2.632 5.868 5.867 5.868 5.866-2.632 5.866-5.868S53.234 65.25 50 65.25h0zm17.603 2.934c1.621 0 2.934 1.313 2.934 2.934s-1.312 2.935-2.934 2.935-2.933-1.313-2.933-2.935a2.93 2.93 0 0 1 2.933-2.934m0-2.934c-3.234 0-5.866 2.632-5.866 5.867s2.632 5.868 5.866 5.868 5.867-2.632 5.867-5.868-2.632-5.867-5.867-5.867h0zm-35.207 2.934c1.62 0 2.933 1.313 2.933 2.934s-1.312 2.935-2.933 2.935-2.934-1.313-2.934-2.935 1.313-2.934 2.934-2.934m0-2.934c-3.235 0-5.867 2.632-5.867 5.867s2.632 5.868 5.867 5.868 5.866-2.632 5.866-5.868-2.631-5.867-5.866-5.867h0z" fill="#0074a2"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

View File

@@ -0,0 +1 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 351.7 352" xml:space="preserve"><path d="M252.2 149.6v125.1h-174.9v-174.9H202.4c-5.2-11.8-8-24.7-8-38.5s3-26.7 8-38.5h-37.7H0v267.9l8.8 8.8 -8.8-8.8C0 324.5 27.5 352 61.3 352l0 0h103.4 164.5V149.3c-11.8 5.2-25 8.3-38.8 8.3C276.9 157.6 264 154.6 252.2 149.6z" fill="#1C1B3A"/><circle cx="290.4" cy="61.3" r="61.3" fill="#0E75A4"/></svg>

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 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: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="35px" viewBox="0 0 20 35" overflow="visible" enable-background="new 0 0 20 35" xml:space="preserve">
<defs>
</defs>
<rect fill="#CC3000" width="20" height="35"/>
<polygon fill="#D13607" points="0,0 10.017,5.828 20,0 "/>
<polygon fill="#D13607" points="10.017,17.5 20,11.672 20,23.345 "/>
<polygon fill="#D13607" points="0,23.345 0,11.672 10.017,17.5 "/>
<polygon fill="#C52E00" points="20,0 10.017,5.828 10.017,17.5 20,11.672 "/>
<polygon fill="#D13607" points="0,35 10.017,29.155 20,35 "/>
<polygon fill="#C52E00" points="10.017,17.5 0,23.345 0,35 10.017,29.155 "/>
</svg>

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="35px" viewBox="0 0 20 35" overflow="visible" enable-background="new 0 0 20 35" xml:space="preserve">
<defs>
</defs>
<rect fill="#0074A2" width="20" height="35"/>
<polygon fill="#0A7BA8" points="0,0 10.017,5.828 20,0 "/>
<polygon fill="#0A7BA8" points="10.017,17.5 20,11.672 20,23.345 "/>
<polygon fill="#0A7BA8" points="0,23.345 0,11.672 10.017,17.5 "/>
<polygon fill="#00719D" points="20,0 10.017,5.828 10.017,17.5 20,11.672 "/>
<polygon fill="#0A7BA8" points="0,35 10.017,29.155 20,35 "/>
<polygon fill="#00719D" points="10.017,17.5 0,23.345 0,35 10.017,29.155 "/>
</svg>

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -0,0 +1,35 @@
window.advads_adblocker_image_data = [
'ad',
'bottom-ads',
'bottom_ad',
'logoads',
'movie',
'x28',
'x2x8',
'malwarebytes-banner',
'728x90',
'betindia',
'worldfirst-currencyconversion',
'ml',
'p2',
'clicktoplay',
'download_ad',
'301',
'banner',
'download-bukkake',
'ad2',
'advertise-img',
'bblogo',
'adtech',
'AppStateBanner',
'ads3',
'banner_member',
'adguard-banner',
'mad_ad',
'hdsale',
'porndude',
'1001505_banner',
'Q1-23-CD-Promo-Banner-A',
'500x100',
'300x250',
];

View File

@@ -0,0 +1,445 @@
/* eslint-disable no-unused-vars */
/* eslint-disable camelcase */
/*
* global js functions for Advanced Ads
*/
jQuery(document).ready(function () {
/**
* ADMIN NOTICES
*/
// close button
// .advads-notice-dismiss class can be used to add a custom close button (e.g., link)
jQuery(document).on(
'click',
'.advads-admin-notice .notice-dismiss, .advads-notice-dismiss',
function (event) {
event.preventDefault();
const messagebox = jQuery(this).parents('.advads-admin-notice');
if (messagebox.attr('data-notice') === undefined) return;
const query = {
action: 'advads-close-notice',
notice: messagebox.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {
messagebox.fadeOut();
});
}
);
// hide notice for 7 days
jQuery(document).on(
'click',
'.advads-admin-notice .advads-notice-hide',
function () {
const messagebox = jQuery(this).parents('.advads-admin-notice');
if (messagebox.attr('data-notice') === undefined) return;
const query = {
action: 'advads-hide-notice',
notice: messagebox.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {
messagebox.fadeOut();
});
}
);
// autoresponder button
jQuery('body').on('click', '.advads-notices-button-subscribe', function () {
if (this.dataset.notice === undefined) {
return;
}
const messageboxes = jQuery(this).parents('.advads-admin-notice');
if (!messageboxes.length) {
return;
}
const $messagebox = jQuery(messageboxes[0]);
jQuery('<span class="spinner advads-spinner"></span>').insertAfter(
this
);
const query = {
action: 'advads-subscribe-notice',
notice: this.dataset.notice,
nonce: advadsglobal.ajax_nonce,
};
// send and replace with server message
jQuery
.post(ajaxurl, query)
.success(function (response) {
$messagebox
.children('.advads-notice-box_wrapper')
.html('<p>' + response.data.message + '</p>');
$messagebox.addClass('notice-success notice');
})
.fail(function (response) {
$messagebox
.children('.advads-notice-box_wrapper')
.html('<p>' + response.responseJSON.data.message + '</p>');
$messagebox.addClass('notice-error notice');
})
.always(function () {
$messagebox.removeClass('notice-info');
});
});
/**
* Functions for Ad Health Notifications in the backend
*/
// hide button (adds item to "ignore" list)
jQuery(document).on('click', '.advads-ad-health-notice-hide', function () {
const notice = jQuery(this).parents('li');
if (notice.attr('data-notice') === undefined) return;
// var list = notice.parent( 'ul' );
const remove = jQuery(this).hasClass('remove');
// fix height to prevent the box from going smaller first, then show the "show" link and grow again
const notice_box = jQuery('#advads_overview_notices');
notice_box.css('height', notice_box.height() + 'px');
const query = {
action: 'advads-ad-health-notice-hide',
notice: notice.attr('data-notice'),
nonce: advadsglobal.ajax_nonce,
};
// fade out first or remove, so users cant click twice
if (remove) {
notice.remove();
} else {
notice.hide();
}
// show loader
notice_box.find('.advads-loader').show();
advads_ad_health_maybe_remove_list();
// send query
jQuery.post(ajaxurl, query, function (r) {
// update number in menu
advads_ad_health_reload_number_in_menu();
// update show button
advads_ad_health_reload_show_link();
// remove the fixed height
jQuery('#advads_overview_notices').css('height', '');
// remove loader
notice_box.find('.advads-loader').hide();
});
});
// show all hidden notices
jQuery(document).on(
'click',
'.advads-ad-health-notices-show-hidden',
function () {
advads_ad_health_show_hidden();
}
);
/**
* DEACTIVATION FEEDBACK FORM
*/
// show overlay when clicked on "deactivate"
const advads_deactivate_link = jQuery(
'.wp-admin.plugins-php tr[data-slug="advanced-ads"] .row-actions .deactivate a'
);
const advads_deactivate_link_url = advads_deactivate_link.attr('href');
advads_deactivate_link.on('click', function (e) {
e.preventDefault();
// only show feedback form once per 30 days
const c_value = advads_admin_get_cookie(
'advanced_ads_hide_deactivate_feedback'
);
if (c_value === undefined) {
jQuery('#advanced-ads-feedback-overlay').show();
} else {
// click on the link
window.location.href = advads_deactivate_link_url;
}
});
// show text fields
jQuery('#advanced-ads-feedback-content input[type="radio"]').on(
'click',
function () {
// show text field if there is one
jQuery(this)
.parents('li')
.next('li')
.children('input[type="text"], textarea')
.show();
}
);
// handle technical issue feedback in particular
jQuery('#advanced-ads-feedback-content .advanced_ads_disable_help_text').on(
'focus',
function () {
// show text field if there is one
jQuery(this)
.parents('li')
.siblings('.advanced_ads_disable_reply')
.show();
}
);
// send form or close it
jQuery('#advanced-ads-feedback-content .button').on('click', function (e) {
e.preventDefault();
const self = jQuery(this);
// set cookie for 30 days
advads_store_feedback_cookie();
// save if plugin should be disabled
const disable_plugin = self.hasClass(
'advanced-ads-feedback-not-deactivate'
)
? false
: true;
// hide the content of the feedback form
jQuery('#advanced-ads-feedback-content form').hide();
if (self.hasClass('advanced-ads-feedback-submit')) {
// show feedback message
jQuery('#advanced-ads-feedback-after-submit-waiting').show();
if (disable_plugin) {
jQuery(
'#advanced-ads-feedback-after-submit-disabling-plugin'
).show();
}
jQuery.ajax({
type: 'POST',
url: ajaxurl,
dataType: 'json',
data: {
action: 'advads_send_feedback',
feedback: self.hasClass(
'advanced-ads-feedback-not-deactivate'
)
? true
: false,
formdata: jQuery(
'#advanced-ads-feedback-content form'
).serialize(),
},
complete(MLHttpRequest, textStatus, errorThrown) {
// deactivate the plugin and close the popup with a timeout
setTimeout(function () {
jQuery('#advanced-ads-feedback-overlay').remove();
}, 2000);
if (disable_plugin) {
window.location.href = advads_deactivate_link_url;
}
},
});
} else {
// currently not reachable
jQuery('#advanced-ads-feedback-overlay').remove();
window.location.href = advads_deactivate_link_url;
}
});
// close form and disable the plugin without doing anything
jQuery('.advanced-ads-feedback-only-deactivate').on('click', function () {
// hide the content of the feedback form
jQuery('#advanced-ads-feedback-content form').hide();
// show feedback message
jQuery('#advanced-ads-feedback-after-submit-goodbye').show();
jQuery('#advanced-ads-feedback-after-submit-disabling-plugin').show();
// set cookie for 30 days
advads_store_feedback_cookie();
// wait one second
setTimeout(function () {
jQuery('#advanced-ads-feedback-overlay').hide();
window.location.href = advads_deactivate_link_url;
}, 1000);
});
// close button for feedback form
jQuery('#advanced-ads-feedback-overlay-close-button').on(
'click',
function () {
jQuery('#advanced-ads-feedback-overlay').hide();
}
);
jQuery('.advads-help').on('mouseenter', function (event) {
const tooltip = jQuery(event.target).children('.advads-tooltip')[0];
if (typeof tooltip === 'undefined') {
return;
}
// reset inline styles before getting bounding client rect.
tooltip.style.position = '';
tooltip.style.left = '';
tooltip.style.top = '';
const topParentRect = document
.getElementById('wpbody')
.getBoundingClientRect(),
helpRect = event.target.getBoundingClientRect(),
offsets = {
left: Math.ceil(helpRect.left) + 13,
top: Math.ceil(helpRect.top) + 13,
};
let tooltipRect = tooltip.getBoundingClientRect();
tooltip.style.position = 'fixed';
tooltip.style.left = offsets.left + 'px';
tooltip.style.top = offsets.top + 'px';
// check element is not overflowing to the right.
while (tooltipRect.right > topParentRect.right - 20) {
offsets.left -= 10;
tooltip.style.left = offsets.left + 'px';
tooltipRect = tooltip.getBoundingClientRect();
}
// check element is not overflowing bottom of parent and is within viewport.
while (tooltipRect.bottom > Math.min(topParentRect.bottom, jQuery(window).height()) - 20) {
offsets.top -= 10;
tooltip.style.top = offsets.top + 'px';
tooltipRect = tooltip.getBoundingClientRect();
}
});
});
// remove duplicate close buttons
jQuery(window).on('load', function () {
jQuery('a.notice-dismiss').next('button.notice-dismiss').remove();
});
function advads_admin_get_cookie(name) {
let i, x, y;
const ADVcookies = document.cookie.split(';');
for (i = 0; i < ADVcookies.length; i++) {
x = ADVcookies[i].substr(0, ADVcookies[i].indexOf('='));
y = ADVcookies[i].substr(ADVcookies[i].indexOf('=') + 1);
x = x.replace(/^\s+|\s+$/g, '');
if (x === name) {
return unescape(y);
}
}
}
/**
* Store a cookie for 30 days
* The cookie prevents the feedback form from showing multiple times
*/
function advads_store_feedback_cookie() {
const exdate = new Date();
exdate.setSeconds(exdate.getSeconds() + 2592000);
document.cookie =
'advanced_ads_hide_deactivate_feedback=1; expires=' +
exdate.toUTCString() +
'; path=/';
}
/**
* Ad Health Notices in backend
*/
// display notices list (deprecated because we load it without AJAX now)
function advads_display_ad_health_notices() {
const query = {
action: 'advads-ad-health-notice-display',
nonce: advadsglobal.ajax_nonce,
};
const widget = jQuery('#advads_overview_notices .main');
// add loader icon to the widget
widget.html('<span class="advads-loader"></span>');
// send query
jQuery.post(ajaxurl, query, function (r) {
widget.html(r);
// update number in menu
advads_ad_health_reload_number_in_menu();
// update list headlines
advads_ad_health_maybe_remove_list();
// remove widget, if return is empty
if (r === '') {
jQuery('#advads_overview_notices').remove();
}
});
}
// push a notice to the queue
function advads_push_notice(key, attr = '') {
const query = {
action: 'advads-ad-health-notice-push-adminui',
key,
attr,
nonce: advadsglobal.ajax_nonce,
};
// send query
jQuery.post(ajaxurl, query, function (r) {});
}
// show notices of a given type again
function advads_ad_health_show_hidden() {
const notice_box = jQuery('#advads__overview_notices');
const query = {
action: 'advads-ad-health-notice-unignore',
nonce: advadsglobal.ajax_nonce,
};
// show all hidden
jQuery(document)
.find('#advads_overview_notices .advads-ad-health-notices > li:hidden')
.show();
// show loader
notice_box.find('.advads-loader').show();
// update the button
advads_ad_health_reload_show_link();
advads_ad_health_maybe_remove_list();
// send query
jQuery.post(ajaxurl, query, function (r) {
// update issue count
advads_ad_health_reload_number_in_menu();
// hide loader
notice_box.find('.advads-loader').hide();
});
}
// hide list fragments if last item was hidden/removed
function advads_ad_health_maybe_remove_list() {
// get all lists
const lists = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices'
);
// check each list separately
lists.each(function (index) {
const list = jQuery(this);
// check if there are visible items in the list
if (list.find('li:visible').length) {
// show parent headline
list.prev('h3').show();
} else {
// hide parent headline
list.prev('h3').hide();
}
});
}
// reload number of notices shown in the sidebar based on element in the problems list
function advads_ad_health_reload_number_in_menu() {
// get number of notices
const number = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices > li:visible'
).length;
jQuery('#toplevel_page_advanced-ads .update-count').html(number);
}
// update show X issues link number and visibility
function advads_ad_health_reload_show_link() {
// get number of invisible elements
const number = jQuery(document).find(
'#advads_overview_notices .advads-ad-health-notices > li:hidden'
).length;
const show_link = jQuery('.advads-ad-health-notices-show-hidden');
// update number in the link
jQuery('.advads-ad-health-notices-show-hidden .count').html(number);
// hide of show, depending on number
if (0 === number) {
show_link.hide();
} else {
show_link.show();
}
}
//Radio Toggle visibility
function toggle_visibility(currentElement, toggleElement) {
jQuery(toggleElement).toggle(jQuery(currentElement).val() === 'on');
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
var advanced_ads_adblocker_test = true;

View File

@@ -0,0 +1,534 @@
/**
* Logic for Display and Visitor Conditions forms
*/
jQuery(document).ready(function ($) {
/**
* Pressing the button to add a new condition to the list of conditions
*/
$('.advads-conditions-new select').on('change', function () {
// get the form fieldset and values.
const condition_form_container = $(this).parents('fieldset');
const condition_type = condition_form_container
.find('.advads-conditions-new select')
.val();
const condition_title = condition_form_container
.find('.advads-conditions-new select option:selected')
.text();
let condition_index = parseInt(
condition_form_container.find('.advads-conditions-index').val()
);
const condition_list_target_ID = $.escapeSelector(
condition_form_container.data('condition-list-target')
); // ID of the container into which the new condition is loaded.
const condition_list_target = $('#' + condition_list_target_ID); // container into which the new condition is loaded.
const conditions_form_name = condition_form_container.data(
'condition-form-name'
); // name prefix for the form.
const conditions_connector_default = condition_form_container.data(
'condition-connector-default'
); // default connector option.
const conditions_action =
condition_form_container.data('condition-action'); // action to which to send the AJAX call to.
if (!condition_type || '' == condition_type) {
return;
}
condition_form_container.find('.advads-loader').show(); // show loader.
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: conditions_action,
type: condition_type,
index: condition_index,
form_name: conditions_form_name,
nonce: advadsglobal.ajax_nonce,
},
success(r, textStatus, XMLHttpRequest) {
// add.
if (r) {
if ('or' === conditions_connector_default) {
// as used for display conditions.
var connector =
'<input style="display:none;" type="checkbox" name="' +
conditions_form_name +
'[' +
condition_index +
'][connector]" checked="checked" value="or" id="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector"><label for="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector">' +
advadstxt.condition_or +
'</label>';
var newline =
'<tr class="advads-conditions-connector advads-conditions-connector-or"><td colspan="3">' +
connector +
'</td></tr><tr><td class="advads-conditions-type" data-condition-type="' +
condition_type +
'">' +
condition_title +
'</td><td>' +
r +
'</td><td><button type="button" class="advads-conditions-remove button">x</button></td></tr>';
} else {
// as used for visitor conditions.
var connector =
'<input type="checkbox" name="' +
conditions_form_name +
'[' +
condition_index +
'][connector]" value="or" id="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector"><label for="advads-conditions-' +
condition_list_target_ID +
'-' +
condition_index +
'-connector">' +
advadstxt.condition_and +
'</label>';
var newline =
'<tr class="advads-conditions-connector advads-conditions-connector-and"><td colspan="3">' +
connector +
'</td></tr><tr><td class="advads-conditions-type" data-condition-type="' +
condition_type +
'">' +
condition_title +
'</td><td>' +
r +
'</td><td><button type="button" class="advads-conditions-remove button">x</button></td></tr>';
}
condition_list_target.find('tbody').append(newline);
condition_list_target
.find(
'tbody .advads-conditions-single.advads-buttonset'
)
.advads_buttonset();
condition_list_target
.find('tbody .advads-conditions-connector input')
.advads_button();
// increase count.
condition_index++;
condition_form_container
.find('.advads-conditions-index')
.val(condition_index);
// reset select.
condition_form_container.find(
'.advads-conditions-new select'
)[0].selectedIndex = 0;
advads_display_condition_option_not_selected();
const tr = $(this).parents('.advads-conditions-table tr');
condition_list_target.next('input').remove();
}
},
error(MLHttpRequest, textStatus, errorThrown) {
condition_form_container
.find('.advads-conditions-new')
.append(errorThrown);
},
complete(MLHttpRequest, textStatus) {
condition_form_container
.find('.advads-conditions-new .advads-loader')
.hide(); // hide loader.
},
});
});
// disable term in the term list of the appropriate condition by just clicking on it.
$(document).on(
'click',
'.advads-conditions-terms-buttons .button',
function (e) {
$(this).remove();
}
);
// display input field to search for terms.
$(document).on(
'click',
'.advads-conditions-terms-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this).siblings('.advads-conditions-terms-search').show().focus();
// register autocomplete.
advads_register_terms_autocomplete(
$(this).siblings('.advads-conditions-terms-search')
);
$(this).next('br').show();
$(this).hide();
}
);
// function for autocomplete.
function advads_register_terms_autocomplete(self) {
self.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
// var searchField = request.term;
advads_term_search(self, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields.
$(
'<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">' +
ui.item.label +
'<input type="hidden" name="' +
self.data('inputName') +
'" value="' +
ui.item.value +
'"></span></label>'
).appendTo(self.siblings('.advads-conditions-terms-buttons'));
// show / hide other elements
// $( '.advads-display-conditions-individual-post' ).hide();
// $( '.advads-conditions-postids-list .show-search a' ).show();
},
// eslint-disable-next-line no-unused-vars
close(event, ui) {
self.val('');
},
});
}
// remove author from list by clicking on it.
$(document).on(
'click',
'.advads-conditions-authors-buttons .button',
function () {
$(this).remove();
}
);
// display input field to search for author.
$(document).on(
'click',
'.advads-conditions-authors-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this)
.siblings('.advads-conditions-authors-search')
.show()
.focus();
// register autocomplete.
advadsRegisterAuthorAutocomplete(
$(this).siblings('.advads-conditions-authors-search')
);
$(this).next('br').show();
$(this).hide();
}
);
// author search box autocomplete.
function advadsRegisterAuthorAutocomplete(self) {
self.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
advadsAuthorSearch(self, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields.
$(
'<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">' +
ui.item.label +
'<input type="hidden" name="' +
self.data('inputName') +
'" value="' +
ui.item.value +
'"></span></label>'
).appendTo(self.siblings('.advads-conditions-authors-buttons'));
},
close() {
self.val('');
},
});
}
// display input field to search for post, page, etc.
$(document).on(
'click',
'.advads-conditions-postids-show-search',
function (e) {
e.preventDefault();
// display input field.
$(this)
.next()
.find('.advads-display-conditions-individual-post')
.show();
//$( '.advads-conditions-postids-search-line .description' ).hide();
$(this).hide();
}
);
// register autocomplete to display condition individual posts.
// eslint-disable-next-line no-unused-vars
$(document).on(
'focus',
'.advads-display-conditions-individual-post',
// eslint-disable-next-line no-unused-vars
function (e) {
const self = this;
if (!$(this).data('autocomplete')) {
// If the autocomplete wasn't called yet:
$(this)
.autocomplete({
classes: {
'ui-autocomplete': 'advads-ui-autocomplete',
},
source(request, callback) {
const searchParam = request.term;
advads_post_search(searchParam, callback);
},
minLength: 1,
select(event, ui) {
// append new line with input fields
const newline = $(
`<label class="button advads-button advads-ui-state-active"><span class="advads-button-text">${ui.item.label}</span></label>`
);
$(
`<input type="hidden" name="${self.dataset.fieldName}[value][]" value="${ui.item.value}"/>`
).appendTo(newline);
newline.insertBefore(
$(self).parent(
'.advads-conditions-postids-search-line'
)
);
},
// eslint-disable-next-line no-unused-vars
close(event, ui) {
$(self).val('');
},
})
.autocomplete()
.data('ui-autocomplete')._renderItem = function (ul, item) {
ul.addClass(
'advads-conditions-postids-autocomplete-suggestions'
);
return $('<li></li>')
.append(
"<span class='left'>" +
item.label +
"</span>&nbsp;<span class='right'>" +
item.info +
'</span>'
)
.appendTo(ul);
};
}
}
);
// remove individual posts from the display conditions post list.
$(document).on(
'click',
'.advads-conditions-postid-buttons .button',
// eslint-disable-next-line no-unused-vars
function (e) {
$(this).remove();
}
);
// display/hide error message if no option was selected
// is also called on every click.
function advads_display_condition_option_not_selected() {
$('.advads-conditions-not-selected').each(function () {
if ($(this).siblings('input:checked').length) {
$(this).hide();
} else {
$(this).show();
}
});
}
advads_display_condition_option_not_selected();
// update error messages when an item is clicked.
$(document).on(
'click',
'.advads-conditions-terms-buttons input[type="checkbox"], .advads-conditions-single input[type="checkbox"]',
function () {
// needs a slight delay until the buttons are updated.
window.setTimeout(
advads_display_condition_option_not_selected,
200
);
}
);
// activate and toggle conditions connector option.
$('.advads-conditions-connector input').advads_button();
// dynamically change label.
jQuery(document).on(
'click',
'.advads-conditions-connector input',
function () {
if (jQuery(this).is(':checked')) {
jQuery(this)
.next('label')
.find('span')
.html(advadstxt.condition_or);
jQuery(this)
.parents('.advads-conditions-connector')
.addClass('advads-conditions-connector-or')
.removeClass('advads-conditions-connector-and');
} else {
jQuery(this)
.next('label')
.find('span')
.html(advadstxt.condition_and);
jQuery(this)
.parents('.advads-conditions-connector')
.addClass('advads-conditions-connector-and')
.removeClass('advads-conditions-connector-or');
}
}
);
// remove a line with a display or visitor condition.
$(document).on('click', '.advads-conditions-remove', function () {
const tr = $(this).parents('.advads-conditions-table tr');
const table = $(this).closest('.advads-conditions-table');
tr.prev('tr').remove();
tr.remove();
if (table.find('tr').length === 0) {
const fieldset = table.next('fieldset');
table.after(
'<input type="hidden" name="' +
fieldset.data('condition-form-name') +
'[0][type]" value="unknown">'
);
}
});
});
/**
* Callback for term search autocomplete
*
* @param {type} search term
* @param field
* @param {type} callback
* @return {obj} json object with labels and values
*/
function advads_term_search(field, callback) {
// return ['post', 'poster'];
const query = {
action: 'advads-terms-search',
nonce: advadsglobal.ajax_nonce,
};
query.search = field.val();
query.tax = field.data('tagName');
let querying = true;
const results = {};
jQuery.post(
ajaxurl,
query,
function (r) {
querying = false;
const results = [];
if (r) {
r.map(function (element, index) {
results[index] = {
value: element.term_id,
label: element.name,
};
});
}
callback(results);
},
'json'
);
}
/**
* Callback for author search autocomplete
*
* @param {string} search author
* @param {HTMLInputElement} field html input field
* @param {Function} callback Callback function
* @return {Object} JSON object with labels and values
*/
function advadsAuthorSearch(field, callback) {
const query = {
action: 'advads-authors-search',
nonce: advadsglobal.ajax_nonce,
};
query.search = field.val();
let querying = true;
const results = [];
// eslint-disable-next-line no-undef
jQuery.post(
// eslint-disable-next-line no-undef
ajaxurl,
query,
function (r) {
querying = false;
if (r) {
r.map(function (element, index) {
results[index] = {
value: element.data.ID,
label: element.data.display_name,
};
});
}
callback(results);
},
'json'
);
}
/**
* Callback for post search autocomplete
*
* @param {str} searchParam
* @param {type} callback
* @return {obj} json object with labels and values
*/
function advads_post_search(searchParam, callback) {
// return ['post', 'poster'];
const query = {
action: 'advads-post-search',
_ajax_linking_nonce: jQuery('#_ajax_linking_nonce').val(),
search: searchParam,
nonce: advadsglobal.ajax_nonce,
};
let querying = true;
const results = {};
jQuery.post(
ajaxurl,
query,
function (r) {
querying = false;
const results = [];
if (r) {
// eslint-disable-next-line array-callback-return
r.map(function (element, index) {
results[index] = {
label: element.title,
value: element.ID,
info: element.info,
};
});
}
callback(results);
},
'json'
);
}

View File

@@ -0,0 +1,175 @@
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact -- PHPCS can't handle es5 short functions
const modal = element => {
let targetForm;
/**
* Remove the pound sign from the location hash.
*
* @return {string}
*/
const getId = () => window.location.hash.replace( '#', '' );
const showModal = () => {
element.showModal();
element.dispatchEvent( new CustomEvent( 'advads-modal-opened' ) );
// Attach the termination object to the dialog node to allow other's code to plug in.
element.advadsTermination = new Advads_Termination( element );
if ( targetForm ) {
element.advadsTermination.collectValues();
}
};
/**
* If the current hash matches the modal id attribute, open it.
*/
const showIfHashMatches = () => {
if ( getId() === element.id ) {
showModal();
}
};
// Check whether to open modal on page load.
showIfHashMatches();
/**
* Listen to the hashchange event, to check if the current modal needs to be opened.
*/
window.addEventListener( 'hashchange', () => {
showIfHashMatches();
if ( getId() !== 'close' ) {
return;
}
if ( ! targetForm || element.advadsTermination.terminationNotice( true ) ) {
element.close();
}
} );
/**
* Attach a click listener to all links referencing this modal and prevent their default action.
* By changing the hash on every click, we also create a history entry.
*/
document.querySelectorAll( 'a[href$="#' + element.id + '"]' ).forEach( link => {
link.addEventListener( 'click', e => {
e.preventDefault();
showModal();
} );
} );
/**
* On the cancel event, check for termination notice and fire a custom event.
*/
element.addEventListener( 'cancel', event => {
event.preventDefault();
if ( ! targetForm ) {
element.close();
return;
}
if ( element.advadsTermination.terminationNotice( true ) ) {
element.close();
element.advadsTermination.observers.disconnect();
document.dispatchEvent( new CustomEvent( 'advads-modal-canceled', {
detail: {
modal_id: element.id
}
} ) );
}
} );
/**
* On the close event, i.e., a form got submit, empty the hash to prevent form from reopening.
*/
element.addEventListener( 'close', event => {
if ( getId() === element.id ) {
window.location.hash = '';
}
} );
// try if there is a form inside the modal, otherwise continue in catch.
targetForm = element.querySelector( 'form' );
if ( targetForm === null ) {
try {
targetForm = element.querySelector( 'button.advads-modal-close-action' ).form;
} catch ( e ) {
}
}
if ( targetForm ) {
/**
* Listen for the keydown event in all inputs.
* If the enter key is pressed and the modal has a form, submit it, else do nothing.
*/
element.querySelectorAll( 'input' ).forEach( input => {
input.addEventListener( 'keydown', e => {
if ( e.key !== 'Enter' ) {
return;
}
if ( targetForm.reportValidity() ) {
let submitForm = true;
if ( 'function' === typeof window[element.closeValidation.function] && ! window[element.closeValidation.function]( element.closeValidation.modal_id ) ) {
e.preventDefault();
return;
}
/**
* Allow other code to prevent the form submission (and send it using an AJAX call for instance).
*/
submitForm = wp.hooks.applyFilters( 'advanced-ads-submit-modal-form', true, targetForm, element.advadsTermination.initialFormValues, element.advadsTermination.changedFormValues );
if ( ! submitForm ) {
e.preventDefault();
return;
}
targetForm.submit();
}
// if there are inputs, but there is no form associated with them, do nothing.
e.preventDefault();
} );
} );
targetForm.addEventListener( 'submit', () => {
window.location.hash = '';
} );
}
/**
* On the cancel buttons, check termination notice and close the modal.
*/
element.querySelectorAll( '.advads-modal-close, .advads-modal-close-background' ).forEach( button => {
button.addEventListener( 'click', e => {
e.preventDefault();
element.dispatchEvent( new Event( 'cancel' ) );
} );
} );
try {
/**
* If the save button is not a `<button>` element. Close the form without changing the hash.
*/
element.querySelector( 'a.advads-modal-close-action' ).addEventListener( 'click', e => {
e.preventDefault();
element.close();
} );
} catch ( e ) {
}
};
window.addEventListener( 'DOMContentLoaded', () => {
try {
if ( typeof document.querySelector( '.advads-modal[id^=modal-]' ).showModal !== 'function' ) {
return;
}
} catch ( e ) {
return;
}
[...document.getElementsByClassName( 'advads-modal' )].forEach( modal );
} );

View File

@@ -0,0 +1,57 @@
jQuery(document).ready(function ($) {
function getCellValue(row, sortby, index) {
const $td = $(row).find('td');
if ('weight' === sortby) {
return parseInt($td.eq(index).find('select').val()) || 0;
}
if ('ad' === sortby) {
return $td.eq(index).find('a').text().trim();
}
return $td.eq(index).text().trim();
}
function sortAds(sortby, isAscending, table) {
const colIndex = $(table).find(`th[data-sortby=${sortby}]`).index();
const tbody = $(table).find('tbody');
const rows = tbody.find('tr').toArray();
rows.sort(function (a, b) {
const aValue = getCellValue(a, sortby, colIndex);
const bValue = getCellValue(b, sortby, colIndex);
if (isNaN(aValue) || isNaN(bValue)) {
return isAscending
? aValue.localeCompare(bValue)
: bValue.localeCompare(aValue);
}
return isAscending ? aValue - bValue : bValue - aValue;
});
tbody.append(rows);
$(table)
.find('th.group-sort')
.removeClass('asc desc')
.eq(colIndex)
.addClass(isAscending ? 'asc' : 'desc');
}
$('.advads-group-ads').each(function () {
const $this = $(this);
// eslint-disable-next-line prefer-const
let sortStates = {
ad: true,
status: true,
weight: true,
};
$this.find('th.group-sort').on('click', function () {
const sortby = $(this).data('sortby');
sortAds(sortby, sortStates[sortby], this.closest('table'));
sortStates[sortby] = !sortStates[sortby];
});
});
});

View File

@@ -0,0 +1,274 @@
// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact -- PHPCS can't handle es5 short functions
function Advads_Termination( element ) {
/**
* Function to reset the changed nodes to default values.
*
* @constructor
*/
function FormValues() {
this.addedNodes = [];
this.removedNodes = [];
};
this.initialFormValues = new FormValues();
this.changedFormValues = new FormValues();
const blocklist = [
'active_post_lock'
];
this.observers = {
list: [],
push: item => {
this.observers.list.push( item );
},
disconnect: () => {
this.observers.list.forEach( observer => {
observer.disconnect();
} );
this.observers.list = [];
}
};
/**
* Set an initial form value.
* Can be used e.g. when a field is updated after an AJAX call.
*
* @param {String} key The key of the value that should be changed in the initial form value array.
* @param {Node} input The input field node.
*
* @returns {void}
*/
this.setInitialValue = ( key, input ) => {
if ( ! input || ! input.value ) {
return;
}
this.initialFormValues[key] = input.value;
};
/**
* Collect input values.
* Checkboxes are true/false, unless they are part of a group.
* Radio buttons have a boolean value on the saved value, only the checked one will be collected.
*
* @param {FormValues} object
* @param {Node} input
* @return {FormValues}
*/
const collectInputValue = function ( object, input ) {
/**
* Collect checkbox group values.
* If there are multiple checkboxes with the same `nome` attribute, collect all values for this group.
*
* @param {NodeList} group Iterable of inputs with the same `name` attribute.
* @return {FormValues}
*/
const collectCheckboxGroup = ( group ) => {
object[group[0].name] = [];
group.forEach( input => {
if ( input.checked ) {
object[input.name].push( input.value );
}
} );
return object;
};
if ( input.type === 'checkbox' ) {
const checkboxGroup = element.querySelectorAll( '[name="' + input.name + '"]' );
if ( checkboxGroup.length > 1 ) {
return collectCheckboxGroup( checkboxGroup, input );
}
object[input.name] = input.checked;
return object;
}
// if a radio button is not checked, don't collect it.
if ( input.type === 'radio' && ! input.checked ) {
return object;
}
object[input.name] = input.value;
return object;
};
/**
* Setup a mutationobserver to check for added and removed form fields.
* This especially applies to conditions.
*
* @type {MutationObserver}
*/
const addedRemovedObserver = new MutationObserver( mutations => {
for ( const mutation of mutations ) {
for ( const removedNode of mutation.removedNodes ) {
const nodes = document.createTreeWalker( removedNode, NodeFilter.SHOW_ELEMENT );
while ( nodes.nextNode() ) {
if ( nodes.currentNode.tagName === 'INPUT' || nodes.currentNode.tagName === 'SELECT' ) {
const index = this.changedFormValues.addedNodes.indexOf( nodes.currentNode.name );
if ( index > - 1 ) {
this.changedFormValues.addedNodes.splice( index, 1 );
} else {
this.changedFormValues.removedNodes.push( nodes.currentNode.name );
}
}
}
}
for ( const addedNode of mutation.addedNodes ) {
if ( addedNode.nodeType === Node.TEXT_NODE ) {
continue;
}
const nodes = document.createTreeWalker( addedNode, NodeFilter.SHOW_ELEMENT );
while ( nodes.nextNode() ) {
if ( nodes.currentNode.tagName === 'INPUT' || nodes.currentNode.tagName === 'SELECT' ) {
if ( nodes.currentNode.name === '' ) {
continue;
}
this.changedFormValues.addedNodes.push( nodes.currentNode.name );
}
}
}
}
} );
// attach the mutation observer to the passed element.
addedRemovedObserver.observe( element, {childList: true, subtree: true} );
this.observers.push( addedRemovedObserver );
/**
* Check if there are inputs that have been changed and if their value is different.
*
* @param {Object} reference The initial values when the modal loaded, indexed by name attribute.
* @param {Object} changed The input values that were changed, indexed by name.
*
* @return {boolean}
*/
this.hasChanged = ( reference, changed ) => {
for ( const name in changed ) {
if ( ! reference.hasOwnProperty( name ) || reference[name].toString() !== changed[name].toString() ) {
return true;
}
}
return false;
};
/**
* If the modal is associated with a form and any values have changed, ask for confirmation to navigate away.
* Returns true if the user agrees with termination, false otherwise.
*
* @param {boolean} reload Whether to reload the page on added and removed nodes (needed for the modal). Default false.
*
* @return {boolean}
*/
this.terminationNotice = ( reload = false ) => {
if ( ! this.hasChanged( this.initialFormValues, this.changedFormValues ) ) {
return true;
}
// ask user for confirmation.
if ( window.confirm( window.advadstxt.confirmation ) ) {
// if we have added or removed nodes, we might need to reload the page.
if ( this.changedFormValues.addedNodes.length || this.changedFormValues.removedNodes.length ) {
if ( reload ) {
window.location.reload();
}
return true;
}
// otherwise, we'll replace the values with the previous values.
for ( const name in this.changedFormValues ) {
const input = element.querySelector( '[name="' + name + '"]' );
if ( input === null ) {
continue;
}
if ( input.type === 'checkbox' ) {
input.checked = this.initialFormValues[name];
} else if ( input.type === 'radio' ) {
let value = (this.initialFormValues[name] !== null && this.initialFormValues[name] !== undefined) ? this.initialFormValues[name] : input.value;
element.querySelector( '[name="' + name + '"][value="' + value + '"]' ).checked = true;
} else {
input.value = this.initialFormValues[name];
}
}
return true;
}
return false;
};
/**
* Set the initial values to the current ones, then reset the changed form values
*/
this.resetInitialValues = () => {
if ( this.changedFormValues.addedNodes.length ) {
for ( const name in this.changedFormValues.addedNodes ) {
this.initialFormValues[name] = this.changedFormValues.addedNodes[name];
}
}
if ( this.changedFormValues.removedNodes.length ) {
for ( const name in this.changedFormValues.removedNodes ) {
if ( this.initialFormValues[name] !== undefined ) {
delete ( this.initialFormValues[name] );
}
}
}
for ( const name in this.changedFormValues ) {
if ( 'removedNodes' === name || 'addedNodes' === name ) {
continue;
}
if ( this.initialFormValues[name] !== undefined ) {
this.initialFormValues[name] = this.changedFormValues[name];
}
}
this.changedFormValues = new FormValues();
};
/**
* Collect inputs in this modal and save their initial and changed values (if any).
*/
this.collectValues = () => {
const isDialog = element.tagName === 'DIALOG';
element.querySelectorAll( 'input, select, textarea' ).forEach( input => {
if ( ! input.name.length || blocklist.includes( input.id ) || blocklist.includes( input.name ) ) {
return;
}
// if the element itself is not a dialog but the input is within a dialog, ignore it. This accounts for split forms, e.g. the placements page where some inputs are hidden in a modal dialog.
if ( ! isDialog && input.closest( 'dialog' ) ) {
return;
}
this.initialFormValues = collectInputValue( this.initialFormValues, input );
// if the input is `hidden` no change event gets triggered. Use MutationObservers to check for changes in the value attribute.
if ( input.type === 'hidden' ) {
const hiddenObserver = new MutationObserver( function ( mutations, observer ) {
mutations.forEach( mutation => {
if ( mutation.attributeName === 'value' ) {
mutation.target.dispatchEvent( new Event( 'input' ) );
}
} );
} );
hiddenObserver.observe( element, {
attributes: true,
subtree: true
} );
this.observers.push( hiddenObserver );
}
input.addEventListener( 'input', event => {
this.changedFormValues = collectInputValue( this.changedFormValues, input );
} );
} );
};
};

View File

@@ -0,0 +1,150 @@
(function ( $ ) {
/**
* Button.
*/
$.fn.advads_button = function() {
var $buttonset = jQuery( this );
var $ancestor = $buttonset.parent();
$buttonset.each( function() {
$this = jQuery( this );
if ( $this.data( 'advads_button' ) ) {
return true;
}
$this.data( 'advads_button', true );
var $button = jQuery( this );
var $label = jQuery( 'label[for="' + $button.attr( 'id' ) + '"]', $ancestor );
var type = $button.attr( 'type' );
$button.addClass( 'advads-accessible' );
$label.addClass( 'advads-button' );
$label.wrapInner( '<span class="advads-button-text"></span>' );
if ( $button.is( ':checked' ) ) {
$label.addClass( 'advads-ui-state-active' );
}
$button.on('change', function() {
var $changed = jQuery( this );
var $label = jQuery( 'label[for="' + $changed.attr( 'id' ) + '"]', $ancestor );
if ( type === 'radio' ) {
$ancestor.find( 'label' ).removeClass( 'advads-ui-state-active' );
}
if ( $changed.is( ':checked' ) ) {
$label.addClass( 'advads-ui-state-active' );
} else {
$label.removeClass( 'advads-ui-state-active' );
}
} );
} );
};
/**
* Buttonset.
*/
$.fn.advads_buttonset = function() {
var $that = jQuery( this );
$that.each( function() {
$buttonset = jQuery( this );
if ( $buttonset.data( 'advads_buttonset' ) ) {
return true;
}
$buttonset.data( 'advads_buttonset', true );
var items = 'input[type=checkbox], input[type=radio]';
var $all_buttons = $buttonset.find( items );
if ( ! $all_buttons.length ) {
return;
}
// Show selected checkboxes first.
if ( jQuery.escapeSelector ) {
$items = jQuery();
$all_buttons.filter( ':checked' ).each( function() {
$items = $items.add( $buttonset.find( 'label[for="' + jQuery.escapeSelector( this.id ) + '"]' ) );
$items = $items.add( this );
} );
$items.prependTo( $buttonset );
}
$buttonset.addClass( 'advads-buttonset' );
$all_buttons.advads_button();
} );
};
/**
* Tooltip.
*
* @param {Function} options.content A function that returns the content.
*/
$.fn.advads_tooltip = function( options ) {
var tooltip;
var tooltip_target;
if ( ! options.content ) {
return this;
}
function open( event ) {
var $target = jQuery( event.currentTarget );
// check if the correct tooltip is already open.
if ( tooltip && $target.is( tooltip_target ) ) {
return;
}
if ( tooltip ) {
tooltip.remove();
tooltip = null;
tooltip_target = null;
}
if ( event.type === 'mouseover' ) {
jQuery( $target ).on( 'mouseleave', close );
}
if ( event.type === 'focusin' ) {
jQuery( $target ).on( 'focusout', close );
}
var content = options.content.call( $target )
if ( content ) {
tooltip = $( '<div>' ).addClass( 'advads-tooltip' );
const parent = typeof options.parent === 'function' ? options.parent.call( this, $target ) : 'body';
$( '<div>' ).addClass( 'advads-tooltip-content' ).appendTo( tooltip );
tooltip.appendTo( parent );
tooltip.find( '.advads-tooltip-content' ).html( content );
position = $target.offset();
position.top += $target.outerHeight() + 15;
tooltip.offset( position );
tooltip_target = $target;
tooltip.show();
}
}
function close( event ) {
if ( tooltip ) {
tooltip.remove();
tooltip = null;
tooltip_target = null;
}
};
this.each( function() {
$this = jQuery( this );
if ( $this.data( 'advads_tooltip' ) ) {
return true;
}
$this.data( 'advads_tooltip', true );
$this.on( 'mouseover focusin', open );
} );
};
} )( jQuery );

View File

@@ -0,0 +1,213 @@
/* eslint-disable camelcase */
const advads_wizard = {
box_order: [
// selectors of elements in the wizard in the correct order
'#post-body-content, #ad-types-box', // show title and type together
'#ad-parameters-box',
'#ad-targeting-box', // display and visitor conditions
],
current_box: '#post-body-content, #ad-types-box', // current active box
one_column: false, // whether the edit screen is in one-column mode
status: false, // what is the current status? true if running, else false
init() {
// status can be "start" to start wizard or nothing to not start it
const _this = this;
jQuery('#advads-wizard-controls-next').on('click', function () {
_this.next();
});
jQuery('#advads-wizard-controls-prev').on('click', function () {
_this.prev();
});
jQuery('#advads-wizard-controls-save').on('click', function (e) {
e.preventDefault();
jQuery('#publish').trigger('click');
}); // save ad
jQuery('#advads-wizard-display-conditions-show').on(
'click',
function () {
_this.show_conditions('#ad-targeting-box');
}
);
jQuery('#advads-wizard-visitor-conditions-show').on(
'click',
function () {
_this.show_conditions('#ad-targeting-box');
}
);
jQuery('.advads-show-in-wizard').hide();
jQuery('#advads-start-wizard').on('click', function () {
_this.start();
});
// end wizard when the button was clicked
jQuery('.advads-stop-wizard').on('click', function () {
_this.close();
});
// jump to next box when ad type is selected
jQuery('#advanced-ad-type input').on('change', function () {
_this.next();
});
},
show_current_box() {
jQuery(this.current_box).removeClass('advads-hide');
},
start() {
// do stuff when wizard is started
if (!this.is_form_valid()) {
return;
}
// show page in 1-column stype
this.status = true;
if (jQuery('#post-body').hasClass('columns-1')) {
this.one_column = true;
} else {
jQuery('#post-body').addClass('columns-1').removeClass('columns-2');
}
// hide all boxes, messages and the headline by adding a hide css class
jQuery(
'#post-body-content, .postbox-container .postbox, h1 ~ div:not(.advads-admin-notice):not(#message.updated), h1'
).addClass('advads-hide');
// display first box
this.show_current_box();
// display close button and controls
jQuery('#advads-stop-wizard, #advads-wizard-controls').removeClass(
'hidden'
);
this.update_nav();
// initially hide some elemente
jQuery('#advads-ad-description').addClass('advads-hide'); // ad description
jQuery('#advads-ad-info').addClass('advads-hide'); // shortcode and php function info
// hide all elements with 'advads-hide-for-wizard' class
jQuery('.advads-hide-in-wizard').hide();
jQuery('.advads-show-in-wizard').show();
jQuery('#advads-start-wizard').hide();
// remove close-class from ad type box
jQuery('#ad-types-box').removeClass('closed');
this.save_hide_wizard(false);
},
close() {
// close the wizard by showing all elements again
this.status = false;
jQuery('.advads-hide').removeClass('advads-hide');
jQuery('#advads-stop-wizard, #advads-wizard-controls').addClass(
'hidden'
);
if (this.one_column !== true) {
jQuery('#post-body').addClass('columns-2').removeClass('columns-1');
}
// reset current box
this.current_box = this.box_order[0];
jQuery('#advads-wizard-welcome').remove(); // close wizard welcome message
// show all elements with 'advads-hide-for-wizard' class
jQuery('.advads-hide-in-wizard').show();
jQuery('.advads-show-in-wizard').hide();
jQuery('#advads-start-wizard').show();
this.save_hide_wizard(true);
},
update_nav() {
// update navigation, display only valid buttons
// display all buttons
jQuery('#advads-wizard-controls button').removeClass('hidden');
// hide next button if there is no next widget
const i = this.box_order.indexOf(this.current_box);
if (i === this.box_order.length - 1) {
jQuery('#advads-wizard-controls-next').addClass('hidden');
}
if (i === 0) {
jQuery('#advads-wizard-controls-prev').addClass('hidden');
}
// hide save button for first boxes
if (i <= 1) {
jQuery('#advads-wizard-controls-save').addClass('hidden');
} else {
jQuery('#advads-wizard-controls-save').removeClass('hidden');
}
},
/**
* Check the form just before some of its fields become hidden.
*/
is_form_valid() {
const form = jQuery('form#post')[0];
if (form.checkValidity && form.reportValidity) {
if (!form.checkValidity()) {
// Highlight invalid fields.
form.reportValidity();
return false;
}
return true;
}
// Disable validation so that hidden invalid fields do not prevent the form from being sent.
form.setAttribute('novalidate', true);
return true;
},
next() {
// show next box
if (!this.is_form_valid()) {
return;
}
if (!this.status) {
return;
}
// get index of current item in box-array
const i = this.box_order.indexOf(this.current_box);
// check if there is a next index
if (this.box_order[i + 1] === undefined) {
return;
}
// hide current element
jQuery(this.current_box).addClass('advads-hide');
// load next element into current
this.current_box = this.box_order[i + 1];
this.show_current_box();
this.update_nav();
},
prev() {
// show previous box
if (!this.is_form_valid()) {
return;
}
// get index of current item in box-array
const i = this.box_order.indexOf(this.current_box);
// check if there is a previous index
if (this.box_order[i - 1] === undefined) {
return;
}
// hide current element
jQuery(this.current_box).addClass('advads-hide');
// load next element into current
this.current_box = this.box_order[i - 1];
this.show_current_box();
this.update_nav();
},
save_hide_wizard(hideWizard) {
// update wizard state (started by default or not?)
jQuery.ajax({
type: 'POST',
url: ajaxurl,
data: {
action: 'advads-save-hide-wizard-state',
hideWizard,
nonce: advadsglobal.ajax_nonce,
},
});
},
show_conditions(box) {
// show the conditions options in display and visitor conditions
jQuery(box).find('.advads-show-in-wizard').hide();
jQuery(box).find('.advads-hide-in-wizard').show();
},
};
jQuery(document).ready(function () {
advads_wizard.init();
});

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<advads-export>
<ads type="array">
<item key="0" type="array">
<ID type="string">1</ID>
<post_content type="string">
<![CDATA[<div style="width: 100%; height: 90px; background: #15A2E1; color: #fff; line-height: 90px; text-align: center; ">Example Ad #1 (only visible for logged-in visitors)</div>]]></post_content>
<post_title type="string">Example Ad #1 (only for logged-in visitors)</post_title>
<post_status type="string">publish</post_status>
<meta_input type="array">
<advanced_ads_ad_options type="array">
<visitor type="array"/>
<visitors type="array">
<item key="0" type="array">
<type type="string">loggedin</type>
<operator type="string">is</operator>
</item>
</visitors>
<output type="array">
<allow_php type="string">0</allow_php>
</output>
<type type="string">plain</type>
<width type="numeric">0</width>
<height type="numeric">0</height>
</advanced_ads_ad_options>
</meta_input>
</item>
<item key="1" type="array">
<ID type="string">2</ID>
<post_content type="string">
<![CDATA[<div style="width: 100%; height: 90px; background: #04B404; color: #fff; line-height: 90px; text-align: center; ">Example Ad #2 (only visible for logged-in visitors)</div>]]></post_content>
<post_title type="string">Example Ad #2 (only for logged-in visitors)</post_title>
<post_status type="string">publish</post_status>
<meta_input type="array">
<advanced_ads_ad_options type="array">
<visitor type="array"/>
<visitors type="array">
<item key="0" type="array">
<type type="string">loggedin</type>
<operator type="string">is</operator>
</item>
</visitors>
<output type="array">
<allow_php type="string">0</allow_php>
</output>
<type type="string">plain</type>
<width type="numeric">0</width>
<height type="numeric">0</height>
</advanced_ads_ad_options>
</meta_input>
</item>
</ads>
<placements type="array">
<item key="0" type="array">
<type type="string">post_top</type>
<name type="string">Before Content Placement</name>
<item type="string">ad_1</item>
<key type="string">before-content-placement</key>
</item>
<item key="1" type="array">
<type type="string">post_content</type>
<name type="string">Content Placement after 3rd Paragraph</name>
<item type="string">ad_2</item>
<options type="array">
<position type="string">after</position>
<index type="numeric">3</index>
<tag type="string">p</tag>
<ad_label type="string">default</ad_label>
<placement_position type="string"/>
</options>
<key type="string">content-placement-after-3rd-paragraph</key>
</item>
</placements>
</advads-export>

View File

@@ -0,0 +1,503 @@
<?php
/**
* Array with ad health messages
*
* Attribute: type
* - "notice" (default, recommendation, etc.)
* - "problem" (critical)
*
* attribute: can_hide
* (user can see a button to hide this warning, default: true)
*
* attribute: hide
* (how to handle click on "hide" button)
* - true (default, hide the item)
* - false (remove the item completely from list of notifications)
*
* attribute: timeout
* (for how long to hide/ignore the message in seconds.)
* - default: empty
*
* attribute: get_help_link
* (enter URL, if exists, will add a link after the message)
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
$advanced_ads_ad_health_notices = apply_filters(
'advanced-ads-ad-health-notices',
[
// old PHP version
// checked using Advanced_Ads_Checks::php_version_minimum().
'old_php' => [
'text' => sprintf(
/* translators: %1$s is a version number */
__( 'Your <strong>PHP version (%1$s) is too low</strong>. Advanced Ads is built for PHP %2$s and higher. It might work, but updating PHP is highly recommended. Please ask your hosting provider for more information.', 'advanced-ads' ),
phpversion(),
Advanced_Ads_Checks::MINIMUM_PHP_VERSION
),
'type' => 'problem',
],
// conflicting plugins found
// Advanced_Ads_Checks::conflicting_plugins().
'conflicting_plugins' => [
'text' => sprintf(
/* translators: %1$s is a list of plugin names; %2$s is a target URL */
__( 'Plugins that are known to cause (partial) problems: <strong>%1$s</strong>. <a href="%2$s" target="_blank">Learn more</a>.', 'advanced-ads' ),
implode( ', ', Advanced_Ads_Checks::conflicting_plugins() ),
'https://wpadvancedads.com/manual/known-plugin-conflicts/?utm_source=advanced-ads&utm_medium=link&utm_campaign=error-plugin-conflicts'
),
'type' => 'problem',
],
// PHP extensions missing
// Advanced_Ads_Checks::php_extensions().
'php_extensions_missing' => [
'text' => sprintf(
/* translators: %s is a list of PHP extensions */
__( 'Missing PHP extensions could cause issues. Please ask your hosting provider to enable them: %s', 'advanced-ads' ),
implode( ', ', Advanced_Ads_Checks::php_extensions() )
),
'type' => 'problem',
],
// ads are disabled
// Advanced_Ads_Checks::ads_disabled().
'ads_disabled' => [
'text' => sprintf(
/* translators: %s is a target URL */
__( 'Ads are disabled for all or some pages. See "disabled ads" in <a href="%s">settings</a>.', 'advanced-ads' ),
admin_url( 'admin.php?page=advanced-ads-settings#top#general' )
),
'type' => 'problem',
],
// check if Advanced Ads related constants are enabled
// Advanced_Ads_Checks::get_defined_constants().
'constants_enabled' => [
'text' => '<a href="' . admin_url( 'admin.php?page=advanced-ads-settings#top#support' ) . '">' . esc_html__( 'Advanced Ads related constants enabled', 'advanced-ads' ) . '</a>',
'type' => 'notice',
],
// adblocker assets expired
// Advanced_Ads_Checks::assets_expired().
'assets_expired' => [
'text' => sprintf(
/* translators: %s is a target URL */
__( 'Some assets were changed. Please <strong>rebuild the asset folder</strong> in the <a href="%s">Advanced Ads settings</a> to update the ad blocker disguise.', 'advanced-ads' ),
admin_url( 'admin.php?page=advanced-ads-settings' )
),
'type' => 'problem',
'hide' => true,
],
// missing license codes
// Advanced_Ads_Checks::license_invalid().
'license_invalid' => [
'text' => __( 'One or more license keys for <strong>Advanced Ads add-ons are invalid or missing</strong>.', 'advanced-ads' ) . ' '
. sprintf(
/* translators: %s is a target URL. */
__( 'Please add valid license keys <a href="%s">here</a>.', 'advanced-ads' ),
get_admin_url( null, 'admin.php?page=advanced-ads-settings#top#licenses' )
),
'type' => 'problem',
'hide' => false,
'timeout' => WEEK_IN_SECONDS,
],
// an individual ad expired.
'ad_expired' => [
'text' => __( 'Ad expired', 'advanced-ads' ) . ': ',
'type' => 'notice',
'hide' => false,
],
// a visible ad is used in <head> tags
// is checked in the frontend by Ad Health in Advanced_Ads_Frontend_Checks::can_use_head_placement().
'ad_with_output_in_head' => [
// we keep the %s here and replace it with an empty string, because we use it somewhere else and dont want to create a new string that is basically the same.
'text' => sprintf(
/* translators: %s is empty here, but the string will be followed by a name of an ad unit. */
__( 'Visible ads should not use the Header placement: %s', 'advanced-ads' ),
''
),
'type' => 'notice',
'hide' => false,
'get_help_link' => 'https://wpadvancedads.com/manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=error-visible-ad-in-header#header-ads',
'timeout' => YEAR_IN_SECONDS,
],
// Ad has HTTP, but site uses HTTPS
// check in Ad Health in frontend.
'ad_has_http' => [
'text' => __( 'Your website is using HTTPS, but the ad code contains HTTP and might not work.', 'advanced-ads' ),
'type' => 'notice',
'hide' => false,
'get_help_link' => 'https://wpadvancedads.com/manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=error-https-ads#https-ads',
],
// dummy text for general AdSense issue.
'adsense_issue' => [
// we keep the %s here and replace it with an empty string, because we use it somewhere else and dont want to create a new string that is basically the same.
'text' => __( 'AdSense issue', 'advanced-ads' ),
'type' => 'problem',
],
// AdSense connection error: disapproved account.
'adsense_connect_disapprovedAccount' => [
'text' => __( 'Last AdSense account connection attempt failed.', 'advanced-ads' ) . '&nbsp;' . __( 'Your account was not approved by AdSense.', 'advanced-ads' ) . ' ' . Advanced_Ads_Ad_Health_Notices::get_adsense_error_link( 'disapprovedAccount' ),
'type' => 'problem',
'hide' => false,
],
// AdSense connection error: no adsense account.
'adsense_connect_noAdSenseAccount' => [
'text' => sprintf(
__( 'Last AdSense account connection attempt failed.', 'advanced-ads' ) . '&nbsp;' .
/* translators: %1$s is the opening a tag and %2$s the closing one. */
__( 'Create a new AdSense account %1$shere%2$s.', 'advanced-ads' ) . ' ' . Advanced_Ads_Ad_Health_Notices::get_adsense_error_link( 'noAdSenseAccount' ),
'<a href="https://www.google.com/adsense/start/?utm_source=AdvancedAdsPlugIn&utm_medium=partnerships&utm_campaign=AdvancedAdsPartner1" target="_blank">',
'</a>'
),
'type' => 'problem',
'hide' => false,
],
// AdSense account alert. Missing ads.txt version 1.
'adsense_alert_ALERT_TYPE_ADS_TXT_UNAUTHORIZED' => [
'text' => sprintf(
__( 'One of your sites is missing the AdSense publisher ID in the ads.txt file.', 'advanced-ads' )
. ' <a class="advads-settings-link" href="%s">'
. _x( 'Create one now.', 'related to ads.txt file', 'advanced-ads' ) . '</a>',
admin_url( 'admin.php?page=advanced-ads-settings#general__advads-ads-txt' )
) . ' ' . Advanced_Ads_Ad_Health_Notices::get_adsense_error_link( 'ALERT_TYPE_ADS_TXT_UNAUTHORIZED' ),
'type' => 'problem',
],
// AdSense account alert. . Missing ads.txt version 2.
'adsense_alert_ADS_TXT_MISSING' => [
'text' => sprintf(
__( 'One of your sites is missing the AdSense publisher ID in the ads.txt file.', 'advanced-ads' )
. ' <a class="advads-settings-link" href="%s">'
. _x( 'Create one now.', 'related to ads.txt file', 'advanced-ads' ) . '</a>',
admin_url( 'admin.php?page=advanced-ads-settings#general__advads-ads-txt' )
) . ' ' . Advanced_Ads_Ad_Health_Notices::get_adsense_error_link( 'ADS_TXT_MISSING' ),
'type' => 'problem',
],
// AdSense account alert. . Missing ads.txt version 3.
'adsense_alert_ADS_TXT_ISSUES' => [
'text' => sprintf(
__( 'One of your sites is missing the AdSense publisher ID in the ads.txt file.', 'advanced-ads' )
. ' <a class="advads-settings-link" href="%s">'
. _x( 'Create one now.', 'related to ads.txt file', 'advanced-ads' ) . '</a>',
admin_url( 'admin.php?page=advanced-ads-settings#general__advads-ads-txt' )
) . ' ' . Advanced_Ads_Ad_Health_Notices::get_adsense_error_link( 'ADS_TXT_ISSUES' ),
'type' => 'problem',
],
// AdSense deprecated link units.
'adsense_link_units_deprecated' => [
'text' => __( 'Google AdSense deprecated Link Units. Please choose another format.', 'advanced-ads' )
. ' <a href="https://wpadvancedads.com/adsense-link-units/" target="_blank" rel="noopener">'
. esc_html__( 'Learn more', 'advanced-ads' )
. '</a>',
'type' => 'problem',
],
'nested_the_content_filters' => [
'text' => sprintf(
/* translators: %s is a filter hook, here `the_content`. */
__( '<strong>%s</strong> filter found multiple times.', 'advanced-ads' ),
'the_content'
) . '&nbsp;' . __( 'Advanced Ads uses the outermost of them.', 'advanced-ads' ),
'get_help_link' => 'https://wpadvancedads.com/manual/ad-health/?utm_source=advanced-ads&utm_medium=link&utm_campaign=error-multiple-the-content#the_content_filter_found_multiple_times',
'type' => 'notice',
'hide' => false,
],
// BuddyPress installed.
'buddypress_no_pro' => [
'text' => sprintf(
/* translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one. */
__( 'Learn how to integrate %1$s with Advanced Ads %2$shere%3$s.', 'advanced-ads' ),
'<strong>BuddyPress</strong>',
'<a href="https://wpadvancedads.com/ads-on-buddypress-pages/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-buddypress" target="_blank">',
'</a>'
),
'type' => 'notice',
],
// BuddyBoss installed.
'buddyboss_no_pro' => [
'text' => sprintf(
/* translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one. */
__( 'Learn how to integrate %1$s with Advanced Ads %2$shere%3$s.', 'advanced-ads' ),
'<strong>BuddyBoss</strong>',
'<a href="https://wpadvancedads.com/manual/buddyboss-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-buddyboss" target="_blank">',
'</a>'
),
'type' => 'pitch',
],
// bbPress installed.
'bbpress_no_pro' => [
'text' => sprintf(
/* translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one. */
__( 'Learn how to integrate %1$s with Advanced Ads %2$shere%3$s.', 'advanced-ads' ),
'<strong>bbPress</strong>',
'<a href="https://wpadvancedads.com/ads-in-bbpress/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-bbpress" target="_blank">',
'</a>'
),
'type' => 'notice',
],
// WPML plugin activated.
'WPML_active' => [
'text' => sprintf(
/* translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one. */
__( 'Learn how to integrate %1$s with Advanced Ads %2$shere%3$s.', 'advanced-ads' ),
'<strong>WPML</strong>',
'<a href="https://wpadvancedads.com/translating-ads-wpml/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-WPML" target="_blank">',
'</a>'
),
'type' => 'notice',
'hide' => false,
'timeout' => YEAR_IN_SECONDS,
],
// AMP and Accelerated Mobile Pages plugins.
'AMP_active' => [
'text' => sprintf(
/* translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one. */
__( 'Learn how to integrate %1$s with Advanced Ads %2$shere%3$s.', 'advanced-ads' ),
'<strong>AMP</strong>',
'<a href="https://wpadvancedads.com/manual/ads-on-amp-pages/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-amp" target="_blank">',
'</a>'
),
'type' => 'notice',
'hide' => false,
'timeout' => YEAR_IN_SECONDS,
],
// Hosting on WP Engine
// Advanced_Ads_Checks::wp_engine_hosting().
'wpengine' => [
'text' => sprintf(
/* translators: %s is a service or plugin name */
'<strong>' . __( '%s detected.', 'advanced-ads' ) . '</strong>'
. ' <a href="https://wpadvancedads.com/wp-engine-and-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-wpengine">' . __( 'Learn how this might impact your ad setup.', 'advanced-ads' ) . '</a>',
'WP Engine'
),
'type' => 'notice',
'hide' => false,
'timeout' => YEAR_IN_SECONDS,
],
// Notice about existing ads.txt plugins.
// Advanced_Ads_Checks::ads_txt_plugins().
'ads_txt_plugins_enabled' => [
'text' => sprintf(
/* translators: %s removable ads.txt plugins */
__( 'Advanced Ads handles your ads.txt file automatically. You might be able to <strong>remove %1$s</strong>.', 'advanced-ads' ),
implode( ', ', Advanced_Ads_Checks::ads_txt_plugins() )
),
'type' => 'notice',
'hide' => false,
'timeout' => YEAR_IN_SECONDS,
],
// Notice about plugins that add header or footer code.
// Advanced_Ads_Checks::header_footer_plugins().
'header_footer_plugins_enabled' => [
'text' =>
__( 'Advanced Ads handles header and footer codes.', 'advanced-ads' ) . '&nbsp;' .
sprintf(
/* translators: %s removable header and footer plugins */
__( 'You might be able to <strong>remove %1$s</strong>.', 'advanced-ads' ),
implode( ', ', Advanced_Ads_Checks::header_footer_plugins() )
) . '&nbsp;' .
'<a href="https://wpadvancedads.com/add-header-and-footer-code-wordpress/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-header-footer" target="_blank">' . __( 'Learn how.', 'advanced-ads' ) . '</a>',
'type' => 'notice',
'hide' => false,
'timeout' => YEAR_IN_SECONDS,
],
// GamiPress.
'gamipress_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to target ads on GamiPress websites %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/manual/gamipress-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-gamipres" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Paid Membership Pro.
'pmp_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to manage ads on membership sites running Paid Memberships Pro %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/paid-memberships-pro/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-pmp" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Members plugin.
'members_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to target ads to specific user roles created with the Members plugin %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/members-plugin-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-members" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Members plugin.
'translatepress_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to target ads to multiple languages in TranslatePress %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/translatepress/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-translatepress" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Weglot.
'weglot_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to target ads to multiple languages in Weglot %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/weglot/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-weglot" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// LearnDash.
'learndash' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to integrate ads into LearnDash %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/learndash-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-learndash" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// AAWP.
'aawp' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to auto-inject Amazon Ads with AAWP and Advanced Ads %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/aawp-amazon/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-aawp" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Polylang.
'polylang' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to target ads to multiple languages in Polylang %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/polylang/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-polylang" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// MailPoet.
'mailpoet' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to integrate Advanced Ads in MailPoet Newsletters %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/mailpoet-newsletters/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-mailpoet" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// WP Rocket.
'wp_rocket' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to use WP Rocket with Advanced Ads %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/wp-rocket-adsense/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-wprocket" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Quiz plugins.
'quiz_plugins_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to embed Ads into a Quiz %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/quiz-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-quiz" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Elementor.
'elementor' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to create and implement ads in Elementor %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/elementor-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-elementor" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// SiteOrigin.
'siteorigin' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to embed ads into a website built with the SiteOrigin page builder %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/siteorigin-page-builder/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-siteorigin" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Divi Theme or Divi builder plugin.
'divi_no_pro' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to integrate ads into the Divi theme and Divi builder %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/divi-theme-builder/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-divi" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Divi Theme or Divi builder plugin.
'beaver_builder' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to embed ads into your Beaver Builder website %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/beaver-builder-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-beaverbuilder" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Pagelayer plugin.
'pagelayer' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to embed ads into a website built with Pagelayer %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/pagelayer/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-pagelayer" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// WPBakery Page Builder.
'wpb' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn more about displaying Ads with WPBakery Page Builder %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/visual-composer-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-wpbakery" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
// Newspaper theme.
'newspaper' => [
'text' => sprintf(
/* translators: 1 opening anchor tag, 2 closing tag, 3 icon */
__( 'Learn how to integrate ads into the tagDiv Newspaper theme %1$shere%2$s %3$s', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/tagdiv-newspaper-theme/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-newspaper" target="_blank">',
'</a>',
'<i class="dashicons dashicons-external"></i>'
),
'type' => 'pitch',
],
]
);

View File

@@ -0,0 +1,108 @@
<?php // phpcs:ignore WordPress.Files.FileName
/**
* This represents an external ad unit. Will be used for importing external ads from various ad networks.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
/**
* Class Advanced_Ads_Ad_Network_Ad_Unit
*/
class Advanced_Ads_Ad_Network_Ad_Unit {
/**
* Contains the raw data (typically from a JSON response) for this ad unit
*
* @var string
*/
public $raw;
/**
* The (external) id of this ad unit (e.g. pub-ca... for adsense)
*
* @var string
*/
public $id;
/**
* The display name of the ad
*
* @var string
*/
public $name;
/**
* The type of this ad unit (displayed in list)
*
* @var string
*/
public $display_type;
/**
* The size of this ad unit (displayed in list)
*
* @var string
*/
public $display_size;
/**
* In case of an AdSense ad, this is the id of the ad without the publisher id
* the value will be displayed in the ads list
*
* @var string
*/
public $slot_id;
/**
* A bool that indicates whether an ad is active (inactives will be hidden by default)
*
* @var bool
*/
public $active;
/**
* Advanced_Ads_Ad_Network_Ad_Unit constructor.
*
* @param string $raw raw ad data.
*/
public function __construct( $raw ) {
$this->raw = $raw;
}
/**
* Sort multiple ad units.
*
* @param array $ad_units array of ad units.
* @param string $selected_id ID of the selected ad. Can be taken from the ad network and therefore also a string.
*
* @return array
*/
public static function sort_ad_units( array &$ad_units, $selected_id ) {
$selected_id = absint( $selected_id );
usort(
$ad_units,
function ( $a, $b ) use ( $selected_id ) {
if ( absint( $a->id ) === $selected_id ) {
return - 1;
}
if ( absint( $b->id ) === $selected_id ) {
return 1;
}
if ( $a->is_supported ) {
if ( ! $b->is_supported ) {
return - 1;
}
} elseif ( $b->is_supported ) {
return 1;
}
return strcasecmp( $a->name, $b->name );
}
);
return $ad_units;
}
}

View File

@@ -0,0 +1,468 @@
<?php // phpcs:ignore WordPress.Files.FileName
/**
* This class represents an ad network. It is used to manage the settings and the ad units of an ad network.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Utilities\Conditional;
use AdvancedAds\Framework\Utilities\Params;
/**
* Class Advanced_Ads_Ad_Network
*/
abstract class Advanced_Ads_Ad_Network {
/**
* The identifier will be used for generated ids, names etc.
*
* @var string
*/
protected $identifier;
/**
* The name of the ad network
*
* @var string
*/
protected $name;
/**
* The name of the hook for the advanced ads settings page
*
* @var string
*/
protected $settings_page_hook;
/**
* The WordPress nonce (retrieve with the get_nonce method)
*
* @var string
*/
protected $nonce;
/**
* The networks settings section ID
*
* @var string
*/
protected $settings_section_id;
/**
* The networks settings init hook.
*
* @var string
*/
private $settings_init_hook;
/**
* Advanced_Ads_Ad_Network constructor.
*
* @param string $identifier an identifier that will be used for hooks, settings, ids and much more - MAKE SURE IT IS UNIQUE.
* @param string $name - the (translateable) display name for this ad network.
*/
public function __construct( $identifier, $name ) {
$this->identifier = $identifier;
$this->name = $name;
$this->settings_page_hook = ADVADS_SLUG . '-' . $this->identifier . '-settings-page';
$this->settings_section_id = ADVADS_SLUG . '-' . $this->identifier . '-settings-section';
$this->settings_init_hook = ADVADS_SLUG . '-' . $this->identifier . '-settings-init';
}
/**
* The identifier for this network
*
* @return string
*/
public function get_identifier() {
return $this->identifier;
}
/**
* The display name for this network
*
* @return string
*/
public function get_display_name() {
return $this->name;
}
/**
* The display value for the settings tab
*
* @return string
*/
public function get_settings_tab_name() {
return $this->get_display_name();
}
/**
* URL for the settings page (admin)
*
* @return string
*/
public function get_settings_href() {
return admin_url( 'admin.php?page=advanced-ads-settings#top#' . $this->identifier );
}
/**
* The identifier / name for the javascript file that will be injected.
*
* @return string
*/
public function get_js_library_name() {
return 'advanced-ads-network' . $this->identifier;
}
/**
* Registers this ad network
*/
public function register() {
if ( is_admin() ) {
if ( wp_doing_ajax() ) {
// we need add all the actions for our ajax calls here.
// our ajax method that will trigger an update of the ad units of this network.
add_action( 'wp_ajax_advanced_ads_get_ad_units_' . $this->identifier, [ $this, 'update_external_ad_units' ] );
add_action( 'wp_ajax_advanced_ads_toggle_idle_ads_' . $this->identifier, [ $this, 'toggle_idle_ads' ] );
} else {
// find out if we need to register the settings. this is necessary
// 1) when viewing the settings (admin.php with page="advanced-ads-settings")
// 2) when posting the settings to options.php
// in all other cases, there is nothing to do.
global $pagenow;
$requires_settings = false;
$requires_javascript = false;
if ( 'admin.php' === $pagenow ) {
$page = Params::request( 'page', null );
switch ( $page ) {
case 'advanced-ads-settings':
$requires_settings = true;
$requires_javascript = true;
break;
case 'advanced-ads':
$requires_javascript = true;
break;
default:
break;
}
} elseif ( 'options.php' === $pagenow ) {
$requires_settings = true;
} elseif ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
add_action( 'advanced-ads-ad-pre-save', [ $this, 'sanitize_ad_settings' ], 10, 2 );
if ( 'edit' === Params::get( 'action' ) ) {
$requires_javascript = true;
} elseif ( 'advanced_ads' === Params::request( 'post_type', '' ) ) {
$requires_javascript = true;
}
}
if ( $requires_settings ) {
// register the settings.
add_action( 'advanced-ads-settings-init', [ $this, 'register_settings_callback' ] );
add_filter( 'advanced-ads-setting-tabs', [ $this, 'register_settings_tabs_callback' ] );
}
if ( $requires_javascript ) {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts_callback' ] );
}
}
}
}
/**
* This method will be called for the wp action "advanced-ads-settings-init" and therefore has to be public.
*/
public function register_settings_callback() {
// register new settings.
register_setting(
ADVADS_SLUG . '-' . $this->identifier,
ADVADS_SLUG . '-' . $this->identifier,
[ $this, 'sanitize_settings_callback' ]
);
/**
* Allow Ad Admin to save AdSense options.
*
* @param array $settings Array with allowed options.
*
* @return array
*/
add_filter(
'advanced-ads-ad-admin-options',
function ( $options ) {
$options[] = ADVADS_SLUG . '-' . $this->identifier;
return $options;
}
);
// add a new section.
add_settings_section(
$this->settings_section_id,
'',
'__return_empty_string',
$this->settings_page_hook
);
// register all the custom settings.
$this->register_settings( $this->settings_page_hook, $this->settings_section_id );
do_action( $this->settings_init_hook, $this->settings_page_hook );
}
/**
* Create name of the object used for localized data
*
* @return string
*/
protected function get_localized_script_object_name() {
return $this->identifier . 'AdvancedAdsJS';
}
/**
* Engueue scripts
*/
public function enqueue_scripts_callback() {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
$js_path = $this->get_javascript_base_path();
if ( $js_path ) {
$id = $this->get_js_library_name();
wp_enqueue_script( $id, $js_path, [ 'jquery' ], '1.7.3' ); // phpcs:ignore
// next we have to pass the data.
$data = [
'nonce' => $this->get_nonce(),
];
$data = $this->append_javascript_data( $data );
wp_localize_script( $id, $this->get_localized_script_object_name(), $data );
}
}
/**
* Get a nonce
*
* @return string
*/
public function get_nonce() {
if ( ! $this->nonce ) {
$this->nonce = wp_create_nonce( $this->get_nonce_action() );
}
return $this->nonce;
}
/**
* Returns the action (name) of the nonce for this network
* in some cases you may want to override this method to faciliate
* integration with existing code
*
* @return string
*/
public function get_nonce_action() {
return 'advads-network-' . $this->identifier;
}
/**
* This method will be called for the wp action "advanced-ads-settings-tabs" and therefore has to be public.
* it simply adds a tab for this ad type. if you don't want that just override this method with an empty one.
*
* @param array $tabs tabs on Advanced Ads settings page.
*
* @return array
*/
public function register_settings_tabs_callback( $tabs ) {
$tab_id = $this->identifier;
$tabs[ $tab_id ] = [
'page' => $this->settings_page_hook,
'group' => ADVADS_SLUG . '-' . $this->identifier,
'tabid' => $tab_id,
'title' => $this->get_settings_tab_name(),
];
return $tabs;
}
/**
* Callback to sanitize settings
*
* @param array $options options to be sanitized.
*
* @return mixed
*/
public function sanitize_settings_callback( $options ) {
$options = $this->sanitize_settings( $options );
return $options;
}
/**
* Performs basic security checks for wp ajax requests (nonce, capabilities)
* dies, when a problem was detected
*/
protected function ajax_security_checks() {
if ( ! Conditional::user_can( 'advanced_ads_manage_options' ) ) {
$this->send_ajax_error_response_and_die( __( 'You don\'t have the permission to manage ads.', 'advanced-ads' ) );
}
$nonce = Params::request( 'nonce', '' );
if ( ! wp_verify_nonce( $nonce, $this->get_nonce_action() ) ) {
$this->send_ajax_error_response_and_die( __( 'You sent an invalid request.', 'advanced-ads' ) );
}
}
/**
* Send data via AJAX but dont react on it.
*
* @param bool $json_serializable_response true if data can be serialized.
*/
protected function send_ajax_response_and_die( $json_serializable_response = false ) {
if ( ! $json_serializable_response ) {
$json_serializable_response = new stdClass();
}
header( 'Content-Type: application/json' );
echo wp_json_encode( $json_serializable_response );
die();
}
/**
* Send message via AJAX but dont react on it.
*
* @param string $message message string.
*/
protected function send_ajax_error_response_and_die( $message ) {
header( 'Content-Type: application/json' );
$r = new stdClass();
$r->error = $message;
echo wp_json_encode( $r );
die();
}
/**
* Toggle ad IDs
*/
public function toggle_idle_ads() {
$this->ajax_security_checks();
global $external_ad_unit_id;
$hide_idle_ads = Params::post( 'hide' );
$external_ad_unit_id = Params::post( 'ad_unit_id', '' );
if ( ! $external_ad_unit_id ) {
$external_ad_unit_id = '';
}
ob_start();
$this->print_external_ads_list( $hide_idle_ads );
$ad_selector = ob_get_clean();
$response = [
'status' => true,
'html' => $ad_selector,
];
$this->send_ajax_response_and_die( $response );
}
/**
* When you need some kind of manual ad setup (meaning you can edit the custom inputs of this ad type)
* you should override this method to return true. this results in an additional link (Setup code manually)
*
* @return bool
*/
public function supports_manual_ad_setup() {
return false;
}
/**
* Print a list of ads.
*
* @param bool $hide_idle_ads true to hide idle ids.
*
* @return mixed
*/
abstract public function print_external_ads_list( $hide_idle_ads = true );
/**
* This method will be called via wp AJAX.
* it has to retrieve the list of ads from the ad network and store it as an option
* does not return ad units - use "get_external_ad_units" if you're looking for an array of ad units
*/
abstract public function update_external_ad_units();
/**
* Adds the custom wp settings to the tab for this ad unit
*
* @param string $hook hook for the settings page.
* @param string $section_id settings section ID.
*/
abstract protected function register_settings( $hook, $section_id );
/**
* Sanitize the network specific options
*
* @param array $options the options to sanitize.
*
* @return mixed the sanitizzed options
*/
abstract protected function sanitize_settings( $options );
/**
* Sanitize the settings for this ad network
*
* @param Ad $ad Ad instance.
* @param array $post_data Post data array.
*
* @return void
*/
abstract public function sanitize_ad_settings( Ad $ad, $post_data );
/**
* Get external ad units from the given network.
*
* @return array of ad units (Advanced_Ads_Ad_Network_Ad_Unit)
*/
abstract public function get_external_ad_units();
/**
* Checks if the ad_unit is supported by Advanced Ads.
* this determines wheter it can be imported or not.
*
* @param object $ad_unit ad unit.
*
* @return boolean
*/
abstract public function is_supported( $ad_unit );
/**
* There is no common way to connect to an external account. you will have to implement it somehow, just
* like the whole setup process (usually done in the settings tab of this network). this method provides
* a way to return this account connection
*
* @return boolean true, when an account was successfully connected
*/
abstract public function is_account_connected();
/**
* External ad networks rely on the same javascript base code. however you still have to provide
* a javascript class that inherits from the AdvancedAdsAdNetwork js class
* this has to point to that file, or return false,
* if you don't have to include it in another way (NOT RECOMMENDED!)
*
* @return string path to the javascript file containing the javascriot class for this ad type
*/
abstract public function get_javascript_base_path();
/**
* Our script might need translations or other variables (llike a nonce, which is included automatically)
* add anything you need in this method and return the array
*
* @param array $data holding the data.
*
* @return array the data, that will be passed to the base javascript file containing the AdvancedAdsAdNetwork class
*/
abstract public function append_javascript_data( &$data );
}

View File

@@ -0,0 +1,683 @@
<?php // phpcs:ignoreFile
/**
* Handle add-on licenses
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
use AdvancedAds\Constants;
use AdvancedAds\Utilities\Data;
defined( 'ABSPATH' ) || exit;
/**
* Handle add-on licenses
*/
class Advanced_Ads_Admin_Licenses {
/**
* Advanced_Ads_Admin_Licenses constructor.
*/
private function __construct() {
add_action( 'plugins_loaded', [ $this, 'wp_plugins_loaded' ] );
// todo: check if this is loaded late enough and all add-ons are registered already.
add_filter( 'upgrader_pre_download', [ $this, 'addon_upgrade_filter' ], 10, 3 );
}
/**
* Actions and filter available after all plugins are initialized
*/
public function wp_plugins_loaded() {
add_action( 'http_api_debug', [ $this, 'update_license_after_version_info' ], 10, 5 );
}
/**
* Return an instance of this class.
*
* @return self object A single instance of this class.
*/
public static function get_instance() {
static $instance;
// If the single instance hasn't been set, set it now.
if ( null === $instance ) {
$instance = new self();
}
return $instance;
}
/**
* Save license key
*
* @param string $addon string with add-on identifier.
* @param string $plugin_name name of the add-on.
* @param string $options_slug slug of the option in the database.
* @param string $license_key license key.
*
* @return string
* @since 1.2.0
*/
public function activate_license( $addon = '', $plugin_name = '', $options_slug = '', $license_key = '' ) {
if ( '' === $addon || '' === $plugin_name || '' === $options_slug ) {
return __( 'Error while trying to register the license. Please contact support.', 'advanced-ads' );
}
$license_key = esc_attr( trim( $license_key ) );
if ( '' === $license_key ) {
return __( 'Please enter a valid license key', 'advanced-ads' );
}
if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
}
/**
* We need to remove the mltlngg_get_url_translated filter added by Multilanguage by BestWebSoft, https://wordpress.org/plugins/multilanguage/
* it causes the URL to look much different than it originally is
* we are adding it again later
*/
remove_filter( 'home_url', 'mltlngg_get_url_translated' );
$api_params = [
'edd_action' => 'activate_license',
'license' => $license_key,
'item_id' => Constants::ADDON_SLUGS_ID[ $options_slug ] ?? false,
'item_name' => rawurlencode( $plugin_name ),
'url' => home_url(),
];
/**
* Re-add the filter removed from above
*/
if ( function_exists( 'mltlngg_get_url_translated' ) ) {
add_filter( 'home_url', 'mltlngg_get_url_translated' );
}
// Call the custom API.
$response = wp_remote_post(
Constants::API_ENDPOINT,
[
'timeout' => 15,
'sslverify' => false,
'body' => $api_params,
]
);
// show license debug output if constant is set.
if ( defined( 'ADVANCED_ADS_SHOW_LICENSE_RESPONSE' ) ) {
return '<p><strong>' . esc_html__( 'The license status does not change as long as ADVANCED_ADS_SHOW_LICENSE_RESPONSE is enabled in wp-config.php.', 'advanced-ads' ) . '</strong></p>' .
'<pre>' . print_r( $response, true ) . '</pre>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
/**
* Send the user to our support when his request is blocked by our firewall
*/
$error = $this->blocked_by_firewall( $response );
if ( $error ) {
return $error;
}
if ( is_wp_error( $response ) ) {
$body = wp_remote_retrieve_body( $response );
if ( $body ) {
return $body;
} else {
$curl = curl_version();
return __( 'License couldnt be activated. Please try again later.', 'advanced-ads' ) . " (cURL {$curl['version']})";
}
}
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
// save license status.
if ( ! empty( $license_data->license ) ) {
$this->clear_license_cache();
update_option( $options_slug . '-license-status', $license_data->license, false );
}
if ( ! empty( $license_data->expires ) ) {
$this->clear_license_cache();
update_option( $options_slug . '-license-expires', $license_data->expires, false );
}
// display activation problem.
if ( ! empty( $license_data->error ) ) {
// user friendly texts for errors.
$errors = [
'license_not_activable' => __( 'This is the bundle license key.', 'advanced-ads' ),
'item_name_mismatch' => __( 'This is not the correct key for this add-on.', 'advanced-ads' ),
'no_activations_left' => __( 'There are no activations left.', 'advanced-ads' )
. '&nbsp;'
. sprintf(
/* translators: %1$s is a starting link tag, %2$s is the closing one. */
__( 'You can manage activations in %1$syour account%2$s.', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/account/?utm_source=advanced-ads&utm_medium=link&utm_campaign=settings-licenses-activations-left" target="_blank">',
'</a>'
) . '&nbsp;'
. sprintf(
/* translators: %1$s is a starting link tag, %2$s is the closing one. */
__( '%1$sUpgrade%2$s for more activations.', 'advanced-ads' ),
'<a href="https://wpadvancedads.com/account/upgrades/?utm_source=advanced-ads&utm_medium=link&utm_campaign=settings-licenses-activations-left" target="_blank">',
'</a>'
),
];
$error = isset( $errors[ $license_data->error ] ) ? $errors[ $license_data->error ] : $license_data->error;
if ( 'expired' === $license_data->error ) {
return 'ex';
} else { // phpcs:ignore
if ( isset( $errors[ $license_data->error ] ) ) {
return $error;
} else {
return sprintf(
/* translators: %s is a string containing information about the issue. */
__( 'License is invalid. Reason: %s', 'advanced-ads' ),
$error
);
}
}
} else {
// reset license_expires admin notification.
Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_expires' ); // this one is no longer added, but we keep the check here in case it is still in the queue for some users.
Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_expired' ); // this one is no longer added, but we keep the check here in case it is still in the queue for some users.
Advanced_Ads_Admin_Notices::get_instance()->remove_from_queue( 'license_invalid' );
// save license key.
$licenses = $this->get_licenses();
$licenses[ $addon ] = $license_key;
$this->save_licenses( $licenses );
}
return 1;
}
/**
* Check if a request was blocked by our firewall
*
* @param array $response response from license call.
*
* @return mixed message or false
*/
public function blocked_by_firewall( $response ) {
$response_code = wp_remote_retrieve_response_code( $response );
if ( 403 === $response_code ) {
$blocked_information = '';
if ( isset( $response['body'] ) ) {
// look for the IP address in this line: `<td><span>95.90.238.103</span></td>`.
$pattern = '/<span>([.0-9]*)<\/span>/';
$matches = [];
preg_match( $pattern, $response['body'], $matches );
$ip = isset( $matches[1] ) ? $matches[1] : '';
$blocked_information = 'IP: ' . $ip;
}
/* translators: %s is a list of server information like IP address. Just keep it as is. */
return sprintf( __( 'Your request was blocked by our firewall. Please send us the following information to unblock you: %s.', 'advanced-ads' ), $blocked_information );
}
return false;
}
/**
* Check if a specific license key was already activated for the current page
*
* @param string $license_key license key.
* @param string $plugin_name name of the add-on.
* @param string $options_slug slug of the option in the database.
*
* @return bool true if already activated
* @since 1.6.17
* @deprecated since version 1.7.2 because it only checks if a key is valid, not if the url registered with that key
*/
public function check_license( $license_key = '', $plugin_name = '', $options_slug = '' ) {
if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
}
$api_params = [
'edd_action' => 'check_license',
'license' => $license_key,
'item_id' => Constants::ADDON_SLUGS_ID[ $options_slug ] ?? false,
'item_name' => rawurlencode( $plugin_name ),
];
$response = wp_remote_get(
add_query_arg( $api_params, 'https://wpadvancedads.com/' ),
[
'timeout' => 15,
'sslverify' => false,
]
);
if ( is_wp_error( $response ) ) {
return false;
}
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
// if this license is still valid.
if ( 'valid' === $license_data->license ) {
update_option( $options_slug . '-license-expires', $license_data->expires, false );
update_option( $options_slug . '-license-status', $license_data->license, false );
return true;
}
return false;
}
/**
* Deactivate license key
*
* @param string $addon string with add-on identifier.
* @param string $plugin_name name of the add-on.
* @param string $options_slug slug of the option in the database.
*
* @return string
* @since 1.6.11
*/
public function deactivate_license( $addon = '', $plugin_name = '', $options_slug = '' ) {
if ( '' === $addon || '' === $plugin_name || '' === $options_slug ) {
return __( 'Error while trying to disable the license. Please contact support.', 'advanced-ads' );
}
$licenses = $this->get_licenses();
$license_key = isset( $licenses[ $addon ] ) ? $licenses[ $addon ] : '';
$short_circuit = $this->shortcuit_deactivation( $addon, $options_slug );
if ( false !== $short_circuit ) {
return true;
}
if ( has_filter( 'advanced_ads_license_' . $options_slug ) ) {
return apply_filters( 'advanced_ads_license_' . $options_slug, false, __METHOD__, $plugin_name, $options_slug, $license_key );
}
$api_params = [
'edd_action' => 'deactivate_license',
'license' => $license_key,
'item_id' => Constants::ADDON_SLUGS_ID[ $options_slug ] ?? false,
'item_name' => rawurlencode( $plugin_name ),
];
// Send the remote request.
$response = wp_remote_post(
Constants::API_ENDPOINT,
[
'body' => $api_params,
'timeout' => 15,
'sslverify' => false,
]
);
// show license debug output if constant is set.
if ( defined( 'ADVANCED_ADS_SHOW_LICENSE_RESPONSE' ) ) {
return '<p><strong>' . esc_html__( 'The license status does not change as long as ADVANCED_ADS_SHOW_LICENSE_RESPONSE is enabled in wp-config.php.', 'advanced-ads' ) . '</strong></p>' .
'<pre>' . print_r( $response, true ) . '</pre>'; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
if ( is_wp_error( $response ) ) {
$body = wp_remote_retrieve_body( $response );
if ( $body ) {
return $body;
} else {
return __( 'License couldnt be deactivated. Please try again later.', 'advanced-ads' );
}
}
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
/**
* Send the user to our support when his request is blocked by our firewall
*/
$error = $this->blocked_by_firewall( $response );
if ( $error ) {
return $error;
}
// remove data.
if ( 'deactivated' === $license_data->license ) {
delete_option( $options_slug . '-license-status' );
delete_option( $options_slug . '-license-expires' );
} elseif ( 'failed' === $license_data->license ) {
update_option( $options_slug . '-license-expires', $license_data->expires, false );
update_option( $options_slug . '-license-status', $license_data->license, false );
return 'ex';
} else {
return __( 'License couldnt be deactivated. Please try again later.', 'advanced-ads' );
}
return 1;
}
/**
* Get license keys for all add-ons
*
* @return string[]
*/
public function get_licenses() {
$licenses = get_option( ADVADS_SLUG . '-licenses', [] );
if ( empty( $licenses ) || ! is_array( $licenses ) ) {
$licenses = [];
}
return $licenses;
}
/**
* Save license keys for all add-ons
*
* @param array $licenses licenses.
*/
public function save_licenses( $licenses = [] ) {
update_option( ADVADS_SLUG . '-licenses', $licenses );
}
/**
* Get license status of an add-on
*
* @param string $slug slug of the add-on.
*
* @return string|false license status, "valid", "invalid" or false if option doesn't exist.
*/
public function get_license_status( $slug = '' ) {
return get_option( $slug . '-license-status', false );
}
/**
* If two or more add-ons use the same valid license this is probably an all-access customer
*
* @return bool
*/
public function get_probably_all_access() {
$valid = array_filter(
$this->get_licenses(),
function ( $key ) {
return $this->get_license_status( ADVADS_SLUG . '-' . $key );
},
ARRAY_FILTER_USE_KEY
);
return [] !== $valid && max( array_count_values( $valid ) ) > 1;
}
/**
* Return the licence expiry time if it is equal for more than one add-on. That indicates it is likely an All Access license
*
* @return string|null
*/
public function get_probably_all_access_expiry() {
/**
* Get expiry dates of all add-ons.
*
* @param string $key Add-on key.
*
* @return string|false the expiration date or false.
*/
$expiry_counts = array_count_values(
array_map(
function ( $key ) {
return $this->get_license_expires( ADVADS_SLUG . '-' . $key );
},
array_keys( array_filter( $this->get_licenses() ) )
)
);
/**
* Remove all licenses that are used only once.
*
* @param int $count the count from array_count_values_above
*
* @return bool whether the count is greater 1
*/
$all_access = array_filter(
$expiry_counts,
function ( $count ) {
return $count > 1;
}
);
// if there is an item in $all_access we can assume this is from All Access and return the expiry date.
return empty( $all_access ) ? null : key( $all_access );
}
/**
* Get license expired value of an add-on
*
* @param string $slug slug of the add-on.
*
* @return string $date expiry date of an add-on, empty string if no option exists
*/
public function get_license_expires( $slug = '' ) {
return get_option( $slug . '-license-expires', '' );
}
/**
* Add custom messages to plugin updater
*
* @param bool $reply Whether to bail without returning the package. Default false.
* @param string $package The package file name.
* @param WP_Upgrader $updater The WP_Upgrader instance.
*
* @return string
*
* @todo check if this is still working.
*/
public function addon_upgrade_filter( $reply, $package, $updater ) {
$key = null;
$value = null;
if ( isset( $updater->skin->plugin ) ) {
$key = 'path';
$value = $updater->skin->plugin;
} elseif ( isset( $updater->skin->plugin_info['Name'] ) ) {
$key = 'name';
$value = $updater->skin->plugin_info['Name'];
}
$add_on = $this->get_installed_add_on_by_key( $key, $value );
if ( ! $add_on || ! isset( $add_on['path'] ) ) {
return $reply;
}
$plugin_file = plugin_basename( $add_on['path'] );
if ( wp_doing_ajax() ) {
$update_link = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $plugin_file, 'upgrade-plugin_' . $plugin_file );
/* translators: %s plugin update link */
$updater->strings['download_failed'] = sprintf( __( 'Download failed. <a href="%s">Click here to try another method</a>.', 'advanced-ads' ), $update_link );
} else {
/* translators: %s download failed knowledgebase link */
$updater->strings['download_failed'] = sprintf( __( 'Download failed. <a href="%s" target="_blank">Click here to learn why</a>.', 'advanced-ads' ), 'https://wpadvancedads.com/manual/download-failed-updating-add-ons/#utm_source=advanced-ads&utm_medium=link&utm_campaign=download-failed' );
}
return $reply;
}
/**
* Search if a name is in the add-on array and return the add-on data of it
*
* @param string $key key to search for.
* @param string $value value to search for.
*
* @return array array with the add-on data
*/
private function get_installed_add_on_by_key( $key, $value ) {
// Early bail!!
if ( empty( $key ) || empty( $value ) ) {
return null;
}
$add_ons = Data::get_addons();
if ( is_array( $add_ons ) ) {
foreach ( $add_ons as $add_on ) {
if ( $add_on[ $key ] === $value ) {
return $add_on;
}
}
}
return null;
}
/**
* Check if any license is valid
* can be used to display information for any Pro user only, like link to direct support
*/
public static function any_license_valid() {
$add_ons = Data::get_addons();
if ( [] === $add_ons ) {
return false;
}
foreach ( $add_ons as $_add_on ) {
$status = self::get_instance()->get_license_status( $_add_on['options_slug'] );
// check expiry date.
$expiry_date = self::get_instance()->get_license_expires( $_add_on['options_slug'] );
if (
( $expiry_date && strtotime( $expiry_date ) > time() )
|| 'valid' === $status || 'lifetime' === $expiry_date
) {
return true;
}
}
return false;
}
/**
* Update the license status based on information retrieved from the version info check
*
* @param array|WP_Error $response HTTP response or WP_Error object.
* @param string $context Context under which the hook is fired.
* @param string $http HTTP transport used.
* @param array $parsed_args HTTP request arguments.
* @param string $url The request URL.
* @return array|WP_Error
*/
public function update_license_after_version_info( $response, $context, $http, $parsed_args, $url ) {
// Early bail!!
if (
Constants::API_ENDPOINT !== $url
|| (
empty( $parsed_args['body']['edd_action'] )
|| 'get_version' !== $parsed_args['body']['edd_action']
)
|| is_wp_error( $response )
) {
return $response;
}
$params = json_decode( wp_remote_retrieve_body( $response ) );
if ( empty( $params->name ) ) {
return $response;
}
$new_license_status = null;
$new_expiry_date = null;
// Some of the conditions could happen at the same time,
// though due to different conditions in EDD we are safer to have multiple checks.
if ( isset( $params->valid_until ) ) {
if ( 'invalid' === $params->valid_until ) {
$new_license_status = 'invalid';
}
if ( 'lifetime' === $params->valid_until ) {
$new_license_status = 'valid';
$new_expiry_date = 'lifetime';
}
if ( is_int( $params->valid_until ) ) {
$new_expiry_date = (int) $params->valid_until;
if ( time() < $params->valid_until ) {
$new_license_status = 'valid';
}
}
} elseif ( empty( $params->download_link ) || empty( $params->package ) || isset( $params->msg ) ) {
// If either of these two parameters is missing then the user does not have a valid license according to our store
// If there is a "msg" parameter then the license did also not work for another reason.
$new_license_status = 'invalid';
}
if ( ! $new_license_status && ! $new_expiry_date ) {
return $response;
}
$add_ons = Data::get_addons();
// Look for the add-on with the appropriate license key.
foreach ( $add_ons as $_add_on ) {
if ( ! isset( $_add_on['name'] ) || $params->name !== $_add_on['name'] ) {
continue;
}
$options_slug = $_add_on['options_slug'];
if ( $new_license_status ) {
update_option( $options_slug . '-license-status', $new_license_status, false );
}
if ( $new_expiry_date ) {
if ( 'lifetime' !== $new_expiry_date ) {
$new_expiry_date = gmdate( 'Y-m-d 23:59:49', $new_expiry_date );
}
update_option( $options_slug . '-license-expires', $new_expiry_date, false );
}
// Return with the first match since there should only be one plugin per name.
return $response;
}
return $response;
}
/**
* Shortcuit deactivation
*
* @param string $addon string with add-on identifier.
* @param string $options_slug slug of the option in the database.
*
* @return false
*/
private function shortcuit_deactivation( $addon, $options_slug ) {
$licenses = $this->get_filtered_licenses();
$license_key = isset( $licenses[ $addon ] ) ? $licenses[ $addon ] : '';
$counts = array_count_values( $licenses );
if ( $counts[ $license_key ] > 1 ) {
delete_option( $options_slug . '-license-status' );
delete_option( $options_slug . '-license-expires' );
return __( 'License deactivated. Please try again later.', 'advanced-ads' );
}
return false;
}
/**
* If two or more add-ons use the same valid license this is probably an all-access customer
*
* @return array
*/
private function get_filtered_licenses() {
$filtered = array_filter(
$this->get_licenses(),
function ( $key ) {
return $this->get_license_status( ADVADS_SLUG . '-' . $key );
},
ARRAY_FILTER_USE_KEY
);
return ! is_array( $filtered ) ? [] : $filtered;
}
/**
* Clear the license cache
*
* @param string $slug slug of the add-on.
* @param string $license_key license key.
*/
private function clear_license_cache() {
global $wpdb;
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'advads_edd_sl_%'" );
}
}

View File

@@ -0,0 +1,557 @@
<?php // phpcs:ignore WordPress.Files.FileName
/**
* Container class for admin notices
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
use AdvancedAds\Abstracts\Ad;
use AdvancedAds\Utilities\WordPress;
use AdvancedAds\Utilities\Conditional;
use AdvancedAds\Framework\Utilities\Arr;
/**
* Container class for admin notices
*
* @package WordPress
* @subpackage Advanced Ads Plugin
*/
class Advanced_Ads_Admin_Notices {
/**
* Maximum number of notices to show at once
*/
const MAX_NOTICES = 2;
/**
* Options
*
* @var array
*/
protected $options;
/**
* Notices to be displayed
*
* @var array
*/
public $notices = [];
/**
* Advanced_Ads_Admin_Notices constructor to load notices
*/
public function __construct() {
$this->load_notices();
}
/**
* Return an instance of this class.
*
* @return object A single instance of this class.
*/
public static function get_instance() {
static $instance;
// if the single instance hasn't been set, set it now.
if ( null === $instance ) {
$instance = new self();
}
return $instance;
}
/**
* Determines if a notice can be displayed.
*
* @param string $notice The notice identifier.
*
* @return bool Returns true if the notice can be displayed, false otherwise.
*/
public function can_display( $notice ) {
$options = $this->options();
$closed = $options['closed'] ?? [];
return ! array_key_exists( $notice, $closed );
}
/**
* Load admin notices
*/
public function load_notices() {
$options = $this->options();
$plugin_options = Advanced_Ads::get_instance()->options();
// load notices from queue.
$this->notices = isset( $options['queue'] ) ? $options['queue'] : [];
$notices_before = $this->notices;
// check license notices.
$this->register_license_notices();
// check wizard notice.
$this->register_wizard_notice();
// check non org plugins update.
$this->check_non_org_plugins();
// dont check non-critical notices if they are disabled.
if ( ! isset( $plugin_options['disable-notices'] ) ) {
// check other notices.
$this->check_notices();
}
// register notices in db so they get displayed until closed for good.
if ( $this->notices !== $notices_before ) {
$this->add_to_queue( $this->notices );
}
}
/**
* Check various notices conditions
*/
public function check_notices() {
$internal_options = Advanced_Ads::get_instance()->internal_options();
$now = time();
$activation = ( isset( $internal_options['installed'] ) ) ? $internal_options['installed'] : $now; // activation time.
$options = $this->options();
$closed = isset( $options['closed'] ) ? $options['closed'] : [];
$queue = isset( $options['queue'] ) ? $options['queue'] : [];
$paused = isset( $options['paused'] ) ? $options['paused'] : [];
// offer free add-ons if not yet subscribed.
if ( Conditional::user_can_subscribe( 'nl_free_addons' ) && ! in_array( 'nl_free_addons', $queue, true ) && ! isset( $closed['nl_free_addons'] ) ) {
// get number of ads.
if ( WordPress::get_count_ads() ) {
$this->notices[] = 'nl_free_addons';
}
}
$number_of_ads = 0;
// needed error handling due to a weird bug in the piklist plugin.
try {
$number_of_ads = WordPress::get_count_ads();
} catch ( Exception $e ) { // phpcs:ignore
// no need to catch anything since we just use TRY/CATCH to prevent an issue caused by another plugin.
}
// ask for a review after 2 days and when 3 ads were created and when not paused.
if (
! in_array( 'review', $queue, true )
&& ! isset( $closed['review'] )
&& ( ! isset( $paused['review'] ) || $paused['review'] <= time() )
&& 172800 < ( time() - $activation )
&& 3 <= $number_of_ads
) {
$this->notices[] = 'review';
} elseif ( in_array( 'review', $queue, true ) && 3 > $number_of_ads ) {
$review_key = array_search( 'review', $this->notices, true );
if ( false !== $review_key ) {
unset( $this->notices[ $review_key ] );
}
}
}
/**
* Register license key notices
*/
public function register_license_notices() {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
$options = $this->options();
$queue = isset( $options['queue'] ) ? $options['queue'] : [];
// check license keys.
if ( Advanced_Ads_Checks::licenses_invalid() ) {
if ( ! in_array( 'license_invalid', $queue, true ) ) {
$this->notices[] = 'license_invalid';
}
} else {
$this->remove_from_queue( 'license_invalid' );
}
}
/**
* Register wizard notice.
*/
public function register_wizard_notice() {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
$options = $this->options();
$queue = isset( $options['queue'] ) ? $options['queue'] : [];
if ( Advanced_Ads_Checks::can_launch_wizard() ) {
if ( ! in_array( 'monetize_wizard', $queue, true ) ) {
$this->notices[] = 'monetize_wizard';
}
} else {
$this->remove_from_queue( 'monetize_wizard' );
}
}
/**
* Check for updates of non wp.org plugins
*/
public function check_non_org_plugins() {
if ( ! Conditional::is_screen_advanced_ads() ) {
return;
}
$addons = \AdvancedAds\Constants::ADDONS_NON_COMPATIBLE_VERSIONS;
$plugins = WordPress::get_wp_plugins();
$options = $this->options();
$queue = isset( $options['queue'] ) ? $options['queue'] : [];
$closed = isset( $options['closed'] ) ? $options['closed'] : [];
foreach ( $addons as $version => $slug ) {
$addon = $plugins[ $slug ] ?? null;
if ( ! $addon ) {
continue;
}
$notice = $slug . '_upgrade';
if ( version_compare( $addon['version'], $version, '<=' ) ) {
if ( ! in_array( $notice, $queue, true ) && ! array_key_exists( $notice, $closed ) ) {
$this->notices[] = $notice;
}
} else {
$this->remove_from_queue( $notice );
}
}
}
/**
* Add update notices to the queue of all notices that still needs to be closed
*
* @param mixed $notices one or more notices to be added to the queue.
*
* @since 1.5.3
*/
public function add_to_queue( $notices = 0 ) {
if ( ! $notices ) {
return;
}
// get queue from options.
$options = $this->options();
$queue = isset( $options['queue'] ) ? $options['queue'] : [];
if ( is_array( $notices ) ) {
$queue = array_merge( $queue, $notices );
} else {
$queue[] = $notices;
}
// remove possible duplicated.
$queue = array_unique( $queue );
// update db.
$options['queue'] = $queue;
$this->update_options( $options );
}
/**
* Remove update notice from queue
* move notice into "closed"
*
* @param string $notice notice to be removed from the queue.
*
* @since 1.5.3
*/
public function remove_from_queue( $notice ) {
if ( ! isset( $notice ) ) {
return;
}
// get queue from options.
$options = $this->options();
$options_before = $options;
if ( ! isset( $options['queue'] ) ) {
return;
}
$queue = (array) $options['queue'];
$closed = isset( $options['closed'] ) ? $options['closed'] : [];
$paused = isset( $options['paused'] ) ? $options['paused'] : [];
$key = array_search( $notice, $queue, true );
if ( false !== $key ) {
unset( $queue[ $key ] );
// close message with timestamp.
}
// dont close again twice.
if ( ! isset( $closed[ $notice ] ) ) {
$closed[ $notice ] = time();
}
// remove from pause.
if ( isset( $paused[ $notice ] ) ) {
unset( $paused[ $notice ] );
}
// update db.
$options['queue'] = $queue;
$options['closed'] = $closed;
$options['paused'] = $paused;
// only update if changed.
if ( $options_before !== $options ) {
$this->update_options( $options );
// update already registered notices.
$this->load_notices();
}
}
/**
* Hide any notice for a given time
* move notice into "paused" with notice as key and timestamp as value
*
* @param string $notice notice to be paused.
*/
public function hide_notice( $notice ) {
if ( ! isset( $notice ) ) {
return;
}
// get queue from options.
$options = $this->options();
$options_before = $options;
if ( ! isset( $options['queue'] ) ) {
return;
}
$queue = (array) $options['queue'];
$paused = isset( $options['paused'] ) ? $options['paused'] : [];
$key = array_search( $notice, $queue, true );
if ( false !== $key ) {
unset( $queue[ $key ] );
}
// close message with timestamp in 7 days
// dont close again twice.
if ( ! isset( $paused[ $notice ] ) ) {
$paused[ $notice ] = time() + WEEK_IN_SECONDS;
}
// update db.
$options['queue'] = $queue;
$options['paused'] = $paused;
// only update if changed.
if ( $options_before !== $options ) {
$this->update_options( $options );
// update already registered notices.
$this->load_notices();
}
}
/**
* Display notices
*/
public function display_notices() {
if ( wp_doing_ajax() ) {
return;
}
// register Black Friday 2023 deals.
if ( time() > 1700654400 &&
time() <= 1701172800 && Conditional::is_screen_advanced_ads() ) {
$options = $this->options();
$closed = isset( $options['closed'] ) ? $options['closed'] : [];
if ( ! isset( $closed['bfcm23'] ) ) {
$this->notices[] = 'bfcm23';
}
}
if ( [] === $this->notices ) {
return;
}
include_once ADVADS_ABSPATH . '/admin/includes/notices.php';
// Iterate through notices.
$count = 0;
foreach ( $this->notices as $_notice ) {
if ( isset( $advanced_ads_admin_notices[ $_notice ] ) ) {
$notice = $advanced_ads_admin_notices[ $_notice ];
$text = $advanced_ads_admin_notices[ $_notice ]['text'];
$type = isset( $advanced_ads_admin_notices[ $_notice ]['type'] ) ? $advanced_ads_admin_notices[ $_notice ]['type'] : '';
} else {
continue;
}
// dont display non-global notices on other than plugin related pages.
if (
( ! isset( $advanced_ads_admin_notices[ $_notice ]['global'] ) || ! $advanced_ads_admin_notices[ $_notice ]['global'] )
&& ! Conditional::is_screen_advanced_ads()
) {
continue;
}
// don't display license nag if ADVANCED_ADS_SUPPRESS_PLUGIN_ERROR_NOTICES is defined.
if ( defined( 'ADVANCED_ADS_SUPPRESS_PLUGIN_ERROR_NOTICES' ) && 'plugin_error' === $advanced_ads_admin_notices[ $_notice ]['type'] ) {
continue;
}
$hash = [
'info' => '/admin/views/notices/info.php',
'subscribe' => '/admin/views/notices/subscribe.php',
'plugin_error' => '/admin/views/notices/plugin_error.php',
'promo' => '/admin/views/notices/promo.php',
];
$locate_tempalte = isset( $hash[ $type ] ) ? $hash[ $type ] : '/admin/views/notices/error.php';
include ADVADS_ABSPATH . $locate_tempalte;
// phpcs:disable
// if ( self::MAX_NOTICES === ++$count ) {
// break;
// }
// phpcs:enable
}
}
/**
* Return notices options
*
* @return array $options
*/
public function options() {
if ( ! isset( $this->options ) ) {
$this->options = get_option( ADVADS_SLUG . '-notices', [] );
}
return $this->options;
}
/**
* Update notices options
*
* @param array $options new options.
*/
public function update_options( array $options ) {
// do not allow to clear options.
if ( [] === $options ) {
return;
}
$this->options = $options;
update_option( ADVADS_SLUG . '-notices', $options );
}
/**
* Subscribe to newsletter and autoresponder
*
* @param string $notice slug of the subscription notice to send the correct reply.
*
* @return string
*/
public function subscribe( $notice ) {
if ( ! isset( $notice ) ) {
return '';
}
$user = wp_get_current_user();
if ( '' === $user->user_email ) {
/* translators: %s: is a URL. */
return sprintf( __( 'You dont seem to have an email address. Please use <a href="%s" target="_blank">this form</a> to sign up.', 'advanced-ads' ), 'http://eepurl.com/bk4z4P' );
}
$data = [
'email' => $user->user_email,
'notice' => $notice,
];
$result = wp_remote_post(
'https://wpadvancedads.com/remote/subscribe.php?source=plugin',
[
'method' => 'POST',
'timeout' => 20,
'redirection' => 5,
'httpversion' => '1.1',
'blocking' => true,
'body' => $data,
]
);
if ( is_wp_error( $result ) ) {
return __( 'How embarrassing. The email server seems to be down. Please try again later.', 'advanced-ads' );
}
// Mark as subscribed and move notice from queue.
$this->mark_as_subscribed( $notice );
$this->remove_from_queue( $notice );
/* translators: the first %s is an email address, the seconds %s is a URL. */
return sprintf( __( 'Please check your email (%1$s) for the confirmation message. If you didnt receive one or want to use another email address then please use <a href="%2$s" target="_blank">this form</a> to sign up.', 'advanced-ads' ), $user->user_email, 'http://eepurl.com/bk4z4P' );
}
/**
* Update information that the current user is subscribed
*
* @param string $notice notice slug.
*/
private function mark_as_subscribed( $notice ) {
// Early bail!!
if ( empty( $notice ) || ! Conditional::user_can_subscribe( $notice ) ) {
return;
}
$user_id = get_current_user_id();
$subscribed_notices = get_user_meta( $user_id, 'advanced-ads-subscribed', true );
// backward compatibility.
if ( ! is_array( $subscribed_notices ) ) {
$subscribed_notices = [];
}
$subscribed_notices[ $notice ] = true;
update_user_meta( $user_id, 'advanced-ads-subscribed', $subscribed_notices );
}
/**
* Check if a usesr can be subscribed to our newsletter
* check if is already subscribed or email is invalid
*
* @deprecated version 2.0 use Conditional::user_can_subscribe() instead
*
* @return bool true if user can subscribe
*/
public function user_can_subscribe() {
_deprecated_function( __METHOD__, '2.0', '\AdvancedAds\Utilities\Conditional::user_can_subscribe()' );
return Conditional::user_can_subscribe( 'nl_first_steps' );
}
/**
* Add AdSense tutorial notice
*
* @param Ad $ad ad object.
*/
public function adsense_tutorial( $ad ) {
$options = $this->options();
$_notice = 'nl_adsense';
if ( 'adsense' !== $ad->get_type() || isset( $options['closed'][ $_notice ] ) ) {
return;
}
include ADVADS_ABSPATH . '/admin/includes/notices.php';
if ( ! isset( $advanced_ads_admin_notices[ $_notice ] ) ) {
return;
}
$notice = $advanced_ads_admin_notices[ $_notice ];
$text = $notice['text'];
include ADVADS_ABSPATH . '/admin/views/notices/inline.php';
}
}

View File

@@ -0,0 +1,271 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
use AdvancedAds\Admin\Translation_Promo;
/**
* Container class for callbacks for overview widgets
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*/
class Advanced_Ads_Overview_Widgets_Callbacks {
/**
* In case one wants to inject several dashboards into a page, we will prevent executing redundant javascript
* with the help of this little bool
*
* @var mixed
*/
private static $processed_adsense_stats_js = false;
/**
* When doing ajax request (refreshing the dashboard), we need to have a nonce.
* one is enough, that's why we need to remember it.
*
* @var mixed
*/
private static $gadsense_dashboard_nonce = false;
/**
* Register the plugin overview widgets
*/
public static function setup_overview_widgets() {
// initiate i18n notice.
( new Translation_Promo(
[
'textdomain' => 'advanced-ads',
'plugin_name' => 'Advanced Ads',
'hook' => 'advanced-ads-overview-below-support',
'glotpress_logo' => false, // disables the plugin icon so we dont need to keep up with potential changes.
]
) );
// show errors.
if ( Advanced_Ads_Ad_Health_Notices::notices_enabled() ) {
self::add_meta_box( 'advads_overview_notices', __( 'Notifications', 'advanced-ads' ), 'right', 'render_notices' );
}
self::add_meta_box(
'advads_overview_news',
__( 'Next Steps', 'advanced-ads' ),
'left',
'render_next_steps'
);
self::add_meta_box(
'advads_overview_support',
__( 'Manual & Support', 'advanced-ads' ),
'right',
'render_support'
);
if (
Advanced_Ads_AdSense_Data::get_instance()->is_setup() &&
! Advanced_Ads_AdSense_Data::get_instance()->is_hide_stats()
) {
$disable_link_markup = '<span class="advads-hndlelinks hndle"><a href="' . esc_url( admin_url( 'admin.php?page=advanced-ads-settings#top#adsense' ) ) . '" target="_blank">' . esc_attr__( 'Disable', 'advanced-ads' ) . '</a></span>';
self::add_meta_box(
'advads_overview_adsense_stats',
__( 'AdSense Earnings', 'advanced-ads' ) . $disable_link_markup,
'full',
'render_adsense_stats'
);
}
// add widgets for pro add ons.
self::add_meta_box( 'advads_overview_addons', __( 'Add-Ons', 'advanced-ads' ), 'full', 'render_addons' );
do_action( 'advanced-ads-overview-widgets-after' );
}
/**
* Loads a meta box into output
*
* @param string $id meta box ID.
* @param string $title title of the meta box.
* @param string $position context in which to show the box.
* @param callable $callback function that fills the box with the desired content.
*/
public static function add_meta_box( $id, $title, $position, $callback ) {
ob_start();
call_user_func( [ 'Advanced_Ads_Overview_Widgets_Callbacks', $callback ] );
do_action( 'advanced-ads-overview-widget-content-' . $id, $id );
$content = ob_get_clean();
include ADVADS_ABSPATH . 'admin/views/overview-widget.php';
}
/**
* Render Ad Health notices widget
*/
public static function render_notices() {
Advanced_Ads_Ad_Health_Notices::get_instance()->render_widget();
?>
<script>jQuery( document ).ready( function(){ advads_ad_health_maybe_remove_list(); });</script>
<?php
}
/**
* Render next steps widget
*/
public static function render_next_steps() {
include ADVADS_ABSPATH . 'views/admin/widgets/aa-dashboard/next-steps/widget.php';
}
/**
* Support widget
*/
public static function render_support() {
include ADVADS_ABSPATH . 'views/admin/widgets/aa-dashboard/support.php';
do_action( 'advanced-ads-overview-below-support' );
}
/**
* Adsense stats widget
*/
public static function render_adsense_stats() {
$report_type = 'domain';
$report_filter = get_option( 'advanced-ads-adsense-dashboard-filter', '' );
if ( ! $report_filter ) {
$report_filter = self::get_site_domain();
}
if ( '*' === $report_filter ) {
$report_filter = '';
}
include ADVADS_ABSPATH . 'views/admin/metaboxes/ads/ad-gadsense-dashboard.php';
}
/**
* JavaScript loaded in AdSense stats widget.
*
* @param string $pub_id AdSense publisher ID.
*
* @return string
* @todo move to JS file.
*/
final public static function adsense_stats_js( $pub_id ) {
if ( self::$processed_adsense_stats_js ) {
return;
}
self::$processed_adsense_stats_js = true;
$nonce = self::get_adsense_dashboard_nonce();
?>
<script>
window.gadsenseData = window.gadsenseData || {};
window.Advanced_Ads_Adsense_Report_Helper = window.Advanced_Ads_Adsense_Report_Helper || {};
window.Advanced_Ads_Adsense_Report_Helper.nonce = '<?php echo esc_html( $nonce ); ?>';
gadsenseData['pubId'] = '<?php echo esc_html( $pub_id ); ?>';
</script>
<?php
}
/**
* Return a nonce used in the AdSense stats widget.
*
* @return false|mixed|string
*/
final public static function get_adsense_dashboard_nonce() {
if ( ! self::$gadsense_dashboard_nonce ) {
self::$gadsense_dashboard_nonce = wp_create_nonce( 'advads-gadsense-dashboard' );
}
return self::$gadsense_dashboard_nonce;
}
/**
* Extracts the domain from the site url
*
* @return string the domain, that was extracted from get_site_url()
*/
public static function get_site_domain() {
$site = get_site_url();
preg_match( '|^([\d\w]+://)?([^/]+)|', $site, $matches );
return count( $matches ) > 1 ? $matches[2] : null;
}
/**
* This method is called when the dashboard data is requested via ajax
* it prints the relevant data as json, then dies.
*/
public static function ajax_gadsense_dashboard() {
$post_data = wp_unslash( $_POST );
if ( wp_verify_nonce( $post_data['nonce'], 'advads-gadsense-dashboard' ) === false ) {
wp_send_json_error( 'Unauthorized request', 401 );
}
$report_type = in_array( $post_data['type'], [ 'domain', 'unit' ], true ) ? $post_data['type'] : false;
if ( ! $report_type ) {
wp_send_json_error( 'Invalid arguments', 400 );
}
$report_filter = wp_strip_all_tags( $post_data['filter'] );
$report = new Advanced_Ads_AdSense_Report( $report_type, $report_filter );
if ( $report->get_data()->is_valid() ) {
wp_send_json_success( [ 'html' => $report->get_markup() ] );
}
if ( $report->refresh_report() ) {
wp_send_json_success( [ 'html' => $report->get_markup() ] );
}
$error_message = $report->get_last_api_error();
// Send markup with error info.
wp_send_json_success( [ 'html' => '<div class="error"><p>' . wp_kses_post( $error_message ) . '</p></div>' ] );
}
/**
* Render stats box
*
* @param string $title title of the box.
* @param string $main main content.
* @param string $footer footer content.
*
* @deprecated ?
*/
final public static function render_stats_box( $title, $main, $footer ) {
?>
<div class="advanced-ads-stats-box flex1">
<?php echo $title; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<div class="advanced-ads-stats-box-main">
<?php
// phpcs:ignore
echo $main;
?>
</div>
<?php echo $footer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php
}
/**
* Add-ons box
*
* @param bool $hide_activated if true, hide activated add-ons.
* @param bool $is_dashboard whether it is used in the AA dashboard.
*
* @return void
*/
public static function render_addons( $hide_activated = false, $is_dashboard = true ) {
$box = new \AdvancedAds\Admin\Addon_Box( $hide_activated );
$box->display( $is_dashboard );
}
/**
* Sort by installed add-ons
*
* @param array $a argument a.
* @param array $b argument b.
*
* @return int
*/
protected static function sort_by_order( $a, $b ) {
return $a['order'] - $b['order'];
}
}

View File

@@ -0,0 +1,156 @@
<?php
/**
* Array with admin notices
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
*/
use AdvancedAds\Utilities\WordPress;
if ( ! defined( 'NOTICE_TYPES' ) ) {
define(
'NOTICE_TYPES',
[
'info' => 'info',
'subscribe' => 'subscribe',
'error' => 'plugin_error',
'promo' => 'promo',
]
);
}
// These add-on names correspond to the names in the class of constants from ADDONS_NON_COMPATIBLE_VERSIONS.
$manual_addons = [
'advanced-ads-page-peel' => [
'title' => 'Advanced Ads Page Peel',
'zip' => esc_url( 'https://wpadvancedads.com/wp-content/uploads/advanced-ads-page-peel.zip' ),
'link' => esc_url( 'https://wpadvancedads.com/manual/how-to-install-an-add-on/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-update-pagepeel-a220' ),
],
'advanced-ads-browser-language' => [
'title' => 'Advanced Ads Browser Language Visitor Condition',
'zip' => esc_url( 'https://wpadvancedads.com/wp-content/uploads/advanced-ads-browser-language.zip' ),
'link' => esc_url( 'https://wpadvancedads.com/manual/how-to-install-an-add-on/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-update-browserlang-a220' ),
],
'slider-ads' => [
'title' => 'Advanced Ads Ad Slider',
'zip' => esc_url( 'https://wpadvancedads.com/wp-content/uploads/advanced-ads-slider.zip' ),
'link' => esc_url( 'https://wpadvancedads.com/manual/how-to-install-an-add-on/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-update-adslider-a220' ),
],
];
$advanced_ads_admin_notices = [
// email tutorial.
'nl_first_steps' => [
'type' => NOTICE_TYPES['subscribe'],
'text' => __( 'Thank you for activating <strong>Advanced Ads</strong>. Would you like to receive the first steps via email?', 'advanced-ads' ),
'confirm_text' => __( 'Yes, send it', 'advanced-ads' ),
'global' => true,
],
// free add-ons.
'nl_free_addons' => [
'type' => NOTICE_TYPES['subscribe'],
'text' => __( 'Hey, welcome to Advanced Ads! Join our newsletter and snag <strong>2 free add-ons</strong> plus our email intro course. Its the perfect way to get started smoothly!', 'advanced-ads' ),
'confirm_text' => __( 'Subscribe me now', 'advanced-ads' ),
'global' => false,
],
// adsense newsletter group.
'nl_adsense' => [
'type' => NOTICE_TYPES['subscribe'],
'text' => __( 'Learn more about how and <strong>how much you can earn with AdSense</strong> and Advanced Ads from my dedicated newsletter.', 'advanced-ads' ),
'global' => true,
],
// missing license codes.
'license_invalid' => [
'type' => NOTICE_TYPES['error'],
'text' => __( 'One or more license keys for <strong>Advanced Ads add-ons are invalid or missing</strong>.', 'advanced-ads' ) . ' '
/* translators: %s is a target URL. */
. sprintf( __( 'Please add valid license keys <a href="%s">here</a>.', 'advanced-ads' ), get_admin_url( null, 'admin.php?page=advanced-ads-settings#top#licenses' ) ),
],
// please review.
'review' => [
'type' => NOTICE_TYPES['info'],
// 'text' => '<img src="' . ADVADS_BASE_URL . 'admin/assets/img/thomas.png" alt="Thomas" width="80" height="115" class="advads-review-image"/>'
'text' => '<div style="float: left; font-size: 4em; line-height: 1em; margin-right: 0.5em;">' . WordPress::get_count_ads() . '</div>'
. '<div style="float:left;">'
. '<p>' . __( '… ads created using <strong>Advanced Ads</strong>.', 'advanced-ads' ) . '</p>'
. '<p>' . __( 'Do you find the plugin useful and would like to thank us for updates, fixing bugs and improving your ad setup?', 'advanced-ads' ) . '</p>'
. '<p>' .
/* translators: this belongs to our message asking the user for a review. You can find a nice equivalent in your own language. */
__( 'When you give 5-stars, an actual person does a little happy dance!', 'advanced-ads' ) . '</p>'
. '<p>'
. '<span class="dashicons dashicons-external"></span>&nbsp;<strong><a href="https://wordpress.org/support/plugin/advanced-ads/reviews/?rate=5#new-post" target=_"blank">' . __( 'Sure, I appreciate your work', 'advanced-ads' ) . '</a></strong>'
. ' &nbsp;&nbsp;<span class="dashicons dashicons-sos"></span>&nbsp;<a href="https://wpadvancedads.com/support/?utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-review" target=_"blank">' . __( 'Yes, but help me first to solve a problem, please', 'advanced-ads' ) . '</a>'
. '</p></div>',
'global' => false,
],
// Black Friday 2023 promotion.
'bfcm23' => [
'type' => NOTICE_TYPES['promo'],
'text' => sprintf(
/* translators: %1$s is the markup for the discount value, %2$s starts a button link, %3$s closes the button link. */
__( 'Save %1$s on all products with our Black Friday / Cyber Monday offer! %2$sGet this deal%3$s', 'advanced-ads' ),
'<span style="font-weight: bold; font-size: 1.6em; vertical-align: sub;">30%</span>',
'<a class="button button-primary" target="_blank" href="https://wpadvancedads.com/pricing/?utm_source=advanced-ads&utm_medium=link&utm_campaign=bfcm-2023">',
'</a>'
),
'global' => true,
],
'monetize_wizard' => [
'type' => NOTICE_TYPES['info'],
'text' => sprintf(
wp_kses_post(
/* translators: %s: URL to the Advanced Ads onboarding wizard. */
__( 'Quickly set up Advanced Ads and monetize your website with just a few clicks. <a class="button button-primary" href="%s">Launch the wizard</a>', 'advanced-ads' )
),
admin_url( 'admin.php?page=advanced-ads-onboarding' )
),
],
];
// Add specific notifications for plugins that are incompatible with Advanced Ads 2.0.
foreach ( \AdvancedAds\Constants::ADDONS_NON_COMPATIBLE_VERSIONS as $version => $addon ) {
if ( isset( $manual_addons[ $addon ] ) ) {
$advanced_ads_admin_notices[ $addon . '_upgrade' ] = [
'type' => NOTICE_TYPES['info'],
'text' => sprintf(
wp_kses(
/* translators: %1$s: URL to the plugin file, %2$s: URL to the guide */
__( 'Your automatically deactivated version of <strong>%1$s needs to be updated manually</strong>. Please <a href="%2$s" target="_blank">download the newest plugin file</a> and follow our guide on <a href="%3$s" target="_blank">How to install an add-on</a>.', 'advanced-ads' ),
[
'strong' => [],
'a' => [
'href' => [],
'target' => [],
],
]
),
$manual_addons[ $addon ]['title'],
$manual_addons[ $addon ]['zip'],
$manual_addons[ $addon ]['link'],
),
'global' => true,
];
} else {
$advanced_ads_admin_notices[ $addon . '_upgrade' ] = [
'type' => NOTICE_TYPES['info'],
'text' => sprintf(
wp_kses(
/* translators: %1$s: URL to the plugin file, %2$s: URL to the guide */
__( 'Your version of <strong>%1$s</strong> is incompatible with <strong>Advanced Ads %2$s</strong> and has been deactivated. Please update the plugin to the latest version.', 'advanced-ads' ),
[
'strong' => [],
]
),
ucwords( str_replace( '-', ' ', $addon ) ),
ADVADS_VERSION,
),
'global' => true,
];
}
}
$advanced_ads_admin_notices = apply_filters(
'advanced-ads-notices',
$advanced_ads_admin_notices
);

View File

@@ -0,0 +1,27 @@
<?php
/**
* Render select field for matching-technique of string-based Display Conditions
*
* @package AdvancedAds
* @author Thomas Maier <support@wpadvancedads.com>
* @license GPL-2.0+
* @link https://wpadvancedads.com
* @copyright since 2013 Thomas Maier, Advanced Ads GmbH
*
* @var string $name option name.
* @var string $operator value of the $operator option.
*/
?>
<select name="<?php echo esc_attr( $name ); ?>[operator]">
<option value="contain" <?php selected( 'contain', $operator ); ?>><?php esc_attr_e( 'contains', 'advanced-ads' ); ?></option>
<option value="start" <?php selected( 'start', $operator ); ?>><?php esc_attr_e( 'starts with', 'advanced-ads' ); ?></option>
<option value="end" <?php selected( 'end', $operator ); ?>><?php esc_attr_e( 'ends with', 'advanced-ads' ); ?></option>
<option value="match" <?php selected( 'match', $operator ); ?>><?php esc_attr_e( 'matches', 'advanced-ads' ); ?></option>
<option value="regex" <?php selected( 'regex', $operator ); ?>><?php esc_attr_e( 'matches regex', 'advanced-ads' ); ?></option>
<option value="contain_not" <?php selected( 'contain_not', $operator ); ?>><?php esc_attr_e( 'does not contain', 'advanced-ads' ); ?></option>
<option value="start_not" <?php selected( 'start_not', $operator ); ?>><?php esc_attr_e( 'does not start with', 'advanced-ads' ); ?></option>
<option value="end_not" <?php selected( 'end_not', $operator ); ?>><?php esc_attr_e( 'does not end with', 'advanced-ads' ); ?></option>
<option value="match_not" <?php selected( 'match_not', $operator ); ?>><?php esc_attr_e( 'does not match', 'advanced-ads' ); ?></option>
<option value="regex_not" <?php selected( 'regex_not', $operator ); ?>><?php esc_attr_e( 'does not match regex', 'advanced-ads' ); ?></option>
</select>

View File

@@ -0,0 +1,22 @@
<?php
/**
* Render preview information for the image ad type
*
* @var string $src image source URL.
* @var string $alt alt attribute value.
* @var string $preview_hwstring width and height information for the smaller preview icon.
* @var string $tooltip_hwstring width and height information for the larger version in the tooltip.
*/
?>
<span class="advads-ad-list-tooltip">
<span class="advads-ad-list-tooltip-content">
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $hwstring is not something we can escape.
printf( '<img src="%s" alt="%s" %s/>', esc_url( $src ), esc_attr( $alt ), $tooltip_hwstring );
?>
</span>
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $hwstring is not something we can escape.
printf( '<img src="%s" alt="%s" %s/>', esc_url( $src ), esc_attr( $alt ), $preview_hwstring );
?>
</span>

View File

@@ -0,0 +1,40 @@
<?php
/**
* A couple of checks to see if there is any critical issue
* listed on support and settings page
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.2
*/
$messages = [];
if ( Advanced_Ads_Ad_Health_Notices::has_visible_problems() ) {
$messages[] = sprintf(
/* translators: %1$s is a starting link tag, %2$s is closing the link tag. */
esc_attr__( 'Advanced Ads detected potential problems with your ad setup. %1$sShow me these errors%2$s', 'advanced-ads' ),
'<a href="' . admin_url( 'admin.php?page=advanced-ads' ) . '">',
'</a>'
);
}
$messages = apply_filters( 'advanced-ads-support-messages', $messages );
if ( count( $messages ) ) :
?><div class="message error">
<?php
foreach ( $messages as $_message ) :
?>
<p>
<?php
// phpcs:ignore
echo $_message;
?>
</p>
<?php
endforeach;
?>
</div>
<?php
endif;

View File

@@ -0,0 +1,74 @@
<?php
/**
* Template for the Author display condition
*
* @package AdvancedAds
*
* @var string $name Form name attribute.
* @var int $max_authors Number of maximum author entries to show.
*/
?>
<div class="advads-conditions-single advads-buttonset">
<?php
if ( count( $authors ) >= $max_authors ) :
// show active authors.
?>
<div class="advads-conditions-authors-buttons dynamic-search">
<?php
foreach ( $authors as $_author ) :
// dont use strict comparision because $values contains strings.
if ( in_array( $_author->ID, $values ) ) : // phpcs:ignore
$author_name = $_author->display_name;
$field_id = 'advads-conditions-' . absint( $_author->ID ) . $rand;
?>
<label class="button advads-button advads-ui-state-active">
<span class="advads-button-text">
<?php echo esc_attr( $author_name ); ?>
<input type="hidden"
name="<?php echo esc_attr( $name ); ?>[value][]"
value="<?php echo absint( $_author->ID ); ?>">
</span>
</label>
<?php
endif;
endforeach;
?>
</div>
<span class="advads-conditions-authors-show-search button" title="<?php echo esc_html_x( 'add more authors', 'display the authors search field on ad edit page', 'advanced-ads' ); ?>">
+
</span>
<br/>
<input type="text" class="advads-conditions-authors-search"
data-input-name="<?php echo esc_attr( $name ); ?>[value][]"
placeholder="<?php esc_html_e( 'author name or id', 'advanced-ads' ); ?>"/>
<?php
else :
$max_counter = $max_authors;
foreach ( $authors as $_author ) {
if ( $max_counter <= 0 ) {
return false;
}
--$max_counter;
// dont use strict comparision because $values contains strings.
if ( in_array( $_author->ID, $values ) ) { // phpcs:ignore
$_val = 1;
} else {
$_val = 0;
}
$author_name = $_author->display_name;
$field_id = 'advads-conditions-' . absint( $_author->ID ) . $rand;
?>
<label class="button advads-button"
for="<?php echo esc_attr( $field_id ); ?>">
<?php echo esc_attr( $author_name ); ?>
</label><input type="checkbox"
id="<?php echo esc_attr( $field_id ); ?>"
name="<?php echo esc_attr( $name ); ?>[value][]" <?php checked( $_val, 1 ); ?>
value="<?php echo absint( $_author->ID ); ?>">
<?php
}
include ADVADS_ABSPATH . 'admin/views/conditions/not-selected.php';
endif;
?>
</div>

View File

@@ -0,0 +1,35 @@
<?php
/**
* Template for the Device visitor condition
*
* @package AdvancedAds
*
* @var string $name Form name attribute.
* @var string $operator The operator, should be one of `is` or `is_not`.
* @var array $type_options Array with additional information.
* @var array $options The options for the current condition.
* @var int $index The zero-based index for the current condition.
*/
?>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[type]" value="<?php echo esc_attr( $options['type'] ); ?>"/>
<div class="advads-conditions-single advads-buttonset">
<?php
$rand = uniqid();
foreach ( $type_options[ $options['type'] ]['device_types'] as $device_type ) :
$input_id = 'advads-visitor-conditions-device-' . $index . '-' . $device_type['id'] . '-' . $rand;
?>
<label for="<?php echo esc_attr( $input_id ); ?>" class="button advads-button">
<?php echo esc_html( $device_type['label'] ); ?>
</label>
<input type="checkbox" id="<?php echo esc_attr( $input_id ); ?>" name="<?php echo esc_attr( $name ); ?>[value][]" value="<?php echo esc_attr( $device_type['id'] ); ?>" <?php checked( $device_type['checked'] ); ?>>
<?php endforeach; ?>
<?php include ADVADS_ABSPATH . 'admin/views/conditions/not-selected.php'; // phpcs:ignore ?>
</div>
<?php
printf(
'<p class="description"><a href="%1$s" class="advads-manual-link" target="_blank">%2$s</a></p>',
esc_url( $type_options[ $options['type'] ]['helplink'] ),
esc_html__( 'Manual', 'advanced-ads' )
);

View File

@@ -0,0 +1,32 @@
<?php
/**
* Template for a condition that only contains of an is/is_not choice.
*
* @package AdvancedAds
*
* @var string $name form field name attribute.
* @var string $operator operator.
* @var array $type_options additional options for the condition.
*/
?>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[type]" value="<?php echo esc_attr( $options['type'] ); ?>"/>
<?php // Note: placeholder tag so it's not considered empty condition. ?>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[value]" value="1">
<?php
require ADVADS_ABSPATH . 'admin/views/conditions/condition-operator.php';
?>
<p class="description">
<?php echo esc_html( $type_options[ $options['type'] ]['description'] ); ?>
<?php
if ( isset( $type_options[ $options['type'] ]['helplink'] ) ) {
printf(
'<a href="%1$s" class="advads-manual-link" target="_blank">%2$s</a>',
esc_url( $type_options[ $options['type'] ]['helplink'] ),
esc_html__( 'Manual', 'advanced-ads' )
);
}
?>
</p>

View File

@@ -0,0 +1,26 @@
<?php
/**
* Template to select number-based conditions.
*
* @var string $name form name attribute.
* @var string $operator operator.
* @var array $type_options array with information. We get the description of the condition from here.
*/
?>
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[type]" value="<?php echo esc_attr( $options['type'] ); ?>"/>
<select name="<?php echo esc_attr( $name ); ?>[operator]">
<option
value="is_equal" <?php selected( 'is_equal', $operator ); ?>><?php esc_html_e( 'equal', 'advanced-ads' ); ?></option>
<option
value="is_higher" <?php selected( 'is_higher', $operator ); ?>><?php esc_html_e( 'equal or higher', 'advanced-ads' ); ?></option>
<option
value="is_lower" <?php selected( 'is_lower', $operator ); ?>><?php esc_html_e( 'equal or lower', 'advanced-ads' ); ?></option>
</select><input type="number" name="<?php echo esc_attr( $name ); ?>[value]" value="<?php echo absint( $value ); ?>"/>
<p class="description">
<?php echo esc_html( $type_options[ $options['type'] ]['description'] ); ?>
<?php if ( isset( $type_options[ $options['type'] ]['helplink'] ) ) : ?>
<a href="<?php echo esc_url( $type_options[ $options['type'] ]['helplink'] ); ?>" class="advads-manual-link" target="_blank">
<?php esc_html_e( 'Manual', 'advanced-ads' ); ?>
</a>
<?php endif; ?>
</p>

View File

@@ -0,0 +1,15 @@
<?php
/**
* Template for the is/is_not operator used in many conditions.
*
* @package AdvancedAds
* @var string $name form field name attribute.
* @var string $operator operator value.
*/
?>
<select name="<?php echo esc_attr( $name ); ?>[operator]">
<option value="is" <?php selected( 'is', $operator ); ?>><?php esc_html_e( 'is', 'advanced-ads' ); ?></option>
<option
value="is_not" <?php selected( 'is_not', $operator ); ?>><?php esc_html_e( 'is not', 'advanced-ads' ); ?></option>
</select>

View File

@@ -0,0 +1,11 @@
<input type="hidden" name="<?php echo esc_attr( $name ); ?>[type]" value="<?php echo esc_attr( $options['type'] ); ?>"/>
<div class="advads-condition-line-wrap">
<?php include ADVADS_ABSPATH . 'admin/views/ad-conditions-string-operators.php'; ?>
<input type="text" name="<?php echo esc_attr( $name ); ?>[value]" value="<?php echo esc_attr( $value ); ?>"/>
</div>
<p class="description">
<?php echo esc_html( $type_options[ $options['type'] ]['description'] ); ?>
<?php if ( isset( $type_options[ $options['type'] ]['helplink'] ) ) : ?>
<a href="<?php echo esc_url( $type_options[ $options['type'] ]['helplink'] ); ?>" class="advads-manual-link" target="_blank"><?php esc_html_e( 'Manual', 'advanced-ads' ); ?></a>
<?php endif; ?>
</p>

View File

@@ -0,0 +1,39 @@
<fieldset data-condition-list-target="<?php echo esc_attr( $list_target ); ?>"
data-condition-form-name="<?php echo esc_attr( $form_name ); ?>"
data-condition-action="<?php echo esc_attr( $action ); ?>"
data-condition-connector-default="<?php echo esc_attr( $connector_default ); ?>"
<?php
if ( $empty_options ) :
?> class="advads-hide-in-wizard"<?php
endif;
?>>
<legend><?php esc_attr_e( 'New condition', 'advanced-ads' ); ?></legend>
<input type="hidden" class="advads-conditions-index"
value="<?php echo is_array( $set_conditions ) ? count( $set_conditions ) : 0; ?>"/>
<div class="advads-conditions-new">
<select>
<option value=""><?php esc_attr_e( '-- choose a condition --', 'advanced-ads' ); ?></option>
<?php foreach ( $conditions as $_condition_id => $_condition ) : ?>
<?php if ( empty( $_condition['disabled'] ) ) : ?>
<option value="<?php echo esc_attr( $_condition_id ); ?>"><?php echo esc_html( $_condition['label'] ); ?></option>
<?php endif; ?>
<?php
endforeach;
if ( isset( $pro_conditions ) && count( $pro_conditions ) ) :
?>
<optgroup label="<?php esc_attr_e( 'Add-On features', 'advanced-ads' ); ?>">
<?php
foreach ( $pro_conditions as $_pro_condition ) :
?>
<option disabled="disabled"><?php echo esc_html( $_pro_condition ); ?></option>
<?php
endforeach;
?>
</optgroup>
<?php
endif;
?>
</select>
<span class="advads-loader" style="display: none;"></span>
</div>
</fieldset>

View File

@@ -0,0 +1,100 @@
<?php
/**
* HTML code to show all the conditions in metabox
*
* @package AdvancedAds
*/
?>
<table id="<?php echo esc_attr( $list_target ); ?>" class="advads-conditions-table">
<tbody>
<?php
$last_index = - 1;
$i = 0;
if ( is_array( $set_conditions ) ) :
foreach ( $set_conditions as $_index => $_options ) :
$show_or_force_warning = false;
$show_is_not_or_warning = false;
// get type attribute from previous option format.
$_options['type'] = isset( $_options['type'] ) ? $_options['type'] : $_index;
$connector = ( ! isset( $_options['connector'] ) || 'or' !== $_options['connector'] ) ? 'and' : 'or';
$operator = ! isset( $_options['operator'] ) || 'is_not' !== $_options['operator'] ? 'is' : 'is_not';
if ( isset( $_options['type'] ) && isset( $conditions[ $_options['type'] ]['metabox'] ) ) {
$metabox = $conditions[ $_options['type'] ]['metabox'];
} else {
continue;
}
if ( method_exists( $metabox[0], $metabox[1] ) ) {
/**
* Show warning for connector when
* not set to OR already
* this condition and the previous are on page level and not from the identical type
* they are both set to SHOW
*/
$taxonomy = isset( $_options['type'] ) && isset( $conditions[ $_options['type'] ]['taxonomy'] ) ? $conditions[ $_options['type'] ]['taxonomy'] : false; // phpcs:ignore
$last_tax = isset( $set_conditions[ $last_index ]['type'] ) && isset( $conditions[ $set_conditions[ $last_index ]['type'] ]['taxonomy'] ) ? $conditions[ $set_conditions[ $last_index ]['type'] ]['taxonomy'] : false;
if (
$taxonomy && $last_tax && $last_tax === $taxonomy
&& ( ! isset( $_options['connector'] ) || 'or' !== $_options['connector'] )
&& 'is' === $operator && 'is' === $set_conditions[ $last_index ]['operator']
&& $_options['type'] !== $set_conditions[ $last_index ]['type']
) {
$show_or_force_warning = true;
}
if (
'is_not' === $operator
&& 'or' === $connector
&& isset( $set_conditions[ $last_index ]['operator'] )
&& 'is_not' === $set_conditions[ $last_index ]['operator']
) {
$show_is_not_or_warning = true;
}
if ( $i > 0 ) :
?>
<tr class="advads-conditions-connector advads-conditions-connector-<?php echo esc_attr( $connector ); ?>">
<td colspan="3">
<?php
echo Advanced_Ads_Display_Conditions::render_connector_option( $i, $connector, $form_name ); // phpcs:ignore
if ( $show_or_force_warning || $show_is_not_or_warning ) {
?>
<p class="advads-notice-inline advads-error" style="display: block;">
<?php
if ( $show_or_force_warning ) {
esc_attr_e( 'Forced to OR.', 'advanced-ads' );
echo '&nbsp;<a target="_blank" href="https://wpadvancedads.com/manual/display-conditions#manual-combining-multiple-conditions">' . esc_attr__( 'manual', 'advanced-ads' ) . '</a>';
} else {
esc_attr_e( 'The ad might always show due to OR and "is not". Better use AND.', 'advanced-ads' );
echo '&nbsp;<a target="_blank" href="https://wpadvancedads.com/manual/display-conditions/#Combining_conditions_with_AND_and_OR">' . esc_attr__( 'manual', 'advanced-ads' ) . '</a>';
}
?>
</p>
<?php
}
?>
</td>
</tr>
<?php endif; ?>
<tr>
<td class="advads-conditions-type"
data-condition-type="<?php echo esc_attr( $_options['type'] ); ?>"><?php echo esc_html( $conditions[ $_options['type'] ]['label'] ); ?>
</td>
<td>
<?php
call_user_func( [ $metabox[0], $metabox[1] ], $_options, $i++, $form_name );
?>
</td>
<td>
<button type="button" class="advads-conditions-remove button">x</button>
</td>
</tr>
<?php
}
$last_index = $_index;
endforeach;
endif;
?>
</tbody>
</table>

View File

@@ -0,0 +1,21 @@
<?php
/**
* View to show a notice when no terms are available for a taxonomy.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.2
*
* @var WP_Taxonomy $taxonomy
*/
?>
<p class="advads-conditions-not-selected advads-notice-inline advads-idea">
<?php
printf(
/* translators: %s is a name of a taxonomy. */
esc_html_x( 'No %s found on your site.', 'Error message shown when no terms exists for display condition; placeholder is taxonomy label.', 'advanced-ads' ),
esc_html( $taxonomy->label )
);
?>
</p>

View File

@@ -0,0 +1,3 @@
<p class="advads-conditions-not-selected advads-notice-inline advads-error">
<?php echo esc_html_x( 'Please select some items.', 'Error message shown when no display condition term is selected', 'advanced-ads' ); ?>
</p>

View File

@@ -0,0 +1,54 @@
<?php
/**
* Visitor conditions list template.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*
* @var array $conditions Visitor conditions.
* @var string $form_name Form name.
* @var string $list_target Target list.
* @var array $set_conditions Set conditions.
* @var array $conditions Conditions.
* @var array $conditions_types Conditions types.
*/
?>
<table id="<?php echo esc_attr( $list_target ); ?>" class="advads-conditions-table">
<tbody>
<?php
if ( isset( $set_conditions ) ) :
$i = 0;
foreach ( $set_conditions as $_options ) :
if ( isset( $conditions[ $_options['type'] ]['metabox'] ) ) {
$metabox = $conditions[ $_options['type'] ]['metabox'];
} else {
continue;
}
$connector = ( ! isset( $_options['connector'] ) || 'or' !== $_options['connector'] ) ? 'and' : 'or';
if ( method_exists( $metabox[0], $metabox[1] ) ) {
if ( $i > 0 ) :
?>
<tr class="advads-conditions-connector advads-conditions-connector-<?php echo esc_attr( $connector ); ?>">
<td colspan="3">
<?php echo Advanced_Ads_Visitor_Conditions::render_connector_option( $i, $connector, $form_name ); // phpcs:ignore ?>
</td>
</tr>
<?php endif; ?>
<tr>
<td class="advads-conditions-type"><?php echo esc_html( $conditions[ $_options['type'] ]['label'] ); ?></td>
<td>
<?php call_user_func( [ $metabox[0], $metabox[1] ], $_options, $i ++, $form_name ); // phpcs:ignore ?>
</td>
<td>
<button type="button" class="advads-conditions-remove button">x</button>
</td>
</tr>
<?php
}
endforeach;
endif;
?>
</tbody>
</table>

View File

@@ -0,0 +1,80 @@
<script>
jQuery( document ).ready( function(){
// set element from frontend into placement input field
if( localStorage.getItem( 'advads_frontend_element' )){
var placement = localStorage.getItem( 'advads_frontend_picker' );
var id = 'advads-frontend-element-' + placement;
jQuery( '[id="' + id + '"]' ).find( '.advads-frontend-element' ).val( localStorage.getItem( 'advads_frontend_element' ) );
var action = localStorage.getItem( 'advads_frontend_action' );
if (typeof(action) !== 'undefined'){
var show_all_link = jQuery( 'a[data-placement="' + placement + '"]');
var tr = jQuery( show_all_link ).closest( 'tr.advanced-ads-placement-row' )
if ( tr ) {
tr.data( 'touched', true )
}
// Auto-save the placement after selecting an element in the frontend.
var param = {
action: 'advads-update-frontend-element',
nonce: advadsglobal.ajax_nonce,
}
var $form = jQuery( '#advanced-ads-placements-form' );
var query = $form.find( '[id="single-placement-' + placement + '"]' ).find( 'input, select' )
.serialize() + '&' + jQuery.param( param );
$form.find( ':submit' ).attr( 'disabled', true );
jQuery.post( ajaxurl, query ).always( function() {
$form.find( ':submit' ).attr( 'disabled', false );
} );
}
localStorage.removeItem( 'advads_frontend_action' );
localStorage.removeItem( 'advads_frontend_element' );
localStorage.removeItem( 'advads_frontend_picker' );
localStorage.removeItem( 'advads_prev_url' );
localStorage.removeItem( 'advads_frontend_pathtype' );
localStorage.removeItem( 'advads_frontend_boundary' );
localStorage.removeItem( 'advads_frontend_blog_id' );
localStorage.removeItem( 'advads_frontend_starttime' );
window.Advanced_Ads_Admin.set_cookie( 'advads_frontend_picker', '', -1 );
}
jQuery('.advads-activate-frontend-picker').click(function( e ){
localStorage.setItem( 'advads_frontend_picker', jQuery( this ).data('placementid') );
localStorage.setItem( 'advads_frontend_action', jQuery( this ).data('action') );
localStorage.setItem( 'advads_prev_url', window.location );
localStorage.setItem( 'advads_frontend_pathtype', jQuery( this ).data('pathtype') );
localStorage.setItem( 'advads_frontend_boundary', jQuery( this ).data('boundary') );
localStorage.setItem( 'advads_frontend_blog_id', <?php echo get_current_blog_id(); ?> );
localStorage.setItem( 'advads_frontend_starttime', (new Date).getTime() );
window.Advanced_Ads_Admin.set_cookie( 'advads_frontend_picker', jQuery( this ).data('placementid'), null );
if ( jQuery( this ).data( 'boundary' ) ) {
/**
* The boundary is set for the "Content" placement.
* Perhaps ads through `the_content` are disabled on non-singular pages, so use a singular one.
*/
window.location = "<?php echo $this->get_url_for_content_placement_picker(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>";
} else {
window.location = "<?php echo home_url(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>";
}
});
// allow to deactivate frontend picker
if ( localStorage.getItem( 'advads_frontend_picker' ) ) {
var id = 'advads-frontend-element-' + localStorage.getItem( 'advads_frontend_picker' );
jQuery( '[id="' + id + '"]' ).find( '.advads-deactivate-frontend-picker' ).show();
}
jQuery( '.advads-deactivate-frontend-picker' ).click( function( e ) {
localStorage.removeItem( 'advads_frontend_action' );
localStorage.removeItem( 'advads_frontend_element' );
localStorage.removeItem( 'advads_frontend_picker' );
localStorage.removeItem( 'advads_prev_url' );
localStorage.removeItem( 'advads_frontend_pathtype' );
localStorage.removeItem( 'advads_frontend_boundary' );
localStorage.removeItem( 'advads_frontend_blog_id' );
localStorage.removeItem( 'advads_frontend_starttime' );
window.Advanced_Ads_Admin.set_cookie( 'advads_frontend_picker', '', -1 );
jQuery('.advads-deactivate-frontend-picker').hide();
});
});
</script>

View File

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

View File

@@ -0,0 +1,77 @@
<?php
/**
* Advanced Ads - Backend modal
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.0.0
*
* @var string $modal_slug Unique slug that can be addressed by a link or button.
* @var string $modal_content The modal content. May contain HTML.
* @var string $modal_title The modal title.
* @var string $cancel_action Show/Hide cancel button.
* @var string $close_action Adds another close button that can trigger an action.
* @var string $close_form Add a form ID. This form will be submitted after clicking the close and action button.
* @var string $close_validation A JavaScript validation function. The function has to return true or the form won't be submitted.
*/
$close_validation_object = [
'function' => $close_validation,
'modal_id' => "#modal-$modal_slug",
];
?>
<script>
document.addEventListener( 'DOMContentLoaded', function () {
document.querySelector( '#modal-<?php echo esc_attr( $modal_slug ); ?>' ).closeValidation = <?php echo wp_json_encode( $close_validation_object ); ?>;
<?php if ( $close_action && $close_form ) : ?>
document.querySelector( '#modal-<?php echo esc_attr( $modal_slug ); ?> .advads-modal-close-action' ).addEventListener( 'click', function ( event ) {
modal_submit_form( event, '<?php echo esc_attr( $close_form ); ?>', '#modal-<?php echo esc_attr( $modal_slug ); ?>', '<?php echo esc_attr( $close_validation ); ?>' );
} );
<?php endif; ?>
} );
</script>
<dialog id="modal-<?php echo esc_attr( $modal_slug ); ?>" class="advads-modal" data-modal-id="<?php echo esc_attr( $modal_slug ); ?>" autofocus>
<a href="#close" class="advads-modal-close-background">Close</a>
<div class="advads-modal-content">
<div class="advads-modal-header">
<a href="#close" class="advads-modal-close" title="<?php esc_html_e( 'Cancel', 'advanced-ads' ); ?>">&times;</a>
<h2>
<?php echo esc_html( $modal_title ); ?>
</h2>
</div>
<div class="advads-modal-body">
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- modal content may contain any kind of custom html
echo $modal_content;
?>
</div>
<div class="advads-modal-footer">
<div class="tablenav bottom">
<?php if ( false === $cancel_action ) : ?>
<a href="#close" class="button button-secondary advads-modal-close">
<?php esc_html_e( 'Cancel', 'advanced-ads' ); ?>
</a>
<?php endif; ?>
<?php if ( $close_action ) : ?>
<?php if ( $close_form ) : ?>
<button type="submit" form="<?php echo esc_attr( $close_form ); ?>" class="button button-primary advads-modal-close-action">
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- close action may contain custom html like button bar, image or span tag e.g.
echo $close_action;
?>
</button>
<?php else : ?>
<a href="#close" class="button button-primary advads-modal-close-action">
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- close action may contain custom html like button bar, image or span tag e.g.
echo $close_action;
?>
</a>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</div>
</dialog>

View File

@@ -0,0 +1,13 @@
<?php
/**
* The view to render the option.
*
* @var string $ad_blocker_notice_id Randomised ad blocker id.
*/
?>
<div id="<?php echo esc_attr( $ad_blocker_notice_id ); ?>" class="message error update-message notice notice-alt notice-error" style="display: none;">
<p>
<?php echo wp_kses_post( __( 'Please disable your <strong>AdBlocker</strong>. Otherwise, the features of Advanced Ads and the layout are broken.', 'advanced-ads' ) ); ?>
<a href="https://wpadvancedads.com/manual/ad-blockers/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adblock-enabled#How_do_you_know_if_you_are_using_an_ad_blocker" target="_blank" class="advads-manual-link"><?php esc_html_e( 'Manual', 'advanced-ads' ); ?></a>
</p>
</div>

View File

@@ -0,0 +1,18 @@
<?php
/**
* Error notice template.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*
* @var string $_notice Notice ID.
* @var string $text Notice text.
*/
?>
<div class="notice notice-error advads-notice advads-admin-notice is-dismissible" data-notice="<?php echo esc_attr( $_notice ); ?>">
<p>
<?php echo wp_kses_post( $text ); ?>
</p>
</div>

View File

@@ -0,0 +1,29 @@
<?php
/**
* Info notice template
*
* @package AdvancedAds
*
* @var string $text notice text
* @var string $_notice notice id
*/
use AdvancedAds\Framework\Utilities\Params;
?>
<div class="notice notice-info advads-notice advads-admin-notice message is-dismissible" data-notice="<?php echo esc_attr( $_notice ); ?>">
<p><?php echo $text; // phpcs:ignore ?></p>
<a href="
<?php
add_query_arg(
[
'action' => 'advads-close-notice',
'notice' => $_notice,
'nonce' => wp_create_nonce( 'advanced-ads-admin-ajax-nonce' ),
'redirect' => Params::server( 'REQUEST_URI' ),
],
admin_url( 'admin-ajax.php' )
);
?>
" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html__( 'Dismiss this notice.', 'advanced-ads' ); ?></span></a>
</div>

View File

@@ -0,0 +1,22 @@
<?php
/**
* Inline notice template.
*
* @package AdvancedAds
*
* @var string $_notice notice ID.
* @var string $text notice text.
* @var array $notice notice data (optional).
* @var string $box_classes additional classes (optional).
*/
?>
<div class="notice notice-info advads-admin-notice is-dismissible inline advads-notice-box <?php echo esc_attr( $box_classes ?? '' ); ?>" data-notice="<?php echo esc_attr( $_notice ); ?>">
<div class="advads-notice-box_wrapper">
<p><?php echo $text; // phpcs:ignore ?></p>
<button type="button" class="button-primary advads-notices-button-subscribe with-icon" data-notice="<?php echo esc_attr( $_notice ); ?>">
<span class="dashicons dashicons-email-alt"></span>
<?php echo esc_html( $notice['confirm_text'] ?? __( 'Subscribe me now', 'advanced-ads' ) ); ?>
</button>
</div>
</div>

View File

@@ -0,0 +1 @@
<div class="notice notice-error advads-admin-notice inline"><p><?php echo wp_kses_post( $text ); ?></p></div>

View File

@@ -0,0 +1,46 @@
<?php
/**
* Template for a promotional banner
*
* @package AdvancedAds
*
* @var string $text content of the notice.
* @var string $_notice internal key of the notice.
*/
use AdvancedAds\Framework\Utilities\Params;
?>
<div class="notice notice-promo advads-notice advads-admin-notice message is-dismissible"
data-notice="<?php echo esc_attr( $_notice ); ?>">
<p>
<?php
echo wp_kses(
$text,
[
'a' => [
'href' => [],
'class' => [],
'target' => [],
],
'span' => [
'style' => [],
],
]
);
?>
</p>
<a href="
<?php
add_query_arg(
[
'action' => 'advads-close-notice',
'notice' => $_notice,
'nonce' => wp_create_nonce( 'advanced-ads-admin-ajax-nonce' ),
'redirect' => Params::server( 'REQUEST_URI' ),
],
admin_url( 'admin-ajax.php' )
);
?>
" class="notice-dismiss"><span class="screen-reader-text"><?php esc_html__( 'Dismiss this notice.', 'advanced-ads' ); ?></span></a>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Success notice for the starter setup.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.x.x
*
* @var string $last_post_link URL to the last created post.
*/
?>
<div class="notice notice-success advads-admin-notice message">
<h2>
<?php esc_html_e( '2 Test Ads successfully added!', 'advanced-ads' ); ?>
</h2>
<p>
<?php esc_html_e( 'Look below for the list of created ads.', 'advanced-ads' ); ?>
</p>
<p>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=advanced-ads-placements' ) ); ?>"><?php esc_attr_e( 'Visit list of placements', 'advanced-ads' ); ?></a>
</p>
<?php if ( $last_post_link ) : ?>
<p>
<a href="<?php echo esc_url( $last_post_link ); ?>" target="_blank">
<?php esc_html_e( 'See them in action', 'advanced-ads' ); ?>
</a>
</p>
<?php endif; ?>
</div>

View File

@@ -0,0 +1,20 @@
<?php
/**
* Subscribe notice template.
*
* @package AdvancedAds
*
* @var string $_notice notice ID.
* @var string $text notice text.
* @var array $notice notice data (optional).
*/
?>
<div class="notice notice-info advads-admin-notice is-dismissible" data-notice="<?php echo esc_attr( $_notice ); ?>">
<div class="advads-notice-box_wrapper">
<p><?php echo $text; // phpcs:ignore ?></p>
<button type="button" class="button-primary advads-notices-button-subscribe" data-notice="<?php echo esc_attr( $_notice ); ?>">
<?php echo esc_html( $notice['confirm_text'] ?? __( 'Subscribe me now', 'advanced-ads' ) ); ?>
</button>
</div>
</div>

View File

@@ -0,0 +1,30 @@
<?php
/**
* Render a row with add-on information on the Advanced Ads overview page
*
* @var array $_addon add-on information.
*/
?>
<tr<?php echo isset( $_addon['class'] ) ? ' class="' . esc_attr( $_addon['class'] ) . '"' : ''; ?>><th>
<?php
// phpcs:ignore
echo $_addon['title'];
?>
</th>
<td>
<?php
// phpcs:ignore
echo $_addon['desc'];
?>
</td>
<td><?php if ( isset( $_addon['link'] ) && $_addon['link'] ) : ?>
<a class="button <?php echo ( isset( $_addon['link_primary'] ) ) ? 'button-primary' : 'button-secondary'; ?>" href="<?php echo esc_url( $_addon['link'] ); ?>" target="_blank">
<?php
echo esc_html( $link_title );
?>
</a>
<?php
endif;
?>
</td>
</tr>

View File

@@ -0,0 +1,35 @@
<?php
/**
* Render a line in the notice meta box on the Advanced Ads overview page
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
*
* @var string $type type of the notice.
* @var string $_notice_key index of the notice.
* @var bool $is_hidden true if the notice is currently hidden.
* @var bool $can_hide true if the notice can be hidden.
* @var bool $hide true if the notice is hidden.
* @var string $date date string.
* @var string $dashicon the dashicons class to use.
* @var string $text the notice text.
*/
?>
<ul class="advads-ad-health-notices advads-ad-health-notices-<?php echo esc_attr( $type ); ?>">
<li class="advads-notice-inline" data-notice="<?php echo esc_attr( $_notice_key ); ?>" <?php echo $is_hidden ? 'style="display: none;"' : ''; ?>>
<span class="dashicons <?php echo esc_attr( $dashicon ); ?>"></span>
<div class="text">
<?php echo $text; // phpcs:ignore ?>
<?php if ( $date ) : ?>
<br>
<small class="date">(<?php echo esc_attr( $date ); ?>)</small>
<?php endif; ?>
</div>
<?php if ( $can_hide ) : ?>
<button type="button" class="advads-ad-health-notice-hide <?php echo ! $hide ? 'remove' : ''; ?>">
<span class="dashicons dashicons-dismiss"></span>
</button>
<?php endif; ?>
</li>
</ul>

View File

@@ -0,0 +1,16 @@
<div id="<?php echo esc_attr( $id ); ?>" class="postbox position-<?php echo esc_attr( $position ); ?>">
<?php if ( ! empty( $title ) ) : ?>
<h2>
<?php
// phpcs:ignore
echo $title;
?>
</h2>
<?php endif; ?>
<div class="inside">
<?php
// phpcs:ignore
echo $content;
?>
</div>
</div>

View File

@@ -0,0 +1,79 @@
<?php
/**
* Render form to create new placements.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
* @since 1.48.2
*
* @var array $placement_types types of placements.
*/
?>
<form method="POST" class="advads-placements-new-form advads-form" id="advads-placements-new-form">
<h3>1. <?php esc_html_e( 'Choose a placement type', 'advanced-ads' ); ?></h3>
<p class="description">
<?php
printf(
wp_kses(
/* translators: %s is a URL. */
__( 'Placement types define where the ad is going to be displayed. Learn more about the different types from the <a href="%s">manual</a>', 'advanced-ads' ),
[
'a' => [
'href' => [],
],
]
),
'https://wpadvancedads.com/manual/placements/#utm_source=advanced-ads&utm_medium=link&utm_campaign=placements'
);
?>
</p>
<?php require_once 'placement-types.php'; ?>
<?php
// show Pro placements if Pro is not activated.
if ( ! defined( 'AAP_VERSION' ) ) :
include ADVADS_ABSPATH . 'admin/views/upgrades/pro-placements.php';
else :
?>
<div class="clear"></div>
<?php
endif;
?>
<p class="advads-notice-inline advads-error advads-form-type-error"><?php esc_html_e( 'Please select a type.', 'advanced-ads' ); ?></p>
<br/>
<h3>2. <?php esc_html_e( 'Choose a Name', 'advanced-ads' ); ?></h3>
<p>
<input name="advads[placement][name]" class="advads-form-name" type="text" value="" placeholder="<?php esc_html_e( 'Placement Name', 'advanced-ads' ); ?>" />
<span class="advads-help">
<span class="advads-tooltip">
<?php esc_html_e( 'The name of the placement is only visible to you. Tip: choose a descriptive one, e.g. Below Post Headline.', 'advanced-ads' ); ?>
</span>
</span>
</p>
<p class="advads-notice-inline advads-error advads-form-name-error"><?php esc_html_e( 'Please enter a name.', 'advanced-ads' ); ?></p>
<h3>
<label for="advads-placement-item">3. <?php esc_html_e( 'Choose the Ad or Group', 'advanced-ads' ); ?></label>
</h3>
<p>
<select name="advads[placement][item]" id="advads-placement-item" disabled>
<option value=""><?php esc_html_e( '--not selected--', 'advanced-ads' ); ?></option>
</select>
</p>
<?php wp_nonce_field( 'advads-placement', 'advads_placement', true ); ?>
</form>
<script type="text/html" id="tmpl-advads-placement-ad-select">
<select name="advads[placement][item]" id="advads-placement-item">
<option value=""><?php esc_html_e( '--not selected--', 'advanced-ads' ); ?></option>
<# for ( group of data.items ) { #>
<optgroup label="{{ group.label }}">
<# for ( item_id in group.items ) { #>
<option value="{{ item_id }}">
{{ group.items[item_id].name }}
</option>
<# } #>
</optgroup>
<# } #>
</select>
</script>

View File

@@ -0,0 +1,197 @@
<?php
/**
* Render placements after publishing an ad.
*
* @package AdvancedAds
*
* @var Ad $ad Ad instance.
* @var array $placements Placements array.
*/
// show quick injection options.
// check if the ad code contains the AdSense verification and Auto ads code.
$is_page_level_ad_in_code_field = $ad->is_type( 'plain' ) && strpos( $ad->get_content(), 'enable_page_level_ads' ) || preg_match( '/script[^>]+data-ad-client=/', $ad->get_content() ); // phpcs:ignore
?>
<div id="advads-ad-injection-box" class="advads-ad-metabox postbox">
<span class="advads-loader" style="display: none;"></span>
<div id="advads-ad-injection-message-placement-created" class="hidden">
<p><?php esc_html_e( 'Congratulations! Your ad is now visible in the frontend.', 'advanced-ads' ); ?></p>
<?php if ( empty( $ad->get_display_conditions() ) && ! empty( $latest_post ) ) : ?>
<a class="button button-primary" target="_blank" href="<?php echo esc_url( get_permalink( $latest_post['ID'] ) ); ?>"><?php esc_html_e( 'Take a look at your ad', 'advanced-ads' ); ?></a>
<?php endif; ?>
<p class="hide-server-placement">
<?php
printf(
wp_kses(
/* translators: %s is a URL. */
__( 'Ad not showing up? Take a look <a href="%s" target="_blank">here</a>', 'advanced-ads' ),
[
'a' => [
'href' => [],
'target' => [],
],
]
),
'https://wpadvancedads.com/manual/ads-not-showing-up/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-ad-not-visible'
);
?>
</p>
<p class="hide-server-placement">
<?php
printf(
/* translators: %1$s is the opening link tag, %2$s is closing link tag. */
esc_html__( 'Adjust the placement options? Take a look %1$shere.%2$s', 'advanced-ads' ),
'<a href="' . esc_url( admin_url( 'admin.php?page=advanced-ads-placements#single-placement-' ) ) . '" target="_blank">',
'</a>'
);
?>
</p>
</div>
<div id="advads-ad-injection-box-placements">
<h2><?php esc_html_e( 'Where do you want to display the ad?', 'advanced-ads' ); ?></h2>
<?php
// show different placements if this is the AdSense Auto ads code.
if ( $is_page_level_ad_in_code_field ) :
if ( Advanced_Ads_AdSense_Data::get_instance()->is_page_level_enabled() ) :
?>
<p>
<?php
sprintf(
wp_kses(
/* translators: %s is a URL. */
__( 'The AdSense verification and Auto ads code is already activated in the <a href="%s">AdSense settings</a>.', 'advanced-ads' ),
[
'a' => [
'href' => [],
],
]
),
admin_url( 'admin.php?page=advanced-ads-settings#top#adsense' )
);
?>
</p><p>
<?php
esc_attr_e( 'No need to add the code manually here, unless you want to include it into certain pages only.', 'advanced-ads' );
endif;
?>
<p><?php esc_attr_e( 'Click on the button below to add the Auto ads code to the header of your site.', 'advanced-ads' ); ?></p>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="header" style="background-image: url(
<?php
// phpcs:ignore
echo ADVADS_BASE_URL . 'admin/assets/img/placements/header.png';
?>
)">
<?php
/**
* Translators: this is a label in a button when a user uses an AdSense Auto ads code in a plain code field
* the button has barely space for the original English text, so keep it short
*/
esc_attr_e( 'inject Auto ads', 'advanced-ads' );
?>
</button></div>
<div class="clear"></div>
<?php else : ?>
<p><?php esc_html_e( 'New placement', 'advanced-ads' ); ?></p>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="post_top" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/content-before.png'; ?>)"><?php esc_html_e( 'Before Content', 'advanced-ads' ); ?></button></div>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="post_content" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/content-within.png'; ?>)"><?php esc_html_e( 'Content', 'advanced-ads' ); ?></button></div>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="post_bottom" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/content-after.png'; ?>)"><?php esc_html_e( 'After Content', 'advanced-ads' ); ?></button></div>
<a href="<?php echo esc_url( admin_url( 'widgets.php' ) ); ?>"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/widget.png'; ?>)"><?php esc_html_e( 'Manage Sidebar', 'advanced-ads' ); ?></button></div></a>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="default" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/manual.png'; ?>)"><?php esc_html_e( 'PHP or Shortcode', 'advanced-ads' ); ?></button></div>
<a href="https://wpadvancedads.com/place-ads-in-website-header/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-placements" target="_blank"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/ads-in-header.png'; ?>)"><?php esc_html_e( 'Header (Manual)', 'advanced-ads' ); ?></button></div></a>
<?php
if ( ! defined( 'AAP_VERSION' ) ) :
?>
<a href="https://wpadvancedads.com/manual/custom-position-placement/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-placements" target="_blank"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary advads-pro-link" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/custom-position.png'; ?>)"><?php esc_html_e( 'Custom Position', 'advanced-ads' ); ?></button></div></a><a href="https://wpadvancedads.com/add-ons/advanced-ads-pro/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-created-injection-pro" target="_blank"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary advads-pro-link" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/content-random.png'; ?>)"><?php esc_html_e( 'Show Pro Places', 'advanced-ads' ); ?></button></div></a>
<?php
else :
?>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="custom_position" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/custom-position.png'; ?>)"><?php esc_html_e( 'Custom Position', 'advanced-ads' ); ?></button></div>
<?php
endif;
if ( class_exists( 'Advanced_Ads_In_Feed', false ) ) :
?>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="adsense_in_feed" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/adsense-in-feed.png'; ?>)"><?php esc_html_e( 'AdSense In-feed', 'advanced-ads' ); ?></button></div>
<?php
endif;
if ( ! defined( 'AASADS_VERSION' ) ) :
?>
<a href="https://wpadvancedads.com/add-ons/sticky-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-created-injection-sticky" target="_blank"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary advads-pro-link" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/sticky-sidebar-left.png'; ?>)"><?php esc_html_e( 'Show Sticky Places', 'advanced-ads' ); ?></button></div></a>
<?php
endif;
if ( ! defined( 'AAPLDS_VERSION' ) ) :
?>
<a href="https://wpadvancedads.com/add-ons/popup-and-layer-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-created-injection-layer" target="_blank"><div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary advads-pro-link" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/layer.png'; ?>)"><?php esc_html_e( 'Show PopUp', 'advanced-ads' ); ?></button></div></a>
<?php
else :
?>
<div class="advads-ad-injection-box-button-wrap"><button type="button" class="advads-ad-injection-button button-primary" data-placement-type="layer" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/layer.png'; ?>)"><?php esc_html_e( 'PopUp & Layer', 'advanced-ads' ); ?></button></div>
<?php
endif;
?>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=advanced-ads-placements' ) ); ?>">
<div class="advads-ad-injection-box-button-wrap">
<button type="button" class="advads-ad-injection-button button-primary" style="background-image: url(<?php echo esc_url( ADVADS_BASE_URL ) . 'admin/assets/img/placements/more.png'; ?>)">
<?php esc_html_e( 'see all…', 'advanced-ads' ); ?>
</button>
</div>
</a>
<?php
ob_start();
foreach ( $placements as $placement_id => $placement ) :
// Early bail!!
if ( empty( $placement->get_type() ) || empty( $placement->get_title() ) ) {
continue;
}
?>
<div class="advads-ad-injection-box-button-wrap">
<?php
printf(
'<button type="button" class="advads-ad-injection-button button-primary" data-placement-id="%1$s" data-placement-type="%2$s" %3$s title="%4$s">%5$s</button>',
esc_attr( $placement_id ),
esc_attr( $placement->get_type() ),
'style="background-image: url(' . $placement->get_type_object()->get_image() . ');"', // phpcs:ignore
esc_html( $placement->get_title() ),
esc_html( $placement->get_type_object()->get_title() )
);
echo esc_html( $placement->get_title() );
?>
</div>
<?php
endforeach;
$existing_p_output = ob_get_clean();
if ( $existing_p_output ) :
?>
<div class="clear"></div>
<p><?php esc_html_e( 'Existing placement', 'advanced-ads' ); ?></p>
<?php
// phpcs:ignore
echo $existing_p_output;
endif;
?>
<div class="clear"></div>
<p>
<?php
printf(
/* translators: %s is some HTML. */
__( 'Or use the shortcode %s to insert the ad into the content manually.', 'advanced-ads' ), // phpcs:ignore
'<input id="advads-ad-injection-shortcode" onclick="this.select();" value="[the_ad id=\'' . absint( $post->ID ) . '\']"/>'
);
?>
<?php
printf(
/* translators: %s is a URL. */
__( 'Learn more about your choices to display an ad in the <a href="%s" target="_blank">manual</a>.', 'advanced-ads' ), // phpcs:ignore
'https://wpadvancedads.com/manual/display-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-created'
);
?>
</p>
<?php endif; ?>
</div>
</div>
<?php

View File

@@ -0,0 +1,29 @@
<?php
/**
* Render all placement types for forms.
*
* @var array $placement_types
*/
?>
<?php if ( is_array( $placement_types ) ) : ?>
<div class="advads-form-types advads-buttonset">
<?php foreach ( $placement_types as $key => $placement_type ) : ?>
<div class="advads-form-type">
<label for="advads-form-type-<?php echo esc_attr( $key ); ?>">
<?php if ( isset( $placement_type['image'] ) ) : ?>
<img src="<?php echo esc_attr( $placement_type['image'] ); ?>" alt="<?php echo esc_attr( $placement_type['title'] ); ?>"/>
<?php else : ?>
<strong><?php echo esc_html( $placement_type['title'] ); ?></strong><br/>
<p class="description"><?php echo esc_html( $placement_type['description'] ); ?></p>
<?php endif; ?>
</label>
<input type="radio" id="advads-form-type-<?php echo esc_attr( $key ); ?>" name="advads[placement][type]" value="<?php echo esc_attr( $key ); ?>"/>
<div class="advads-form-description">
<h4><?php echo esc_html( $placement_type['title'] ); ?></h4>
<?php echo esc_html( $placement_type['description'] ); ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Render ad label option for placements.
*
* @deprecated
*
* @var string $_placement_slug slug of the current placement.
* @var string $_label value of the label option.
* @package AdvancedAds
*/
?>
<label title="<?php esc_html_e( 'default', 'advanced-ads' ); ?>">
<input type="radio" name="advads[placements][<?php echo esc_attr( $_placement_slug ); ?>][options][ad_label]" value="default" <?php checked( $_label, 'default' ); ?>/>
<?php esc_html_e( 'default', 'advanced-ads' ); ?>
</label>
<label title="<?php esc_html_e( 'enabled', 'advanced-ads' ); ?>">
<input type="radio" name="advads[placements][<?php echo esc_attr( $_placement_slug ); ?>][options][ad_label]" value="enabled" <?php checked( $_label, 'enabled' ); ?>/>
<?php esc_html_e( 'enabled', 'advanced-ads' ); ?>
</label>
<label title="<?php esc_html_e( 'disabled', 'advanced-ads' ); ?>">
<input type="radio" name="advads[placements][<?php echo esc_attr( $_placement_slug ); ?>][options][ad_label]" value="disabled" <?php checked( $_label, 'disabled' ); ?>/>
<?php esc_html_e( 'disabled', 'advanced-ads' ); ?>
</label>

View File

@@ -0,0 +1,52 @@
<?php
/**
* Render content index option for placements.
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
*
* @var Placement $placement information of the current placement.
* @var string $option_xpath xpath option.
* @var string $option_tag tag option.
* @var string $option_index index option.
* @var array $positions positions option.
*/
use AdvancedAds\Utilities\Content_Injection;
$tags = Content_Injection::get_tags();
?>
<select name="advads[placements][<?php echo esc_attr( $placement->get_slug() ); ?>][options][position]">
<?php foreach ( $positions as $_pos_key => $_pos ) : ?>
<option value="<?php echo esc_attr( $_pos_key ); ?>"<?php selected( $placement->get_prop( 'position' ), $_pos_key ); ?>>
<?php echo esc_html( $_pos ); ?>
</option>
<?php endforeach; ?>
</select>
<input type="number" name="advads[placements][<?php echo esc_attr( $placement->get_slug() ); ?>][options][index]" value="<?php echo absint( $option_index ); ?>" min="1"/>.
<select class="advads-placements-content-tag" name="advads[placements][<?php echo esc_attr( $placement->get_slug() ); ?>][options][tag]">
<?php foreach ( $tags as $_tag_key => $_tag ) : ?>
<option value="<?php echo esc_attr( $_tag_key ); ?>"<?php selected( $option_tag, $_tag_key ); ?>>
<?php echo esc_html( $_tag ); ?>
</option>
<?php endforeach; ?>
</select>
<div id="advads-frontend-element-<?php echo esc_attr( $placement->get_slug() ); ?>" class="advads-placements-content-custom-xpath<?php echo 'custom' !== $option_tag ? ' hidden' : ''; ?>">
<input name="advads[placements][<?php echo esc_attr( $placement->get_slug() ); ?>][options][xpath]"
class="advads-frontend-element "
type="text"
value="<?php echo esc_html( $option_xpath ); ?>"
placeholder="<?php esc_html_e( 'use xpath, e.g. `p[not(parent::blockquote)]`', 'advanced-ads' ); ?>"/>
<button style="display:none; color: red;" type="button" class="advads-deactivate-frontend-picker button "><?php echo esc_html_x( 'stop selection', 'frontend picker', 'advanced-ads' ); ?></button>
<button type="button" class="advads-activate-frontend-picker button " data-placementid="<?php echo esc_attr( $placement->get_slug() ); ?>" data-pathtype="xpath" data-boundary="true"><?php esc_html_e( 'select position', 'advanced-ads' ); ?></button>
</div>
<p>
<label>
<input type="checkbox" name="advads[placements][<?php echo esc_attr( $placement->get_slug() ); ?>][options][start_from_bottom]" value="1"<?php checked( $placement->get_prop( 'start_from_bottom' ), 1 ); ?> />
<?php esc_html_e( 'start counting from bottom', 'advanced-ads' ); ?>
</label>
</p>

View File

@@ -0,0 +1,15 @@
<?php
/**
* Render inline css option for placements.
*
* @var string $_placement_slug slug of the current placement.
* @var string $_placement Placement with all options.
* @package AdvancedAds
*/
$inline_css = isset( $_placement['options']['inline-css'] ) ? $_placement['options']['inline-css'] : '';
?>
<input
type="text"
value="<?php echo esc_attr( $inline_css ); ?>"
name="advads[placements][<?php echo esc_attr( $_placement_slug ); ?>][options][inline-css]"/>

View File

@@ -0,0 +1,70 @@
<?php
/**
* Render item option for placements.
*
* @var array $items Array of available items.
* @var string $slug slug of the current placement.
* @var array $placement information of the current placement.
* @var string $placement_item_type type of the item currently selected for the placement
* @var int $placement_item_id ID of the item currently selected for the placement
* @package AdvancedAds
*/
?>
<select id="advads-placements-item-<?php echo esc_attr( $slug ); ?>" name="advads[placements][<?php echo esc_attr( $slug ); ?>][item]">
<option value=""><?php esc_html_e( '--not selected--', 'advanced-ads' ); ?></option>
<?php foreach ( $items as $item_group ) : ?>
<optgroup label="<?php echo esc_attr( $item_group['label'] ); ?>">
<?php foreach ( $item_group['items'] as $item_id => $item ) : ?>
<option value="<?php echo esc_attr( $item_id ); ?>" <?php selected( $item['selected'] ); ?> <?php disabled( $item['disabled'] ); ?>>
<?php echo esc_html( $item['name'] ); ?>
</option>
<?php endforeach; ?>
</optgroup>
<?php endforeach; ?>
</select>
<?php
// link to item.
if ( $placement_item_type ) :
$link_to_item = false;
switch ( $placement_item_type ) :
case 'ad':
/**
* Deliver the translated version of an ad if set up with WPML.
*
* @source https://wpml.org/wpml-hook/wpml_object_id/
*/
$placement_item_id = apply_filters( 'wpml_object_id', $placement_item_id, 'advanced_ads' );
$link_to_item = get_edit_post_link( $placement_item_id );
break;
case 'group':
$link_to_item = admin_url( 'admin.php?page=advanced-ads-groups#modal-group-edit-' . $placement_item_id );
break;
endswitch;
if ( $link_to_item ) {
?>
<a href="<?php echo esc_url( $link_to_item ); ?>"><span class="dashicons dashicons-external"></span></span></a>
<?php
} elseif ( 'ad' === $placement_item_type && defined( 'ICL_LANGUAGE_NAME' ) ) {
// translation missing notice.
?>
<p>
<?php
printf(
/* translators: %s is the name of a language in English. */
esc_html__( 'The ad is not translated into %s', 'advanced-ads' ),
esc_html( ICL_LANGUAGE_NAME )
);
?>
</p>
<?php
}
endif;
// show a button when no ads exist, yet.
if ( empty( $items ) ) :
?>
<a class="button" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=advanced_ads' ) ); ?>"><?php esc_html_e( 'Create your first ad', 'advanced-ads' ); ?></a>
<?php
endif;

View File

@@ -0,0 +1,24 @@
<?php
/**
* Filter for the ad visibility on post and page list pages.
*
* @var string $viewability selected ad viewability by which posts are filtered.
*/
?>
<select name="ad-viewability">
<option value="">
<?php esc_html_e( 'All ad states', 'advanced-ads' ); ?>
</option>
<option value="disable_ads" <?php selected( 'disable_ads', $viewability ); ?>>
<?php esc_html_e( 'All ads disabled', 'advanced-ads' ); ?>
</option>
<option
value="disable_the_content"
<?php selected( 'disable_the_content', $viewability ); ?>
<?php disabled( defined( 'AAP_VERSION' ), false ); ?>>
<?php
esc_html_e( 'Ads in content disabled', 'advanced-ads' );
echo ! defined( 'AAP_VERSION' ) ? ' (Pro)' : '';
?>
</option>
</select>

View File

@@ -0,0 +1,102 @@
<?php // phpcs:ignoreFile
/**
* Template for license fields.
*
* Do not move since it could be used by add-ons.
*
* @var string $index internal name of the add-on.
* @var string $plugin_name name of the add-on.
* @var string $options_slug slug of the add-on.
* @var string $license_status status code of the license.
*/
$errortext = false;
$expires = Advanced_Ads_Admin_Licenses::get_instance()->get_license_expires( $options_slug );
$expired = false;
$expired_error = __( 'Your license expired.', 'advanced-ads' );
ob_start();
?>
<button type="button" class="button-secondary advads-license-activate"
data-addon="<?php echo esc_attr( $index ); ?>"
data-pluginname="<?php echo esc_attr( $plugin_name ); ?>"
data-optionslug="<?php echo esc_attr( $options_slug ); ?>"
name="advads_license_activate"><?php esc_html_e( 'Update expiry date', 'advanced-ads' ); ?></button>
<?php
$update_button = ob_get_clean();
$license_key_for_expired_link = $license_key ? $license_key : '%LICENSE_KEY%';
//phpcs:ignore
$expired_error .= $expired_renew_link = ' ' . sprintf(
/* translators: 1: is a URL, 2: is HTML of a button. */
__( 'Click on %2$s if you renewed it or have a subscription or <a href="%1$s" class="advads-renewal-link" target="_blank">renew your license</a>.', 'advanced-ads' ), // phpcs:ignore
'https://wpadvancedads.com/checkout/?edd_license_key=' . esc_attr( $license_key_for_expired_link ) . '&utm_source=advanced-ads&utm_medium=link&utm_campaign=settings-licenses',
$update_button
);
if ( 'lifetime' !== $expires ) {
$expires_time = strtotime( $expires );
$days_left = ( $expires_time - time() ) / DAY_IN_SECONDS;
}
// phpcs:ignore
if ( 'lifetime' === $expires ) {
// do nothing.
} elseif ( $expired && $days_left <= 0 ) {
$plugin_url = isset( $plugin_url ) ? $plugin_url : 'https://wpadvancedads.com/';
$errortext = $expired_error;
$expired = true;
} elseif ( 0 < $days_left && 31 > $days_left ) {
$errortext = sprintf(
/* translators: %d is a number of days. */
esc_html__( '(%d days left)', 'advanced-ads' ),
$days_left
);
}
$show_active = ( false !== $license_status && 'valid' === $license_status && ! $expired ) ? true : false;
?>
<input type="text" class="regular-text advads-license-key" placeholder="<?php esc_html_e( 'License key', 'advanced-ads' ); ?>"
name="<?php echo esc_attr( ADVADS_SLUG ) . '-licenses'; ?>[<?php echo esc_attr( $index ); ?>]"
value="<?php echo esc_attr( $license_key ); ?>"
<?php
if ( false !== $license_status && 'valid' === $license_status && ! $expired ) :
?>
readonly="readonly"<?php endif; ?>/>
<button type="button" class="button-secondary advads-license-deactivate"
<?php
if ( 'valid' !== $license_status ) {
echo ' style="display: none;" ';
}
?>
data-addon="<?php echo esc_attr( $index ); ?>"
data-pluginname="<?php echo esc_attr( $plugin_name ); ?>"
data-optionslug="<?php echo esc_attr( $options_slug ); ?>"
name="advads_license_activate"><?php esc_html_e( 'Deactivate License', 'advanced-ads' ); ?></button>
<button type="button" class="button-primary advads-license-activate"
data-addon="<?php echo esc_attr( $index ); ?>"
data-pluginname="<?php echo esc_attr( $plugin_name ); ?>"
data-optionslug="<?php echo esc_attr( $options_slug ); ?>"
name="advads_license_activate">
<?php
// phpcs:ignore
echo ( 'valid' === $license_status && ! $expired ) ? esc_html__( 'Update License', 'advanced-ads' ) : esc_html__( 'Activate License', 'advanced-ads' ); ?></button>
<?php
if ( '' === trim( $license_key ) ) {
$errortext = __( 'Please enter a valid license key', 'advanced-ads' );
} elseif ( ! $expired && ! $errortext ) {
$errortext = ( 'invalid' === $license_status ) ? esc_html__( 'License key invalid', 'advanced-ads' ) : '';
}
?>
&nbsp;
<span class="advads-license-activate-active advads-notice-inline advads-check" <?php echo ( ! $show_active ) ? 'style="display: none;"' : ''; ?>><?php esc_html_e( 'active', 'advanced-ads' ); ?></span>
<span class="advads-license-activate-error advads-notice-inline advads-error" <?php echo ( ! $errortext ) ? 'style="display: none;"' : ''; ?>>
<?php
// phpcs:ignore
echo $errortext;
?>
</span>
<span class="advads-license-expired-error advads-notice-inline advads-error" style="display: none;">
<?php
// phpcs:ignore
echo $expired_error;
?>
</span>

View File

@@ -0,0 +1,18 @@
<?php
/**
* Support callout.
*
* @package Advanced_Ads
* @since 1.0.0
*/
use AdvancedAds\Utilities\Data;
?>
<div id="advads-support-callout">
<p class="advads-notice-inline advads-idea">
<a href="<?php echo esc_url( Data::support_url( '/?utm_source=advanced-ads&utm_medium=link&utm_campaign=overview-notices-support' ) ); ?>" target="_blank"><strong><?php esc_html_e( 'Problems or questions?', 'advanced-ads' ); ?></strong>
<?php esc_html_e( 'Save time and get personal support.', 'advanced-ads' ); ?>&nbsp;<strong style="text-decoration: underline;"><?php esc_html_e( 'Ask your question!', 'advanced-ads' ); ?></strong>
</a>
</p>
</div>

View File

@@ -0,0 +1,97 @@
<?php
/**
* The view for the support page
*
* @package AdvancedAds
* @author Advanced Ads <info@wpadvancedads.com>
*/
use AdvancedAds\Utilities\Conditional;
?>
<div class="wrap">
<?php if ( Advanced_Ads_Admin_Notices::get_instance()->can_display( 'nl_first_steps' ) && Conditional::user_can_subscribe( 'nl_first_steps' ) ) : ?>
<div class="notice notice-info advads-admin-notice inline is-dismissible" data-notice="nl_first_steps">
<p>
<?php
printf(
/* translators: %s: number of free add-ons. */
esc_html__(
'Subscribe to our free First Steps email course, receive our newsletter for periodic tutorials, and get %s for Advanced Ads.',
'advanced-ads'
),
'<strong>' . esc_html__( '2 free add-ons', 'advanced-ads' ) . '</strong>'
);
?>
<button type="button" class="button-primary advads-notices-button-subscribe" data-notice="nl_first_steps"><?php esc_html_e( 'Subscribe me now', 'advanced-ads' ); ?></button>
</p>
</div>
<?php endif; ?>
<p><?php esc_html_e( 'Please fix the red highlighted issues on this page or try to understand their consequences before contacting support.', 'advanced-ads' ); ?></p>
<h2><?php esc_html_e( 'Possible Issues', 'advanced-ads' ); ?></h2>
<ul>
<li><a href="https://wpadvancedads.com/manual/ads-not-showing-up/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support"><?php esc_html_e( 'Ads not showing up', 'advanced-ads' ); ?></a></li>
<li><a href="https://wpadvancedads.com/manual/purchase-licenses/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support"><?php esc_html_e( 'Purchase & Licenses', 'advanced-ads' ); ?></a></li>
<li><a href="https://wpadvancedads.com/manual/issues-after-updates/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support"><?php esc_html_e( 'Issues after updating', 'advanced-ads' ); ?></a></li>
<li><a href="https://wpadvancedads.com/manual-category/troubleshooting/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support"><?php esc_html_e( 'General Issues', 'advanced-ads' ); ?></a></li>
<li><a href="https://wpadvancedads.com/manual-category/add-on-issues/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support"><?php esc_html_e( 'Issues with Add-Ons', 'advanced-ads' ); ?></a></li>
</ul>
<p><?php esc_html_e( 'Use the following form to search for solutions in the manual on wpadvancedads.com', 'advanced-ads' ); ?></p>
<form action="https://wpadvancedads.com/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support-form" method="get" class="advads-support-form">
<input type="search" name="s"/>
<input type="submit" class="button button-primary" value="<?php esc_html_e( 'search', 'advanced-ads' ); ?>">
</form>
<?php if ( Advanced_Ads_Admin_Licenses::any_license_valid() ) : ?>
<p>
<?php
printf(
wp_kses(
/* translators: %s is a URL. */
__( 'Take a look at more common issues or contact us directly through the <a href="%s" target="_blank">support page</a>.', 'advanced-ads' ),
[
'a' => [
'href' => [],
'target' => [],
],
]
),
'https://wpadvancedads.com/support/?utm_source=advanced-ads&utm_medium=link&utm_campaign=support'
);
?>
</p>
<?php else : ?>
<p>
<?php
printf(
wp_kses(
/* translators: %s is a URL. */
__( 'Upgrade to any premium add-on and get <strong>priority email support</strong> or reach out through the <a href="%s" target="_blank">support forum</a> for individual help.', 'advanced-ads' ),
[
'a' => [
'href' => [],
'target' => [],
],
]
),
'https://wordpress.org/support/plugin/advanced-ads'
);
?>
</p>
<?php endif; ?>
<?php $constants = Advanced_Ads_Checks::get_defined_constants(); ?>
<?php if ( $constants ) : ?>
<h2><?php esc_html_e( 'Advanced Ads related constants enabled', 'advanced-ads' ); ?></h2>
<ul>
<li>
<?php
echo wp_kses(
implode( '</li><li>', $constants ),
[ 'li' => [] ]
);
?>
</li>
</ul>
<?php endif; ?>
</div>
<?php AdvancedAds\Modules\ProductExperimentationFramework\Module::get_instance()->render( 'support' ); ?>

View File

@@ -0,0 +1,16 @@
<?php
/**
* AdSense AMP upgrade notice.
*
* @package Advanced_Ads
*/
use AdvancedAds\Admin\Upgrades;
?>
<label class="label">AMP</label>
<div id="advads-adsense-responsive-amp-inputs">
<?php esc_html_e( 'Automatically convert AdSense ads into their AMP format', 'advanced-ads' ); ?>
<p><?php Upgrades::upgrade_link( null, 'https://wpadvancedads.com/add-ons/responsive-ads/', 'upgrade-ad-edit-adsense-amp' ); ?></p>
</div>
<hr />

View File

@@ -0,0 +1,96 @@
<?php
/**
* Pro placements upgrade notice.
*
* @package Advanced_Ads
* TODO: move the array somewhere else.
*/
use AdvancedAds\Admin\Upgrades;
$pro_placements = [
// ad injection on random position.
'post_content_random' => [
'title' => __( 'Random Paragraph', 'advanced-ads' ),
'description' => __( 'After a random paragraph in the main content.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-random.png',
],
// ad injection above the post headline.
'post_above_headline' => [
'title' => __( 'Above Headline', 'advanced-ads' ),
'description' => __( 'Above the main headline on the page (&lt;h1&gt;).', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-above-headline.png',
],
// ad injection in the middle of a post.
'post_content_middle' => [
'title' => __( 'Content Middle', 'advanced-ads' ),
'description' => __( 'In the middle of the main content based on the number of paragraphs.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-middle.png',
],
// ad injection at a hand selected element in the frontend.
'custom_position' => [
'title' => __( 'Custom Position', 'advanced-ads' ),
'description' => __( 'Attach the ad to any element in the frontend.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/custom-position.png',
],
// ad injection between posts on archive and category pages.
'archive_pages' => [
'title' => __( 'Post Lists', 'advanced-ads' ),
'description' => __( 'Display the ad between posts on post lists, e.g. home, archives, search etc.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/post-list.png',
],
'background' => [
'title' => __( 'Background Ad', 'advanced-ads' ),
'description' => __( 'Background of the website behind the main wrapper.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/background.png',
],
];
// BuddyBoss & BuddyPress.
if ( defined( 'BP_PLATFORM_VERSION' ) ) { // BuddyBoss.
$pro_placements['buddypress'] = [
'title' => __( 'BuddyBoss Content', 'advanced-ads' ),
'description' => __( 'Display ads on BuddyBoss related pages.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/buddyboss-icon.png',
];
} elseif ( class_exists( 'BuddyPress', false ) ) { // BuddyPress.
$pro_placements['buddypress'] = [
'title' => __( 'BuddyPress Content', 'advanced-ads' ),
'description' => __( 'Display ads on BuddyPress related pages.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/buddypress-icon.png',
];
}
// bbPress.
if ( class_exists( 'bbPress', false ) ) {
$pro_placements['bbpress'] = [
'title' => __( 'bbPress Content', 'advanced-ads' ),
'description' => __( 'Display ads in content created with bbPress.', 'advanced-ads' ),
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/bbpress-reply.png',
];
}
?>
<?php
if ( is_array( $pro_placements ) ) :
foreach ( $pro_placements as $key => $placement ) :
?>
<div class="advads-form-type">
<label class="advads-button advads-pro-link">
<span class="advads-button-text">
<?php
if ( isset( $placement['image'] ) ) {
echo '<img src="' . esc_attr( $placement['image'] ) . '" alt="' . esc_attr( $placement['title'] ) . '"/>';
} else {
echo '<strong>' . esc_html( $placement['title'] ) . '</strong><br/><p class="description">' . esc_html( $placement['description'] ) . '</p>';
}
?>
</span>
</label>
<p class="advads-form-description">
<strong><?php echo esc_html( $placement['title'] ); ?></strong>
<br/><?php echo esc_html( $placement['description'] ); ?>
</p>
</div>
<?php endforeach; ?>
<div class="clear"></div>
<h4><?php Upgrades::upgrade_link( __( 'Get all placements with All Access', 'advanced-ads' ), 'https://wpadvancedads.com/add-ons/all-access/', 'upgrades-pro-placements' ); ?></h4>
<?php endif; ?>

View File

@@ -0,0 +1,13 @@
<?php
/**
* Repeat the position upgrade notice.
*
* @package Advanced_Ads
*/
use AdvancedAds\Admin\Upgrades;
?>
<p><label><input type="checkbox" disabled="disabled"/><?php esc_html_e( 'repeat the position', 'advanced-ads' ); ?></label>
<?php Upgrades::upgrade_link( null, 'https://wpadvancedads.com/add-ons/advanced-ads-pro/', 'upgrade-content-repeat' ); ?>
</p>

View File

@@ -0,0 +1 @@
<a href="<?php echo esc_url( $url ); ?>" target="_blank"><?php echo esc_html( $title ); ?></a>