Advanced Ads - Version 1.22.0

Version Description

  • made dashboard layout compatible with WordPress 5.6
  • removed irrelevant AdSense warnings
  • allow filtering of data-attributes for encoded ads if privacy module is enabled
  • added advanced-ads-ad-edit-show-placement-injection filter to allow removing the placement-injection box on the ad edit screen
  • added advanced-ads-unhide-meta-boxes filter to allow adding of meta box ids that should always be visible on ad edit pages
  • added advanced-ads-ad-option-{$field} filter for ad options
  • added action hooks for ad status changes: advanced-ads-ad-status-published, advanced-ads-ad-status-unpublished, advanced-ads-ad-status-{$old_status}-to-{$new_status}
  • removed public URLs for single ads on some installations
  • fixed old icon in the menu
  • fixed Internet Explorer 11 incompatibility
  • fixed possible error in TinyMCE editor caused by ad blockers
Download this release

Release Info

Developer advancedads
Plugin Icon 128x128 Advanced Ads
Version 1.22.0
Comparing to
See all releases

Code changes from version 1.21.1 to 1.22.0

admin/assets/css/admin.css CHANGED
@@ -126,7 +126,7 @@ h2.hndle .advads-hndlelinks a + a, #advads_overview_adsense_stats .advads-hndlel
126
  .advads-conditions-table label { margin-right: 1em; }
127
  .advads-conditions-table td, .advads-conditions-table th { padding: 10px 0 10px 10px; }
128
  .advads-conditions-table .advanced-ads-display-condition-set label { float: left; margin-right: -1px; }
129
- .advads-conditions-table .ui-widget { font-size: inherit; }
130
  #advads-visitor-conditions-new select,
131
  .advads-conditions-new select { text-transform: capitalize; }
132
  .advads-display-conditions-remove + h5 { display: inline-block; margin-top: 0; margin-left: 1em; }
@@ -150,7 +150,8 @@ select + .advads-conditions-single { display: inline-block; }
150
  .advads-conditions-single { margin: 0; padding: 0 10px 0 0; line-height: 1em; }
151
  select + .advads-conditions-single { padding-left: 10px }
152
  .advads-conditions-single.disabled { display: none; opacity: .5; }
153
- .advads-conditions-table .advads-conditions-single.advads-buttonset label { margin: 0 -1px .3em 0; padding: 0 .5em; background: #f7f7f7; height: 26px; line-height: 26px; color: #555; border: 1px solid #ccc; border-radius: 0; font-family: inherit; box-shadow: none; }
 
154
  .advads-conditions-single.advads-buttonset label span { margin: 0; padding: 0; line-height: inherit; }
155
  .advads-conditions-postid-buttons { padding: 0 10px; }
156
  .advads-conditions-postids-show-search { margin-left: .5em !important; }
@@ -159,11 +160,6 @@ select + .advads-conditions-single { padding-left: 10px }
159
  .advads-conditions-postids-autocomplete-suggestions li span.left { float: left; }
160
  .advads-conditions-postids-autocomplete-suggestions li span.right { float: right; color: #aaa; font-size: .8em; }
161
 
162
- .advads-buttonset label span { margin: 0; padding: 0; }
163
-
164
- .advads-buttonset .ui-state-active,
165
- .advads-buttonset .ui-button.ui-state-active { border-color: #0074a2 !important; background: #2ea2cc !important; color: #fff !important; box-shadow: none; border: 0; }
166
-
167
  #ad-display-box .advads-conditions-terms-show-search { height: 22px; line-height: 22px; font-weight: bold; font-size: 1.5em; }
168
  .advads-conditions-terms-search { display: none; }
169
  .post-type-advanced_ads #ad-parameters-box .advads-ad-parameters-spinner { display: block; float: none; }
@@ -278,11 +274,11 @@ fieldset.advads-group-add-ad { margin-top: 1em; }
278
  */
279
  .advads-placement-description { display: none; }
280
  .advads-placements-new-form .advads-placement-type { position: relative; top: 0; left: 0; float: left; width: 140px; margin: 15px 0 0 15px; }
281
- .advads-placements-new-form .advads-placement-type .ui-button { background: none; border-radius: 0; height: auto; }
282
- .advads-placements-new-form .advads-placement-type .ui-button-text { padding: 0; width: 140px; height: 105px; border: solid 1px #0085ba; border-radius: 3px; box-shadow: 0px 0px 2px #0085ba; overflow: hidden; box-sizing: border-box; }
283
- .advads-placements-new-form .advads-placement-type .ui-button-text img { max-width: 100%; pointer-events: none; }
284
  .advads-placements-new-form .advads-placement-type label { display: inline-block; width: 140px; text-align: center; border: 0; padding: 0; }
285
- .advads-placements-new-form .advads-buttonset .ui-button.ui-state-active { outline: 8px solid #2ea2cc; }
286
  .advads-placements-new-form .advads-placement-type label .description { padding: 10px; }
287
  .advads-placements-new-form .advads-error-message { display: none; }
288
  .advads-placements-table { min-width: 80%; border-collapse: collapse; background: #fff; }
126
  .advads-conditions-table label { margin-right: 1em; }
127
  .advads-conditions-table td, .advads-conditions-table th { padding: 10px 0 10px 10px; }
128
  .advads-conditions-table .advanced-ads-display-condition-set label { float: left; margin-right: -1px; }
129
+ .advads-conditions-table .advads-button { font-size: inherit; }
130
  #advads-visitor-conditions-new select,
131
  .advads-conditions-new select { text-transform: capitalize; }
132
  .advads-display-conditions-remove + h5 { display: inline-block; margin-top: 0; margin-left: 1em; }
150
  .advads-conditions-single { margin: 0; padding: 0 10px 0 0; line-height: 1em; }
151
  select + .advads-conditions-single { padding-left: 10px }
152
  .advads-conditions-single.disabled { display: none; opacity: .5; }
153
+ .advads-conditions-table .advads-conditions-single.advads-buttonset label { margin-top: 0; margin-bottom: .3em; padding: 0 .5em; background: #f7f7f7; height: 26px; line-height: 26px; color: #555; border: 1px solid #ccc; border-radius: 0; font-family: inherit; box-shadow: none; }
154
+ .advads-conditions-table .advads-conditions-single.advads-buttonset .advads-ui-state-active { border-color: #0074a2 !important; }
155
  .advads-conditions-single.advads-buttonset label span { margin: 0; padding: 0; line-height: inherit; }
156
  .advads-conditions-postid-buttons { padding: 0 10px; }
157
  .advads-conditions-postids-show-search { margin-left: .5em !important; }
160
  .advads-conditions-postids-autocomplete-suggestions li span.left { float: left; }
161
  .advads-conditions-postids-autocomplete-suggestions li span.right { float: right; color: #aaa; font-size: .8em; }
162
 
 
 
 
 
 
163
  #ad-display-box .advads-conditions-terms-show-search { height: 22px; line-height: 22px; font-weight: bold; font-size: 1.5em; }
164
  .advads-conditions-terms-search { display: none; }
165
  .post-type-advanced_ads #ad-parameters-box .advads-ad-parameters-spinner { display: block; float: none; }
274
  */
275
  .advads-placement-description { display: none; }
276
  .advads-placements-new-form .advads-placement-type { position: relative; top: 0; left: 0; float: left; width: 140px; margin: 15px 0 0 15px; }
277
+ .advads-placements-new-form .advads-placement-type .advads-button { background: none; border-radius: 0; height: auto; }
278
+ .advads-placements-new-form .advads-placement-type .advads-button-text { padding: 0; width: 140px; height: 105px; border: solid 1px #0085ba; border-radius: 3px; box-shadow: 0px 0px 2px #0085ba; overflow: hidden; box-sizing: border-box; }
279
+ .advads-placements-new-form .advads-placement-type .advads-button-text img { max-width: 100%; pointer-events: none; }
280
  .advads-placements-new-form .advads-placement-type label { display: inline-block; width: 140px; text-align: center; border: 0; padding: 0; }
281
+ .advads-placements-new-form .advads-buttonset .advads-button.advads-ui-state-active { outline: 8px solid #2ea2cc; border: 0; }
282
  .advads-placements-new-form .advads-placement-type label .description { padding: 10px; }
283
  .advads-placements-new-form .advads-error-message { display: none; }
284
  .advads-placements-table { min-width: 80%; border-collapse: collapse; background: #fff; }
admin/assets/css/ui.css ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .advads-buttonset .advads-button {
2
+ margin-left: 0;
3
+ margin-right: -.3em;
4
+ }
5
+ .advads-buttonset .advads-button.advads-ui-state-active {
6
+ /*border-color: #0074a2 !important;*/
7
+ border-color: #2ea2cc !important;
8
+ background: #2ea2cc !important;
9
+ color: #fff !important;
10
+ box-shadow: none;
11
+ border-width: 1px;
12
+ }
13
+ .advads-button {
14
+ text-decoration: none;
15
+ display: inline-block;
16
+ position: relative;
17
+ padding: 0;
18
+ line-height: normal;
19
+ margin-right: .1em;
20
+ cursor: pointer;
21
+ vertical-align: middle;
22
+ text-align: center;
23
+ overflow: visible;
24
+ color: #555;
25
+ border: 1px solid #d3d3d3;
26
+ background: #e6e6e6;
27
+ font-weight: normal;
28
+ font-family: Verdana,Arial,sans-serif;
29
+ font-size: 1.1em;
30
+ }
31
+ .advads-button .advads-button-text {
32
+ display: block;
33
+ line-height: normal;
34
+ padding: .4em 1em;
35
+ }
36
+ .advads-accessible {
37
+ border: 0;
38
+ clip: rect(0 0 0 0);
39
+ height: 1px;
40
+ margin: -1px;
41
+ overflow: hidden;
42
+ padding: 0;
43
+ position: absolute;
44
+ width: 1px;
45
+ }
46
+ .advads-tooltip {
47
+ padding: 8px;
48
+ position: absolute;
49
+ z-index: 9999;
50
+ max-width: 300px;
51
+ box-shadow: 0 0 5px #aaa;
52
+ border-radius: 4px;
53
+ border: 1px solid #aaa;
54
+ border-width: 2px;
55
+ background: #fff;
56
+ color: #222;
57
+ font-family: Verdana,Arial,sans-serif;
58
+ font-size: 1.1em;
59
+ }
60
+
61
+ /* jQueryUI autocomplete */
62
+ .ui-menu-item:hover {
63
+ border: 1px solid #999;
64
+ background: #dadada;
65
+ color: #212121;
66
+ }
67
+
admin/assets/js/admin.js CHANGED
@@ -92,9 +92,7 @@ jQuery( document ).ready( function ( $ ) {
92
  } )
93
 
94
  // activate general buttons
95
- if ( $.fn.advads_buttonset ) {
96
- $( '.advads-buttonset' ).advads_buttonset()
97
- }
98
  // activate accordions
99
  if ( $.fn.accordion ) {
100
  $( '.advads-accordion' ).accordion( {
@@ -395,14 +393,11 @@ jQuery( document ).ready( function ( $ ) {
395
  * PLACEMENTS
396
  */
397
  // show image tooltips
398
- if ( $.fn.advads_tooltip ) {
399
- $( '.advads-placements-new-form .advads-placement-type' ).advads_tooltip( {
400
- items: 'label',
401
- content: function () {
402
- return $( this ).parents( '.advads-placement-type' ).find( '.advads-placement-description' ).html()
403
- }
404
- } )
405
- }
406
 
407
  // keep track of placements that were changed
408
  $( 'form#advanced-ads-placements-form input, #advanced-ads-placements-form select' ).on( 'change', function () {
@@ -875,62 +870,6 @@ function advads_ads_txt_find_issues () {
875
 
876
  }
877
 
878
- jQuery.fn.advads_tooltip = function () {
879
- return _advads_apply_jqueryui_widget.call( this, 'tooltip', [ 'tooltip' ], arguments )
880
- }
881
-
882
- jQuery.fn.advads_button = function () {
883
- return _advads_apply_jqueryui_widget.call( this, 'button', [ 'button' ], arguments )
884
- }
885
-
886
- jQuery.fn.advads_buttonset = function () {
887
- return _advads_apply_jqueryui_widget.call( this, 'buttonset', [ 'button', 'buttonset' ], arguments )
888
- }
889
-
890
- /**
891
- * Apply jQueryUI widget.
892
- *
893
- * @param str name Widget name.
894
- * @param arr revoke Names of Twitter Bootstrap widgets to revoke.
895
- * @param arguments_ mixed Widget arguments.
896
- */
897
- function _advads_apply_jqueryui_widget ( name, revoke, args ) {
898
- var can_apply = true
899
-
900
- jQuery.each( revoke, function ( _index, _name ) {
901
- if ( jQuery.fn[ _name ].noConflict ) {
902
- // Revoke Twitter Bootstrap, assign jQuery UI.
903
- jQuery.fn[ _name ].noConflict()
904
- }
905
- can_apply = _advads_can_apply_jqueryui_widget( _name )
906
- } )
907
-
908
- if ( ! can_apply ) {
909
- // The culprit is not Bootstrap, we haven't been able to assign jQuery UI.
910
- jQuery( '.advads-jqueryui-error' ).show()
911
- return
912
- }
913
-
914
- var r = this[ name ].apply( this, args )
915
- return r
916
- }
917
-
918
- /**
919
- * Check whether jQueryUI widget was overridden by another library.
920
- *
921
- * @param name Widget name.
922
- * @return bool
923
- */
924
- var _advads_can_apply_jqueryui_widget = (function ( name ) {
925
- var r = {}
926
- return function ( name ) {
927
- if ( ! r.hasOwnProperty( name ) ) {
928
- var needle = 'prior to initialization;' // A string from jquery-ui source code.
929
- r[ name ] = jQuery.fn[ name ].toString().indexOf( needle ) !== -1
930
- }
931
- return r[ name ]
932
- }
933
- })()
934
 
935
  window.advanced_ads_admin = window.advanced_ads_admin || {}
936
  advanced_ads_admin.filesystem = {
92
  } )
93
 
94
  // activate general buttons
95
+ $( '.advads-buttonset' ).advads_buttonset()
 
 
96
  // activate accordions
97
  if ( $.fn.accordion ) {
98
  $( '.advads-accordion' ).accordion( {
393
  * PLACEMENTS
394
  */
395
  // show image tooltips
396
+ $( '.advads-placements-new-form .advads-placement-type' ).advads_tooltip( {
397
+ content: function () {
398
+ return jQuery( this ).find( '.advads-placement-description' ).html()
399
+ }
400
+ } )
 
 
 
401
 
402
  // keep track of placements that were changed
403
  $( 'form#advanced-ads-placements-form input, #advanced-ads-placements-form select' ).on( 'change', function () {
870
 
871
  }
872
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
873
 
874
  window.advanced_ads_admin = window.advanced_ads_admin || {}
875
  advanced_ads_admin.filesystem = {
admin/assets/js/conditions.js CHANGED
@@ -48,12 +48,8 @@ jQuery( document ).ready(
48
  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>'
49
  }
50
  condition_list_target.find( 'tbody' ).append( newline )
51
- if ( jQuery.fn.advads_buttonset ) {
52
- condition_list_target.find( 'tbody .advads-conditions-single.advads-buttonset' ).advads_buttonset()
53
- }
54
- if ( jQuery.fn.advads_button ) {
55
- condition_list_target.find( 'tbody .advads-conditions-connector input' ).advads_button()
56
- }
57
  // increase count.
58
  condition_index++
59
  condition_form_container.find( '.advads-conditions-index' ).val( condition_index )
@@ -100,7 +96,7 @@ jQuery( document ).ready(
100
  minLength: 1,
101
  select: function ( event, ui ) {
102
  // append new line with input fields.
103
- $( '<label class="button ui-state-active">' + ui.item.label + '<input type="hidden" name="' + self.data( 'inputName' ) + '" value="' + ui.item.value + '"></label>' ).appendTo( self.siblings( '.advads-conditions-terms-buttons' ) )
104
 
105
  // show / hide other elements
106
  // $( '.advads-display-conditions-individual-post' ).hide();
@@ -135,7 +131,7 @@ jQuery( document ).ready(
135
  minLength: 1,
136
  select: function ( event, ui ) {
137
  // append new line with input fields
138
- var newline = $( '<label class="button ui-state-active">' + ui.item.label + '</label>' )
139
  $( '<input type="hidden" name="' + self.dataset.fieldName + '[value][]" value="' + ui.item.value + '"/>' ).appendTo( newline )
140
  newline.insertBefore( $( self ).parent( '.advads-conditions-postids-search-line' ) )
141
  },
@@ -180,19 +176,18 @@ jQuery( document ).ready(
180
  }
181
  )
182
  // activate and toggle conditions connector option.
183
- $( '.advads-conditions-connector input' ).advads_button()
184
 
185
  // dynamically change label.
186
- $( document ).on( 'click', '.advads-conditions-connector input', function () {
187
- if ( $( this ).is( ':checked' ) ) {
188
- $( this ).advads_button( 'option', 'label', advadstxt.condition_or )
189
- $( this ).parents( '.advads-conditions-connector' ).addClass( 'advads-conditions-connector-or' ).removeClass( 'advads-conditions-connector-and' )
190
- } else {
191
- $( this ).advads_button( 'option', 'label', advadstxt.condition_and )
192
- $( this ).parents( '.advads-conditions-connector' ).addClass( 'advads-conditions-connector-and' ).removeClass( 'advads-conditions-connector-or' )
193
- }
194
  }
195
- )
196
  // remove a line with a display or visitor condition.
197
  $( document ).on( 'click', '.advads-conditions-remove', function () {
198
  $( this ).parents( '.advads-conditions-table tr' ).prev( 'tr' ).remove()
@@ -282,4 +277,4 @@ function advads_post_search ( searchParam, callback ) {
282
  },
283
  'json'
284
  )
285
- }
48
  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>'
49
  }
50
  condition_list_target.find( 'tbody' ).append( newline )
51
+ condition_list_target.find( 'tbody .advads-conditions-single.advads-buttonset' ).advads_buttonset()
52
+ condition_list_target.find( 'tbody .advads-conditions-connector input' ).advads_button()
 
 
 
 
53
  // increase count.
54
  condition_index++
55
  condition_form_container.find( '.advads-conditions-index' ).val( condition_index )
96
  minLength: 1,
97
  select: function ( event, ui ) {
98
  // append new line with input fields.
99
+ $( '<label class="button advads-ui-state-active">' + ui.item.label + '<input type="hidden" name="' + self.data( 'inputName' ) + '" value="' + ui.item.value + '"></label>' ).appendTo( self.siblings( '.advads-conditions-terms-buttons' ) )
100
 
101
  // show / hide other elements
102
  // $( '.advads-display-conditions-individual-post' ).hide();
131
  minLength: 1,
132
  select: function ( event, ui ) {
133
  // append new line with input fields
134
+ var newline = $( '<label class="button advads-ui-state-active">' + ui.item.label + '</label>' )
135
  $( '<input type="hidden" name="' + self.dataset.fieldName + '[value][]" value="' + ui.item.value + '"/>' ).appendTo( newline )
136
  newline.insertBefore( $( self ).parent( '.advads-conditions-postids-search-line' ) )
137
  },
176
  }
177
  )
178
  // activate and toggle conditions connector option.
179
+ $( '.advads-conditions-connector input' ).advads_button();
180
 
181
  // dynamically change label.
182
+ jQuery( document ).on( 'click', '.advads-conditions-connector input', function () {
183
+ if ( jQuery( this ).is( ':checked' ) ) {
184
+ jQuery( this ).next( 'label' ).find( 'span' ).html( advadstxt.condition_or );
185
+ jQuery( this ).parents( '.advads-conditions-connector' ).addClass( 'advads-conditions-connector-or' ).removeClass( 'advads-conditions-connector-and' )
186
+ } else {
187
+ jQuery( this ).next( 'label' ).find( 'span' ).html( advadstxt.condition_and );
188
+ jQuery( this ).parents( '.advads-conditions-connector' ).addClass( 'advads-conditions-connector-and' ).removeClass( 'advads-conditions-connector-or' )
 
189
  }
190
+ } );
191
  // remove a line with a display or visitor condition.
192
  $( document ).on( 'click', '.advads-conditions-remove', function () {
193
  $( this ).parents( '.advads-conditions-table tr' ).prev( 'tr' ).remove()
277
  },
278
  'json'
279
  )
280
+ }
admin/assets/js/shortcode.js CHANGED
@@ -9,10 +9,10 @@
9
  init : function( ed, url ) {
10
  ed.addButton( 'advads_shortcode_button', {
11
  title: ed.getLang( 'advads_shortcode.title', 'Advanced ads shortcodes' ),
12
- image : url + '/../img/tinymce-icon.png',
13
  cmd: 'advads_shortcode_command'
14
  });
15
-
16
  ed.addCommand( 'advads_shortcode_command', function() {
17
  ed.windowManager.open({
18
  title: ed.getLang( 'advads_shortcode.title', 'Advanced Ads shortcodes' ),
@@ -26,7 +26,7 @@
26
  buttons: [{
27
  text: ed.getLang( 'advads_shortcode.ok', 'Add shortcode' ),
28
  id: 'advads-shortcode-button-insert-wrap',
29
-
30
  onclick: function( e ) {
31
  if ( jQuery( '#advads-shortcode-modal-container-body #advads-select-for-shortcode' ).length > 0 ) {
32
  var item = jQuery( '#advads-select-for-shortcode option:selected' ).val();
@@ -51,15 +51,15 @@
51
  text: ed.getLang( 'advads_shortcode.cancel', 'Cancel' ),
52
  onclick: 'close'
53
  }],
54
-
55
  });
56
 
57
  append_select_field();
58
 
59
  });
60
- },
61
  });
62
-
63
  // Register the plugin
64
  tinymce.PluginManager.add( 'advads_shortcode', tinymce.plugins.advads_shortcode );
65
 
@@ -80,14 +80,14 @@
80
  })
81
  .done( function( data, textStatus, jqXHR ) {
82
  container_body.html( data );
83
-
84
  jQuery( '#advads-select-for-shortcode' ).on( 'change', function() {
85
  if ( jQuery( this ).prop( 'selectedIndex' ) === 0 ) {
86
  insert_button_wrap.addClass( 'mce-disabled' );
87
  insert_button.prop( 'disabled', true );
88
  } else {
89
  insert_button_wrap.removeClass( 'mce-disabled' );
90
- insert_button.prop( 'disabled', false );
91
  }
92
  });
93
 
@@ -96,4 +96,4 @@
96
  container_body.html( errorThrown );
97
  });
98
  }
99
- })();
9
  init : function( ed, url ) {
10
  ed.addButton( 'advads_shortcode_button', {
11
  title: ed.getLang( 'advads_shortcode.title', 'Advanced ads shortcodes' ),
12
+ image: ed.getLang( 'advads_shortcode.image' ),
13
  cmd: 'advads_shortcode_command'
14
  });
15
+
16
  ed.addCommand( 'advads_shortcode_command', function() {
17
  ed.windowManager.open({
18
  title: ed.getLang( 'advads_shortcode.title', 'Advanced Ads shortcodes' ),
26
  buttons: [{
27
  text: ed.getLang( 'advads_shortcode.ok', 'Add shortcode' ),
28
  id: 'advads-shortcode-button-insert-wrap',
29
+
30
  onclick: function( e ) {
31
  if ( jQuery( '#advads-shortcode-modal-container-body #advads-select-for-shortcode' ).length > 0 ) {
32
  var item = jQuery( '#advads-select-for-shortcode option:selected' ).val();
51
  text: ed.getLang( 'advads_shortcode.cancel', 'Cancel' ),
52
  onclick: 'close'
53
  }],
54
+
55
  });
56
 
57
  append_select_field();
58
 
59
  });
60
+ },
61
  });
62
+
63
  // Register the plugin
64
  tinymce.PluginManager.add( 'advads_shortcode', tinymce.plugins.advads_shortcode );
65
 
80
  })
81
  .done( function( data, textStatus, jqXHR ) {
82
  container_body.html( data );
83
+
84
  jQuery( '#advads-select-for-shortcode' ).on( 'change', function() {
85
  if ( jQuery( this ).prop( 'selectedIndex' ) === 0 ) {
86
  insert_button_wrap.addClass( 'mce-disabled' );
87
  insert_button.prop( 'disabled', true );
88
  } else {
89
  insert_button_wrap.removeClass( 'mce-disabled' );
90
+ insert_button.prop( 'disabled', false );
91
  }
92
  });
93
 
96
  container_body.html( errorThrown );
97
  });
98
  }
99
+ })();
admin/assets/js/ui.js ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function ( $ ) {
2
+ /**
3
+ * Button.
4
+ */
5
+ $.fn.advads_button = function() {
6
+ var $buttonset = jQuery( this );
7
+ var $ancestor = $buttonset.parent();
8
+
9
+ $buttonset.each( function() {
10
+ $this = jQuery( this );
11
+ if ( $this.data( 'advads_button' ) ) {
12
+ return true;
13
+ }
14
+ $this.data( 'advads_button', true );
15
+
16
+ var $button = jQuery( this );
17
+ var $label = jQuery( 'label[for="' + $button.attr( 'id' ) + '"]', $ancestor );
18
+ var type = $button.attr( 'type' );
19
+
20
+ $button.addClass( 'advads-accessible' );
21
+ $label.addClass( 'advads-button' );
22
+ $label.wrapInner( '<span class="advads-button-text"></span>' );
23
+
24
+ if ( $button.is( ':checked' ) ) {
25
+ $label.addClass( 'advads-ui-state-active' );
26
+ }
27
+
28
+ $button.change( function() {
29
+ var $changed = jQuery( this );
30
+ var $label = jQuery( 'label[for="' + $changed.attr( 'id' ) + '"]', $ancestor );
31
+
32
+ if ( type === 'radio' ) {
33
+ $buttonset.parent().find( 'label' ).removeClass( 'advads-ui-state-active' );
34
+ }
35
+
36
+ if ( $changed.is( ':checked' ) ) {
37
+ $label.addClass( 'advads-ui-state-active' );
38
+ } else {
39
+ $label.removeClass( 'advads-ui-state-active' );
40
+ }
41
+ } );
42
+
43
+ } );
44
+ };
45
+ /**
46
+ * Buttonset.
47
+ */
48
+ $.fn.advads_buttonset = function() {
49
+ var $that = jQuery( this );
50
+
51
+ $that.each( function() {
52
+ $this = jQuery( this );
53
+
54
+ if ( $this.data( 'advads_buttonset' ) ) {
55
+ return true;
56
+ }
57
+ $this.data( 'advads_buttonset', true );
58
+
59
+ var items = 'input[type=checkbox], input[type=radio]';
60
+ var $all_buttons = $this.find( items );
61
+ $this.addClass( 'advads-buttonset' );
62
+
63
+ $all_buttons.advads_button();
64
+ } );
65
+ };
66
+
67
+ /**
68
+ * Tooltip.
69
+ *
70
+ * @param {Function} options.content A function that returns the content.
71
+ */
72
+ $.fn.advads_tooltip = function( options ) {
73
+ var tooltip;
74
+ var tooltip_target;
75
+
76
+ if ( ! options.content ) {
77
+ return this;
78
+ }
79
+
80
+ function open( event ) {
81
+ var $target = jQuery( event.currentTarget );
82
+
83
+ // check if the correct tooltip is already open.
84
+ if ( tooltip && $target.is( tooltip_target ) ) {
85
+ return;
86
+ }
87
+ if ( tooltip ) {
88
+ tooltip.remove();
89
+ tooltip = null;
90
+ tooltip_target = null;
91
+ }
92
+
93
+ if ( event.type === 'mouseover' ) {
94
+ jQuery( $target ).on( 'mouseleave', close );
95
+ }
96
+ if ( event.type === 'focusin' ) {
97
+ jQuery( $target ).on( 'focusout', close );
98
+ }
99
+
100
+ var content = options.content.call( $target )
101
+ if ( content ) {
102
+ tooltip = $( '<div>' ).addClass( 'advads-tooltip' );
103
+ $( '<div>' ).addClass( 'advads-tooltip-content' ).appendTo( tooltip );
104
+ tooltip.appendTo( 'body' );
105
+ tooltip.find( '.advads-tooltip-content' ).html( content );
106
+
107
+ position = $target.offset();
108
+ position.top += $target.outerHeight() + 15;
109
+ tooltip.offset( position );
110
+ tooltip_target = $target;
111
+
112
+ tooltip.show();
113
+ }
114
+
115
+ }
116
+ function close( event ) {
117
+ if ( tooltip ) {
118
+ tooltip.remove();
119
+ tooltip = null;
120
+ tooltip_target = null;
121
+ }
122
+ };
123
+
124
+ this.each( function() {
125
+ $this = jQuery( this );
126
+ if ( $this.data( 'advads_tooltip' ) ) {
127
+ return true;
128
+ }
129
+ $this.data( 'advads_tooltip', true );
130
+
131
+ $this
132
+ .on( 'mouseover', open )
133
+ .on( 'focusin', open );
134
+ } );
135
+ };
136
+ } )( jQuery );
admin/class-advanced-ads-admin.php CHANGED
@@ -181,11 +181,8 @@ class Advanced_Ads_Admin {
181
  * Register and enqueue admin-specific style sheet.
182
  */
183
  public function enqueue_admin_styles() {
 
184
  wp_enqueue_style( $this->plugin_slug . '-admin-styles', plugins_url( 'assets/css/admin.css', __FILE__ ), array(), ADVADS_VERSION );
185
- if ( self::screen_belongs_to_advanced_ads() ) {
186
- // jQuery ui smoothness style 1.11.4.
187
- wp_enqueue_style( $this->plugin_slug . '-jquery-ui-styles', plugins_url( 'assets/jquery-ui/jquery-ui.min.css', __FILE__ ), array(), '1.11.4' );
188
- }
189
  }
190
 
191
  /**
@@ -204,15 +201,11 @@ class Advanced_Ads_Admin {
204
  wp_localize_script( $this->plugin_slug . '-admin-global-script', 'advadsglobal', $params );
205
 
206
  if ( self::screen_belongs_to_advanced_ads() ) {
207
- wp_register_script( $this->plugin_slug . '-admin-script', plugins_url( 'assets/js/admin.js', __FILE__ ), array( 'jquery', 'jquery-ui-autocomplete', 'jquery-ui-button' ), ADVADS_VERSION, false );
208
- wp_register_script( $this->plugin_slug . '-conditions-script', plugins_url( 'assets/js/conditions.js', __FILE__ ), array( 'jquery', 'jquery-ui-autocomplete', 'jquery-ui-button' ), ADVADS_VERSION, false );
 
209
  wp_register_script( $this->plugin_slug . '-wizard-script', plugins_url( 'assets/js/wizard.js', __FILE__ ), array( 'jquery' ), ADVADS_VERSION, false );
210
 
211
- // jquery ui.
212
- wp_enqueue_script( 'jquery-ui-accordion' );
213
- wp_enqueue_script( 'jquery-ui-button' );
214
- wp_enqueue_script( 'jquery-ui-tooltip' );
215
-
216
  // just register this script for later inclusion on ad group list page.
217
  wp_register_script( 'inline-edit-group-ads', plugins_url( 'assets/js/inline-edit-group-ads.js', __FILE__ ), array( 'jquery' ), ADVADS_VERSION, false );
218
 
@@ -359,7 +352,6 @@ class Advanced_Ads_Admin {
359
  if ( current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
360
  if ( $this->screen_belongs_to_advanced_ads() ) {
361
  include ADVADS_BASE_PATH . 'admin/views/notices/adblock.php';
362
- include ADVADS_BASE_PATH . 'admin/views/notices/jqueryui_error.php';
363
  }
364
  }
365
 
181
  * Register and enqueue admin-specific style sheet.
182
  */
183
  public function enqueue_admin_styles() {
184
+ wp_enqueue_style( $this->plugin_slug . '-ui-styles', plugins_url( 'assets/css/ui.css', __FILE__ ), array(), ADVADS_VERSION );
185
  wp_enqueue_style( $this->plugin_slug . '-admin-styles', plugins_url( 'assets/css/admin.css', __FILE__ ), array(), ADVADS_VERSION );
 
 
 
 
186
  }
187
 
188
  /**
201
  wp_localize_script( $this->plugin_slug . '-admin-global-script', 'advadsglobal', $params );
202
 
203
  if ( self::screen_belongs_to_advanced_ads() ) {
204
+ wp_register_script( $this->plugin_slug . '-ui-scripts', plugins_url( 'assets/js/ui.js', __FILE__ ), array( 'jquery' ), ADVADS_VERSION, false );
205
+ wp_register_script( $this->plugin_slug . '-admin-script', plugins_url( 'assets/js/admin.js', __FILE__ ), array( 'jquery', $this->plugin_slug . '-ui-scripts', 'jquery-ui-autocomplete' ), ADVADS_VERSION, false );
206
+ wp_register_script( $this->plugin_slug . '-conditions-script', plugins_url( 'assets/js/conditions.js', __FILE__ ), array( 'jquery', $this->plugin_slug . '-ui-scripts' ), ADVADS_VERSION, false );
207
  wp_register_script( $this->plugin_slug . '-wizard-script', plugins_url( 'assets/js/wizard.js', __FILE__ ), array( 'jquery' ), ADVADS_VERSION, false );
208
 
 
 
 
 
 
209
  // just register this script for later inclusion on ad group list page.
210
  wp_register_script( 'inline-edit-group-ads', plugins_url( 'assets/js/inline-edit-group-ads.js', __FILE__ ), array( 'jquery' ), ADVADS_VERSION, false );
211
 
352
  if ( current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
353
  if ( $this->screen_belongs_to_advanced_ads() ) {
354
  include ADVADS_BASE_PATH . 'admin/views/notices/adblock.php';
 
355
  }
356
  }
357
 
admin/includes/ad-health-notices.php CHANGED
@@ -72,16 +72,6 @@ $advanced_ads_ad_health_notices = apply_filters(
72
  'text' => '<a href="' . admin_url( 'admin.php?page=advanced-ads-settings#top#support' ) . '">' . esc_html__( 'Advanced Ads related constants enabled', 'advanced-ads' ) . '</a>',
73
  'type' => 'notice',
74
  ),
75
- // possible JavaScript conflicts
76
- // Advanced_Ads_Checks::jquery_ui_conflict().
77
- 'jquery_ui_conflict' => array(
78
- 'text' => sprintf(
79
- // translators: %s is a target URL.
80
- __( 'Possible conflict between jQueryUI library, used by Advanced Ads and other libraries (probably <a href="%s">Twitter Bootstrap</a>). This might lead to misfortunate formats in forms, but should not damage features.', 'advanced-ads' ),
81
- 'http://getbootstrap.com/javascript/#js-noconflict'
82
- ),
83
- 'type' => 'problem',
84
- ),
85
  // adblocker assets expired
86
  // Advanced_Ads_Checks::assets_expired().
87
  'assets_expired' => array(
72
  'text' => '<a href="' . admin_url( 'admin.php?page=advanced-ads-settings#top#support' ) . '">' . esc_html__( 'Advanced Ads related constants enabled', 'advanced-ads' ) . '</a>',
73
  'type' => 'notice',
74
  ),
 
 
 
 
 
 
 
 
 
 
75
  // adblocker assets expired
76
  // Advanced_Ads_Checks::assets_expired().
77
  'assets_expired' => array(
admin/includes/class-ad-type.php CHANGED
@@ -725,8 +725,12 @@ class Advanced_Ads_Admin_Ad_Type {
725
  return;
726
  }
727
  }
728
- // Display ad injection information after ad is created.
729
- if ( isset( $_GET['message'] ) && 6 === $_GET['message'] ) {
 
 
 
 
730
  include ADVADS_BASE_PATH . 'admin/views/placement-injection-top.php';
731
  }
732
  }
725
  return;
726
  }
727
  }
728
+ /**
729
+ * Display ad injection information after ad is created.
730
+ *
731
+ * Set `advanced-ads-ad-edit-show-placement-injection` to false if you want to prevent the box from appearing
732
+ */
733
+ if ( isset( $_GET['message'] ) && 6 === $_GET['message'] && apply_filters( 'advanced-ads-ad-edit-show-placement-injection', true ) ) {
734
  include ADVADS_BASE_PATH . 'admin/views/placement-injection-top.php';
735
  }
736
  }
admin/includes/class-menu.php CHANGED
@@ -91,7 +91,7 @@ class Advanced_Ads_Admin_Menu {
91
  Advanced_Ads_Plugin::user_cap( 'advanced_ads_see_interface' ),
92
  $this->plugin_slug,
93
  array( $this, 'display_overview_page' ),
94
- 'dashicons-chart-line',
95
  '58.74'
96
  );
97
 
91
  Advanced_Ads_Plugin::user_cap( 'advanced_ads_see_interface' ),
92
  $this->plugin_slug,
93
  array( $this, 'display_overview_page' ),
94
+ Advanced_Ads_Plugin::get_icon_svg(),
95
  '58.74'
96
  );
97
 
admin/includes/class-meta-box.php CHANGED
@@ -128,7 +128,7 @@ class Advanced_Ads_Admin_Meta_Boxes {
128
  if ( ! defined( 'AAT_VERSION' ) ) {
129
  add_meta_box(
130
  'advads-tracking-pitch',
131
- __( 'Ad Stats', 'advanced-ads' ),
132
  array( $this, 'markup_meta_boxes' ),
133
  $post_type,
134
  'normal',
@@ -152,6 +152,8 @@ class Advanced_Ads_Admin_Meta_Boxes {
152
 
153
  // force AA meta boxes to never be completely hidden by screen options.
154
  add_filter( 'hidden_meta_boxes', array( $this, 'unhide_meta_boxes' ), 10, 2 );
 
 
155
 
156
  $whitelist = apply_filters(
157
  'advanced-ads-ad-edit-allowed-metaboxes',
@@ -371,7 +373,29 @@ class Advanced_Ads_Admin_Meta_Boxes {
371
  }
372
 
373
  // return only hidden elements which are not among the Advanced Ads meta box ids.
374
- return array_diff( $hidden, $this->meta_box_ids );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  }
376
 
377
  /**
128
  if ( ! defined( 'AAT_VERSION' ) ) {
129
  add_meta_box(
130
  'advads-tracking-pitch',
131
+ __( 'Statistics', 'advanced-ads' ),
132
  array( $this, 'markup_meta_boxes' ),
133
  $post_type,
134
  'normal',
152
 
153
  // force AA meta boxes to never be completely hidden by screen options.
154
  add_filter( 'hidden_meta_boxes', array( $this, 'unhide_meta_boxes' ), 10, 2 );
155
+ // hide the checkboxes for "unhideable" meta boxes within screen options via CSS.
156
+ add_action( 'admin_head', array( $this, 'unhide_meta_boxes_style' ) );
157
 
158
  $whitelist = apply_filters(
159
  'advanced-ads-ad-edit-allowed-metaboxes',
373
  }
374
 
375
  // return only hidden elements which are not among the Advanced Ads meta box ids.
376
+ return array_diff( $hidden, (array) apply_filters( 'advanced-ads-unhide-meta-boxes', $this->meta_box_ids ) );
377
+ }
378
+
379
+ /**
380
+ * Add dynamic CSS for un-hideable meta boxes.
381
+ */
382
+ public function unhide_meta_boxes_style() {
383
+ $screen = get_current_screen();
384
+ if ( empty( $screen ) || ! isset( $screen->id ) || 'advanced_ads' !== $screen->id ) {
385
+ return;
386
+ }
387
+
388
+ $meta_boxes = (array) apply_filters( 'advanced-ads-unhide-meta-boxes', $this->meta_box_ids );
389
+ if ( empty( $meta_boxes ) ) {
390
+ return;
391
+ }
392
+
393
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- we don't need to escape the string we just concatenated.
394
+ printf( '<style>%s {display: none;}</style>', implode( ', ', array_reduce( $meta_boxes, function( $styles, $box_id ) {
395
+ $styles[] = sprintf( 'label[for="%s-hide"]', $box_id );
396
+
397
+ return $styles;
398
+ }, array() ) ) );
399
  }
400
 
401
  /**
admin/includes/class-overview-widgets.php CHANGED
@@ -639,7 +639,7 @@ endif;
639
  if ( 'ga' !== Advanced_Ads_Tracking_Plugin::get_instance()->get_tracking_method() ) {
640
 
641
  // don’t show Tracking link if Analytics method is enabled.
642
- $add_ons['tracking']['desc'] = '<a href="' . admin_url( '/admin.php?page=advanced-ads-stats' ) . '">' . __( 'Visit your ad stats', 'advanced-ads' ) . '</a>';
643
  } else {
644
  $add_ons['tracking']['desc'] = '';
645
  }
639
  if ( 'ga' !== Advanced_Ads_Tracking_Plugin::get_instance()->get_tracking_method() ) {
640
 
641
  // don’t show Tracking link if Analytics method is enabled.
642
+ $add_ons['tracking']['desc'] = '<a href="' . admin_url( '/admin.php?page=advanced-ads-stats' ) . '">' . __( 'Visit your ad statistics', 'advanced-ads' ) . '</a>';
643
  } else {
644
  $add_ons['tracking']['desc'] = '';
645
  }
admin/includes/class-shortcode-creator.php CHANGED
@@ -45,29 +45,39 @@ class Advanced_Ads_Shortcode_Creator {
45
  return;
46
  }
47
 
48
- add_filter( 'mce_external_plugins', array( $this, 'add_plugin' ) );
49
 
50
  add_filter( 'mce_buttons', array( $this, 'register_buttons' ) );
51
- add_filter( 'mce_external_languages', array( $this, 'add_l10n' ) );
52
  add_action( 'wp_ajax_advads_content_for_shortcode_creator', array( $this, 'get_content_for_shortcode_creator' ) );
53
 
54
- add_filter( 'the_editor', array( $this, 'add_addblocker_warning' ) );
55
- add_action( 'admin_footer', array( $this, 'maybe_show_adblocker_warning' ) );
56
  }
57
 
58
  /**
59
- * Add the plugin to array of external TinyMCE plugins
 
60
  *
61
- * @param array $plugin_array array with TinyMCE plugins.
62
  *
63
- * @return array
 
64
  */
65
- public function add_plugin( $plugin_array ) {
66
- if ( ! is_array( $plugin_array ) ) {
67
- $plugin_array = array();
68
- }
69
- $plugin_array['advads_shortcode'] = ADVADS_BASE_URL . 'admin/assets/js/shortcode.js';
70
- return $plugin_array;
 
 
 
 
 
 
 
 
 
 
71
  }
72
 
73
  /**
@@ -158,71 +168,4 @@ class Advanced_Ads_Shortcode_Creator {
158
 
159
  return $select;
160
  }
161
-
162
- /**
163
- * Add localisation
164
- *
165
- * @param array $mce_external_languages localization template.
166
- *
167
- * @return array
168
- */
169
- public function add_l10n( $mce_external_languages ) {
170
- if ( ! is_array( $mce_external_languages ) ) {
171
- $mce_external_languages = array();
172
- }
173
- $mce_external_languages['advads_shortcode'] = ADVADS_BASE_PATH . 'admin/includes/shortcode-creator-l10n.php';
174
- return $mce_external_languages;
175
- }
176
-
177
- /**
178
- * Add a warning above TinyMCE editor.
179
- *
180
- * @param string $output editor's HTML markup.
181
- *
182
- * @return string
183
- */
184
- public function add_addblocker_warning( $output ) {
185
- ob_start();
186
- ?>
187
- <div style="display: none; margin: 10px 8px; color: red;" class="advanced-ads-shortcode-button-warning">
188
- <?php
189
- printf(
190
- wp_kses(
191
- // translators: %s is a URL.
192
- __( 'Please, either switch off your ad blocker or disable the shortcode button in the <a href="%s" target="_blank">settings</a>.', 'advanced-ads' ),
193
- array(
194
- 'a' => array(
195
- 'href' => array(),
196
- 'target' => array(),
197
- ),
198
- )
199
- ),
200
- esc_url( admin_url( 'admin.php?page=advanced-ads-settings' ) )
201
- );
202
- ?>
203
- </div>
204
- <?php
205
- return ob_get_clean() . $output;
206
- }
207
-
208
- /**
209
- * Show a warning above TinyMCE editor when an adblock is enabled.
210
- */
211
- public function maybe_show_adblocker_warning() {
212
- ?>
213
- <script>
214
- (function(){
215
- if ( 'undefined' === typeof advanced_ads_adblocker_test ) {
216
- try {
217
- var messages = document.querySelectorAll( '.advanced-ads-shortcode-button-warning' )
218
- } catch ( e ) { return; }
219
- for ( var i = 0; i < messages.length; i++ ) {
220
- messages[ i ].style.display = 'block';
221
- }
222
- }
223
- })();
224
- </script>
225
- <?php
226
- }
227
-
228
  }
45
  return;
46
  }
47
 
 
48
 
49
  add_filter( 'mce_buttons', array( $this, 'register_buttons' ) );
 
50
  add_action( 'wp_ajax_advads_content_for_shortcode_creator', array( $this, 'get_content_for_shortcode_creator' ) );
51
 
52
+ add_filter( 'tiny_mce_plugins', array( $this, 'tiny_mce_plugins' ) );
53
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
54
  }
55
 
56
  /**
57
+ * Add the plugin to the array of default TinyMCE plugins.
58
+ * We do not use the array of external TinyMCE plugins because we print the plugin file inline.
59
  *
60
+ * @see self::admin_enqueue_scripts
61
  *
62
+ * @param array $plugins An array of default TinyMCE plugins.
63
+ * @return array $plugins An array of default TinyMCE plugins.
64
  */
65
+ public function tiny_mce_plugins( $plugins ) {
66
+ $plugins[] = 'advads_shortcode';
67
+ return $plugins;
68
+ }
69
+
70
+ /**
71
+ * Include the shortcode plugin inline to prevent it from being blocked by ad blockers.
72
+ */
73
+ public function admin_enqueue_scripts() {
74
+ // Add the localization.
75
+ include_once ADVADS_BASE_PATH . 'admin/includes/shortcode-creator-l10n.php';
76
+ $script = $strings . "\n";
77
+ // Add the plugin.
78
+ $script .= file_get_contents( ADVADS_BASE_PATH . 'admin/assets/js/shortcode.js' );
79
+
80
+ wp_add_inline_script( 'wp-tinymce', $script );
81
  }
82
 
83
  /**
168
 
169
  return $select;
170
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
admin/includes/shortcode-creator-l10n.php CHANGED
@@ -17,8 +17,9 @@ function advads_shortcode_creator_l10n() {
17
  'title' => _x( 'Add an ad', 'shortcode creator', 'advanced-ads' ),
18
  'ok' => _x( 'Add shortcode', 'shortcode creator', 'advanced-ads' ),
19
  'cancel' => _x( 'Cancel', 'shortcode creator', 'advanced-ads' ),
 
20
  );
21
- $locale = _WP_Editors::$mce_locale;
22
  $translated = 'tinyMCE.addI18n("' . $locale . '.advads_shortcode", ' . wp_json_encode( $strings ) . ");\n";
23
 
24
  return $translated;
17
  'title' => _x( 'Add an ad', 'shortcode creator', 'advanced-ads' ),
18
  'ok' => _x( 'Add shortcode', 'shortcode creator', 'advanced-ads' ),
19
  'cancel' => _x( 'Cancel', 'shortcode creator', 'advanced-ads' ),
20
+ 'image' => ADVADS_BASE_URL . 'admin/assets/img/tinymce-icon.png',
21
  );
22
+ $locale = _WP_Editors::get_mce_locale();
23
  $translated = 'tinyMCE.addI18n("' . $locale . '.advads_shortcode", ' . wp_json_encode( $strings ) . ");\n";
24
 
25
  return $translated;
admin/views/checks.php CHANGED
@@ -7,9 +7,6 @@
7
 
8
  $messages = array();
9
 
10
- // this check is left here even though we no longer show it here, but we don’t want to check it all the time on each page.
11
- Advanced_Ads_Checks::jquery_ui_conflict();
12
-
13
  if ( Advanced_Ads_Ad_Health_Notices::has_visible_problems() ) {
14
  $messages[] = sprintf(
15
  // translators: %1$s is a starting link tag, %2$s is closing the link tag.
7
 
8
  $messages = array();
9
 
 
 
 
10
  if ( Advanced_Ads_Ad_Health_Notices::has_visible_problems() ) {
11
  $messages[] = sprintf(
12
  // translators: %1$s is a starting link tag, %2$s is closing the link tag.
admin/views/conditions/ad-display-metabox.php CHANGED
@@ -39,25 +39,10 @@ if ( $empty_options ) :
39
  <?php
40
  endif;
41
  ?>
42
- <p class="advads-jqueryui-error advads-error-message hidden">
43
- <?php
44
- printf(
45
- wp_kses(
46
- // translators: %s is a link to a tutorial.
47
- __( 'There might be a problem with layouts and scripts in your dashboard. Please check <a href="%s" target="_blank">this article to learn more</a>.', 'advanced-ads' ),
48
- array(
49
- 'a' => array(
50
- 'href' => array(),
51
- 'target' => array(),
52
- ),
53
- )
54
- ),
55
- esc_url( ADVADS_URL ) . 'manual/jquery-problem-in-dashboard/#utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-jquery-error'
56
- );
57
- ?></p>
58
  <p><?php esc_attr_e( 'A page with this ad on it must match all of the following conditions.', 'advanced-ads' ); ?></p>
59
  <?php
60
  $conditions_list_target = 'advads-ad-display-conditions';
61
  Advanced_Ads_Display_Conditions::render_condition_list( $set_conditions, $conditions_list_target );
62
  ?></div><?php
63
- do_action( 'advanced-ads-display-conditions-after', $ad );
39
  <?php
40
  endif;
41
  ?>
42
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  <p><?php esc_attr_e( 'A page with this ad on it must match all of the following conditions.', 'advanced-ads' ); ?></p>
44
  <?php
45
  $conditions_list_target = 'advads-ad-display-conditions';
46
  Advanced_Ads_Display_Conditions::render_condition_list( $set_conditions, $conditions_list_target );
47
  ?></div><?php
48
+ do_action( 'advanced-ads-display-conditions-after', $ad );
admin/views/conditions/condition-author.php CHANGED
@@ -18,7 +18,7 @@
18
  $author_name = $_author->display_name;
19
  $field_id = 'advads-conditions-' . absint( $_author->ID ) . $rand;
20
  ?>
21
- <label class="button ui-button"
22
  for="<?php echo esc_attr( $field_id ); ?>">
23
  <?php echo esc_attr( $author_name ); ?>
24
  </label><input type="checkbox"
18
  $author_name = $_author->display_name;
19
  $field_id = 'advads-conditions-' . absint( $_author->ID ) . $rand;
20
  ?>
21
+ <label class="button advads-button"
22
  for="<?php echo esc_attr( $field_id ); ?>">
23
  <?php echo esc_attr( $author_name ); ?>
24
  </label><input type="checkbox"
admin/views/notices/jqueryui_error.php DELETED
@@ -1,3 +0,0 @@
1
- <div class="notice notice-error advads-jqueryui-error" style="display: none;">
2
- <p><?php printf( __( 'There might be a problem with layouts and scripts in your dashboard. Please check <a href="%s" target="_blank">this article to learn more</a>.', 'advanced-ads' ), ADVADS_URL . 'manual/jquery-problem-in-dashboard/#utm_source=advanced-ads&utm_medium=link&utm_campaign=notice-jquery-error' ); ?></p>
3
- </div>
 
 
 
admin/views/upgrades/pro-placements.php CHANGED
@@ -70,7 +70,7 @@ if ( class_exists( 'bbPress', false ) ) {
70
  $image = '<strong>' . $_place['title'] . '</strong><br/><p class="description">' . $_place['description'] . '</p>';
71
  endif;
72
  ?>
73
- <div class="advads-placement-type"><label class="ui-button advads-pro-link"><span class="ui-button-text">
74
  <?php
75
  // phpcs:ignore
76
  echo $image;
70
  $image = '<strong>' . $_place['title'] . '</strong><br/><p class="description">' . $_place['description'] . '</p>';
71
  endif;
72
  ?>
73
+ <div class="advads-placement-type"><label class="advads-button advads-pro-link"><span class="advads-button-text">
74
  <?php
75
  // phpcs:ignore
76
  echo $image;
advanced-ads.php CHANGED
@@ -12,7 +12,7 @@
12
  * Plugin Name: Advanced Ads
13
  * Plugin URI: https://wpadvancedads.com
14
  * Description: Manage and optimize your ads in WordPress
15
- * Version: 1.21.1
16
  * Author: Thomas Maier, Advanced Ads GmbH
17
  * Author URI: https://wpadvancedads.com
18
  * Text Domain: advanced-ads
@@ -39,7 +39,7 @@ define( 'ADVADS_BASE_DIR', dirname( ADVADS_BASE ) ); // directory of the plugin
39
  // general and global slug, e.g. to store options in WP.
40
  define( 'ADVADS_SLUG', 'advanced-ads' );
41
  define( 'ADVADS_URL', 'https://wpadvancedads.com/' );
42
- define( 'ADVADS_VERSION', '1.21.1' );
43
 
44
  // Autoloading, modules and functions.
45
 
12
  * Plugin Name: Advanced Ads
13
  * Plugin URI: https://wpadvancedads.com
14
  * Description: Manage and optimize your ads in WordPress
15
+ * Version: 1.22.0
16
  * Author: Thomas Maier, Advanced Ads GmbH
17
  * Author URI: https://wpadvancedads.com
18
  * Text Domain: advanced-ads
39
  // general and global slug, e.g. to store options in WP.
40
  define( 'ADVADS_SLUG', 'advanced-ads' );
41
  define( 'ADVADS_URL', 'https://wpadvancedads.com/' );
42
+ define( 'ADVADS_VERSION', '1.22.0' );
43
 
44
  // Autoloading, modules and functions.
45
 
classes/ad.php CHANGED
@@ -108,7 +108,7 @@ class Advanced_Ads_Ad {
108
  *
109
  * @var array $options ad options.
110
  */
111
- protected $options = array();
112
 
113
  /**
114
  * Name of the meta field to save options to
@@ -255,19 +255,17 @@ class Advanced_Ads_Ad {
255
  /**
256
  * Get options from meta field and return specific field
257
  *
258
- * @param string $field post meta key to be returned.
259
  * @param array $default default options.
260
  *
261
  * @return mixed meta field content
262
- * @todo check against default values
263
  */
264
  public function options( $field = '', $default = null ) {
265
  // retrieve options, if not given yet
266
- // -TODO may execute multiple times (if empty); bad design and risk to access unintialised data with direct access to $this->options property.
267
- if ( array() === $this->options ) {
268
  // may return false.
269
  $meta = get_post_meta( $this->id, self::$options_meta_field, true );
270
- if ( $meta ) {
271
  // merge meta with arguments given on ad load.
272
  $this->options = Advanced_Ads_Utils::merge_deep_array( array( $meta, $this->args ) );
273
  } else {
@@ -286,18 +284,33 @@ class Advanced_Ads_Ad {
286
  }
287
  }
288
 
289
- // return specific option.
290
- if ( '' !== $field ) {
291
- if ( isset( $this->options[ $field ] ) ) {
292
- return $this->options[ $field ];
293
- }
294
- } else { // return all options.
295
- if ( ! empty( $this->options ) ) {
296
- return $this->options;
 
 
 
297
  }
 
298
  }
299
 
300
- return $default;
 
 
 
 
 
 
 
 
 
 
 
301
  }
302
 
303
  /**
108
  *
109
  * @var array $options ad options.
110
  */
111
+ protected $options;
112
 
113
  /**
114
  * Name of the meta field to save options to
255
  /**
256
  * Get options from meta field and return specific field
257
  *
258
+ * @param string $field post meta key to be returned. Can be passed as array keys separated with `.`, i.e. 'parent.child' to retrieve multidimensional array values.
259
  * @param array $default default options.
260
  *
261
  * @return mixed meta field content
 
262
  */
263
  public function options( $field = '', $default = null ) {
264
  // retrieve options, if not given yet
265
+ if ( is_null( $this->options ) ) {
 
266
  // may return false.
267
  $meta = get_post_meta( $this->id, self::$options_meta_field, true );
268
+ if ( $meta && is_array( $meta ) ) {
269
  // merge meta with arguments given on ad load.
270
  $this->options = Advanced_Ads_Utils::merge_deep_array( array( $meta, $this->args ) );
271
  } else {
284
  }
285
  }
286
 
287
+ // return all options if no field given.
288
+ if ( empty( $field ) ) {
289
+ return $this->options;
290
+ }
291
+
292
+ $field = preg_replace( '/\s/', '', $field );
293
+ $value = $this->options;
294
+ foreach ( explode( '.', $field ) as $key ) {
295
+ if ( ! isset( $value[ $key ] ) ) {
296
+ $value = $default;
297
+ break;
298
  }
299
+ $value = $value[ $key ];
300
  }
301
 
302
+ if ( is_null( $value ) ) {
303
+ $value = $default;
304
+ }
305
+
306
+ /**
307
+ * Filter the option value retrieved for $field.
308
+ * `$field` parameter makes dynamic hook portion.
309
+ *
310
+ * @var mixed $value The option value (may be set to default).
311
+ * @var Advanced_Ads_Ad $this The current Advanced_Ads_Ad instance.
312
+ */
313
+ return apply_filters( "advanced-ads-ad-option-{$field}", $value, $this );
314
  }
315
 
316
  /**
classes/checks.php CHANGED
@@ -330,23 +330,6 @@ class Advanced_Ads_Checks {
330
  return ( ! empty( $plugin_options['use-adblocker'] ) && empty( $adblocker_options['module_can_work'] ) );
331
  }
332
 
333
- /**
334
- * Check for potential jQuery errors
335
- * only script, so no return, but direct output
336
- */
337
- public static function jquery_ui_conflict() {
338
- ?>
339
- <script>
340
- jQuery(document).ready(function(){
341
- var needle = 'prior to initialization;' // A string from jquery-ui source code.
342
- if ( jQuery.fn.button.toString().indexOf( needle ) === -1 || jQuery.fn.tooltip.toString().indexOf( needle ) === -1 ) {
343
- advads_push_notice( 'jquery_ui_conflict' );
344
- }
345
- });
346
- </script>
347
- <?php
348
- }
349
-
350
  /**
351
  * Check for other ads.txt plugins
352
  *
330
  return ( ! empty( $plugin_options['use-adblocker'] ) && empty( $adblocker_options['module_can_work'] ) );
331
  }
332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  /**
334
  * Check for other ads.txt plugins
335
  *
classes/display-conditions.php CHANGED
@@ -581,7 +581,7 @@ class Advanced_Ads_Display_Conditions {
581
  ?>
582
  <div class="advads-conditions-terms-buttons dynamic-search"><?php
583
  foreach ( $checked_terms as $_checked_term ) :
584
- ?><label class="button ui-state-active"><?php echo $_checked_term->name;
585
  ?><input type="hidden" name="<?php echo $inputname; ?>"
586
  value="<?php echo $_checked_term->term_id; ?>"></label><?php
587
  endforeach;
@@ -657,7 +657,7 @@ class Advanced_Ads_Display_Conditions {
657
  while ( $the_query->have_posts() ) {
658
  $the_query->next_post();
659
  ?><label
660
- class="button ui-state-active"><?php echo get_the_title( $the_query->post->ID ) . ' (' . $the_query->post->post_type . ')';
661
  ?><input type="hidden" name="<?php echo $name; ?>[value][]" value="<?php echo $the_query->post->ID; ?>">
662
  </label><?php
663
  }
581
  ?>
582
  <div class="advads-conditions-terms-buttons dynamic-search"><?php
583
  foreach ( $checked_terms as $_checked_term ) :
584
+ ?><label class="button advads-ui-state-active"><?php echo $_checked_term->name;
585
  ?><input type="hidden" name="<?php echo $inputname; ?>"
586
  value="<?php echo $_checked_term->term_id; ?>"></label><?php
587
  endforeach;
657
  while ( $the_query->have_posts() ) {
658
  $the_query->next_post();
659
  ?><label
660
+ class="button advads-ui-state-active"><?php echo get_the_title( $the_query->post->ID ) . ' (' . $the_query->post->post_type . ')';
661
  ?><input type="hidden" name="<?php echo $name; ?>[value][]" value="<?php echo $the_query->post->ID; ?>">
662
  </label><?php
663
  }
classes/plugin.php CHANGED
@@ -111,6 +111,17 @@ class Advanced_Ads_Plugin {
111
  // load widgets.
112
  add_action( 'widgets_init', array( $this, 'widget_init' ) );
113
 
 
 
 
 
 
 
 
 
 
 
 
114
  // load display conditions.
115
  Advanced_Ads_Display_Conditions::get_instance();
116
  new Advanced_Ads_Frontend_Checks();
@@ -838,4 +849,46 @@ class Advanced_Ads_Plugin {
838
  return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE4LjEuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJFYmVuZV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDY0Ljk5MyA2NS4wMjQiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDY0Ljk5MyA2NS4wMjQ7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIHN0eWxlPSJmaWxsOiNFNEU0RTQ7IiBkPSJNNDYuNTcxLDI3LjY0MXYyMy4xMzNIMTQuMjVWMTguNDUzaDIzLjExOGMtMC45NTYtMi4xODMtMS40OTQtNC41OS0xLjQ5NC03LjEyNg0KCWMwLTIuNTM1LDAuNTM4LTQuOTQyLDEuNDk0LTcuMTI0aC02Ljk1N0gwdjQ5LjQ5M2wxLjYxOCwxLjYxOEwwLDUzLjY5NmMwLDYuMjU2LDUuMDY4LDExLjMyNiwxMS4zMjQsMTEuMzI4djBoMTkuMDg3aDMwLjQxMlYyNy42MTENCgljLTIuMTkxLDAuOTY0LTQuNjA5LDEuNTA5LTcuMTU3LDEuNTA5QzUxLjE0MiwyOS4xMiw0OC43NDYsMjguNTg4LDQ2LjU3MSwyNy42NDF6Ii8+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiM5ODk4OTg7IiBjeD0iNTMuNjY2IiBjeT0iMTEuMzI4IiByPSIxMS4zMjgiLz4NCjwvc3ZnPg0K';
839
  }
840
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
841
  }
111
  // load widgets.
112
  add_action( 'widgets_init', array( $this, 'widget_init' ) );
113
 
114
+ // Call action hooks for ad status changes.
115
+ add_action(
116
+ 'transition_post_status',
117
+ array(
118
+ $this,
119
+ 'transition_ad_status',
120
+ ),
121
+ 10,
122
+ 3
123
+ );
124
+
125
  // load display conditions.
126
  Advanced_Ads_Display_Conditions::get_instance();
127
  new Advanced_Ads_Frontend_Checks();
849
  return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE4LjEuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJFYmVuZV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDY0Ljk5MyA2NS4wMjQiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDY0Ljk5MyA2NS4wMjQ7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIHN0eWxlPSJmaWxsOiNFNEU0RTQ7IiBkPSJNNDYuNTcxLDI3LjY0MXYyMy4xMzNIMTQuMjVWMTguNDUzaDIzLjExOGMtMC45NTYtMi4xODMtMS40OTQtNC41OS0xLjQ5NC03LjEyNg0KCWMwLTIuNTM1LDAuNTM4LTQuOTQyLDEuNDk0LTcuMTI0aC02Ljk1N0gwdjQ5LjQ5M2wxLjYxOCwxLjYxOEwwLDUzLjY5NmMwLDYuMjU2LDUuMDY4LDExLjMyNiwxMS4zMjQsMTEuMzI4djBoMTkuMDg3aDMwLjQxMlYyNy42MTENCgljLTIuMTkxLDAuOTY0LTQuNjA5LDEuNTA5LTcuMTU3LDEuNTA5QzUxLjE0MiwyOS4xMiw0OC43NDYsMjguNTg4LDQ2LjU3MSwyNy42NDF6Ii8+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiM5ODk4OTg7IiBjeD0iNTMuNjY2IiBjeT0iMTEuMzI4IiByPSIxMS4zMjgiLz4NCjwvc3ZnPg0K';
850
  }
851
 
852
+ /**
853
+ * Fires when a post is transitioned from one status to another.
854
+ *
855
+ * @param string $new_status New post status.
856
+ * @param string $old_status Old post status.
857
+ * @param WP_Post $post Post object.
858
+ */
859
+ public function transition_ad_status( $new_status, $old_status, $post ) {
860
+ if ( ! isset( $post->post_type ) || Advanced_Ads::POST_TYPE_SLUG !== $post->post_type || ! isset( $post->ID ) ) {
861
+ return;
862
+ }
863
+
864
+ $ad = new Advanced_Ads_Ad( $post->ID );
865
+
866
+ if ( $old_status !== $new_status ) {
867
+ /**
868
+ * Fires when an ad has transitioned from one status to another.
869
+ *
870
+ * @param Advanced_Ads_Ad $ad Ad object.
871
+ */
872
+ do_action( "advanced-ads-ad-status-{$old_status}-to-{$new_status}", $ad );
873
+ }
874
+
875
+ if ( 'publish' === $new_status && 'publish' !== $old_status ) {
876
+ /**
877
+ * Fires when an ad has transitioned from any other status to `publish`.
878
+ *
879
+ * @param Advanced_Ads_Ad $ad Ad object.
880
+ */
881
+ do_action( 'advanced-ads-ad-status-published', $ad );
882
+ }
883
+
884
+ if ( 'publish' === $old_status && 'publish' !== $new_status ) {
885
+ /**
886
+ * Fires when an ad has transitioned from `publish` to any other status.
887
+ *
888
+ * @param Advanced_Ads_Ad $ad Ad object.
889
+ */
890
+ do_action( 'advanced-ads-ad-status-unpublished', $ad );
891
+ }
892
+ }
893
+
894
  }
languages/advanced-ads.pot CHANGED
@@ -2,14 +2,14 @@
2
  # This file is distributed under the same license as the Advanced Ads plugin.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Advanced Ads 1.21.1\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/advanced-ads/\n"
7
  "Last-Translator: Thomas Maier <post@webzunft.de>\n"
8
  "Language-Team: webgilde <support@wpadvancedads.com>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "POT-Creation-Date: 2020-11-19T08:51:38+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: advanced-ads\n"
@@ -32,7 +32,7 @@ msgstr ""
32
  msgid "Thomas Maier, Advanced Ads GmbH"
33
  msgstr ""
34
 
35
- #: admin/class-advanced-ads-admin.php:223
36
  #: classes/display-conditions.php:290
37
  #: classes/visitor-conditions.php:311
38
  #: modules/gadsense/admin/views/external-ads-links.php:17
@@ -41,65 +41,65 @@ msgstr ""
41
  msgid "or"
42
  msgstr ""
43
 
44
- #: admin/class-advanced-ads-admin.php:224
45
  #: classes/display-conditions.php:290
46
  #: classes/visitor-conditions.php:311
47
  msgid "and"
48
  msgstr ""
49
 
50
- #: admin/class-advanced-ads-admin.php:225
51
  msgid "After which paragraph?"
52
  msgstr ""
53
 
54
- #: admin/class-advanced-ads-admin.php:227
55
  msgid "Today"
56
  msgstr ""
57
 
58
- #: admin/class-advanced-ads-admin.php:228
59
  msgid "Yesterday"
60
  msgstr ""
61
 
62
- #: admin/class-advanced-ads-admin.php:229
63
  msgid "This Month"
64
  msgstr ""
65
 
66
  #. translators: 1: The number of days.
67
- #: admin/class-advanced-ads-admin.php:231
68
  msgid "Last %1$d days"
69
  msgstr ""
70
 
71
- #: admin/class-advanced-ads-admin.php:234
72
  msgid "All"
73
  msgstr ""
74
 
75
- #: admin/class-advanced-ads-admin.php:235
76
  msgid "There were no results returned for this ad. Please make sure it is active, generating impressions and double check your ad parameters."
77
  msgstr ""
78
 
79
- #: admin/class-advanced-ads-admin.php:236
80
  #: modules/gadsense/admin/views/external-ads-list.php:33
81
  msgid "Show inactive ads"
82
  msgstr ""
83
 
84
- #: admin/class-advanced-ads-admin.php:237
85
  msgid "Hide inactive ads"
86
  msgstr ""
87
 
88
- #: admin/class-advanced-ads-admin.php:398
89
  #: admin/includes/class-menu.php:156
90
  #: admin/includes/class-menu.php:159
91
  #: admin/views/settings.php:29
92
  msgid "Support"
93
  msgstr ""
94
 
95
- #: admin/class-advanced-ads-admin.php:402
96
  #: admin/includes/class-overview-widgets.php:71
97
  msgid "Add-Ons"
98
  msgstr ""
99
 
100
  #. translators: %s is the URL to add a new review, https://wordpress.org/support/plugin/advanced-ads/reviews/#new-post
101
  #. translators: %s is a URL.
102
- #: admin/class-advanced-ads-admin.php:673
103
  #: admin/includes/class-overview-widgets.php:194
104
  msgid "Thank the developer with a &#9733;&#9733;&#9733;&#9733;&#9733; review on <a href=\"%s\" target=\"_blank\">wordpress.org</a>"
105
  msgstr ""
@@ -133,116 +133,111 @@ msgstr ""
133
 
134
  #. translators: %s is a target URL.
135
  #: admin/includes/ad-health-notices.php:80
136
- msgid "Possible conflict between jQueryUI library, used by Advanced Ads and other libraries (probably <a href=\"%s\">Twitter Bootstrap</a>). This might lead to misfortunate formats in forms, but should not damage features."
137
- msgstr ""
138
-
139
- #. translators: %s is a target URL.
140
- #: admin/includes/ad-health-notices.php:90
141
  msgid "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."
142
  msgstr ""
143
 
144
- #: admin/includes/ad-health-notices.php:99
145
  #: admin/includes/notices.php:38
146
  msgid "One or more license keys for <strong>Advanced Ads add-ons are invalid or missing</strong>."
147
  msgstr ""
148
 
149
  #. translators: %s is a target URL.
150
  #. translators: %s is a URL.
151
- #: admin/includes/ad-health-notices.php:102
152
  #: admin/includes/notices.php:40
153
  msgid "Please add valid license keys <a href=\"%s\">here</a>."
154
  msgstr ""
155
 
156
- #: admin/includes/ad-health-notices.php:111
157
  msgid "Ad expired"
158
  msgstr ""
159
 
160
  #. translators: %s is empty here, but the string will be followed by a name of an ad unit.
161
- #: admin/includes/ad-health-notices.php:121
162
  #: classes/frontend_checks.php:263
163
  msgid "Visible ads should not use the Header placement: %s"
164
  msgstr ""
165
 
166
- #: admin/includes/ad-health-notices.php:135
167
  #: classes/frontend_checks.php:277
168
  msgid "AdSense violation"
169
  msgstr ""
170
 
171
- #: admin/includes/ad-health-notices.php:136
172
  #: classes/frontend_checks.php:278
173
  msgid "Ad is hidden"
174
  msgstr ""
175
 
176
- #: admin/includes/ad-health-notices.php:145
177
  #: classes/ad-debug.php:272
178
  #: classes/frontend_checks.php:250
179
  msgid "Your website is using HTTPS, but the ad code contains HTTP and might not work."
180
  msgstr ""
181
 
182
- #: admin/includes/ad-health-notices.php:158
183
- #: admin/includes/ad-health-notices.php:165
184
  #: modules/gadsense/includes/class-mapi.php:93
185
  msgid "Last AdSense account connection attempt failed."
186
  msgstr ""
187
 
188
  #. translators: %1$s is the opening a tag and %2$s the closing one.
189
- #: admin/includes/ad-health-notices.php:167
190
  msgid "Create a new AdSense account %1$shere%2$s."
191
  msgstr ""
192
 
 
193
  #: admin/includes/ad-health-notices.php:177
194
  #: admin/includes/ad-health-notices.php:187
195
- #: admin/includes/ad-health-notices.php:197
196
  msgid "One of your sites is missing the AdSense publisher ID in the ads.txt file."
197
  msgstr ""
198
 
 
199
  #: admin/includes/ad-health-notices.php:179
200
  #: admin/includes/ad-health-notices.php:189
201
- #: admin/includes/ad-health-notices.php:199
202
  msgctxt "related to ads.txt file"
203
  msgid "Create one now."
204
  msgstr ""
205
 
206
  #. translators: %s is a filter hook, here `the_content`.
207
- #: admin/includes/ad-health-notices.php:207
208
  msgid "<strong>%s</strong> filter found multiple times."
209
  msgstr ""
210
 
211
- #: admin/includes/ad-health-notices.php:209
212
  msgid "Advanced Ads uses the outermost of them."
213
  msgstr ""
214
 
215
  #. translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one.
216
- #: admin/includes/ad-health-notices.php:218
217
- #: admin/includes/ad-health-notices.php:229
218
- #: admin/includes/ad-health-notices.php:240
219
- #: admin/includes/ad-health-notices.php:253
220
  msgid "Learn how to integrate %1$s with Advanced Ads %2$shere%3$s."
221
  msgstr ""
222
 
223
  #. translators: %s is a service or plugin name.
224
- #: admin/includes/ad-health-notices.php:267
225
  msgid "%s detected."
226
  msgstr ""
227
 
228
  #. translators: %s is a service or plugin name.
229
- #: admin/includes/ad-health-notices.php:268
230
  msgid "Learn how this might impact your ad setup."
231
  msgstr ""
232
 
233
- #: admin/includes/ad-health-notices.php:279
234
  msgid "Advanced Ads handles your ads.txt file automatically. You might be able to <strong>remove %1$s</strong>."
235
  msgstr ""
236
 
237
- #: admin/includes/ad-health-notices.php:290
238
  msgid "Advanced Ads handles header and footer codes."
239
  msgstr ""
240
 
241
- #: admin/includes/ad-health-notices.php:291
242
  msgid "You might be able to <strong>remove %1$s</strong>."
243
  msgstr ""
244
 
245
- #: admin/includes/ad-health-notices.php:294
246
  msgid "Learn how."
247
  msgstr ""
248
 
@@ -393,44 +388,44 @@ msgstr[1] ""
393
  msgid "Ad created on %s"
394
  msgstr ""
395
 
396
- #: admin/includes/class-ad-type.php:848
397
- #: admin/includes/class-ad-type.php:849
398
  msgid "Ad updated."
399
  msgstr ""
400
 
401
  #. translators: %s: date and time of the revision
402
- #: admin/includes/class-ad-type.php:850
403
  msgid "Ad restored to revision from %s"
404
  msgstr ""
405
 
406
- #: admin/includes/class-ad-type.php:851
407
- #: admin/includes/class-ad-type.php:852
408
  msgid "Ad saved."
409
  msgstr ""
410
 
411
- #: admin/includes/class-ad-type.php:853
412
  msgid "Ad submitted."
413
  msgstr ""
414
 
415
  #. translators: %1$s is a date.
416
- #: admin/includes/class-ad-type.php:856
417
  msgid "Ad scheduled for: <strong>%1$s</strong>."
418
  msgstr ""
419
 
420
  #. translators: Publish box date format, see http://php.net/date.
421
- #: admin/includes/class-ad-type.php:858
422
  msgid "M j, Y @ G:i"
423
  msgstr ""
424
 
425
- #: admin/includes/class-ad-type.php:860
426
  msgid "Ad draft updated."
427
  msgstr ""
428
 
429
- #: admin/includes/class-ad-type.php:916
430
  msgid "You don’t have access to ads. Please deactivate and re-enable Advanced Ads again to fix this."
431
  msgstr ""
432
 
433
- #: admin/includes/class-ad-type.php:917
434
  #: classes/frontend_checks.php:507
435
  msgid "Get help"
436
  msgstr ""
@@ -541,7 +536,7 @@ msgstr ""
541
 
542
  #: admin/includes/class-menu.php:80
543
  #: admin/includes/class-menu.php:81
544
- #: admin/includes/class-shortcode-creator.php:101
545
  #: admin/views/ad-group-list-form-row.php:91
546
  #: admin/views/ad-group-list-header.php:16
547
  #: admin/views/placement-form.php:88
@@ -578,7 +573,7 @@ msgid "Ad Placements"
578
  msgstr ""
579
 
580
  #: admin/includes/class-menu.php:132
581
- #: admin/includes/class-shortcode-creator.php:115
582
  #: admin/views/placements.php:54
583
  #: classes/widget.php:115
584
  #: modules/gutenberg/includes/class-gutenberg.php:81
@@ -644,12 +639,12 @@ msgid "Increase your ad revenue"
644
  msgstr ""
645
 
646
  #: admin/includes/class-meta-box.php:131
647
- msgid "Ad Stats"
648
  msgstr ""
649
 
650
- #: admin/includes/class-meta-box.php:199
651
- #: admin/includes/class-meta-box.php:218
652
- #: admin/includes/class-meta-box.php:223
653
  #: admin/includes/class-overview-widgets.php:182
654
  #: admin/views/ad-main-metabox.php:25
655
  #: admin/views/ad-output-metabox.php:61
@@ -659,43 +654,43 @@ msgstr ""
659
  msgid "Manual"
660
  msgstr ""
661
 
662
- #: admin/includes/class-meta-box.php:217
663
  msgid "Video"
664
  msgstr ""
665
 
666
- #: admin/includes/class-meta-box.php:254
667
  #: admin/includes/class-overview-widgets.php:60
668
  msgid "Disable"
669
  msgstr ""
670
 
671
- #: admin/includes/class-meta-box.php:402
672
  msgid "Ad Settings"
673
  msgstr ""
674
 
675
- #: admin/includes/class-meta-box.php:501
676
  #: admin/views/overview.php:8
677
  msgid "Ads Dashboard"
678
  msgstr ""
679
 
680
  #. translators: %1$d is the number of ads, %2$s and %3$s are URLs.
681
- #: admin/includes/class-meta-box.php:517
682
  msgid "%1$d ads – <a href=\"%2$s\">manage</a> - <a href=\"%3$s\">new</a>"
683
  msgstr ""
684
 
685
- #: admin/includes/class-meta-box.php:530
686
  msgid "Get the tutorial via email"
687
  msgstr ""
688
 
689
- #: admin/includes/class-meta-box.php:539
690
  msgid "Get AdSense tips via email"
691
  msgstr ""
692
 
693
- #: admin/includes/class-meta-box.php:548
694
  msgid "Visit our blog for more articles about ad optimization"
695
  msgstr ""
696
 
697
  #. translators: %s is our URL.
698
- #: admin/includes/class-meta-box.php:602
699
  msgid "Latest posts on wpadvancedads.com"
700
  msgstr ""
701
 
@@ -879,7 +874,7 @@ msgid "Activate now"
879
  msgstr ""
880
 
881
  #: admin/includes/class-overview-widgets.php:642
882
- msgid "Visit your ad stats"
883
  msgstr ""
884
 
885
  #: admin/includes/class-overview-widgets.php:784
@@ -996,13 +991,13 @@ msgctxt "label before ads"
996
  msgid "Advertisements"
997
  msgstr ""
998
 
999
- #: admin/includes/class-shortcode-creator.php:99
1000
  #: classes/widget.php:113
1001
  #: modules/gutenberg/includes/class-gutenberg.php:77
1002
  msgid "--empty--"
1003
  msgstr ""
1004
 
1005
- #: admin/includes/class-shortcode-creator.php:108
1006
  #: admin/views/placement-form.php:81
1007
  #: admin/views/placements-item.php:14
1008
  #: classes/widget.php:122
@@ -1010,11 +1005,6 @@ msgstr ""
1010
  msgid "Ad Groups"
1011
  msgstr ""
1012
 
1013
- #. translators: %s is a URL.
1014
- #: admin/includes/class-shortcode-creator.php:192
1015
- msgid "Please, either switch off your ad blocker or disable the shortcode button in the <a href=\"%s\" target=\"_blank\">settings</a>."
1016
- msgstr ""
1017
-
1018
  #: admin/includes/notices.php:17
1019
  msgid "Thank you for activating <strong>Advanced Ads</strong>. Would you like to receive the first steps via email?"
1020
  msgstr ""
@@ -1511,7 +1501,7 @@ msgid "%1$s %2$s, %3$s @ %4$s %5$s"
1511
  msgstr ""
1512
 
1513
  #. translators: %1$s is a starting link tag, %2$s is closing the link tag.
1514
- #: admin/views/checks.php:16
1515
  msgid "Advanced Ads detected potential problems with your ad setup. %1$sShow me these errors%2$s"
1516
  msgstr ""
1517
 
@@ -1527,13 +1517,7 @@ msgstr ""
1527
  msgid "Watch video"
1528
  msgstr ""
1529
 
1530
- #. translators: %s is a link to a tutorial.
1531
- #: admin/views/conditions/ad-display-metabox.php:47
1532
- #: admin/views/notices/jqueryui_error.php:2
1533
- msgid "There might be a problem with layouts and scripts in your dashboard. Please check <a href=\"%s\" target=\"_blank\">this article to learn more</a>."
1534
- msgstr ""
1535
-
1536
- #: admin/views/conditions/ad-display-metabox.php:58
1537
  msgid "A page with this ad on it must match all of the following conditions."
1538
  msgstr ""
1539
 
@@ -2500,7 +2484,7 @@ msgstr ""
2500
 
2501
  #. translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag.
2502
  #: classes/ad-health-notices.php:865
2503
- #: modules/gadsense/includes/class-mapi.php:1615
2504
  msgid "Learn more about AdSense account issues %1$shere%2$s."
2505
  msgstr ""
2506
 
@@ -3743,58 +3727,58 @@ msgstr ""
3743
  msgid "This ad code is from a different AdSense Account"
3744
  msgstr ""
3745
 
3746
- #: modules/gadsense/includes/class-mapi.php:968
3747
  msgid "Invalid response body while retrieving account alerts"
3748
  msgstr ""
3749
 
3750
- #: modules/gadsense/includes/class-mapi.php:977
3751
  msgid "error while retrieving account alerts"
3752
  msgstr ""
3753
 
3754
- #: modules/gadsense/includes/class-mapi.php:1133
3755
  msgid "No token provided. Token data needed to get account details."
3756
  msgstr ""
3757
 
3758
- #: modules/gadsense/includes/class-mapi.php:1197
3759
  msgid "An error occurred while requesting account details."
3760
  msgstr ""
3761
 
3762
- #: modules/gadsense/includes/class-mapi.php:1422
3763
  #: modules/gadsense/includes/class-network-adsense.php:509
3764
  msgctxt "AdSense ad type"
3765
  msgid "Matched Content"
3766
  msgstr ""
3767
 
3768
- #: modules/gadsense/includes/class-mapi.php:1425
3769
  #: modules/gadsense/includes/class-network-adsense.php:510
3770
  msgctxt "AdSense ad type"
3771
  msgid "In-article"
3772
  msgstr ""
3773
 
3774
- #: modules/gadsense/includes/class-mapi.php:1427
3775
  #: modules/gadsense/includes/class-network-adsense.php:511
3776
  msgctxt "AdSense ad type"
3777
  msgid "In-feed"
3778
  msgstr ""
3779
 
3780
- #: modules/gadsense/includes/class-mapi.php:1432
3781
  #: modules/gadsense/includes/class-network-adsense.php:512
3782
  msgctxt "AdSense ad type"
3783
  msgid "Display"
3784
  msgstr ""
3785
 
3786
- #: modules/gadsense/includes/class-mapi.php:1434
3787
  #: modules/gadsense/includes/class-network-adsense.php:513
3788
  msgctxt "AdSense ad type"
3789
  msgid "Link"
3790
  msgstr ""
3791
 
3792
- #: modules/gadsense/includes/class-mapi.php:1582
3793
  msgid "There are one or more warnings about the currently linked AdSense account. You can view them <a href=\"%s\">here</a>"
3794
  msgstr ""
3795
 
3796
  #. translators: 1:A link to the settings page translators: 2:The name of an ad network
3797
- #: modules/gadsense/includes/class-mapi.php:1669
3798
  msgid "Please try to <a href=\"%1$s\" target=\"_blank\">reconnect to your %2$s account</a>."
3799
  msgstr ""
3800
 
2
  # This file is distributed under the same license as the Advanced Ads plugin.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Advanced Ads 1.22.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/advanced-ads/\n"
7
  "Last-Translator: Thomas Maier <post@webzunft.de>\n"
8
  "Language-Team: webgilde <support@wpadvancedads.com>\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "POT-Creation-Date: 2020-12-09T08:49:17+00:00\n"
13
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
14
  "X-Generator: WP-CLI 2.4.0\n"
15
  "X-Domain: advanced-ads\n"
32
  msgid "Thomas Maier, Advanced Ads GmbH"
33
  msgstr ""
34
 
35
+ #: admin/class-advanced-ads-admin.php:216
36
  #: classes/display-conditions.php:290
37
  #: classes/visitor-conditions.php:311
38
  #: modules/gadsense/admin/views/external-ads-links.php:17
41
  msgid "or"
42
  msgstr ""
43
 
44
+ #: admin/class-advanced-ads-admin.php:217
45
  #: classes/display-conditions.php:290
46
  #: classes/visitor-conditions.php:311
47
  msgid "and"
48
  msgstr ""
49
 
50
+ #: admin/class-advanced-ads-admin.php:218
51
  msgid "After which paragraph?"
52
  msgstr ""
53
 
54
+ #: admin/class-advanced-ads-admin.php:220
55
  msgid "Today"
56
  msgstr ""
57
 
58
+ #: admin/class-advanced-ads-admin.php:221
59
  msgid "Yesterday"
60
  msgstr ""
61
 
62
+ #: admin/class-advanced-ads-admin.php:222
63
  msgid "This Month"
64
  msgstr ""
65
 
66
  #. translators: 1: The number of days.
67
+ #: admin/class-advanced-ads-admin.php:224
68
  msgid "Last %1$d days"
69
  msgstr ""
70
 
71
+ #: admin/class-advanced-ads-admin.php:227
72
  msgid "All"
73
  msgstr ""
74
 
75
+ #: admin/class-advanced-ads-admin.php:228
76
  msgid "There were no results returned for this ad. Please make sure it is active, generating impressions and double check your ad parameters."
77
  msgstr ""
78
 
79
+ #: admin/class-advanced-ads-admin.php:229
80
  #: modules/gadsense/admin/views/external-ads-list.php:33
81
  msgid "Show inactive ads"
82
  msgstr ""
83
 
84
+ #: admin/class-advanced-ads-admin.php:230
85
  msgid "Hide inactive ads"
86
  msgstr ""
87
 
88
+ #: admin/class-advanced-ads-admin.php:390
89
  #: admin/includes/class-menu.php:156
90
  #: admin/includes/class-menu.php:159
91
  #: admin/views/settings.php:29
92
  msgid "Support"
93
  msgstr ""
94
 
95
+ #: admin/class-advanced-ads-admin.php:394
96
  #: admin/includes/class-overview-widgets.php:71
97
  msgid "Add-Ons"
98
  msgstr ""
99
 
100
  #. translators: %s is the URL to add a new review, https://wordpress.org/support/plugin/advanced-ads/reviews/#new-post
101
  #. translators: %s is a URL.
102
+ #: admin/class-advanced-ads-admin.php:665
103
  #: admin/includes/class-overview-widgets.php:194
104
  msgid "Thank the developer with a &#9733;&#9733;&#9733;&#9733;&#9733; review on <a href=\"%s\" target=\"_blank\">wordpress.org</a>"
105
  msgstr ""
133
 
134
  #. translators: %s is a target URL.
135
  #: admin/includes/ad-health-notices.php:80
 
 
 
 
 
136
  msgid "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."
137
  msgstr ""
138
 
139
+ #: admin/includes/ad-health-notices.php:89
140
  #: admin/includes/notices.php:38
141
  msgid "One or more license keys for <strong>Advanced Ads add-ons are invalid or missing</strong>."
142
  msgstr ""
143
 
144
  #. translators: %s is a target URL.
145
  #. translators: %s is a URL.
146
+ #: admin/includes/ad-health-notices.php:92
147
  #: admin/includes/notices.php:40
148
  msgid "Please add valid license keys <a href=\"%s\">here</a>."
149
  msgstr ""
150
 
151
+ #: admin/includes/ad-health-notices.php:101
152
  msgid "Ad expired"
153
  msgstr ""
154
 
155
  #. translators: %s is empty here, but the string will be followed by a name of an ad unit.
156
+ #: admin/includes/ad-health-notices.php:111
157
  #: classes/frontend_checks.php:263
158
  msgid "Visible ads should not use the Header placement: %s"
159
  msgstr ""
160
 
161
+ #: admin/includes/ad-health-notices.php:125
162
  #: classes/frontend_checks.php:277
163
  msgid "AdSense violation"
164
  msgstr ""
165
 
166
+ #: admin/includes/ad-health-notices.php:126
167
  #: classes/frontend_checks.php:278
168
  msgid "Ad is hidden"
169
  msgstr ""
170
 
171
+ #: admin/includes/ad-health-notices.php:135
172
  #: classes/ad-debug.php:272
173
  #: classes/frontend_checks.php:250
174
  msgid "Your website is using HTTPS, but the ad code contains HTTP and might not work."
175
  msgstr ""
176
 
177
+ #: admin/includes/ad-health-notices.php:148
178
+ #: admin/includes/ad-health-notices.php:155
179
  #: modules/gadsense/includes/class-mapi.php:93
180
  msgid "Last AdSense account connection attempt failed."
181
  msgstr ""
182
 
183
  #. translators: %1$s is the opening a tag and %2$s the closing one.
184
+ #: admin/includes/ad-health-notices.php:157
185
  msgid "Create a new AdSense account %1$shere%2$s."
186
  msgstr ""
187
 
188
+ #: admin/includes/ad-health-notices.php:167
189
  #: admin/includes/ad-health-notices.php:177
190
  #: admin/includes/ad-health-notices.php:187
 
191
  msgid "One of your sites is missing the AdSense publisher ID in the ads.txt file."
192
  msgstr ""
193
 
194
+ #: admin/includes/ad-health-notices.php:169
195
  #: admin/includes/ad-health-notices.php:179
196
  #: admin/includes/ad-health-notices.php:189
 
197
  msgctxt "related to ads.txt file"
198
  msgid "Create one now."
199
  msgstr ""
200
 
201
  #. translators: %s is a filter hook, here `the_content`.
202
+ #: admin/includes/ad-health-notices.php:197
203
  msgid "<strong>%s</strong> filter found multiple times."
204
  msgstr ""
205
 
206
+ #: admin/includes/ad-health-notices.php:199
207
  msgid "Advanced Ads uses the outermost of them."
208
  msgstr ""
209
 
210
  #. translators: %1$s is a plugin name, %2$s is the opening a tag and %3$s the closing one.
211
+ #: admin/includes/ad-health-notices.php:208
212
+ #: admin/includes/ad-health-notices.php:219
213
+ #: admin/includes/ad-health-notices.php:230
214
+ #: admin/includes/ad-health-notices.php:243
215
  msgid "Learn how to integrate %1$s with Advanced Ads %2$shere%3$s."
216
  msgstr ""
217
 
218
  #. translators: %s is a service or plugin name.
219
+ #: admin/includes/ad-health-notices.php:257
220
  msgid "%s detected."
221
  msgstr ""
222
 
223
  #. translators: %s is a service or plugin name.
224
+ #: admin/includes/ad-health-notices.php:258
225
  msgid "Learn how this might impact your ad setup."
226
  msgstr ""
227
 
228
+ #: admin/includes/ad-health-notices.php:269
229
  msgid "Advanced Ads handles your ads.txt file automatically. You might be able to <strong>remove %1$s</strong>."
230
  msgstr ""
231
 
232
+ #: admin/includes/ad-health-notices.php:280
233
  msgid "Advanced Ads handles header and footer codes."
234
  msgstr ""
235
 
236
+ #: admin/includes/ad-health-notices.php:281
237
  msgid "You might be able to <strong>remove %1$s</strong>."
238
  msgstr ""
239
 
240
+ #: admin/includes/ad-health-notices.php:284
241
  msgid "Learn how."
242
  msgstr ""
243
 
388
  msgid "Ad created on %s"
389
  msgstr ""
390
 
391
+ #: admin/includes/class-ad-type.php:852
392
+ #: admin/includes/class-ad-type.php:853
393
  msgid "Ad updated."
394
  msgstr ""
395
 
396
  #. translators: %s: date and time of the revision
397
+ #: admin/includes/class-ad-type.php:854
398
  msgid "Ad restored to revision from %s"
399
  msgstr ""
400
 
401
+ #: admin/includes/class-ad-type.php:855
402
+ #: admin/includes/class-ad-type.php:856
403
  msgid "Ad saved."
404
  msgstr ""
405
 
406
+ #: admin/includes/class-ad-type.php:857
407
  msgid "Ad submitted."
408
  msgstr ""
409
 
410
  #. translators: %1$s is a date.
411
+ #: admin/includes/class-ad-type.php:860
412
  msgid "Ad scheduled for: <strong>%1$s</strong>."
413
  msgstr ""
414
 
415
  #. translators: Publish box date format, see http://php.net/date.
416
+ #: admin/includes/class-ad-type.php:862
417
  msgid "M j, Y @ G:i"
418
  msgstr ""
419
 
420
+ #: admin/includes/class-ad-type.php:864
421
  msgid "Ad draft updated."
422
  msgstr ""
423
 
424
+ #: admin/includes/class-ad-type.php:920
425
  msgid "You don’t have access to ads. Please deactivate and re-enable Advanced Ads again to fix this."
426
  msgstr ""
427
 
428
+ #: admin/includes/class-ad-type.php:921
429
  #: classes/frontend_checks.php:507
430
  msgid "Get help"
431
  msgstr ""
536
 
537
  #: admin/includes/class-menu.php:80
538
  #: admin/includes/class-menu.php:81
539
+ #: admin/includes/class-shortcode-creator.php:111
540
  #: admin/views/ad-group-list-form-row.php:91
541
  #: admin/views/ad-group-list-header.php:16
542
  #: admin/views/placement-form.php:88
573
  msgstr ""
574
 
575
  #: admin/includes/class-menu.php:132
576
+ #: admin/includes/class-shortcode-creator.php:125
577
  #: admin/views/placements.php:54
578
  #: classes/widget.php:115
579
  #: modules/gutenberg/includes/class-gutenberg.php:81
639
  msgstr ""
640
 
641
  #: admin/includes/class-meta-box.php:131
642
+ msgid "Statistics"
643
  msgstr ""
644
 
645
+ #: admin/includes/class-meta-box.php:201
646
+ #: admin/includes/class-meta-box.php:220
647
+ #: admin/includes/class-meta-box.php:225
648
  #: admin/includes/class-overview-widgets.php:182
649
  #: admin/views/ad-main-metabox.php:25
650
  #: admin/views/ad-output-metabox.php:61
654
  msgid "Manual"
655
  msgstr ""
656
 
657
+ #: admin/includes/class-meta-box.php:219
658
  msgid "Video"
659
  msgstr ""
660
 
661
+ #: admin/includes/class-meta-box.php:256
662
  #: admin/includes/class-overview-widgets.php:60
663
  msgid "Disable"
664
  msgstr ""
665
 
666
+ #: admin/includes/class-meta-box.php:426
667
  msgid "Ad Settings"
668
  msgstr ""
669
 
670
+ #: admin/includes/class-meta-box.php:525
671
  #: admin/views/overview.php:8
672
  msgid "Ads Dashboard"
673
  msgstr ""
674
 
675
  #. translators: %1$d is the number of ads, %2$s and %3$s are URLs.
676
+ #: admin/includes/class-meta-box.php:541
677
  msgid "%1$d ads – <a href=\"%2$s\">manage</a> - <a href=\"%3$s\">new</a>"
678
  msgstr ""
679
 
680
+ #: admin/includes/class-meta-box.php:554
681
  msgid "Get the tutorial via email"
682
  msgstr ""
683
 
684
+ #: admin/includes/class-meta-box.php:563
685
  msgid "Get AdSense tips via email"
686
  msgstr ""
687
 
688
+ #: admin/includes/class-meta-box.php:572
689
  msgid "Visit our blog for more articles about ad optimization"
690
  msgstr ""
691
 
692
  #. translators: %s is our URL.
693
+ #: admin/includes/class-meta-box.php:626
694
  msgid "Latest posts on wpadvancedads.com"
695
  msgstr ""
696
 
874
  msgstr ""
875
 
876
  #: admin/includes/class-overview-widgets.php:642
877
+ msgid "Visit your ad statistics"
878
  msgstr ""
879
 
880
  #: admin/includes/class-overview-widgets.php:784
991
  msgid "Advertisements"
992
  msgstr ""
993
 
994
+ #: admin/includes/class-shortcode-creator.php:109
995
  #: classes/widget.php:113
996
  #: modules/gutenberg/includes/class-gutenberg.php:77
997
  msgid "--empty--"
998
  msgstr ""
999
 
1000
+ #: admin/includes/class-shortcode-creator.php:118
1001
  #: admin/views/placement-form.php:81
1002
  #: admin/views/placements-item.php:14
1003
  #: classes/widget.php:122
1005
  msgid "Ad Groups"
1006
  msgstr ""
1007
 
 
 
 
 
 
1008
  #: admin/includes/notices.php:17
1009
  msgid "Thank you for activating <strong>Advanced Ads</strong>. Would you like to receive the first steps via email?"
1010
  msgstr ""
1501
  msgstr ""
1502
 
1503
  #. translators: %1$s is a starting link tag, %2$s is closing the link tag.
1504
+ #: admin/views/checks.php:13
1505
  msgid "Advanced Ads detected potential problems with your ad setup. %1$sShow me these errors%2$s"
1506
  msgstr ""
1507
 
1517
  msgid "Watch video"
1518
  msgstr ""
1519
 
1520
+ #: admin/views/conditions/ad-display-metabox.php:43
 
 
 
 
 
 
1521
  msgid "A page with this ad on it must match all of the following conditions."
1522
  msgstr ""
1523
 
2484
 
2485
  #. translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag.
2486
  #: classes/ad-health-notices.php:865
2487
+ #: modules/gadsense/includes/class-mapi.php:1658
2488
  msgid "Learn more about AdSense account issues %1$shere%2$s."
2489
  msgstr ""
2490
 
3727
  msgid "This ad code is from a different AdSense Account"
3728
  msgstr ""
3729
 
3730
+ #: modules/gadsense/includes/class-mapi.php:972
3731
  msgid "Invalid response body while retrieving account alerts"
3732
  msgstr ""
3733
 
3734
+ #: modules/gadsense/includes/class-mapi.php:981
3735
  msgid "error while retrieving account alerts"
3736
  msgstr ""
3737
 
3738
+ #: modules/gadsense/includes/class-mapi.php:1137
3739
  msgid "No token provided. Token data needed to get account details."
3740
  msgstr ""
3741
 
3742
+ #: modules/gadsense/includes/class-mapi.php:1201
3743
  msgid "An error occurred while requesting account details."
3744
  msgstr ""
3745
 
3746
+ #: modules/gadsense/includes/class-mapi.php:1426
3747
  #: modules/gadsense/includes/class-network-adsense.php:509
3748
  msgctxt "AdSense ad type"
3749
  msgid "Matched Content"
3750
  msgstr ""
3751
 
3752
+ #: modules/gadsense/includes/class-mapi.php:1429
3753
  #: modules/gadsense/includes/class-network-adsense.php:510
3754
  msgctxt "AdSense ad type"
3755
  msgid "In-article"
3756
  msgstr ""
3757
 
3758
+ #: modules/gadsense/includes/class-mapi.php:1431
3759
  #: modules/gadsense/includes/class-network-adsense.php:511
3760
  msgctxt "AdSense ad type"
3761
  msgid "In-feed"
3762
  msgstr ""
3763
 
3764
+ #: modules/gadsense/includes/class-mapi.php:1436
3765
  #: modules/gadsense/includes/class-network-adsense.php:512
3766
  msgctxt "AdSense ad type"
3767
  msgid "Display"
3768
  msgstr ""
3769
 
3770
+ #: modules/gadsense/includes/class-mapi.php:1438
3771
  #: modules/gadsense/includes/class-network-adsense.php:513
3772
  msgctxt "AdSense ad type"
3773
  msgid "Link"
3774
  msgstr ""
3775
 
3776
+ #: modules/gadsense/includes/class-mapi.php:1625
3777
  msgid "There are one or more warnings about the currently linked AdSense account. You can view them <a href=\"%s\">here</a>"
3778
  msgstr ""
3779
 
3780
  #. translators: 1:A link to the settings page translators: 2:The name of an ad network
3781
+ #: modules/gadsense/includes/class-mapi.php:1712
3782
  msgid "Please try to <a href=\"%1$s\" target=\"_blank\">reconnect to your %2$s account</a>."
3783
  msgstr ""
3784
 
modules/gadsense/includes/class-mapi.php CHANGED
@@ -4,21 +4,21 @@
4
  * AdSense Management API class.
5
  */
6
  class Advanced_Ads_AdSense_MAPI {
7
-
8
  const OPTNAME = 'advanced-ads-adsense-mapi';
9
-
10
  const ALERTS_URL = 'https://www.googleapis.com/adsense/v1.4/accounts/PUBID/alerts/';
11
-
12
  const CID = '400595147946-alk0j13qk563bg94rd4f3ip2t0b2tr5r.apps.googleusercontent.com';
13
-
14
  const CS = '5jecyWgvCszB8UxSM0oS1W22';
15
-
16
  const CALL_PER_24H = 20;
17
-
18
  private static $instance = null;
19
-
20
  private static $default_options = array();
21
-
22
  private static $empty_account_data = array(
23
  'default_app' => array(
24
  'access_token' => '',
@@ -36,11 +36,11 @@ class Advanced_Ads_AdSense_MAPI {
36
  'details' => array(),
37
  'alerts' => array(),
38
  );
39
-
40
  private function __construct() {
41
-
42
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
43
-
44
  add_action( 'wp_ajax_advads_gadsense_mapi_confirm_code', array( $this, 'ajax_confirm_code' ) );
45
  //add_action( 'wp_ajax_advads_gadsense_mapi_get_adUnits', array( $this, 'ajax_get_adUnits' ) );
46
  add_action( 'wp_ajax_advads_gadsense_mapi_get_details', array( $this, 'ajax_get_account_details' ) );
@@ -55,7 +55,7 @@ class Advanced_Ads_AdSense_MAPI {
55
  add_action( 'wp_ajax_advads_gadsense_dashboard', array( 'Advanced_Ads_Overview_Widgets_Callbacks', 'ajax_gadsense_dashboard' ) );
56
 
57
  add_action( 'admin_footer', array( $this, 'admin_footer' ) );
58
-
59
  self::$default_options = array(
60
  'accounts' => array(),
61
  'ad_codes' => array(),
@@ -66,26 +66,26 @@ class Advanced_Ads_AdSense_MAPI {
66
  ),
67
  'connect_error' => array(),
68
  );
69
-
70
  add_filter( 'advanced-ads-support-messages', array( 'Advanced_Ads_AdSense_MAPI', 'adsense_warnings_check' ) );
71
-
72
  add_action( 'wp_loaded', array( $this, 'update_ad_health_notices' ) );
73
-
74
  }
75
-
76
  /**
77
  * Update all MAPI related notices.
78
  */
79
  public function update_ad_health_notices() {
80
  $mapi_options = self::get_option();
81
-
82
  $connection_error_messages = self::get_connect_error_messages();
83
-
84
  $health_class = Advanced_Ads_Ad_Health_Notices::get_instance();
85
-
86
  // Last connection failed.
87
  if ( isset ( $mapi_options['connect_error'] ) && ! empty( $mapi_options['connect_error'] ) ) {
88
-
89
  if ( isset( $connection_error_messages[ $mapi_options['connect_error']['reason'] ] ) ) {
90
  $health_class->add( 'adsense_connect_' . $mapi_options['connect_error']['reason'] );
91
  } else {
@@ -94,36 +94,36 @@ class Advanced_Ads_AdSense_MAPI {
94
  'type' => 'problem',
95
  ) );
96
  }
97
-
98
  foreach( $health_class->notices as $key => $value ) {
99
  // There was already a connection error but the user tried again and obtained another error.
100
  if ( false !== stripos( $key, 'adsense_connect_' ) && 'adsense_connect_' . $mapi_options['connect_error']['reason'] !== $key ) {
101
  $health_class->remove( $key );
102
  }
103
  }
104
-
105
  } else {
106
-
107
  // Once a connection has been established (or a the warning has been discarded on the AA settings page), remove connection related notices.
108
  foreach( $health_class->notices as $key => $value ) {
109
  if ( false !== stripos( $key, 'adsense_connect_' ) ) {
110
  $health_class->remove( $key );
111
  }
112
  }
113
-
114
  }
115
-
116
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
117
  $adsense_id = $gadsense_data->get_adsense_id();
118
-
119
  $alerts = Advanced_Ads_AdSense_MAPI::get_stored_account_alerts( $adsense_id );
120
-
121
  // AdSense account alerts (can not happens simultaneously with the connection error).
122
  if ( is_array( $alerts ) && isset( $alerts['items'] ) && is_array( $alerts['items'] ) && $alerts['items'] ) {
123
-
124
  $alerts_advads_messages = Advanced_Ads_Adsense_MAPI::get_adsense_alert_messages();
125
  $item_ids = array();
126
-
127
  foreach ( $alerts['items'] as $internal_id => $item ) {
128
  $item_ids[] = $item['id'];
129
  if ( isset( $alerts_advads_messages[ $item['id'] ] ) ) {
@@ -131,9 +131,9 @@ class Advanced_Ads_AdSense_MAPI {
131
  } else {
132
  $health_class->add( 'adsense_alert_' . $item['id'], array( 'text' => $item['message'] . ' ' . self::get_adsense_error_link( $item['id'] ), 'type' => 'problem' ) );
133
  }
134
-
135
  }
136
-
137
  // Remove notices that no more exist in the AdSense account (or have been dismissed).
138
  $_remove_ids = array();
139
  foreach( $health_class->notices as $key => $value ) {
@@ -147,7 +147,7 @@ class Advanced_Ads_AdSense_MAPI {
147
  foreach( $_remove_ids as $id ) {
148
  $health_class->remove( $id );
149
  }
150
-
151
  } else {
152
  // No more alerts.
153
  foreach( $health_class->notices as $key => $value ) {
@@ -155,10 +155,10 @@ class Advanced_Ads_AdSense_MAPI {
155
  $health_class->remove( $key );
156
  }
157
  }
158
-
159
  }
160
  }
161
-
162
  /**
163
  * Discard account connection error
164
  */
@@ -175,7 +175,7 @@ class Advanced_Ads_AdSense_MAPI {
175
  }
176
  die;
177
  }
178
-
179
  /**
180
  * Get available quota and eventual message about remaining call
181
  */
@@ -198,25 +198,25 @@ class Advanced_Ads_AdSense_MAPI {
198
  }
199
  }
200
  }
201
-
202
  /**
203
  * Get the readable quota
204
  */
205
  public function get_quota_msg() {
206
-
207
  $options = $this->get_option();
208
  $now = time();
209
  $secs = $options['quota']['ts'] + ( 24 * 3600 ) - $now;
210
  $hours = floor( $secs / 3600 );
211
  $mins = ceil( ( $secs - ( $hours * 3600 ) ) / 60 );
212
-
213
  if ( 60 == $mins ) {
214
  $hours += 1;
215
  $mins = 0;
216
  }
217
-
218
  if ( 0 == $options['quota']['count'] ) {
219
-
220
  $msg = sprintf(
221
  /*
222
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -228,7 +228,7 @@ class Advanced_Ads_AdSense_MAPI {
228
  sprintf( '%s hours', $hours ),
229
  sprintf( '%s minutes', $mins )
230
  );
231
-
232
  if ( 0 == $hours ) {
233
  /*
234
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -239,7 +239,7 @@ class Advanced_Ads_AdSense_MAPI {
239
  */
240
  $msg = 'No API call left before.';
241
  }
242
-
243
  if ( 0 == $mins ) {
244
  /*
245
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -251,7 +251,7 @@ class Advanced_Ads_AdSense_MAPI {
251
  $msg = 'No API call left.';
252
  }
253
  } else {
254
-
255
  $msg = sprintf(
256
  /*
257
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -265,7 +265,7 @@ class Advanced_Ads_AdSense_MAPI {
265
  sprintf( '%s hours', $hours ),
266
  sprintf( '%s minutes', $mins )
267
  );
268
-
269
  if ( 0 == $hours ) {
270
  /*
271
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -277,7 +277,7 @@ class Advanced_Ads_AdSense_MAPI {
277
  */
278
  $msg = sprintf( '%s API calls remaining.', $options['quota']['count'] );
279
  }
280
-
281
  if ( 0 == $mins ) {
282
  /*
283
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
@@ -296,7 +296,7 @@ class Advanced_Ads_AdSense_MAPI {
296
  }
297
  return $msg;
298
  }
299
-
300
  /**
301
  * Decrement quota by 1, and return message about remaining call
302
  */
@@ -312,7 +312,7 @@ class Advanced_Ads_AdSense_MAPI {
312
  return $this->get_quota_msg();
313
  }
314
  }
315
-
316
  /**
317
  * Return the ad code for a given client and unit
318
  *
@@ -322,20 +322,20 @@ class Advanced_Ads_AdSense_MAPI {
322
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
323
  $adsense_id = $gadsense_data->get_adsense_id();
324
  $options = self::get_option();
325
-
326
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
327
  $adsense_id = $gadsense_data->get_adsense_id();
328
-
329
  $url = 'https://www.googleapis.com/adsense/v1.4/accounts/' . $adsense_id . '/adclients/ca-' . $adsense_id . '/adunits/' . $adUnit . '/adcode';
330
  $access_token = self::get_access_token( $adsense_id );
331
-
332
  if ( ! isset( $access_token['msg'] ) ) {
333
  $headers = array(
334
  'Authorization' => 'Bearer ' . $access_token,
335
  );
336
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
337
  self::log( 'Get ad code for ad Unit [' . $adUnit . ']' );
338
-
339
  if ( is_wp_error( $response ) ) {
340
  return array(
341
  'status' => false,
@@ -384,10 +384,10 @@ class Advanced_Ads_AdSense_MAPI {
384
  return $access_token;
385
  }
386
  }
387
-
388
  /**
389
  * Get/Update ad unit list for a given client
390
- *
391
  * @param [string] $account The publisher ID.
392
  * @param [bool] $inactive Whether to include inactive ads.
393
  */
@@ -610,7 +610,7 @@ class Advanced_Ads_AdSense_MAPI {
610
  }
611
  }
612
  }
613
-
614
  /**
615
  * Renew the current access token.
616
  */
@@ -620,7 +620,7 @@ class Advanced_Ads_AdSense_MAPI {
620
  $options = self::get_option();
621
  $access_token = $options['accounts'][ $account ]['default_app']['access_token'];
622
  $refresh_token = $options['accounts'][ $account ]['default_app']['refresh_token'];
623
-
624
  if ( self::use_user_app() ) {
625
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
626
  $_options = $gadsense_data->get_options();
@@ -629,7 +629,7 @@ class Advanced_Ads_AdSense_MAPI {
629
  $access_token = $options['accounts'][ $account ]['user_app']['access_token'];
630
  $refresh_token = $options['accounts'][ $account ]['user_app']['refresh_token'];
631
  }
632
-
633
  $url = 'https://www.googleapis.com/oauth2/v4/token';
634
  $args = array(
635
  'body' => array(
@@ -639,10 +639,10 @@ class Advanced_Ads_AdSense_MAPI {
639
  'grant_type' => 'refresh_token',
640
  ),
641
  );
642
-
643
  $response = wp_remote_post( $url, $args );
644
  self::log( 'Refresh access token' );
645
-
646
  if ( is_wp_error( $response ) ) {
647
  return array(
648
  'status' => false,
@@ -677,12 +677,12 @@ class Advanced_Ads_AdSense_MAPI {
677
  }
678
  }
679
  }
680
-
681
  /**
682
  * Recoke a refresh token
683
  */
684
  public function ajax_revoke_tokken() {
685
-
686
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
687
  if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
688
  die;
@@ -690,7 +690,7 @@ class Advanced_Ads_AdSense_MAPI {
690
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
691
  $adsense_id = stripslashes( $_POST['adsenseId'] );
692
  $options = self::get_option();
693
-
694
  if ( self::use_user_app() ) {
695
  $token = $options['accounts'][ $adsense_id ]['user_app']['refresh_token'];
696
  } else {
@@ -701,11 +701,11 @@ class Advanced_Ads_AdSense_MAPI {
701
  'timeout' => 5,
702
  'header' => array( 'Content-type' => 'application/x-www-form-urlencoded' ),
703
  );
704
-
705
  $response = wp_remote_post( $url, $args );
706
-
707
  self::log( 'Revoke API access for ca-' . $adsense_id );
708
-
709
  if ( is_wp_error( $response ) ) {
710
  echo json_encode( array( 'status' => false ) );
711
  } else {
@@ -721,7 +721,7 @@ class Advanced_Ads_AdSense_MAPI {
721
  }
722
  }
723
  die;
724
-
725
  }
726
 
727
  /**
@@ -800,7 +800,7 @@ class Advanced_Ads_AdSense_MAPI {
800
  }
801
  die;
802
  }
803
-
804
  /**
805
  * Get ad code for a given unit
806
  */
@@ -811,10 +811,10 @@ class Advanced_Ads_AdSense_MAPI {
811
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
812
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
813
  $unit = stripslashes( $_POST['unit'] );
814
-
815
  if ( ! self::use_user_app() ) {
816
  $quota = $this->get_quota();
817
-
818
  // No more quota left
819
  if ( $quota['count'] < 1 ) {
820
  $quota_msg = $this->get_quota_msg();
@@ -829,9 +829,9 @@ class Advanced_Ads_AdSense_MAPI {
829
  die;
830
  }
831
  }
832
-
833
  $code = $this->get_ad_code( $unit );
834
-
835
  /**
836
  * Ad code is returned as string. Otherwise it's an error
837
  */
@@ -857,16 +857,16 @@ class Advanced_Ads_AdSense_MAPI {
857
  $response['quota'] = $quota['count'];
858
  $response['quotaMsg'] = $quota_msg;
859
  }
860
-
861
  header( 'Content-Type: application/json' );
862
  echo wp_json_encode( $response );
863
-
864
  } else {
865
-
866
  // return info about the error
867
  header( 'Content-Type: application/json' );
868
  echo wp_json_encode( $code );
869
-
870
  }
871
  }
872
  die;
@@ -884,15 +884,15 @@ class Advanced_Ads_AdSense_MAPI {
884
  $account = stripslashes( $_POST['account'] );
885
  $id = stripslashes( $_POST['id'] );
886
  $options = self::get_option();
887
-
888
  $items = array();
889
-
890
  // the account exists.
891
  if ( isset( $options['accounts'][ $account ] ) ) {
892
  // the alert exists.
893
  if ( isset( $options['accounts'][ $account ]['alerts']['items'][ $id ] ) ) {
894
  unset( $options['accounts'][ $account ]['alerts']['items'][ $id ] );
895
-
896
  update_option( self::OPTNAME, $options );
897
  $items = $options['accounts'][ $account ]['alerts']['items'];
898
  }
@@ -906,7 +906,7 @@ class Advanced_Ads_AdSense_MAPI {
906
  }
907
  die;
908
  }
909
-
910
  /**
911
  * Get / Update the list of alerts on an AdSense account.
912
  */
@@ -918,25 +918,25 @@ class Advanced_Ads_AdSense_MAPI {
918
  if ( false !== wp_verify_nonce( $nonce, 'mapi-alerts' ) ) {
919
  $account = stripslashes( $_POST['account'] );
920
  $options = self::get_option();
921
-
922
  // the account exists.
923
  if ( isset( $options['accounts'][ $account ] ) && self::has_token( $account ) ) {
924
  $access_token = $this->get_access_token( $account );
925
  $url = str_replace( 'PUBID', $account, self::ALERTS_URL );
926
-
927
  // the token is valid.
928
  if ( ! isset( $access_token['msg'] ) ) {
929
  $headers = array(
930
  'Authorization' => 'Bearer ' . $access_token,
931
  );
932
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
933
-
934
  $this->log( 'Get AdSense alerts for ' . $account );
935
-
936
  // the HTTP response is not an error.
937
  if ( ! is_wp_error( $response ) ) {
938
  $alerts = json_decode( $response['body'], true );
939
-
940
  // the response body is valid.
941
  if ( null !== $alerts || !is_array( $alerts ) || empty( $alerts['kind'] ) ) {
942
  $items = array();
@@ -948,11 +948,15 @@ class Advanced_Ads_AdSense_MAPI {
948
  }
949
  }
950
  }
951
-
 
 
 
952
  $alerts_array = array(
953
  'items' => $items ,
954
  'lastCheck' => time(),
955
  );
 
956
  $options['accounts'][ $account ]['alerts'] = $alerts_array;
957
  update_option( self::OPTNAME, $options );
958
  $results = array(
@@ -963,16 +967,16 @@ class Advanced_Ads_AdSense_MAPI {
963
  header( 'Content-Type:application/json' );
964
  echo wp_json_encode( $results );
965
  } else {
966
- $results = array(
967
  'status' => false,
968
  'msg' => esc_html__( 'Invalid response body while retrieving account alerts', 'advanced-ads' ),
969
  );
970
  header( 'Content-Type:application/json' );
971
  echo wp_json_encode( $results );
972
  }
973
-
974
  } else {
975
- $results = array(
976
  'status' => false,
977
  'msg' => esc_html__( 'error while retrieving account alerts', 'advanced-ads' ),
978
  'raw' => $response->get_error_message(),
@@ -984,16 +988,16 @@ class Advanced_Ads_AdSense_MAPI {
984
  // return the original error info
985
  return $access_token;
986
  }
987
-
988
  } else {
989
  header( 'Content-Type:application/json' );
990
  echo wp_json_encode( array( 'status' => false ) );
991
  }
992
-
993
  }
994
  die;
995
  }
996
-
997
  // /**
998
  // * Show / Hide idle ads on the ad list table.
999
  // */
@@ -1020,7 +1024,7 @@ class Advanced_Ads_AdSense_MAPI {
1020
  // }
1021
  // die;
1022
  // }
1023
-
1024
  /**
1025
  * Get / Update the ad unit list for a given ad client. The corresponding <select /> input used in the ad selector is passed as a fied of an array
1026
  */
@@ -1079,11 +1083,11 @@ class Advanced_Ads_AdSense_MAPI {
1079
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
1080
  $token_data = wp_unslash( $_POST['token_data'] );
1081
  $account = wp_unslash( $_POST['account'] );
1082
-
1083
  if ( $token_data && $account ) {
1084
-
1085
  self::save_token_from_data( $token_data, $account, array( 'autoads' => isset( $_POST['autoads'] ) ) );
1086
-
1087
  header( 'Content-Type: application/json' );
1088
  echo json_encode(
1089
  array(
@@ -1091,9 +1095,9 @@ class Advanced_Ads_AdSense_MAPI {
1091
  'adsense_id' => $account['id'],
1092
  )
1093
  );
1094
-
1095
  } else {
1096
-
1097
  $error = 'Token data missing';
1098
  if ( $token_data ) {
1099
  $error = 'No account provided';
@@ -1105,12 +1109,12 @@ class Advanced_Ads_AdSense_MAPI {
1105
  'error_msg' => $error,
1106
  )
1107
  );
1108
-
1109
  }
1110
  }
1111
  die;
1112
  }
1113
-
1114
  /**
1115
  * Get AdSense account details from a new access token.
1116
  */
@@ -1120,12 +1124,12 @@ class Advanced_Ads_AdSense_MAPI {
1120
  }
1121
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
1122
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
1123
-
1124
  $url = 'https://www.googleapis.com/adsense/v1.4/accounts';
1125
  $token_data = wp_unslash( $_POST['token_data'] );
1126
-
1127
  if ( ! is_array( $token_data ) ) {
1128
-
1129
  header( 'Content-Type: application/json' );
1130
  echo json_encode(
1131
  array(
@@ -1134,16 +1138,16 @@ class Advanced_Ads_AdSense_MAPI {
1134
  )
1135
  );
1136
  die;
1137
-
1138
  }
1139
-
1140
  $headers = array( 'Authorization' => 'Bearer ' . $token_data['access_token'] );
1141
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
1142
-
1143
  self::log( 'Get account details from new access token' );
1144
-
1145
  if ( is_wp_error( $response ) ) {
1146
-
1147
  header( 'Content-Type: application/json' );
1148
  echo json_encode(
1149
  array(
@@ -1151,21 +1155,21 @@ class Advanced_Ads_AdSense_MAPI {
1151
  'error_msg' => $response->get_error_message(),
1152
  )
1153
  );
1154
-
1155
  } else {
1156
-
1157
  $accounts = json_decode( $response['body'], true );
1158
-
1159
  if ( isset( $accounts['items'] ) ) {
1160
  $options = self::get_option();
1161
  $options['connect_error'] = array();
1162
  update_option( self::OPTNAME, $options );
1163
-
1164
  if ( 2 > count( $accounts['items'] ) ) {
1165
-
1166
  $adsense_id = $accounts['items'][0]['id'];
1167
  self::save_token_from_data( $token_data, $accounts['items'][0], array( 'autoads' => isset( $_POST['autoads'] ) ) );
1168
-
1169
  header( 'Content-Type: application/json' );
1170
  echo json_encode(
1171
  array(
@@ -1173,7 +1177,7 @@ class Advanced_Ads_AdSense_MAPI {
1173
  'adsense_id' => $adsense_id,
1174
  )
1175
  );
1176
-
1177
  } else {
1178
  $html = '';
1179
  $details = array();
@@ -1190,7 +1194,7 @@ class Advanced_Ads_AdSense_MAPI {
1190
  'token_data' => $token_data,
1191
  )
1192
  );
1193
-
1194
  }
1195
  } else {
1196
  if ( isset( $accounts['error'] ) ) {
@@ -1198,18 +1202,18 @@ class Advanced_Ads_AdSense_MAPI {
1198
  if ( isset( $accounts['error']['message'] ) ) {
1199
  $msg = $accounts['error']['message'];
1200
  }
1201
-
1202
  $options = self::get_option();
1203
  $options['connect_error'] = array(
1204
  'message' => $msg,
1205
  );
1206
-
1207
  if ( isset( $accounts['error']['errors'][0]['reason'] ) ) {
1208
  $options['connect_error']['reason'] = $accounts['error']['errors'][0]['reason'];
1209
  }
1210
-
1211
  update_option( self::OPTNAME, $options );
1212
-
1213
  header( 'Content-Type: application/json' );
1214
  echo json_encode(
1215
  array(
@@ -1218,14 +1222,14 @@ class Advanced_Ads_AdSense_MAPI {
1218
  'raw' => $accounts['error'],
1219
  )
1220
  );
1221
-
1222
  }
1223
  }
1224
  }
1225
  }
1226
  die;
1227
  }
1228
-
1229
  /**
1230
  * Submit Google API confirmation code. Save the token and update ad client list.
1231
  */
@@ -1238,18 +1242,18 @@ class Advanced_Ads_AdSense_MAPI {
1238
  $code = urldecode( $_POST['code'] );
1239
  $cid = self::CID;
1240
  $cs = self::CS;
1241
-
1242
  $use_user_app = self::use_user_app();
1243
-
1244
  if ( $use_user_app ) {
1245
  $cid = ADVANCED_ADS_MAPI_CID;
1246
  $cs = ADVANCED_ADS_MAPI_CIS;
1247
  }
1248
-
1249
  $code_url = 'https://www.googleapis.com/oauth2/v4/token';
1250
  $redirect_uri = 'urn:ietf:wg:oauth:2.0:oob';
1251
  $grant_type = 'authorization_code';
1252
-
1253
  $args = array(
1254
  'timeout' => 10,
1255
  'body' => array(
@@ -1260,11 +1264,11 @@ class Advanced_Ads_AdSense_MAPI {
1260
  'grant_type' => $grant_type,
1261
  ),
1262
  );
1263
-
1264
  $response = wp_remote_post( $code_url, $args );
1265
-
1266
  self::log( 'Confirm authorization code' );
1267
-
1268
  if ( is_wp_error( $response ) ) {
1269
  return json_encode(
1270
  array(
@@ -1275,7 +1279,7 @@ class Advanced_Ads_AdSense_MAPI {
1275
  );
1276
  } else {
1277
  $token = json_decode( $response['body'], true );
1278
-
1279
  if ( null !== $token && isset( $token['refresh_token'] ) ) {
1280
  $expires = time() + absint( $token['expires_in'] );
1281
  $token['expires'] = $expires;
@@ -1286,7 +1290,7 @@ class Advanced_Ads_AdSense_MAPI {
1286
  'token_data' => $token,
1287
  )
1288
  );
1289
-
1290
  } else {
1291
  header( 'Content-Type: application/json' );
1292
  echo json_encode(
@@ -1300,7 +1304,7 @@ class Advanced_Ads_AdSense_MAPI {
1300
  }
1301
  die;
1302
  }
1303
-
1304
  /**
1305
  * Enqueue admin scripts
1306
  */
@@ -1309,7 +1313,7 @@ class Advanced_Ads_AdSense_MAPI {
1309
  wp_enqueue_script( 'gasense/mapi/settings', GADSENSE_BASE_URL . 'admin/assets/js/mapi-settings.js', array( 'jquery' ), ADVADS_VERSION );
1310
  }
1311
  }
1312
-
1313
  /**
1314
  * Print alert data in admin footer
1315
  */
@@ -1319,7 +1323,7 @@ class Advanced_Ads_AdSense_MAPI {
1319
  $has_token = Advanced_Ads_AdSense_MAPI::has_token( $adsense_id );
1320
  $alerts = self::get_stored_account_alerts( $adsense_id );
1321
  $refresh_alerts = false;
1322
-
1323
  // default value, never checked for alerts.
1324
  if ( array() === $alerts && $has_token ) {
1325
  $refresh_alerts = true;
@@ -1336,7 +1340,7 @@ class Advanced_Ads_AdSense_MAPI {
1336
  <input type="hidden" id="advads-mapi-refresh-alerts" />
1337
  <script type="text/javascript">
1338
  ;(function($){
1339
-
1340
  $( '#mapi-alerts-overlay' ).css( 'display', 'block' );
1341
 
1342
  var pubId = $( '#adsense-id' ).val();
@@ -1364,7 +1368,7 @@ class Advanced_Ads_AdSense_MAPI {
1364
  <?php
1365
  }
1366
  }
1367
-
1368
  public static function log( $task = 'No task provided' ) {
1369
  if ( ! defined( 'ADVANCED_ADS_LOG_ADSENSE_API' ) || ! ADVANCED_ADS_LOG_ADSENSE_API ) {
1370
  return;
@@ -1373,7 +1377,7 @@ class Advanced_Ads_AdSense_MAPI {
1373
  $message = date_i18n( '[Y-m-d H:i:s]' ) . ' ' . $task . "\n";
1374
  error_log( $message, 3, WP_CONTENT_DIR . '/advanced-ads-google-api-requests.log' );
1375
  }
1376
-
1377
  /**
1378
  * Sort ad units list alphabetically
1379
  */
@@ -1517,7 +1521,7 @@ class Advanced_Ads_AdSense_MAPI {
1517
 
1518
  /**
1519
  * Get a list of stored alerts for a given AdSense account.
1520
- *
1521
  * @param string $pub_id the publisher account.
1522
  * @return array $alerts
1523
  */
@@ -1537,36 +1541,75 @@ class Advanced_Ads_AdSense_MAPI {
1537
  return false;
1538
  }
1539
 
1540
- /**
1541
- * Remove unneeded stored alerts.
1542
- *
1543
- * @param array $alerts Existing alerts.
1544
- * @return array $alerts Modified allerts.
1545
- */
1546
- public static function filter_stored_account_alerts( array $alerts ) {
1547
- if ( empty( $alerts['items'] ) || ! is_array( $alerts['items'] ) ) {
1548
- return $alerts;
1549
- }
 
 
 
1550
 
1551
- // Remove `ads.txt` related alerts if the file is displayed to visitors.
1552
- if ( Advanced_Ads_Ads_Txt_Admin::is_displayed() ) {
1553
- $ads_txt_alerts = array( 'ALERT_TYPE_ADS_TXT_UNAUTHORIZED', 'ADS_TXT_MISSING', 'ADS_TXT_ISSUES' );
 
 
1554
 
1555
- foreach ( $alerts['items'] as $internal_id => $item ) {
1556
- if ( isset( $item['id'] ) && in_array( $item['id'], $ads_txt_alerts ) ) {
1557
- unset( $alerts['items'][ $internal_id ] );
1558
- }
1559
- }
1560
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1561
 
1562
  return $alerts;
1563
  }
1564
-
1565
  /**
1566
  * Checks if there is any AdSense warning for the currently connected AdSense account.
1567
- *
1568
  * @param array $messages The array of messages.
1569
- *
1570
  * @return array The modified array.
1571
  */
1572
  public static function adsense_warnings_check( $messages ) {
@@ -1587,7 +1630,7 @@ class Advanced_Ads_AdSense_MAPI {
1587
  }
1588
  return $messages;
1589
  }
1590
-
1591
  /**
1592
  * Get the class's option
1593
  */
@@ -1600,10 +1643,10 @@ class Advanced_Ads_AdSense_MAPI {
1600
  }
1601
 
1602
  /**
1603
- * Get the URL to the AdSense error page
1604
- *
1605
  * @param string $code Add the error code to the URL.
1606
- *
1607
  * @return string The entire text with the url.
1608
  */
1609
  public static function get_adsense_error_link( $code = '' ) {
@@ -1618,7 +1661,7 @@ class Advanced_Ads_AdSense_MAPI {
1618
  );
1619
  return $link;
1620
  }
1621
-
1622
  /**
1623
  * Get custom account connection error message list.
1624
  */
@@ -1632,7 +1675,7 @@ class Advanced_Ads_AdSense_MAPI {
1632
  }
1633
  return $messages;
1634
  }
1635
-
1636
  /**
1637
  * Get custom messages for AdSense alerts.
1638
  */
@@ -1646,7 +1689,7 @@ class Advanced_Ads_AdSense_MAPI {
1646
  }
1647
  return $messages;
1648
  }
1649
-
1650
  public static function get_instance() {
1651
  if ( null == self::$instance ) {
1652
  self::$instance = new self();
4
  * AdSense Management API class.
5
  */
6
  class Advanced_Ads_AdSense_MAPI {
7
+
8
  const OPTNAME = 'advanced-ads-adsense-mapi';
9
+
10
  const ALERTS_URL = 'https://www.googleapis.com/adsense/v1.4/accounts/PUBID/alerts/';
11
+
12
  const CID = '400595147946-alk0j13qk563bg94rd4f3ip2t0b2tr5r.apps.googleusercontent.com';
13
+
14
  const CS = '5jecyWgvCszB8UxSM0oS1W22';
15
+
16
  const CALL_PER_24H = 20;
17
+
18
  private static $instance = null;
19
+
20
  private static $default_options = array();
21
+
22
  private static $empty_account_data = array(
23
  'default_app' => array(
24
  'access_token' => '',
36
  'details' => array(),
37
  'alerts' => array(),
38
  );
39
+
40
  private function __construct() {
41
+
42
  add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
43
+
44
  add_action( 'wp_ajax_advads_gadsense_mapi_confirm_code', array( $this, 'ajax_confirm_code' ) );
45
  //add_action( 'wp_ajax_advads_gadsense_mapi_get_adUnits', array( $this, 'ajax_get_adUnits' ) );
46
  add_action( 'wp_ajax_advads_gadsense_mapi_get_details', array( $this, 'ajax_get_account_details' ) );
55
  add_action( 'wp_ajax_advads_gadsense_dashboard', array( 'Advanced_Ads_Overview_Widgets_Callbacks', 'ajax_gadsense_dashboard' ) );
56
 
57
  add_action( 'admin_footer', array( $this, 'admin_footer' ) );
58
+
59
  self::$default_options = array(
60
  'accounts' => array(),
61
  'ad_codes' => array(),
66
  ),
67
  'connect_error' => array(),
68
  );
69
+
70
  add_filter( 'advanced-ads-support-messages', array( 'Advanced_Ads_AdSense_MAPI', 'adsense_warnings_check' ) );
71
+
72
  add_action( 'wp_loaded', array( $this, 'update_ad_health_notices' ) );
73
+
74
  }
75
+
76
  /**
77
  * Update all MAPI related notices.
78
  */
79
  public function update_ad_health_notices() {
80
  $mapi_options = self::get_option();
81
+
82
  $connection_error_messages = self::get_connect_error_messages();
83
+
84
  $health_class = Advanced_Ads_Ad_Health_Notices::get_instance();
85
+
86
  // Last connection failed.
87
  if ( isset ( $mapi_options['connect_error'] ) && ! empty( $mapi_options['connect_error'] ) ) {
88
+
89
  if ( isset( $connection_error_messages[ $mapi_options['connect_error']['reason'] ] ) ) {
90
  $health_class->add( 'adsense_connect_' . $mapi_options['connect_error']['reason'] );
91
  } else {
94
  'type' => 'problem',
95
  ) );
96
  }
97
+
98
  foreach( $health_class->notices as $key => $value ) {
99
  // There was already a connection error but the user tried again and obtained another error.
100
  if ( false !== stripos( $key, 'adsense_connect_' ) && 'adsense_connect_' . $mapi_options['connect_error']['reason'] !== $key ) {
101
  $health_class->remove( $key );
102
  }
103
  }
104
+
105
  } else {
106
+
107
  // Once a connection has been established (or a the warning has been discarded on the AA settings page), remove connection related notices.
108
  foreach( $health_class->notices as $key => $value ) {
109
  if ( false !== stripos( $key, 'adsense_connect_' ) ) {
110
  $health_class->remove( $key );
111
  }
112
  }
113
+
114
  }
115
+
116
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
117
  $adsense_id = $gadsense_data->get_adsense_id();
118
+
119
  $alerts = Advanced_Ads_AdSense_MAPI::get_stored_account_alerts( $adsense_id );
120
+
121
  // AdSense account alerts (can not happens simultaneously with the connection error).
122
  if ( is_array( $alerts ) && isset( $alerts['items'] ) && is_array( $alerts['items'] ) && $alerts['items'] ) {
123
+
124
  $alerts_advads_messages = Advanced_Ads_Adsense_MAPI::get_adsense_alert_messages();
125
  $item_ids = array();
126
+
127
  foreach ( $alerts['items'] as $internal_id => $item ) {
128
  $item_ids[] = $item['id'];
129
  if ( isset( $alerts_advads_messages[ $item['id'] ] ) ) {
131
  } else {
132
  $health_class->add( 'adsense_alert_' . $item['id'], array( 'text' => $item['message'] . ' ' . self::get_adsense_error_link( $item['id'] ), 'type' => 'problem' ) );
133
  }
134
+
135
  }
136
+
137
  // Remove notices that no more exist in the AdSense account (or have been dismissed).
138
  $_remove_ids = array();
139
  foreach( $health_class->notices as $key => $value ) {
147
  foreach( $_remove_ids as $id ) {
148
  $health_class->remove( $id );
149
  }
150
+
151
  } else {
152
  // No more alerts.
153
  foreach( $health_class->notices as $key => $value ) {
155
  $health_class->remove( $key );
156
  }
157
  }
158
+
159
  }
160
  }
161
+
162
  /**
163
  * Discard account connection error
164
  */
175
  }
176
  die;
177
  }
178
+
179
  /**
180
  * Get available quota and eventual message about remaining call
181
  */
198
  }
199
  }
200
  }
201
+
202
  /**
203
  * Get the readable quota
204
  */
205
  public function get_quota_msg() {
206
+
207
  $options = $this->get_option();
208
  $now = time();
209
  $secs = $options['quota']['ts'] + ( 24 * 3600 ) - $now;
210
  $hours = floor( $secs / 3600 );
211
  $mins = ceil( ( $secs - ( $hours * 3600 ) ) / 60 );
212
+
213
  if ( 60 == $mins ) {
214
  $hours += 1;
215
  $mins = 0;
216
  }
217
+
218
  if ( 0 == $options['quota']['count'] ) {
219
+
220
  $msg = sprintf(
221
  /*
222
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
228
  sprintf( '%s hours', $hours ),
229
  sprintf( '%s minutes', $mins )
230
  );
231
+
232
  if ( 0 == $hours ) {
233
  /*
234
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
239
  */
240
  $msg = 'No API call left before.';
241
  }
242
+
243
  if ( 0 == $mins ) {
244
  /*
245
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
251
  $msg = 'No API call left.';
252
  }
253
  } else {
254
+
255
  $msg = sprintf(
256
  /*
257
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
265
  sprintf( '%s hours', $hours ),
266
  sprintf( '%s minutes', $mins )
267
  );
268
+
269
  if ( 0 == $hours ) {
270
  /*
271
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
277
  */
278
  $msg = sprintf( '%s API calls remaining.', $options['quota']['count'] );
279
  }
280
+
281
  if ( 0 == $mins ) {
282
  /*
283
  commented out so that these unused strings don’t show up for translators; using fixed strings instead in case we forget this when we might add the check again later
296
  }
297
  return $msg;
298
  }
299
+
300
  /**
301
  * Decrement quota by 1, and return message about remaining call
302
  */
312
  return $this->get_quota_msg();
313
  }
314
  }
315
+
316
  /**
317
  * Return the ad code for a given client and unit
318
  *
322
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
323
  $adsense_id = $gadsense_data->get_adsense_id();
324
  $options = self::get_option();
325
+
326
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
327
  $adsense_id = $gadsense_data->get_adsense_id();
328
+
329
  $url = 'https://www.googleapis.com/adsense/v1.4/accounts/' . $adsense_id . '/adclients/ca-' . $adsense_id . '/adunits/' . $adUnit . '/adcode';
330
  $access_token = self::get_access_token( $adsense_id );
331
+
332
  if ( ! isset( $access_token['msg'] ) ) {
333
  $headers = array(
334
  'Authorization' => 'Bearer ' . $access_token,
335
  );
336
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
337
  self::log( 'Get ad code for ad Unit [' . $adUnit . ']' );
338
+
339
  if ( is_wp_error( $response ) ) {
340
  return array(
341
  'status' => false,
384
  return $access_token;
385
  }
386
  }
387
+
388
  /**
389
  * Get/Update ad unit list for a given client
390
+ *
391
  * @param [string] $account The publisher ID.
392
  * @param [bool] $inactive Whether to include inactive ads.
393
  */
610
  }
611
  }
612
  }
613
+
614
  /**
615
  * Renew the current access token.
616
  */
620
  $options = self::get_option();
621
  $access_token = $options['accounts'][ $account ]['default_app']['access_token'];
622
  $refresh_token = $options['accounts'][ $account ]['default_app']['refresh_token'];
623
+
624
  if ( self::use_user_app() ) {
625
  $gadsense_data = Advanced_Ads_AdSense_Data::get_instance();
626
  $_options = $gadsense_data->get_options();
629
  $access_token = $options['accounts'][ $account ]['user_app']['access_token'];
630
  $refresh_token = $options['accounts'][ $account ]['user_app']['refresh_token'];
631
  }
632
+
633
  $url = 'https://www.googleapis.com/oauth2/v4/token';
634
  $args = array(
635
  'body' => array(
639
  'grant_type' => 'refresh_token',
640
  ),
641
  );
642
+
643
  $response = wp_remote_post( $url, $args );
644
  self::log( 'Refresh access token' );
645
+
646
  if ( is_wp_error( $response ) ) {
647
  return array(
648
  'status' => false,
677
  }
678
  }
679
  }
680
+
681
  /**
682
  * Recoke a refresh token
683
  */
684
  public function ajax_revoke_tokken() {
685
+
686
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
687
  if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
688
  die;
690
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
691
  $adsense_id = stripslashes( $_POST['adsenseId'] );
692
  $options = self::get_option();
693
+
694
  if ( self::use_user_app() ) {
695
  $token = $options['accounts'][ $adsense_id ]['user_app']['refresh_token'];
696
  } else {
701
  'timeout' => 5,
702
  'header' => array( 'Content-type' => 'application/x-www-form-urlencoded' ),
703
  );
704
+
705
  $response = wp_remote_post( $url, $args );
706
+
707
  self::log( 'Revoke API access for ca-' . $adsense_id );
708
+
709
  if ( is_wp_error( $response ) ) {
710
  echo json_encode( array( 'status' => false ) );
711
  } else {
721
  }
722
  }
723
  die;
724
+
725
  }
726
 
727
  /**
800
  }
801
  die;
802
  }
803
+
804
  /**
805
  * Get ad code for a given unit
806
  */
811
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
812
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
813
  $unit = stripslashes( $_POST['unit'] );
814
+
815
  if ( ! self::use_user_app() ) {
816
  $quota = $this->get_quota();
817
+
818
  // No more quota left
819
  if ( $quota['count'] < 1 ) {
820
  $quota_msg = $this->get_quota_msg();
829
  die;
830
  }
831
  }
832
+
833
  $code = $this->get_ad_code( $unit );
834
+
835
  /**
836
  * Ad code is returned as string. Otherwise it's an error
837
  */
857
  $response['quota'] = $quota['count'];
858
  $response['quotaMsg'] = $quota_msg;
859
  }
860
+
861
  header( 'Content-Type: application/json' );
862
  echo wp_json_encode( $response );
863
+
864
  } else {
865
+
866
  // return info about the error
867
  header( 'Content-Type: application/json' );
868
  echo wp_json_encode( $code );
869
+
870
  }
871
  }
872
  die;
884
  $account = stripslashes( $_POST['account'] );
885
  $id = stripslashes( $_POST['id'] );
886
  $options = self::get_option();
887
+
888
  $items = array();
889
+
890
  // the account exists.
891
  if ( isset( $options['accounts'][ $account ] ) ) {
892
  // the alert exists.
893
  if ( isset( $options['accounts'][ $account ]['alerts']['items'][ $id ] ) ) {
894
  unset( $options['accounts'][ $account ]['alerts']['items'][ $id ] );
895
+
896
  update_option( self::OPTNAME, $options );
897
  $items = $options['accounts'][ $account ]['alerts']['items'];
898
  }
906
  }
907
  die;
908
  }
909
+
910
  /**
911
  * Get / Update the list of alerts on an AdSense account.
912
  */
918
  if ( false !== wp_verify_nonce( $nonce, 'mapi-alerts' ) ) {
919
  $account = stripslashes( $_POST['account'] );
920
  $options = self::get_option();
921
+
922
  // the account exists.
923
  if ( isset( $options['accounts'][ $account ] ) && self::has_token( $account ) ) {
924
  $access_token = $this->get_access_token( $account );
925
  $url = str_replace( 'PUBID', $account, self::ALERTS_URL );
926
+
927
  // the token is valid.
928
  if ( ! isset( $access_token['msg'] ) ) {
929
  $headers = array(
930
  'Authorization' => 'Bearer ' . $access_token,
931
  );
932
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
933
+
934
  $this->log( 'Get AdSense alerts for ' . $account );
935
+
936
  // the HTTP response is not an error.
937
  if ( ! is_wp_error( $response ) ) {
938
  $alerts = json_decode( $response['body'], true );
939
+
940
  // the response body is valid.
941
  if ( null !== $alerts || !is_array( $alerts ) || empty( $alerts['kind'] ) ) {
942
  $items = array();
948
  }
949
  }
950
  }
951
+
952
+ // filter alerts that are not relevant to the user
953
+ $items = self::filter_account_alerts( $items );
954
+
955
  $alerts_array = array(
956
  'items' => $items ,
957
  'lastCheck' => time(),
958
  );
959
+
960
  $options['accounts'][ $account ]['alerts'] = $alerts_array;
961
  update_option( self::OPTNAME, $options );
962
  $results = array(
967
  header( 'Content-Type:application/json' );
968
  echo wp_json_encode( $results );
969
  } else {
970
+ $results = array(
971
  'status' => false,
972
  'msg' => esc_html__( 'Invalid response body while retrieving account alerts', 'advanced-ads' ),
973
  );
974
  header( 'Content-Type:application/json' );
975
  echo wp_json_encode( $results );
976
  }
977
+
978
  } else {
979
+ $results = array(
980
  'status' => false,
981
  'msg' => esc_html__( 'error while retrieving account alerts', 'advanced-ads' ),
982
  'raw' => $response->get_error_message(),
988
  // return the original error info
989
  return $access_token;
990
  }
991
+
992
  } else {
993
  header( 'Content-Type:application/json' );
994
  echo wp_json_encode( array( 'status' => false ) );
995
  }
996
+
997
  }
998
  die;
999
  }
1000
+
1001
  // /**
1002
  // * Show / Hide idle ads on the ad list table.
1003
  // */
1024
  // }
1025
  // die;
1026
  // }
1027
+
1028
  /**
1029
  * Get / Update the ad unit list for a given ad client. The corresponding <select /> input used in the ad selector is passed as a fied of an array
1030
  */
1083
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
1084
  $token_data = wp_unslash( $_POST['token_data'] );
1085
  $account = wp_unslash( $_POST['account'] );
1086
+
1087
  if ( $token_data && $account ) {
1088
+
1089
  self::save_token_from_data( $token_data, $account, array( 'autoads' => isset( $_POST['autoads'] ) ) );
1090
+
1091
  header( 'Content-Type: application/json' );
1092
  echo json_encode(
1093
  array(
1095
  'adsense_id' => $account['id'],
1096
  )
1097
  );
1098
+
1099
  } else {
1100
+
1101
  $error = 'Token data missing';
1102
  if ( $token_data ) {
1103
  $error = 'No account provided';
1109
  'error_msg' => $error,
1110
  )
1111
  );
1112
+
1113
  }
1114
  }
1115
  die;
1116
  }
1117
+
1118
  /**
1119
  * Get AdSense account details from a new access token.
1120
  */
1124
  }
1125
  $nonce = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
1126
  if ( false !== wp_verify_nonce( $nonce, 'advads-mapi' ) ) {
1127
+
1128
  $url = 'https://www.googleapis.com/adsense/v1.4/accounts';
1129
  $token_data = wp_unslash( $_POST['token_data'] );
1130
+
1131
  if ( ! is_array( $token_data ) ) {
1132
+
1133
  header( 'Content-Type: application/json' );
1134
  echo json_encode(
1135
  array(
1138
  )
1139
  );
1140
  die;
1141
+
1142
  }
1143
+
1144
  $headers = array( 'Authorization' => 'Bearer ' . $token_data['access_token'] );
1145
  $response = wp_remote_get( $url, array( 'headers' => $headers ) );
1146
+
1147
  self::log( 'Get account details from new access token' );
1148
+
1149
  if ( is_wp_error( $response ) ) {
1150
+
1151
  header( 'Content-Type: application/json' );
1152
  echo json_encode(
1153
  array(
1155
  'error_msg' => $response->get_error_message(),
1156
  )
1157
  );
1158
+
1159
  } else {
1160
+
1161
  $accounts = json_decode( $response['body'], true );
1162
+
1163
  if ( isset( $accounts['items'] ) ) {
1164
  $options = self::get_option();
1165
  $options['connect_error'] = array();
1166
  update_option( self::OPTNAME, $options );
1167
+
1168
  if ( 2 > count( $accounts['items'] ) ) {
1169
+
1170
  $adsense_id = $accounts['items'][0]['id'];
1171
  self::save_token_from_data( $token_data, $accounts['items'][0], array( 'autoads' => isset( $_POST['autoads'] ) ) );
1172
+
1173
  header( 'Content-Type: application/json' );
1174
  echo json_encode(
1175
  array(
1177
  'adsense_id' => $adsense_id,
1178
  )
1179
  );
1180
+
1181
  } else {
1182
  $html = '';
1183
  $details = array();
1194
  'token_data' => $token_data,
1195
  )
1196
  );
1197
+
1198
  }
1199
  } else {
1200
  if ( isset( $accounts['error'] ) ) {
1202
  if ( isset( $accounts['error']['message'] ) ) {
1203
  $msg = $accounts['error']['message'];
1204
  }
1205
+
1206
  $options = self::get_option();
1207
  $options['connect_error'] = array(
1208
  'message' => $msg,
1209
  );
1210
+
1211
  if ( isset( $accounts['error']['errors'][0]['reason'] ) ) {
1212
  $options['connect_error']['reason'] = $accounts['error']['errors'][0]['reason'];
1213
  }
1214
+
1215
  update_option( self::OPTNAME, $options );
1216
+
1217
  header( 'Content-Type: application/json' );
1218
  echo json_encode(
1219
  array(
1222
  'raw' => $accounts['error'],
1223
  )
1224
  );
1225
+
1226
  }
1227
  }
1228
  }
1229
  }
1230
  die;
1231
  }
1232
+
1233
  /**
1234
  * Submit Google API confirmation code. Save the token and update ad client list.
1235
  */
1242
  $code = urldecode( $_POST['code'] );
1243
  $cid = self::CID;
1244
  $cs = self::CS;
1245
+
1246
  $use_user_app = self::use_user_app();
1247
+
1248
  if ( $use_user_app ) {
1249
  $cid = ADVANCED_ADS_MAPI_CID;
1250
  $cs = ADVANCED_ADS_MAPI_CIS;
1251
  }
1252
+
1253
  $code_url = 'https://www.googleapis.com/oauth2/v4/token';
1254
  $redirect_uri = 'urn:ietf:wg:oauth:2.0:oob';
1255
  $grant_type = 'authorization_code';
1256
+
1257
  $args = array(
1258
  'timeout' => 10,
1259
  'body' => array(
1264
  'grant_type' => $grant_type,
1265
  ),
1266
  );
1267
+
1268
  $response = wp_remote_post( $code_url, $args );
1269
+
1270
  self::log( 'Confirm authorization code' );
1271
+
1272
  if ( is_wp_error( $response ) ) {
1273
  return json_encode(
1274
  array(
1279
  );
1280
  } else {
1281
  $token = json_decode( $response['body'], true );
1282
+
1283
  if ( null !== $token && isset( $token['refresh_token'] ) ) {
1284
  $expires = time() + absint( $token['expires_in'] );
1285
  $token['expires'] = $expires;
1290
  'token_data' => $token,
1291
  )
1292
  );
1293
+
1294
  } else {
1295
  header( 'Content-Type: application/json' );
1296
  echo json_encode(
1304
  }
1305
  die;
1306
  }
1307
+
1308
  /**
1309
  * Enqueue admin scripts
1310
  */
1313
  wp_enqueue_script( 'gasense/mapi/settings', GADSENSE_BASE_URL . 'admin/assets/js/mapi-settings.js', array( 'jquery' ), ADVADS_VERSION );
1314
  }
1315
  }
1316
+
1317
  /**
1318
  * Print alert data in admin footer
1319
  */
1323
  $has_token = Advanced_Ads_AdSense_MAPI::has_token( $adsense_id );
1324
  $alerts = self::get_stored_account_alerts( $adsense_id );
1325
  $refresh_alerts = false;
1326
+
1327
  // default value, never checked for alerts.
1328
  if ( array() === $alerts && $has_token ) {
1329
  $refresh_alerts = true;
1340
  <input type="hidden" id="advads-mapi-refresh-alerts" />
1341
  <script type="text/javascript">
1342
  ;(function($){
1343
+
1344
  $( '#mapi-alerts-overlay' ).css( 'display', 'block' );
1345
 
1346
  var pubId = $( '#adsense-id' ).val();
1368
  <?php
1369
  }
1370
  }
1371
+
1372
  public static function log( $task = 'No task provided' ) {
1373
  if ( ! defined( 'ADVANCED_ADS_LOG_ADSENSE_API' ) || ! ADVANCED_ADS_LOG_ADSENSE_API ) {
1374
  return;
1377
  $message = date_i18n( '[Y-m-d H:i:s]' ) . ' ' . $task . "\n";
1378
  error_log( $message, 3, WP_CONTENT_DIR . '/advanced-ads-google-api-requests.log' );
1379
  }
1380
+
1381
  /**
1382
  * Sort ad units list alphabetically
1383
  */
1521
 
1522
  /**
1523
  * Get a list of stored alerts for a given AdSense account.
1524
+ *
1525
  * @param string $pub_id the publisher account.
1526
  * @return array $alerts
1527
  */
1541
  return false;
1542
  }
1543
 
1544
+ /**
1545
+ * We filter out specific alerts from the AdSense account when they are
1546
+ * - duplicates
1547
+ * - irrelevant when placing ads in the frontend
1548
+ *
1549
+ * @param array $alert_items alerts.
1550
+ * @param null|array $disabled_alerts additional disabled alerts.
1551
+ * @return array filtered alert items.
1552
+ */
1553
+ public static function filter_account_alerts( array $alert_items, $disabled_alerts = null ) {
1554
+ if ( empty( $alert_items ) || ! is_array( $alert_items ) ) {
1555
+ return $alert_items;
1556
+ }
1557
 
1558
+ // the message IDs we don’t even import from AdSense
1559
+ $disabled_adsense_alerts = array(
1560
+ 'SELLERS_JSON_CONSENT', // AdSense message: We encourage you to publish your seller information in the Google sellers.json file. Visit the account settings page to review your current visibility status.
1561
+ 'REPORTING_HORIZON_LEGACY_DATA_NOTICE', // AdSense message: Data older than three years is no longer available in Reporting. This data can be downloaded for a limited time.
1562
+ );
1563
 
1564
+ // additional messages to disable. Useful if the function is used in different situations
1565
+ if ( ! empty( $disabled_alerts ) && is_array( $disabled_alerts ) ) {
1566
+ $disabled_adsense_alerts = array_merge( $disabled_adsense_alerts, $disabled_alerts );
1567
+ }
1568
+
1569
+ // remove alerts based on specific IDs
1570
+ foreach ( $alert_items as $internal_id => $item ) {
1571
+ if ( isset( $item['id'] ) && in_array( $item['id'], $disabled_adsense_alerts, true ) ) {
1572
+ unset( $alert_items[ $internal_id ] );
1573
+ }
1574
+ }
1575
+
1576
+ return $alert_items;
1577
+ }
1578
+
1579
+ /**
1580
+ * Remove alerts dynamically when showing them.
1581
+ * only applies to stored alerts and not when they are loaded directly from AdSense
1582
+ *
1583
+ * @param array $alerts Alert options.
1584
+ * @return array $alerts Modified alert options.
1585
+ */
1586
+ public static function filter_stored_account_alerts( array $alerts ) {
1587
+ if ( empty( $alerts['items'] ) || ! is_array( $alerts['items'] ) ) {
1588
+ return $alerts;
1589
+ }
1590
+
1591
+ $disabled_alerts = array();
1592
+
1593
+ /**
1594
+ * Asside from the basic filter, we also filter out some messages only from showing up while we still import them
1595
+ * This allows us to show them only under related conditions
1596
+ */
1597
+ // Remove `ads.txt` related alerts if the file is displayed to visitors.
1598
+ if ( Advanced_Ads_Ads_Txt_Admin::is_displayed() ) {
1599
+ $disabled_alerts = array( 'ALERT_TYPE_ADS_TXT_UNAUTHORIZED', 'ADS_TXT_MISSING', 'ADS_TXT_ISSUES' );
1600
+ }
1601
+
1602
+ // filter alerts
1603
+ $alerts['items'] = self::filter_account_alerts( $alerts['items'], $disabled_alerts );
1604
 
1605
  return $alerts;
1606
  }
1607
+
1608
  /**
1609
  * Checks if there is any AdSense warning for the currently connected AdSense account.
1610
+ *
1611
  * @param array $messages The array of messages.
1612
+ *
1613
  * @return array The modified array.
1614
  */
1615
  public static function adsense_warnings_check( $messages ) {
1630
  }
1631
  return $messages;
1632
  }
1633
+
1634
  /**
1635
  * Get the class's option
1636
  */
1643
  }
1644
 
1645
  /**
1646
+ * Get the URL to the AdSense error page
1647
+ *
1648
  * @param string $code Add the error code to the URL.
1649
+ *
1650
  * @return string The entire text with the url.
1651
  */
1652
  public static function get_adsense_error_link( $code = '' ) {
1661
  );
1662
  return $link;
1663
  }
1664
+
1665
  /**
1666
  * Get custom account connection error message list.
1667
  */
1675
  }
1676
  return $messages;
1677
  }
1678
+
1679
  /**
1680
  * Get custom messages for AdSense alerts.
1681
  */
1689
  }
1690
  return $messages;
1691
  }
1692
+
1693
  public static function get_instance() {
1694
  if ( null == self::$instance ) {
1695
  self::$instance = new self();
modules/gutenberg/js/advanced-ads.block.js CHANGED
@@ -1,5 +1,5 @@
1
  ;(function(wp){
2
-
3
  /**
4
  * Shortcut variables
5
  */
@@ -7,10 +7,10 @@
7
  registerBlockType = wp.blocks.registerBlockType;
8
 
9
  /**
10
- * Register the single ad block type
11
  */
12
  registerBlockType( 'advads/gblock', {
13
-
14
  title: advadsGutenberg.i18n.advads,
15
 
16
  icon: 'chart-line',
@@ -22,67 +22,70 @@
22
  type: 'string',
23
  },
24
  },
25
-
 
 
 
26
  edit: function( props ) {
27
-
28
  var itemID = props.attributes.itemID;
29
-
30
  /**
31
- * Update property on submit
32
  */
33
  function setItemID( event ) {
34
  var selected = event.target.querySelector( 'option:checked' );
35
  props.setAttributes( { itemID: selected.value } );
36
  event.preventDefault();
37
  }
38
-
39
  // the form children elements
40
  var children = [];
41
-
42
  // argument list (in array form) for the children creation
43
  var args = [];
44
  var ads = [];
45
  var groups = [];
46
  var placements = [];
47
-
48
  args.push( 'select' );
49
  args.push( { value: itemID, onChange: setItemID } );
50
  args.push( el( 'option', null, advadsGutenberg.i18n['--empty--'] ) );
51
-
52
  for ( var adID in advadsGutenberg.ads ) {
53
  if ( 'undefined' == typeof advadsGutenberg.ads[adID].id ) continue;
54
  ads.push( el( 'option', {value: 'ad_' + advadsGutenberg.ads[adID].id}, advadsGutenberg.ads[adID].title ) );
55
  }
56
-
57
  for ( var GID in advadsGutenberg.groups ) {
58
  if ( 'undefined' == typeof advadsGutenberg.groups[GID].id ) continue;
59
  groups.push( el( 'option', {value: 'group_' + advadsGutenberg.groups[GID]['id'] }, advadsGutenberg.groups[GID]['name'] ) );
60
-
61
  }
62
-
63
  if ( advadsGutenberg.placements ) {
64
  for ( var pid in advadsGutenberg.placements ) {
65
  if ( 'undefined' == typeof advadsGutenberg.placements[pid].id ) continue;
66
  placements.push( el( 'option', {value: 'place_' + advadsGutenberg.placements[pid]['id']}, advadsGutenberg.placements[pid]['name'] ) );
67
  }
68
  }
69
-
70
  if ( advadsGutenberg.placements ) {
71
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['placements']}, placements ) );
72
  }
73
-
74
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['adGroups']}, groups ) );
75
-
76
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['ads']}, ads ) );
77
-
78
  // add a <label /> first and style it.
79
  children.push( el( 'label', {style:{fontWeight:'bold',display:'block'}}, advadsGutenberg.i18n.advads ) );
80
-
81
  // then add the <select /> input with its own children
82
  children.push( el.apply( null, args ) );
83
-
84
  if ( itemID && advadsGutenberg.i18n['--empty--'] != itemID ) {
85
-
86
  var url = '#';
87
  if ( 0 === itemID.indexOf( 'place_' ) ) {
88
  url = advadsGutenberg.editLinks.placement;
@@ -92,7 +95,7 @@
92
  var _adID = itemID.substr(3);
93
  url = advadsGutenberg.editLinks.ad.replace( '%ID%', _adID );
94
  }
95
-
96
  children.push(
97
  el(
98
  'a',
@@ -108,18 +111,18 @@
108
  }
109
  )
110
  );
111
-
112
  }
113
  // return the complete form
114
  return el( 'form', { onSubmit: setItemID }, children );
115
-
116
  },
117
 
118
  save: function() {
119
  // server side rendering
120
  return null;
121
  },
122
-
123
  } );
124
-
125
- })(window.wp);
1
  ;(function(wp){
2
+
3
  /**
4
  * Shortcut variables
5
  */
7
  registerBlockType = wp.blocks.registerBlockType;
8
 
9
  /**
10
+ * Register the single ad block type
11
  */
12
  registerBlockType( 'advads/gblock', {
13
+
14
  title: advadsGutenberg.i18n.advads,
15
 
16
  icon: 'chart-line',
22
  type: 'string',
23
  },
24
  },
25
+
26
+ // todo: make the keywords translatable
27
+ keywords: [ 'advert', 'adsense', 'banner' ],
28
+
29
  edit: function( props ) {
30
+
31
  var itemID = props.attributes.itemID;
32
+
33
  /**
34
+ * Update property on submit
35
  */
36
  function setItemID( event ) {
37
  var selected = event.target.querySelector( 'option:checked' );
38
  props.setAttributes( { itemID: selected.value } );
39
  event.preventDefault();
40
  }
41
+
42
  // the form children elements
43
  var children = [];
44
+
45
  // argument list (in array form) for the children creation
46
  var args = [];
47
  var ads = [];
48
  var groups = [];
49
  var placements = [];
50
+
51
  args.push( 'select' );
52
  args.push( { value: itemID, onChange: setItemID } );
53
  args.push( el( 'option', null, advadsGutenberg.i18n['--empty--'] ) );
54
+
55
  for ( var adID in advadsGutenberg.ads ) {
56
  if ( 'undefined' == typeof advadsGutenberg.ads[adID].id ) continue;
57
  ads.push( el( 'option', {value: 'ad_' + advadsGutenberg.ads[adID].id}, advadsGutenberg.ads[adID].title ) );
58
  }
59
+
60
  for ( var GID in advadsGutenberg.groups ) {
61
  if ( 'undefined' == typeof advadsGutenberg.groups[GID].id ) continue;
62
  groups.push( el( 'option', {value: 'group_' + advadsGutenberg.groups[GID]['id'] }, advadsGutenberg.groups[GID]['name'] ) );
63
+
64
  }
65
+
66
  if ( advadsGutenberg.placements ) {
67
  for ( var pid in advadsGutenberg.placements ) {
68
  if ( 'undefined' == typeof advadsGutenberg.placements[pid].id ) continue;
69
  placements.push( el( 'option', {value: 'place_' + advadsGutenberg.placements[pid]['id']}, advadsGutenberg.placements[pid]['name'] ) );
70
  }
71
  }
72
+
73
  if ( advadsGutenberg.placements ) {
74
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['placements']}, placements ) );
75
  }
76
+
77
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['adGroups']}, groups ) );
78
+
79
  args.push( el( 'optgroup', {label: advadsGutenberg.i18n['ads']}, ads ) );
80
+
81
  // add a <label /> first and style it.
82
  children.push( el( 'label', {style:{fontWeight:'bold',display:'block'}}, advadsGutenberg.i18n.advads ) );
83
+
84
  // then add the <select /> input with its own children
85
  children.push( el.apply( null, args ) );
86
+
87
  if ( itemID && advadsGutenberg.i18n['--empty--'] != itemID ) {
88
+
89
  var url = '#';
90
  if ( 0 === itemID.indexOf( 'place_' ) ) {
91
  url = advadsGutenberg.editLinks.placement;
95
  var _adID = itemID.substr(3);
96
  url = advadsGutenberg.editLinks.ad.replace( '%ID%', _adID );
97
  }
98
+
99
  children.push(
100
  el(
101
  'a',
111
  }
112
  )
113
  );
114
+
115
  }
116
  // return the complete form
117
  return el( 'form', { onSubmit: setItemID }, children );
118
+
119
  },
120
 
121
  save: function() {
122
  // server side rendering
123
  return null;
124
  },
125
+
126
  } );
127
+
128
+ })(window.wp);
modules/privacy/classes/class-privacy.php CHANGED
@@ -73,11 +73,32 @@ class Advanced_Ads_Privacy {
73
  * @return string
74
  */
75
  public function encode_ad( $output, Advanced_Ads_Ad $ad ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  return sprintf(
77
- '<script type="text/plain" data-tcf="waiting-for-consent" data-id="%d" data-bid="%s" %s>%s</script>',
78
- $ad->id,
79
- get_current_blog_id(),
80
- ( ! empty( $ad->output['placement_id'] ) ? 'data-placement="' . $ad->output['placement_id'] . '"' : '' ),
81
  // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- we need to obfuscate the html (and maybe decode it in JS).
82
  base64_encode( $output )
83
  );
73
  * @return string
74
  */
75
  public function encode_ad( $output, Advanced_Ads_Ad $ad ) {
76
+ $data_attributes = array(
77
+ 'id' => $ad->id,
78
+ 'bid' => get_current_blog_id(),
79
+ );
80
+ if ( ! empty( $ad->output['placement_id'] ) ) {
81
+ $data_attributes['placement'] = $ad->output['placement_id'];
82
+ }
83
+
84
+ /**
85
+ * Filter the data attributes and allow removing/adding attributes.
86
+ * All attributes will be prefix with `data-` on output.
87
+ *
88
+ * @param array $data_attributes The default data attributes.
89
+ * @param Advanced_Ads_Ad $ad The current ad.
90
+ */
91
+ $data_attributes = (array) apply_filters( 'advanced-ads-privacy-output-attributes', $data_attributes, $ad );
92
+
93
+ // convert the data-attributes array into a string.
94
+ $attributes_string = '';
95
+ array_walk( $data_attributes, function( $value, $key ) use ( &$attributes_string ) {
96
+ $attributes_string .= sprintf( 'data-%s="%s"', sanitize_key( $key ), esc_attr( $value ) );
97
+ } );
98
+
99
  return sprintf(
100
+ '<script type="text/plain" data-tcf="waiting-for-consent" %s>%s</script>',
101
+ $attributes_string,
 
 
102
  // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- we need to obfuscate the html (and maybe decode it in JS).
103
  base64_encode( $output )
104
  );
public/assets/js/advanced.js CHANGED
@@ -2,6 +2,83 @@
2
  * advanced ads functions to be used directly within ad codes
3
  */
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  advads = {
6
  /**
7
  * check if localstorage is supported/enabled by client
@@ -565,15 +642,13 @@ advads = {
565
  * Decode ad content.
566
  *
567
  * @param {Element} el
568
- * @param {boolean} inject
569
  */
570
  decode_ad: function ( el, inject ) {
571
  // this can also be a number if used in a foreach.
572
- inject = typeof inject === 'boolean' ? inject : true;
573
  var string = decodeURIComponent( Array.prototype.map.call( atob( el.textContent ), function ( c ) {
574
- return '%' + (
575
- '00' + c.charCodeAt( 0 ).toString( 16 )
576
- ).slice( - 2 )
577
  } ).join( '' ) );
578
 
579
  if ( ! inject ) {
2
  * advanced ads functions to be used directly within ad codes
3
  */
4
 
5
+ /**
6
+ * Polyfills
7
+ */
8
+ (function () {
9
+ if ( typeof window.CustomEvent !== "function" ) {
10
+ /**
11
+ * CustomEvent polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
12
+ *
13
+ * @param {string} event Event name.
14
+ * @param {object} params Event parameters.
15
+ * @returne {object} Custom event.
16
+ */
17
+ function CustomEvent ( event, params ) {
18
+ params = params || { bubbles: false, cancelable: false, detail: null };
19
+ var evt = document.createEvent( 'CustomEvent' );
20
+ evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
21
+ return evt;
22
+ }
23
+
24
+ window.CustomEvent = CustomEvent;
25
+ }
26
+
27
+ /**
28
+ * ReplaceWith polyfill for IE11: https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith
29
+ */
30
+ function ReplaceWithPolyfill() {
31
+ 'use-strict'; // For safari, and IE > 10
32
+ var parent = this.parentNode, i = arguments.length, currentNode;
33
+ if ( ! parent) {
34
+ return;
35
+ }
36
+ if ( ! i ) {// if there are no arguments
37
+ parent.removeChild( this );
38
+ }
39
+ while ( i-- ) { // i-- decrements i and returns the value of i before the decrement
40
+ currentNode = arguments[i];
41
+ if ( typeof currentNode !== 'object' ) {
42
+ currentNode = this.ownerDocument.createTextNode( currentNode );
43
+ } else if ( currentNode.parentNode ) {
44
+ currentNode.parentNode.removeChild( currentNode );
45
+ }
46
+ // the value of "i" below is after the decrement
47
+ if ( ! i ) { // if currentNode is the first argument (currentNode === arguments[0])
48
+ parent.replaceChild( currentNode, this );
49
+ } else { // if currentNode isn't the first
50
+ parent.insertBefore( currentNode, this.nextSibling );
51
+ }
52
+ }
53
+ }
54
+ if ( ! Element.prototype.replaceWith ) {
55
+ Element.prototype.replaceWith = ReplaceWithPolyfill;
56
+ }
57
+ if ( ! CharacterData.prototype.replaceWith ) {
58
+ CharacterData.prototype.replaceWith = ReplaceWithPolyfill;
59
+ }
60
+ if ( ! DocumentType.prototype.replaceWith ) {
61
+ DocumentType.prototype.replaceWith = ReplaceWithPolyfill;
62
+ }
63
+
64
+ /**
65
+ * Polyfill for NodeList.foreach() because we need to support IE11: https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach
66
+ */
67
+ if ( window.NodeList && ! NodeList.prototype.forEach ) {
68
+ NodeList.prototype.forEach = function( callback, thisArg ) {
69
+ var i;
70
+ var len = this.length;
71
+
72
+ thisArg = thisArg || window;
73
+
74
+ for ( i = 0; i < len; i++ ) {
75
+ callback.call( thisArg, this[ i ], i, this );
76
+ }
77
+ };
78
+ }
79
+
80
+ })();
81
+
82
  advads = {
83
  /**
84
  * check if localstorage is supported/enabled by client
642
  * Decode ad content.
643
  *
644
  * @param {Element} el
645
+ * @param {boolean} [inject=true]
646
  */
647
  decode_ad: function ( el, inject ) {
648
  // this can also be a number if used in a foreach.
649
+ inject = typeof inject === 'boolean' ? inject : true;
650
  var string = decodeURIComponent( Array.prototype.map.call( atob( el.textContent ), function ( c ) {
651
+ return '%' + ( '00' + c.charCodeAt( 0 ).toString( 16 ) ).slice( - 2 );
 
 
652
  } ).join( '' ) );
653
 
654
  if ( ! inject ) {
public/assets/js/advanced.min.js CHANGED
@@ -1 +1 @@
1
- advads={supports_localstorage:function(){"use strict";try{return!(!window||void 0===window.localStorage)&&(window.localStorage.setItem("x","x"),window.localStorage.removeItem("x"),!0)}catch(e){return!1}},max_per_session:function(e,t){var a=1;if(void 0!==t&&0!==parseInt(t)||(t=1),this.cookie_exists(e)){if(this.get_cookie(e)>=t)return!0;a+=parseInt(this.get_cookie(e))}return this.set_cookie(e,a),!1},count_up:function(e,t){var a=1;this.cookie_exists(e)&&(a+=parseInt(this.get_cookie(e))),this.set_cookie(e,a)},set_cookie_exists:function(e){return!!get_cookie(e)||(set_cookie(e,"",0),!1)},get_cookie:function(e){var t,a,o,n=document.cookie.split(";");for(t=0;t<n.length;t++)if(a=n[t].substr(0,n[t].indexOf("=")),o=n[t].substr(n[t].indexOf("=")+1),(a=a.replace(/^\s+|\s+$/g,""))===e)return unescape(o)},set_cookie:function(e,t,a,o,n,i){var r=null==a?null:24*a*60*60;this.set_cookie_sec(e,t,r,o,n,i)},set_cookie_sec:function(e,t,a,o,n,i){var r=new Date;r.setSeconds(r.getSeconds()+parseInt(a)),document.cookie=e+"="+escape(t)+(null==a?"":"; expires="+r.toUTCString())+(null==o?"; path=/":"; path="+o)+(null==n?"":"; domain="+n)+(null==i?"":"; secure")},cookie_exists:function(e){var t=this.get_cookie(e);return null!==t&&""!==t&&void 0!==t},move:function(e,t,a){var o=jQuery(e);if(void 0===a&&(a={}),void 0===a.css&&(a.css={}),void 0===a.method&&(a.method="prependTo"),""===t&&void 0!==a.target)switch(a.target){case"wrapper":var n="left";void 0!==a.offset&&(n=a.offset),t=this.find_wrapper(e,n)}switch((t=void 0===a.moveintohidden?jQuery(t).filter(":visible"):jQuery(t)).length>1&&t.length,a.method){case"insertBefore":o.insertBefore(t);break;case"insertAfter":o.insertAfter(t);break;case"appendTo":o.appendTo(t);break;case"prependTo":o.prependTo(t);break;default:o.prependTo(t)}},set_parent_relative:function(e,t){t=void 0!==t?t:{};var a=jQuery(e).parent();t.use_grandparent&&(a=a.parent()),"static"!==a.css("position")&&""!==a.css("position")||a.css("position","relative")},fix_element:function(e,t){t=void 0!==t?t:{};var a=jQuery(e);t.use_grandparent?this.set_parent_relative(a.parent()):this.set_parent_relative(a),t.is_invisible&&a.show();var o=parseInt(a.offset().top),n=parseInt(a.offset().left);if(t.is_invisible&&a.hide(),"left"===t.offset){var i=jQuery(window).width()-n-a.outerWidth();a.css("position","fixed").css("top",o+"px").css("right",i+"px").css("left","")}else a.css("position","fixed").css("top",o+"px").css("left",n+"px").css("right","")},find_wrapper:function(e,t){var a;return jQuery("body").children().each((function(o,n){if(n.id!==e.substring(1)){var i=jQuery(n);if("right"===t&&i.offset().left+jQuery(i).width()<jQuery(window).width()||"left"===t&&i.offset().left>0)return"static"!==i.css("position")&&""!==i.css("position")||i.css("position","relative"),a=n,!1}})),a},center_fixed_element:function(e){var t=jQuery(e),a=jQuery(window).width()/2-parseInt(t.css("width"))/2;t.css("left",a+"px")},center_vertically:function(e){var t=jQuery(e),a=jQuery(window).height()/2-parseInt(t.css("height"))/2;"fixed"!==t.css("position")&&(a-=topoffset=parseInt(t.offset().top)),t.css("top",a+"px")},close:function(e){jQuery(e).remove()},wait_for_images:function(e,t){var a=0,o=[];e.find('img[src][src!=""]').each((function(){o.push(this.src)})),0===o.length&&t.call(e),jQuery.each(o,(function(n,i){var r=new Image;r.src=i;var s="load error";jQuery(r).one(s,(function n(i){if(jQuery(this).off(s,n),++a==o.length)return t.call(e[0]),!1}))}))},privacy:{state:"unknown",state_executed:!1,get_state:function(){if("unknown"!==window.advads_options.privacy.state)return advads.privacy.state_executed||(advads.privacy.state_executed=!0,advads.privacy.dispatch_event(window.advads_options.privacy.state,!1)),advads.privacy.state;if("custom"===window.advads_options.privacy["consent-method"]){var e=new RegExp(window.advads_options.privacy["custom-cookie-name"]+"=.*?"+window.advads_options.privacy["custom-cookie-value"]+"[^;]*");advads.privacy.state_executed||(advads.privacy.state_executed=!0,advads.privacy.dispatch_event(null!==document.cookie.match(e)?"accepted":"unknown",!0))}advads.privacy.state_executed=!0;var t=0,a=setInterval((function(){switch(600==++t&&clearInterval(a),window.advads_options.privacy["consent-method"]){case"custom":null!==document.cookie.match(e)&&(clearInterval(a),"accepted"!==advads.privacy.state&&advads.privacy.dispatch_event("accepted",!0));break;case"iab_tcf_20":if(void 0===window.__tcfapi)return;clearInterval(a),window.__tcfapi("addEventListener",2,(function(e,t){if(t&&("tcloaded"===e.eventStatus||"useractioncomplete"===e.eventStatus||null===e.eventStatus&&void 0!==window.googlefc&&(void 0!==e.purpose||!e.gdprApplies))){var a="useractioncomplete"===e.eventStatus;if(!e.gdprApplies)return void("not_needed"!==advads.privacy.state&&advads.privacy.dispatch_event("not_needed",a));if(e.purpose.consents[1])return void("accepted"!==advads.privacy.state&&advads.privacy.dispatch_event("accepted",a));"rejected"!==advads.privacy.state&&advads.privacy.dispatch_event("rejected",a)}}))}}),100);return advads.privacy.state},is_adsense_npa_enabled:function(){return!window.advads_options||!window.advads_options.privacy||!(!window.advads_options.privacy["show-non-personalized-adsense"]||"custom"!==window.advads_options.privacy["consent-method"])},dispatch_event:function(e,t){var a=advads.privacy.state,o=function(){document.dispatchEvent(new CustomEvent("advanced_ads_privacy",{detail:{state:e,previousState:a,userAction:t}}))};if(advads.privacy.state=e,"loading"!==document.readyState)return o();document.addEventListener("readystatechange",o,{once:!0})},is_ad_decoded:function(e){return null===document.querySelector('script[data-tcf="waiting-for-consent"][data-id="'+e+'"]')},decode_ad:function(e,t){t="boolean"!=typeof t||t;var a=decodeURIComponent(Array.prototype.map.call(atob(e.textContent),(function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));if(!t)return a;e.replaceWith(document.createRange().createContextualFragment(a))}}},(window.advanced_ads_ready||jQuery(document).ready).call(null,(function(){advads.privacy.get_state()})),document.addEventListener("advanced_ads_privacy",(function(e){"accepted"!==e.detail.state&&"not_needed"!==e.detail.state||e.detail.userAction||"loading"===document.readyState||document.querySelectorAll('script[type="text/plain"][data-tcf="waiting-for-consent"]').forEach(advads.privacy.decode_ad)})),jQuery(document).ready((function(){if(!(!advads.supports_localstorage()||!localStorage.getItem("advads_frontend_picker")||window.advads_options.blog_id&&localStorage.getItem("advads_frontend_blog_id")&&window.advads_options.blog_id!==localStorage.getItem("advads_frontend_blog_id")||localStorage.getItem("advads_frontend_starttime")&&parseInt(localStorage.getItem("advads_frontend_starttime"),10)<(new Date).getTime()-27e5&&(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"),advads.set_cookie("advads_frontend_picker","",-1),1))){var e,t=jQuery("<div id='advads-picker-overlay'>"),a=[document.body,document.documentElement,document];if(t.css({position:"absolute",border:"solid 2px #428bca",backgroundColor:"rgba(66,139,202,0.5)",boxSizing:"border-box",zIndex:1e6,pointerEvents:"none"}).prependTo("body"),"true"===localStorage.getItem("advads_frontend_boundary")&&jQuery("body").css("cursor","not-allowed"),window.advads.is_boundary_reached=function(e){if("true"!==localStorage.getItem("advads_frontend_boundary"))return!1;$advads_picker_cur=jQuery(e);var t=jQuery(".advads-frontend-picker-boundary-helper");return $boundaries=t.parent(),$boundaries.css("cursor","pointer"),$advads_picker_cur.is($boundaries)||!$advads_picker_cur.closest($boundaries).length},"xpath"===localStorage.getItem("advads_frontend_pathtype"))var o="getXPath";else o="getPath";jQuery(document).mousemove((function(n){if(n.target!==e){if(~a.indexOf(n.target))return e=null,void t.hide();var i=jQuery(n.target),r=i.offset(),s=i.outerWidth(),d=i.outerHeight();e=n.target;var c=jQuery(e)[o]();c&&t.css({top:r.top,left:r.left,width:s,height:d}).show()}})),jQuery(document).click((function(t){var a=jQuery(e)[o]();advads.is_boundary_reached(e)||(localStorage.setItem("advads_frontend_element",a),window.location=localStorage.getItem("advads_prev_url"))}))}})),jQuery.fn.extend({getPath:function(e,t){if(void 0===e&&(e=""),void 0===t&&(t=0),this.is("html"))return"html > "+e;if(3===t)return e;var a=this.get(0).nodeName.toLowerCase(),o=this.attr("id"),n=this.attr("class");return t+=1,void 0===o||/\d/.test(o)?void 0!==n&&(n=n.split(/[\s\n]+/),(n=jQuery.grep(n,(function(e,t){return!/\d/.test(e)}))).length&&(a+="."+n.slice(0,2).join("."))):a+="#"+o,this.siblings(a).length&&(a+=":eq("+this.siblings(a).addBack().not("#advads-picker-overlay").index(this)+")"),""===e?this.parent().getPath(a,t):this.parent().getPath(a+" > "+e,t)},getXPath:function(e,t){if(void 0===e&&(e=""),void 0===t&&(t=0),this.is("body")||3===t)return e;if(advads.is_boundary_reached(this))return e;var a=this.get(0).nodeName.toLowerCase(),o=a,n=this.attr("id"),i=this.attr("class"),r=[];if(void 0!==n&&!/\d/.test(n))return o+'[@id and id="'+n+'"]/'+e;if(void 0!==i&&(i=i.split(/[\s\n]+/),(i=jQuery.grep(i,(function(e,t){return!/\d/.test(e)}))).length)){t+=1;r=i.slice(0,2);for(var s=[],d=0;d<r.length;d++)s.push('(@class and contains(concat(" ", normalize-space(@class), " "), " '+r[d]+' "))');o+="["+s.join(" and ")+"]"}if(r.length)var c=this.siblings(a+"."+r.join("."));else c=this.siblings(a);c.length&&(o+="["+c.addBack().not("#advads-picker-overlay").index(this)+"]");return""===e?this.parent().getXPath(o,t):this.parent().getXPath(o+"/"+e,t)}});
1
+ !function(){if("function"!=typeof window.CustomEvent){window.CustomEvent=function(e,t){t=t||{bubbles:!1,cancelable:!1,detail:null};var a=document.createEvent("CustomEvent");return a.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),a}}function e(){var e,t=this.parentNode,a=arguments.length;if(t)for(a||t.removeChild(this);a--;)"object"!=typeof(e=arguments[a])?e=this.ownerDocument.createTextNode(e):e.parentNode&&e.parentNode.removeChild(e),a?t.insertBefore(e,this.nextSibling):t.replaceChild(e,this)}Element.prototype.replaceWith||(Element.prototype.replaceWith=e),CharacterData.prototype.replaceWith||(CharacterData.prototype.replaceWith=e),DocumentType.prototype.replaceWith||(DocumentType.prototype.replaceWith=e),window.NodeList&&!NodeList.prototype.forEach&&(NodeList.prototype.forEach=function(e,t){var a,o=this.length;for(t=t||window,a=0;a<o;a++)e.call(t,this[a],a,this)})}(),advads={supports_localstorage:function(){"use strict";try{return!(!window||void 0===window.localStorage)&&(window.localStorage.setItem("x","x"),window.localStorage.removeItem("x"),!0)}catch(e){return!1}},max_per_session:function(e,t){var a=1;if(void 0!==t&&0!==parseInt(t)||(t=1),this.cookie_exists(e)){if(this.get_cookie(e)>=t)return!0;a+=parseInt(this.get_cookie(e))}return this.set_cookie(e,a),!1},count_up:function(e,t){var a=1;this.cookie_exists(e)&&(a+=parseInt(this.get_cookie(e))),this.set_cookie(e,a)},set_cookie_exists:function(e){return!!get_cookie(e)||(set_cookie(e,"",0),!1)},get_cookie:function(e){var t,a,o,n=document.cookie.split(";");for(t=0;t<n.length;t++)if(a=n[t].substr(0,n[t].indexOf("=")),o=n[t].substr(n[t].indexOf("=")+1),(a=a.replace(/^\s+|\s+$/g,""))===e)return unescape(o)},set_cookie:function(e,t,a,o,n,i){var r=null==a?null:24*a*60*60;this.set_cookie_sec(e,t,r,o,n,i)},set_cookie_sec:function(e,t,a,o,n,i){var r=new Date;r.setSeconds(r.getSeconds()+parseInt(a)),document.cookie=e+"="+escape(t)+(null==a?"":"; expires="+r.toUTCString())+(null==o?"; path=/":"; path="+o)+(null==n?"":"; domain="+n)+(null==i?"":"; secure")},cookie_exists:function(e){var t=this.get_cookie(e);return null!==t&&""!==t&&void 0!==t},move:function(e,t,a){var o=jQuery(e);if(void 0===a&&(a={}),void 0===a.css&&(a.css={}),void 0===a.method&&(a.method="prependTo"),""===t&&void 0!==a.target)switch(a.target){case"wrapper":var n="left";void 0!==a.offset&&(n=a.offset),t=this.find_wrapper(e,n)}switch((t=void 0===a.moveintohidden?jQuery(t).filter(":visible"):jQuery(t)).length>1&&t.length,a.method){case"insertBefore":o.insertBefore(t);break;case"insertAfter":o.insertAfter(t);break;case"appendTo":o.appendTo(t);break;case"prependTo":o.prependTo(t);break;default:o.prependTo(t)}},set_parent_relative:function(e,t){t=void 0!==t?t:{};var a=jQuery(e).parent();t.use_grandparent&&(a=a.parent()),"static"!==a.css("position")&&""!==a.css("position")||a.css("position","relative")},fix_element:function(e,t){t=void 0!==t?t:{};var a=jQuery(e);t.use_grandparent?this.set_parent_relative(a.parent()):this.set_parent_relative(a),t.is_invisible&&a.show();var o=parseInt(a.offset().top),n=parseInt(a.offset().left);if(t.is_invisible&&a.hide(),"left"===t.offset){var i=jQuery(window).width()-n-a.outerWidth();a.css("position","fixed").css("top",o+"px").css("right",i+"px").css("left","")}else a.css("position","fixed").css("top",o+"px").css("left",n+"px").css("right","")},find_wrapper:function(e,t){var a;return jQuery("body").children().each((function(o,n){if(n.id!==e.substring(1)){var i=jQuery(n);if("right"===t&&i.offset().left+jQuery(i).width()<jQuery(window).width()||"left"===t&&i.offset().left>0)return"static"!==i.css("position")&&""!==i.css("position")||i.css("position","relative"),a=n,!1}})),a},center_fixed_element:function(e){var t=jQuery(e),a=jQuery(window).width()/2-parseInt(t.css("width"))/2;t.css("left",a+"px")},center_vertically:function(e){var t=jQuery(e),a=jQuery(window).height()/2-parseInt(t.css("height"))/2;"fixed"!==t.css("position")&&(a-=topoffset=parseInt(t.offset().top)),t.css("top",a+"px")},close:function(e){jQuery(e).remove()},wait_for_images:function(e,t){var a=0,o=[];e.find('img[src][src!=""]').each((function(){o.push(this.src)})),0===o.length&&t.call(e),jQuery.each(o,(function(n,i){var r=new Image;r.src=i;var s="load error";jQuery(r).one(s,(function n(i){if(jQuery(this).off(s,n),++a==o.length)return t.call(e[0]),!1}))}))},privacy:{state:"unknown",state_executed:!1,get_state:function(){if("unknown"!==window.advads_options.privacy.state)return advads.privacy.state_executed||(advads.privacy.state_executed=!0,advads.privacy.dispatch_event(window.advads_options.privacy.state,!1)),advads.privacy.state;if("custom"===window.advads_options.privacy["consent-method"]){var e=new RegExp(window.advads_options.privacy["custom-cookie-name"]+"=.*?"+window.advads_options.privacy["custom-cookie-value"]+"[^;]*");advads.privacy.state_executed||(advads.privacy.state_executed=!0,advads.privacy.dispatch_event(null!==document.cookie.match(e)?"accepted":"unknown",!0))}advads.privacy.state_executed=!0;var t=0,a=setInterval((function(){switch(600==++t&&clearInterval(a),window.advads_options.privacy["consent-method"]){case"custom":null!==document.cookie.match(e)&&(clearInterval(a),"accepted"!==advads.privacy.state&&advads.privacy.dispatch_event("accepted",!0));break;case"iab_tcf_20":if(void 0===window.__tcfapi)return;clearInterval(a),window.__tcfapi("addEventListener",2,(function(e,t){if(t&&("tcloaded"===e.eventStatus||"useractioncomplete"===e.eventStatus||null===e.eventStatus&&void 0!==window.googlefc&&(void 0!==e.purpose||!e.gdprApplies))){var a="useractioncomplete"===e.eventStatus;if(!e.gdprApplies)return void("not_needed"!==advads.privacy.state&&advads.privacy.dispatch_event("not_needed",a));if(e.purpose.consents[1])return void("accepted"!==advads.privacy.state&&advads.privacy.dispatch_event("accepted",a));"rejected"!==advads.privacy.state&&advads.privacy.dispatch_event("rejected",a)}}))}}),100);return advads.privacy.state},is_adsense_npa_enabled:function(){return!window.advads_options||!window.advads_options.privacy||!(!window.advads_options.privacy["show-non-personalized-adsense"]||"custom"!==window.advads_options.privacy["consent-method"])},dispatch_event:function(e,t){var a=advads.privacy.state,o=function(){document.dispatchEvent(new CustomEvent("advanced_ads_privacy",{detail:{state:e,previousState:a,userAction:t}}))};if(advads.privacy.state=e,"loading"!==document.readyState)return o();document.addEventListener("readystatechange",o,{once:!0})},is_ad_decoded:function(e){return null===document.querySelector('script[data-tcf="waiting-for-consent"][data-id="'+e+'"]')},decode_ad:function(e,t){t="boolean"!=typeof t||t;var a=decodeURIComponent(Array.prototype.map.call(atob(e.textContent),(function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));if(!t)return a;e.replaceWith(document.createRange().createContextualFragment(a))}}},(window.advanced_ads_ready||jQuery(document).ready).call(null,(function(){advads.privacy.get_state()})),document.addEventListener("advanced_ads_privacy",(function(e){"accepted"!==e.detail.state&&"not_needed"!==e.detail.state||e.detail.userAction||"loading"===document.readyState||document.querySelectorAll('script[type="text/plain"][data-tcf="waiting-for-consent"]').forEach(advads.privacy.decode_ad)})),jQuery(document).ready((function(){if(!(!advads.supports_localstorage()||!localStorage.getItem("advads_frontend_picker")||window.advads_options.blog_id&&localStorage.getItem("advads_frontend_blog_id")&&window.advads_options.blog_id!==localStorage.getItem("advads_frontend_blog_id")||localStorage.getItem("advads_frontend_starttime")&&parseInt(localStorage.getItem("advads_frontend_starttime"),10)<(new Date).getTime()-27e5&&(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"),advads.set_cookie("advads_frontend_picker","",-1),1))){var e,t=jQuery("<div id='advads-picker-overlay'>"),a=[document.body,document.documentElement,document];if(t.css({position:"absolute",border:"solid 2px #428bca",backgroundColor:"rgba(66,139,202,0.5)",boxSizing:"border-box",zIndex:1e6,pointerEvents:"none"}).prependTo("body"),"true"===localStorage.getItem("advads_frontend_boundary")&&jQuery("body").css("cursor","not-allowed"),window.advads.is_boundary_reached=function(e){if("true"!==localStorage.getItem("advads_frontend_boundary"))return!1;$advads_picker_cur=jQuery(e);var t=jQuery(".advads-frontend-picker-boundary-helper");return $boundaries=t.parent(),$boundaries.css("cursor","pointer"),$advads_picker_cur.is($boundaries)||!$advads_picker_cur.closest($boundaries).length},"xpath"===localStorage.getItem("advads_frontend_pathtype"))var o="getXPath";else o="getPath";jQuery(document).mousemove((function(n){if(n.target!==e){if(~a.indexOf(n.target))return e=null,void t.hide();var i=jQuery(n.target),r=i.offset(),s=i.outerWidth(),d=i.outerHeight();e=n.target;var c=jQuery(e)[o]();c&&t.css({top:r.top,left:r.left,width:s,height:d}).show()}})),jQuery(document).click((function(t){var a=jQuery(e)[o]();advads.is_boundary_reached(e)||(localStorage.setItem("advads_frontend_element",a),window.location=localStorage.getItem("advads_prev_url"))}))}})),jQuery.fn.extend({getPath:function(e,t){if(void 0===e&&(e=""),void 0===t&&(t=0),this.is("html"))return"html > "+e;if(3===t)return e;var a=this.get(0).nodeName.toLowerCase(),o=this.attr("id"),n=this.attr("class");return t+=1,void 0===o||/\d/.test(o)?void 0!==n&&(n=n.split(/[\s\n]+/),(n=jQuery.grep(n,(function(e,t){return!/\d/.test(e)}))).length&&(a+="."+n.slice(0,2).join("."))):a+="#"+o,this.siblings(a).length&&(a+=":eq("+this.siblings(a).addBack().not("#advads-picker-overlay").index(this)+")"),""===e?this.parent().getPath(a,t):this.parent().getPath(a+" > "+e,t)},getXPath:function(e,t){if(void 0===e&&(e=""),void 0===t&&(t=0),this.is("body")||3===t)return e;if(advads.is_boundary_reached(this))return e;var a=this.get(0).nodeName.toLowerCase(),o=a,n=this.attr("id"),i=this.attr("class"),r=[];if(void 0!==n&&!/\d/.test(n))return o+'[@id and id="'+n+'"]/'+e;if(void 0!==i&&(i=i.split(/[\s\n]+/),(i=jQuery.grep(i,(function(e,t){return!/\d/.test(e)}))).length)){t+=1;r=i.slice(0,2);for(var s=[],d=0;d<r.length;d++)s.push('(@class and contains(concat(" ", normalize-space(@class), " "), " '+r[d]+' "))');o+="["+s.join(" and ")+"]"}if(r.length)var c=this.siblings(a+"."+r.join("."));else c=this.siblings(a);c.length&&(o+="["+c.addBack().not("#advads-picker-overlay").index(this)+"]");return""===e?this.parent().getXPath(o,t):this.parent().getXPath(o+"/"+e,t)}});
public/class-advanced-ads.php CHANGED
@@ -834,7 +834,7 @@ class Advanced_Ads {
834
  'create_posts' => 'advanced_ads_edit_ads',
835
  ),
836
  'has_archive' => false,
837
- 'query_var' => true,
838
  'supports' => $supports,
839
  'taxonomies' => array( self::AD_GROUP_TAXONOMY ),
840
  );
834
  'create_posts' => 'advanced_ads_edit_ads',
835
  ),
836
  'has_archive' => false,
837
+ 'query_var' => false, // set to true and refresh your permalink settings to query ads under a public URL
838
  'supports' => $supports,
839
  'taxonomies' => array( self::AD_GROUP_TAXONOMY ),
840
  );
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: webzunft, advancedads
3
  Tags: ads, ad manager, ad rotation, adsense, banner
4
  Requires at least: 4.6
5
- Tested up to: 5.5
6
  Requires PHP: 5.6
7
- Stable tag: 1.21.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -153,7 +153,7 @@ Learn more on the [plugin homepage](https://wpadvancedads.com).
153
 
154
  Thank you for motivating us with your [positive review](https://wordpress.org/support/plugin/advanced-ads/reviews/?rate=5#new-post).
155
 
156
- Localizations: Czech, Dutch, English, French, German, Italian, Japanese, Norwegian, Portuguese, Slovak, Spanish, Turkish, Vietnamese, Polish, Chinese (Taiwan)
157
 
158
  > <strong>Add-Ons</strong>
159
  >
@@ -317,6 +317,20 @@ Yes. You can use plenty of [hooks](https://wpadvancedads.com/codex/) to customiz
317
 
318
  == Changelog ==
319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  = 1.21.1 =
321
 
322
  - fixed pagination on the ad list page
@@ -357,9 +371,6 @@ Yes. You can use plenty of [hooks](https://wpadvancedads.com/codex/) to customiz
357
  - added missing spaces to image ad tags to fix Cache-Busting issue
358
  - made ad centering work when right and left margin are set
359
  - add ad health check if __tcfapi responds but the privacy module is either not enabled or not set to TCF 2.0
360
-
361
- = 1.19.1 =
362
-
363
  - remove duplicate lines from the ads.txt file
364
  - fixed layout issues that happens due to the JNews theme
365
 
2
  Contributors: webzunft, advancedads
3
  Tags: ads, ad manager, ad rotation, adsense, banner
4
  Requires at least: 4.6
5
+ Tested up to: 5.6
6
  Requires PHP: 5.6
7
+ Stable tag: 1.22.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
153
 
154
  Thank you for motivating us with your [positive review](https://wordpress.org/support/plugin/advanced-ads/reviews/?rate=5#new-post).
155
 
156
+ Localizations: Arabic, Chinese, Czech, Dutch, English, French, German, Hungarian, Italian, Japanese, Norwegian, Polish, Portuguese, Russian, Slovak, Spanish, Turkish, Vietnamese
157
 
158
  > <strong>Add-Ons</strong>
159
  >
317
 
318
  == Changelog ==
319
 
320
+ = 1.22.0 =
321
+
322
+ - made dashboard layout compatible with WordPress 5.6
323
+ - removed irrelevant AdSense warnings
324
+ - allow filtering of data-attributes for encoded ads if privacy module is enabled
325
+ - added `advanced-ads-ad-edit-show-placement-injection` filter to allow removing the placement-injection box on the ad edit screen
326
+ - added `advanced-ads-unhide-meta-boxes` filter to allow adding of meta box ids that should always be visible on ad edit pages
327
+ - added `advanced-ads-ad-option-{$field}` filter for ad options
328
+ - added action hooks for ad status changes: `advanced-ads-ad-status-published`, `advanced-ads-ad-status-unpublished`, `advanced-ads-ad-status-{$old_status}-to-{$new_status}`
329
+ - removed public URLs for single ads on some installations
330
+ - fixed old icon in the menu
331
+ - fixed Internet Explorer 11 incompatibility
332
+ - fixed possible error in TinyMCE editor caused by ad blockers
333
+
334
  = 1.21.1 =
335
 
336
  - fixed pagination on the ad list page
371
  - added missing spaces to image ad tags to fix Cache-Busting issue
372
  - made ad centering work when right and left margin are set
373
  - add ad health check if __tcfapi responds but the privacy module is either not enabled or not set to TCF 2.0
 
 
 
374
  - remove duplicate lines from the ads.txt file
375
  - fixed layout issues that happens due to the JNews theme
376