Advanced Ads - Version 1.30.0

Version Description

  • Improvement: add advanced-ads-group-taxonomy-params filter to change ad group taxonomy parameters
  • Improvement: add "Manual Placements" to the Advanced Ads block and sidebar widget
  • Improvement: update Black Friday promotion
  • Fix: enable Ad Admin and Ad Manager to assign ads to groups from ad edit page and quick edit view
  • Fix: disable unavailable ad types on the ad edit page
  • Fix: improve AdSense auto ads code warning on ad edit page
  • Fix: handle AdSense report API response for accounts without earnings
  • Fix: remove amp-auto-ads element on non-AMP URLs
  • Fix: honor disabling ads settings for AMP pages
  • Fix: escape placement selectors for jQuery to allow adding conditions to multibyte placement names
  • Fix: ensure correct text domain for translations
  • Fix: make the ad list sortable in descending order
  • Fix: remove hard-coded orderby and order for posts list
  • Fix: prevent updating ad weights of non-published ads
  • Fix: correct Display Conditions meta box video player
  • Fix: remove escaped HTML tags in new placement form
  • Fix: resolve a conflict with WPML where conditions were not displayed correctly on the placement page
  • Fix: move placement of the ad blocker disguise settings
Download this release

Release Info

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

Code changes from version 1.29.1 to 1.30.0

admin/assets/css/admin.css CHANGED
@@ -433,6 +433,17 @@ body.rtl #mapi-archived-ads { left: 78px; right:auto; }
433
  .advads-settings-tab-main-form textarea { resize: both; }
434
  .advads-settings-tab-main-form .description + label { display: block; margin-top: 12px; }
435
 
 
 
 
 
 
 
 
 
 
 
 
436
  /**
437
  - MODAL
438
  */
@@ -521,6 +532,10 @@ a.advads-modal-close-background {
521
  cursor: default;
522
  }
523
 
 
 
 
 
524
  /**
525
  - SUPPORT PAGE
526
  -*/
433
  .advads-settings-tab-main-form textarea { resize: both; }
434
  .advads-settings-tab-main-form .description + label { display: block; margin-top: 12px; }
435
 
436
+ /* AdBlocker Settings */
437
+ #advads-adblocker-wrapper h3 {
438
+ margin-bottom: 0;
439
+ }
440
+ #advanced-ads-rebuild-assets-form td, #advanced-ads-rebuild-assets-form th {
441
+ padding-bottom: 0;
442
+ }
443
+ #advanced-ads-rebuild-assets-form button {
444
+ margin-top: 15px;
445
+ }
446
+
447
  /**
448
  - MODAL
449
  */
532
  cursor: default;
533
  }
534
 
535
+ .advads-ui-autocomplete.ui-front {
536
+ z-index: 10000;
537
+ }
538
+
539
  /**
540
  - SUPPORT PAGE
541
  -*/
admin/assets/js/admin.js CHANGED
@@ -23,7 +23,7 @@ jQuery( document ).ready( function ( $ ) {
23
  $( '#advanced-ads-ad-parameters' ).html( errorThrown )
24
  }
25
  } ).always( function ( MLHttpRequest, textStatus, errorThrown ) {
26
- jQuery( '#advanced-ad-type input' ).prop( 'disabled', false )
27
  } )
28
  }
29
 
@@ -581,39 +581,41 @@ jQuery( document ).ready( function ( $ ) {
581
  } )
582
 
583
  // processing of the rebuild asset form and the FTP/SSH credentials form
584
- var $advads_adblocker_wrapper = $( '#advads-adblocker-wrapper' )
585
- $advads_adblocker_wrapper.find( 'input[type="submit"]' ).prop( 'disabled', false )
586
- $advads_adblocker_wrapper.on( 'submit', 'form', function ( event ) {
587
- event.preventDefault()
588
- var $form = $( '#advanced-ads-rebuild-assets-form' )
589
- $form.prev( '.error' ).remove()
590
- $form.find( 'input[type="submit"]' ).prop( 'disabled', true ).after( '<span class="spinner advads-spinner"></span>' )
 
 
 
591
 
592
  var args = {
593
- data: {
594
- action: 'advads-adblock-rebuild-assets',
595
- nonce: advadsglobal.ajax_nonce,
596
  },
597
- done: function ( data, textStatus, jqXHR ) {
598
- var $advads_adblocker_wrapper = $( '#advads-adblocker-wrapper' )
599
- $advads_adblocker_wrapper.html( data )
600
  },
601
- fail: function ( jqXHR, textStatus, errorThrown ) {
602
- $form.before( '<div class="error"><p>' + textStatus + ': ' + errorThrown + '</p></div>' )
603
- $form.find( 'input[type="submit"]' ).prop( 'disabled', false ).next( '.advads-spinner' ).remove()
604
  },
605
  on_modal_close: function () {
606
- var $form = $( '#advanced-ads-rebuild-assets-form' )
607
- $form.find( 'input[type="submit"]' ).prop( 'disabled', false ).next( '.advads-spinner' ).remove()
608
  }
609
- }
610
 
611
- $.each( $form.serializeArray(), function ( i, o ) {
612
- args.data[ o.name ] = o.value
613
- } )
614
 
615
- advanced_ads_admin.filesystem.ajax( args )
616
- } )
617
 
618
  // process "reserve this space" checkbox
619
  $( '#advanced-ads-ad-parameters' ).on( 'change', '#advanced-ads-ad-parameters-size input[type=number]', function () {
@@ -639,9 +641,9 @@ jQuery( document ).ready( function ( $ ) {
639
  $( this ).removeClass( 'hidden' )
640
  } );
641
  // open tutorial link when clicked on it
642
- $( '.advads-video-link' ).on( 'click', function ( el ) {
643
- el.preventDefault()
644
- var video_container = $( this ).parents( 'h2' ).siblings( '.inside' ).find( '.advads-video-link-container' )
645
  video_container.html( video_container.data( 'videolink' ) )
646
  } );
647
  // open inline tutorial link when clicked on it
@@ -662,12 +664,12 @@ jQuery( document ).ready( function ( $ ) {
662
  } );
663
 
664
  // Find Adsense Auto Ads inside ad content.
665
- var ad_content = jQuery( 'textarea[name=advanced_ad\\[content\\]]' ).html()
666
  if (
667
- (ad_content && ad_content.indexOf('enable_page_level_ads') !== -1)
668
- || /script[^>]+data-ad-client=/.test(ad_content)
669
  ) {
670
- advads_show_adsense_auto_ads_warning()
671
  }
672
 
673
  advads_ads_txt_find_issues()
@@ -1611,3 +1613,16 @@ jQuery( document ).ready( function () {
1611
  jQuery( this ).closest( 'tr' ).remove();
1612
  });
1613
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  $( '#advanced-ads-ad-parameters' ).html( errorThrown )
24
  }
25
  } ).always( function ( MLHttpRequest, textStatus, errorThrown ) {
26
+ jQuery( '#advanced-ad-type input[name^="advanced_ad"]' ).prop( 'disabled', false );
27
  } )
28
  }
29
 
581
  } )
582
 
583
  // processing of the rebuild asset form and the FTP/SSH credentials form
584
+ var $advads_adblocker_wrapper = $( '#advads-adblocker-wrapper' ),
585
+ $advads_adblocker_rebuild_button = $( '#advads-adblocker-rebuild' );
586
+
587
+ $advads_adblocker_rebuild_button.prop( 'disabled', false );
588
+
589
+ $( document ).on( 'click', '#advads-adblocker-rebuild', function ( event ) {
590
+ event.preventDefault();
591
+ var $form = $( '#advanced-ads-rebuild-assets-form' );
592
+ $form.prev( '.error' ).remove();
593
+ $advads_adblocker_rebuild_button.prop( 'disabled', true ).after( '<span class="spinner advads-spinner"></span>' );
594
 
595
  var args = {
596
+ data: {
597
+ action: 'advads-adblock-rebuild-assets',
598
+ nonce: advadsglobal.ajax_nonce
599
  },
600
+ done: function ( data ) {
601
+ $advads_adblocker_wrapper.html( data );
602
+ $advads_adblocker_rebuild_button = $( '#advads-adblocker-rebuild' )
603
  },
604
+ fail: function ( jqXHR, textStatus, errorThrown ) {
605
+ $form.before( '<div class="error"><p>' + textStatus + ': ' + errorThrown + '</p></div>' );
606
+ $advads_adblocker_rebuild_button.prop( 'disabled', false ).next( '.advads-spinner' ).remove();
607
  },
608
  on_modal_close: function () {
609
+ $advads_adblocker_rebuild_button.prop( 'disabled', false ).next( '.advads-spinner' ).remove();
 
610
  }
611
+ };
612
 
613
+ if ( $( '[name="advads_ab_assign_new_folder"]' ).is( ':checked' ) ) {
614
+ args.data.advads_ab_assign_new_folder = true;
615
+ }
616
 
617
+ advanced_ads_admin.filesystem.ajax( args );
618
+ } );
619
 
620
  // process "reserve this space" checkbox
621
  $( '#advanced-ads-ad-parameters' ).on( 'change', '#advanced-ads-ad-parameters-size input[type=number]', function () {
641
  $( this ).removeClass( 'hidden' )
642
  } );
643
  // open tutorial link when clicked on it
644
+ $( '.advads-video-link' ).on( 'click', function (event) {
645
+ event.preventDefault()
646
+ var video_container = $( event.target ).parents( '.postbox' ).find( '.advads-video-link-container' )
647
  video_container.html( video_container.data( 'videolink' ) )
648
  } );
649
  // open inline tutorial link when clicked on it
664
  } );
665
 
666
  // Find Adsense Auto Ads inside ad content.
667
+ var ad_content = jQuery( 'textarea[name=advanced_ad\\[content\\]]' ).text() || '';
668
  if (
669
+ ad_content.indexOf( 'enable_page_level_ads' ) !== - 1
670
+ || /script[^>]+(?:data-ad-client=|adsbygoogle\.js\?client=)/.test( ad_content )
671
  ) {
672
+ advads_show_adsense_auto_ads_warning();
673
  }
674
 
675
  advads_ads_txt_find_issues()
1613
  jQuery( this ).closest( 'tr' ).remove();
1614
  });
1615
  });
1616
+
1617
+ /**
1618
+ * If the jQuery function `escapeSelector` does not exist (add in jQuery 3.0) then add it.
1619
+ */
1620
+ if ( typeof jQuery.escapeSelector === 'undefined' ) {
1621
+ jQuery.escapeSelector = function ( selector ) {
1622
+ return selector.replace(
1623
+ // phpcs:ignore WordPress.WhiteSpace.OperatorSpacing.NoSpaceBefore,WordPress.WhiteSpace.OperatorSpacing.NoSpaceAfter,WordPress.WhiteSpace.OperatorSpacing.NoSpaceBeforeAmp,WordPress.WhiteSpace.OperatorSpacing.NoSpaceAfterAmp -- PHPCS incorrectly reports whitespace errors for this regex
1624
+ /([$%&()*+,./:;<=>?@\[\\\]^{|}~])/g,
1625
+ '\\$1'
1626
+ );
1627
+ };
1628
+ }
admin/assets/js/conditions.js CHANGED
@@ -13,7 +13,7 @@ jQuery( document ).ready(
13
  var condition_type = condition_form_container.find( '.advads-conditions-new select' ).val()
14
  var condition_title = condition_form_container.find( '.advads-conditions-new select option:selected' ).text()
15
  var condition_index = parseInt( condition_form_container.find( '.advads-conditions-index' ).val() )
16
- var condition_list_target_ID = condition_form_container.data( 'condition-list-target' ) // ID of the container into which the new condition is loaded.
17
  var condition_list_target = $( '#' + condition_list_target_ID ) // container into which the new condition is loaded.
18
  var conditions_form_name = condition_form_container.data( 'condition-form-name' ) // name prefix for the form.
19
  var conditions_connector_default = condition_form_container.data( 'condition-connector-default' ) // default connector option.
@@ -89,6 +89,9 @@ jQuery( document ).ready(
89
  function advads_register_terms_autocomplete ( self ) {
90
  self.autocomplete(
91
  {
 
 
 
92
  source: function ( request, callback ) {
93
  // var searchField = request.term;
94
  advads_term_search( self, callback )
@@ -124,6 +127,9 @@ jQuery( document ).ready(
124
  if ( ! $( this ).data( 'autocomplete' ) ) { // If the autocomplete wasn't called yet:
125
  $( this ).autocomplete(
126
  {
 
 
 
127
  source: function ( request, callback ) {
128
  var searchParam = request.term
129
  advads_post_search( searchParam, callback )
13
  var condition_type = condition_form_container.find( '.advads-conditions-new select' ).val()
14
  var condition_title = condition_form_container.find( '.advads-conditions-new select option:selected' ).text()
15
  var condition_index = parseInt( condition_form_container.find( '.advads-conditions-index' ).val() )
16
+ var condition_list_target_ID = $.escapeSelector( condition_form_container.data( 'condition-list-target' ) ) // ID of the container into which the new condition is loaded.
17
  var condition_list_target = $( '#' + condition_list_target_ID ) // container into which the new condition is loaded.
18
  var conditions_form_name = condition_form_container.data( 'condition-form-name' ) // name prefix for the form.
19
  var conditions_connector_default = condition_form_container.data( 'condition-connector-default' ) // default connector option.
89
  function advads_register_terms_autocomplete ( self ) {
90
  self.autocomplete(
91
  {
92
+ classes: {
93
+ 'ui-autocomplete': 'advads-ui-autocomplete'
94
+ },
95
  source: function ( request, callback ) {
96
  // var searchField = request.term;
97
  advads_term_search( self, callback )
127
  if ( ! $( this ).data( 'autocomplete' ) ) { // If the autocomplete wasn't called yet:
128
  $( this ).autocomplete(
129
  {
130
+ classes: {
131
+ 'ui-autocomplete': 'advads-ui-autocomplete'
132
+ },
133
  source: function ( request, callback ) {
134
  var searchParam = request.term
135
  advads_post_search( searchParam, callback )
admin/class-advanced-ads-admin.php CHANGED
@@ -209,14 +209,12 @@ class Advanced_Ads_Admin {
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
 
212
- $auto_ads_strings = Advanced_Ads_AdSense_Admin::get_auto_ads_messages();
213
-
214
  // register admin.js translations.
215
  $translation_array = array(
216
  'condition_or' => __( 'or', 'advanced-ads' ),
217
  'condition_and' => __( 'and', 'advanced-ads' ),
218
  'after_paragraph_promt' => __( 'After which paragraph?', 'advanced-ads' ),
219
- 'page_level_ads_enabled' => $auto_ads_strings['enabled'],
220
  'today' => __( 'Today', 'advanced-ads' ),
221
  'yesterday' => __( 'Yesterday', 'advanced-ads' ),
222
  'this_month' => __( 'This Month', 'advanced-ads' ),
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
 
 
 
212
  // register admin.js translations.
213
  $translation_array = array(
214
  'condition_or' => __( 'or', 'advanced-ads' ),
215
  'condition_and' => __( 'and', 'advanced-ads' ),
216
  'after_paragraph_promt' => __( 'After which paragraph?', 'advanced-ads' ),
217
+ 'page_level_ads_enabled' => Advanced_Ads_AdSense_Admin::get_auto_ads_messages()['enabled'],
218
  'today' => __( 'Today', 'advanced-ads' ),
219
  'yesterday' => __( 'Yesterday', 'advanced-ads' ),
220
  'this_month' => __( 'This Month', 'advanced-ads' ),
admin/includes/class-ad-groups-list.php CHANGED
@@ -152,12 +152,15 @@ class Advanced_Ads_Groups_List {
152
  * @param Advanced_Ads_Group $group group object.
153
  */
154
  public function render_ads_list( Advanced_Ads_Group $group ) {
155
-
156
- $ads = $this->get_ads( $group );
157
-
158
- $weights = $group->get_ad_weights();
159
- $weight_sum = array_sum( $weights );
160
- $ads_output = $weights;
 
 
 
161
  arsort( $ads_output );
162
 
163
  // The Loop.
@@ -167,8 +170,11 @@ class Advanced_Ads_Groups_List {
167
  $ads->the_post();
168
  $line_output = '<li><a href="' . get_edit_post_link( get_the_ID() ) . '">' . get_the_title() . '</a>';
169
 
170
- $_weight = ( isset( $weights[ get_the_ID() ] ) ) ? $weights[ get_the_ID() ] : Advanced_Ads_Group::MAX_AD_GROUP_DEFAULT_WEIGHT;
171
  if ( 'default' === $group->type && $weight_sum ) {
 
 
 
 
172
  $line_output .= '<span class="ad-weight" title="' . __( 'Ad weight', 'advanced-ads' ) . '">' . number_format( ( $_weight / $weight_sum ) * 100 ) . '%</span>';
173
  }
174
 
@@ -515,7 +521,7 @@ class Advanced_Ads_Groups_List {
515
  }
516
 
517
  // save ad weights.
518
- $all_weights[ $group->id ] = $group->sanitize_ad_weights( $_group['ads'] );
519
  }
520
 
521
  // save other attributes.
@@ -569,4 +575,25 @@ class Advanced_Ads_Groups_List {
569
  return add_query_arg( $args, admin_url( 'admin.php' ) );
570
  }
571
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
  }
152
  * @param Advanced_Ads_Group $group group object.
153
  */
154
  public function render_ads_list( Advanced_Ads_Group $group ) {
155
+ $ads = $this->get_ads( $group );
156
+ $weights = $group->get_ad_weights();
157
+ $published_ads = array_map( static function( WP_Post $post ) {
158
+ return $post->ID;
159
+ }, array_filter( $ads->posts, static function( WP_Post $post ) {
160
+ return get_post_status( $post ) === 'publish';
161
+ } ) );
162
+ $weight_sum = array_sum( array_intersect_key( $weights, array_flip( $published_ads ) ) );
163
+ $ads_output = $weights;
164
  arsort( $ads_output );
165
 
166
  // The Loop.
170
  $ads->the_post();
171
  $line_output = '<li><a href="' . get_edit_post_link( get_the_ID() ) . '">' . get_the_title() . '</a>';
172
 
 
173
  if ( 'default' === $group->type && $weight_sum ) {
174
+ $_weight = ( isset( $weights[ get_the_ID() ] ) ) ? $weights[ get_the_ID() ] : Advanced_Ads_Group::MAX_AD_GROUP_DEFAULT_WEIGHT;
175
+ if ( get_post_status() !== 'publish' ) {
176
+ $_weight = 0;
177
+ }
178
  $line_output .= '<span class="ad-weight" title="' . __( 'Ad weight', 'advanced-ads' ) . '">' . number_format( ( $_weight / $weight_sum ) * 100 ) . '%</span>';
179
  }
180
 
521
  }
522
 
523
  // save ad weights.
524
+ $all_weights[ $group->id ] = $this->sanitize_ad_weights( $_group['ads'] );
525
  }
526
 
527
  // save other attributes.
575
  return add_query_arg( $args, admin_url( 'admin.php' ) );
576
  }
577
 
578
+ /**
579
+ * Sanitize ad weights.
580
+ * Make sure keys (ad_ids) can be converted to positive integers and weights are integers as well.
581
+ *
582
+ * @param array $weights ad weights array with (key: ad id; value: weight).
583
+ *
584
+ * @return array
585
+ */
586
+ private function sanitize_ad_weights( array $weights ) {
587
+ $sanitized_weights = array();
588
+ foreach ( $weights as $ad_id => $weight ) {
589
+ $ad_id_int = absint( $ad_id );
590
+ if ( $ad_id_int === 0 || array_key_exists( $ad_id_int, $sanitized_weights ) ) {
591
+ continue;
592
+ }
593
+ $sanitized_weights[ $ad_id_int ] = absint( $weight );
594
+ }
595
+
596
+ return $sanitized_weights;
597
+ }
598
+
599
  }
admin/includes/class-ad-type.php CHANGED
@@ -471,6 +471,9 @@ class Advanced_Ads_Admin_Ad_Type {
471
  'order' => 'ASC',
472
  )
473
  );
 
 
 
474
  }
475
 
476
  return $vars;
471
  'order' => 'ASC',
472
  )
473
  );
474
+ // set get parameters, so the column header arrow shows up correctly.
475
+ $_GET['orderby'] = $vars['orderby'];
476
+ $_GET['order'] = $vars['order'];
477
  }
478
 
479
  return $vars;
admin/includes/class-list-filters.php CHANGED
@@ -61,7 +61,6 @@ class Advanced_Ads_Ad_List_Filters {
61
  private function __construct() {
62
  if ( is_admin() && ! wp_doing_ajax() ) {
63
  add_filter( 'posts_results', array( $this, 'post_results' ), 10, 2 );
64
- add_filter( 'posts_orderby', array( $this, 'orderby_filter' ), 10, 2 );
65
  add_filter( 'post_limits', array( $this, 'limit_filter' ), 10, 2 );
66
  }
67
  }
@@ -260,33 +259,6 @@ class Advanced_Ads_Ad_List_Filters {
260
  return $this->all_filters;
261
  }
262
 
263
- /**
264
- * Re-order the posts list by post title.
265
- *
266
- * @param string $orderby the previous orderby value.
267
- * @param WP_Query $the_query the current WP_Query object.
268
- *
269
- * @return mixed
270
- */
271
- public function orderby_filter( $orderby, $the_query ) {
272
- // Execute only in the main query.
273
- if ( ! $the_query->is_main_query() ) {
274
- return $orderby;
275
- }
276
-
277
- if ( ! function_exists( 'get_current_screen' ) ) {
278
- return $orderby;
279
- }
280
-
281
- $scr = get_current_screen();
282
- // Execute only in the ad list page.
283
- if ( ! $scr || 'edit-advanced_ads' !== $scr->id ) {
284
- return $orderby;
285
- }
286
-
287
- return 'post_title ASC';
288
- }
289
-
290
  /**
291
  * Remove limits because we need to get all ads.
292
  *
61
  private function __construct() {
62
  if ( is_admin() && ! wp_doing_ajax() ) {
63
  add_filter( 'posts_results', array( $this, 'post_results' ), 10, 2 );
 
64
  add_filter( 'post_limits', array( $this, 'limit_filter' ), 10, 2 );
65
  }
66
  }
259
  return $this->all_filters;
260
  }
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  /**
263
  * Remove limits because we need to get all ads.
264
  *
admin/includes/class-meta-box.php CHANGED
@@ -304,19 +304,10 @@ class Advanced_Ads_Admin_Meta_Boxes {
304
  }
305
 
306
  if ( 'ad-parameters-box' === $box['id'] ) {
307
- $auto_ads_strings = Advanced_Ads_AdSense_Admin::get_auto_ads_messages();
308
-
309
- if ( Advanced_Ads_AdSense_Data::get_instance()->is_page_level_enabled() ) {
310
- $warnings[] = array(
311
- 'text' => $auto_ads_strings['enabled'],
312
- 'class' => 'advads-auto-ad-in-ad-content hidden error',
313
- );
314
- } else {
315
- $warnings[] = array(
316
- 'text' => $auto_ads_strings['disabled'],
317
- 'class' => 'advads-auto-ad-in-ad-content hidden error',
318
- );
319
- }
320
  }
321
 
322
  // Let users know that they could use the Google AdSense ad type when they enter an AdSense code.
304
  }
305
 
306
  if ( 'ad-parameters-box' === $box['id'] ) {
307
+ $warnings[] = array(
308
+ 'text' => Advanced_Ads_AdSense_Admin::get_auto_ads_messages()[ Advanced_Ads_AdSense_Data::get_instance()->is_page_level_enabled() ? 'enabled' : 'disabled' ],
309
+ 'class' => 'advads-auto-ad-in-ad-content hidden error',
310
+ );
 
 
 
 
 
 
 
 
 
311
  }
312
 
313
  // Let users know that they could use the Google AdSense ad type when they enter an AdSense code.
admin/includes/class-notices.php CHANGED
@@ -318,21 +318,21 @@ class Advanced_Ads_Admin_Notices {
318
  return;
319
  }
320
 
321
- if ( array() === $this->notices ) {
322
- return;
323
- }
324
-
325
- // register Black Friday 2020 deals.
326
- if ( time() > 1606392000 &&
327
- time() <= 1606824000 && Advanced_Ads_Admin::get_instance()->screen_belongs_to_advanced_ads() ) {
328
  $options = $this->options();
329
  $closed = isset( $options['closed'] ) ? $options['closed'] : array();
330
 
331
- if ( ! isset( $closed['bf2020'] ) ) {
332
- $this->notices[] = 'bf2020';
333
  }
334
  }
335
 
 
 
 
 
336
  // hide the welcome panel on the ad edit page
337
  $screen = get_current_screen();
338
  if ( isset( $screen->id ) && $screen->id === 'advanced_ads' ) {
318
  return;
319
  }
320
 
321
+ // register Black Friday 2021 deals.
322
+ if ( time() > 1637841600 &&
323
+ time() <= 1638273600 && Advanced_Ads_Admin::get_instance()->screen_belongs_to_advanced_ads() ) {
 
 
 
 
324
  $options = $this->options();
325
  $closed = isset( $options['closed'] ) ? $options['closed'] : array();
326
 
327
+ if ( ! isset( $closed['bf2021'] ) ) {
328
+ $this->notices[] = 'bf2021';
329
  }
330
  }
331
 
332
+ if ( array() === $this->notices ) {
333
+ return;
334
+ }
335
+
336
  // hide the welcome panel on the ad edit page
337
  $screen = get_current_screen();
338
  if ( isset( $screen->id ) && $screen->id === 'advanced_ads' ) {
admin/includes/notices.php CHANGED
@@ -56,13 +56,13 @@ $advanced_ads_admin_notices = apply_filters(
56
  . '</p></div>',
57
  'global' => false,
58
  ),
59
- // Black Friday 2020 promotion.
60
- 'bf2020' => array(
61
  'type' => 'info',
62
  'text' => sprintf(
63
  // translators: %s is a link. `30%%` is correct, please use exactly that value so that it shows "30%".
64
  __( 'Our Black Friday / Cyber Monday Offer: <span style="font-weight: bold; font-size: 1.4em; color: green;">-30%%</span> on all add-ons and All Access.<a class="button button-primary" target="_blank" href="%s">Get All Access</a>', 'advanced-ads' ),
65
- ADVADS_URL . 'checkout/?edd_action=add_to_cart&download_id=95170&edd_options[price_id]=1&discount=BFCM2020#utm_source=advanced-ads&utm_medium=link&utm_campaign=bfcm-2020'
66
  ),
67
  'global' => true,
68
  ),
56
  . '</p></div>',
57
  'global' => false,
58
  ),
59
+ // Black Friday 2021 promotion.
60
+ 'bf2021' => array(
61
  'type' => 'info',
62
  'text' => sprintf(
63
  // translators: %s is a link. `30%%` is correct, please use exactly that value so that it shows "30%".
64
  __( 'Our Black Friday / Cyber Monday Offer: <span style="font-weight: bold; font-size: 1.4em; color: green;">-30%%</span> on all add-ons and All Access.<a class="button button-primary" target="_blank" href="%s">Get All Access</a>', 'advanced-ads' ),
65
+ ADVADS_URL . 'checkout/?edd_action=add_to_cart&download_id=95170&edd_options[price_id]=1&discount=BFCM2021#utm_source=advanced-ads&utm_medium=link&utm_campaign=bfcm-2021'
66
  ),
67
  'global' => true,
68
  ),
admin/views/placement-form.php CHANGED
@@ -69,7 +69,9 @@
69
  <p class="advads-notice-inline advads-error advads-placement-type-error"><?php esc_html_e( 'Please select a placement type.', 'advanced-ads' ); ?></p>
70
  <br/>
71
  <h3>2. <?php esc_html_e( 'Choose a Name', 'advanced-ads' ); ?></h3>
72
- <p class="description"><?php esc_html_e( 'The name of the placement is only visible to you. Tip: choose a descriptive one, e.g. <em>Below Post Headline</em>.', 'advanced-ads' ); ?></p>
 
 
73
  <p><input name="advads[placement][name]" class="advads-new-placement-name" type="text" value=""
74
  placeholder="<?php esc_html_e( 'Placement Name', 'advanced-ads' ); ?>"/></p>
75
  <p class="advads-notice-inline advads-error advads-placement-name-error"><?php esc_html_e( 'Please enter a name for your placement.', 'advanced-ads' ); ?></p>
69
  <p class="advads-notice-inline advads-error advads-placement-type-error"><?php esc_html_e( 'Please select a placement type.', 'advanced-ads' ); ?></p>
70
  <br/>
71
  <h3>2. <?php esc_html_e( 'Choose a Name', 'advanced-ads' ); ?></h3>
72
+ <p class="description">
73
+ <?php esc_html_e( 'The name of the placement is only visible to you. Tip: choose a descriptive one, e.g. Below Post Headline.', 'advanced-ads' ); ?>
74
+ </p>
75
  <p><input name="advads[placement][name]" class="advads-new-placement-name" type="text" value=""
76
  placeholder="<?php esc_html_e( 'Placement Name', 'advanced-ads' ); ?>"/></p>
77
  <p class="advads-notice-inline advads-error advads-placement-name-error"><?php esc_html_e( 'Please enter a name for your placement.', 'advanced-ads' ); ?></p>
admin/views/placements.php CHANGED
@@ -78,14 +78,14 @@ $quick_actions['delete'] = '<a style="cursor: pointer;" class="advads-delete-tag
78
  <?php if ( isset( $placement_types ) && ! empty( $placement_types ) ) : ?>
79
  <div class="tablenav top">
80
  <select class="advads_filter_placement_type">
81
- <option value="0"><?php esc_html_e( '- show all types -', 'advanced_ads' ); ?></option>
82
  <?php foreach ( $placement_types as $type_name => $placement_type ) : ?>
83
  <?php if ( in_array( $type_name, $existing_types, true ) ) : ?>
84
  <option value="<?php echo esc_attr( $type_name ); ?>"><?php echo esc_html( $placement_type['title'] ); ?></option>
85
  <?php endif; ?>
86
  <?php endforeach; ?>
87
  </select>
88
- <input type="text" class="advads_search_placement_name" placeholder="<?php esc_html_e( 'filter by name', 'advanced_ads' ); ?>"/>
89
  </div>
90
  <?php endif; ?>
91
 
78
  <?php if ( isset( $placement_types ) && ! empty( $placement_types ) ) : ?>
79
  <div class="tablenav top">
80
  <select class="advads_filter_placement_type">
81
+ <option value="0"><?php esc_html_e( '- show all types -', 'advanced-ads' ); ?></option>
82
  <?php foreach ( $placement_types as $type_name => $placement_type ) : ?>
83
  <?php if ( in_array( $type_name, $existing_types, true ) ) : ?>
84
  <option value="<?php echo esc_attr( $type_name ); ?>"><?php echo esc_html( $placement_type['title'] ); ?></option>
85
  <?php endif; ?>
86
  <?php endforeach; ?>
87
  </select>
88
+ <input type="text" class="advads_search_placement_name" placeholder="<?php esc_html_e( 'filter by name', 'advanced-ads' ); ?>"/>
89
  </div>
90
  <?php endif; ?>
91
 
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.29.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.29.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.30.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.30.0' );
43
 
44
  // Autoloading, modules and functions.
45
 
changelog.txt ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ == Changelog ==
2
+
3
+ = 1.30.0 =
4
+
5
+ - Improvement: add `advanced-ads-group-taxonomy-params` filter to change ad group taxonomy parameters
6
+ - Improvement: add "Manual Placements" to the Advanced Ads block and sidebar widget
7
+ - Improvement: update Black Friday promotion
8
+ - Fix: enable `Ad Admin` and `Ad Manager` to assign ads to groups from ad edit page and quick edit view
9
+ - Fix: disable unavailable ad types on the ad edit page
10
+ - Fix: improve AdSense auto ads code warning on ad edit page
11
+ - Fix: handle AdSense report API response for accounts without earnings
12
+ - Fix: remove `amp-auto-ads` element on non-AMP URLs
13
+ - Fix: honor disabling ads settings for AMP pages
14
+ - Fix: escape placement selectors for jQuery to allow adding conditions to multibyte placement names
15
+ - Fix: ensure correct text domain for translations
16
+ - Fix: make the ad list sortable in descending order
17
+ - Fix: remove hard-coded `orderby` and `order` for posts list
18
+ - Fix: prevent updating ad weights of non-published ads
19
+ - Fix: correct Display Conditions meta box video player
20
+ - Fix: remove escaped HTML tags in new placement form
21
+ - Fix: resolve a conflict with WPML where conditions were not displayed correctly on the placement page
22
+ - Fix: move placement of the ad blocker disguise settings
23
+
24
+ = 1.29.1 =
25
+
26
+ - Fix: ensure `Advanced_Ads_Adsense_Report_Helper` JavaScript global is defined
27
+ - Fix: hide AdSense setting submit button if there is no publisher ID
28
+ - Fix: show error message when no AdSense account data found
29
+
30
+ = 1.29.0 =
31
+
32
+ - Improvement: update AdSense API to V2
33
+ - Improvement: unify layout of backend notices
34
+ - Improvement: move some descriptions into tooltips
35
+ - Improvement: move ad blocker fix options to the related setting
36
+ - Fix: correct uppercase CSS rule for labels in backend
37
+ - Fix: remove usage link for every type except manual placement
38
+ - Fix: correct sorting of placements by type on placement list page
39
+ - Fix: bad language in Analytics Adblock Counter option
40
+
41
+ = 1.28.0 =
42
+
43
+ - Improvement: add an `inline` attribute to the `the_ad` shortcode that allows the user to change the wrapper from `div` to `span`
44
+ - Improvement: update plugin updater class
45
+ - Improvement: rename "Item" option into "Ad / Group" to clarify its purpose
46
+ - Improvement: show a link to create a new ad on the placement page
47
+ - Improvement: show content placements first when creating a new one
48
+ - Improvement: remove welcome panel on ad edit screen
49
+ - Improvement: rename last button in the wizard to "Save" to highlight that this is the last step
50
+ - Fix: wrap `advanced_ads_ready_queue` in an IIEF to prevent naming collisions
51
+
52
+ = 1.27.0 =
53
+
54
+ - Improvement: prevent issues with functionality from other plugins that delay JavaScript execution (WP Rocket, Complianz, et al.).
55
+ - Improvement: unify the layout of the Next buttons in the ad Wizard
56
+ - Improvement: add the updated AdSense code. Added a filter to continue using the old AdSense code. [Learn more](https://wpadvancedads.com/adsense-crossorigin-attribute-performance)
57
+ - Improvement: update Ad Block Counter to work with Google Analytics 4 properties
58
+ - Fix: ensure Ad Admin can save AdSense, Privacy, and License settings
59
+ - Fix: prevent error when "Remove data on uninstall" option is set due to uninitialised constants
60
+ - Fix: ad edit button for ads delivered using groups
61
+ - Fix: improve compatibility with PHP 8 by removing default values from required function parameters
62
+
63
+ = 1.26.0 =
64
+
65
+ - overwrite existing options when importing new options
66
+ - add possibility to export privacy, ads.txt and Google AdSense options
67
+ - remove duplicate inline styles for placements with passive cache-busting and activated TCF 2.0 privacy option
68
+ - adjust the Advanced Ads block layout to the default WordPress block layout
69
+ - add migration from Advanced Ads widget to Advanced Ads block
70
+ - fix saving of additional CSS class in Advanced Ads block
71
+ - make placement deletion confirmation dialogue translatable
72
+ - add WebP as allowed image media type for exports
73
+
74
+ = 1.25.1 =
75
+
76
+ - fixed a bug that prevented removing placement conditions
77
+ - trim `inline-css` to remove duplicate spaces
78
+ - check if `inline-css` index exists in ad options to prevent undefined index notice
79
+ - move `Advanced_Ads_Inline_Css` class from singleton to one instance per ad, to fix issues with `inline-css` not being added
80
+ - fixed ad edit button visibility in frontend when ad label was activated
81
+
82
+ = 1.25.0 =
83
+
84
+ - show ad label event when ad wrapper is now shown
85
+ - add filter `advanced-ads-ajax-ad-select-arguments` to modify arguments of AJAX ad selection
86
+ - display ads on BuddyPress pages when no ads allowed on 404 pages
87
+ - Ad blocker fix: do not copy assets from "vendor" and "lib" folders
88
+ - Ad blocker fix: compare assets based on `filemtime` instead of `filesize`
89
+ - bump minimal require WP core version to 4.9
90
+ - allow to add a replacement for AdSense page-level code
91
+
92
+ = 1.24.2 =
93
+
94
+ - fix authenticated (i.e. logged-in) DOM-based XSS vulnerability while creating jQuery object from user input in Safari and IE
95
+
96
+ = 1.24.1 =
97
+
98
+ - fix compatibilty with WP prior to 5.0
99
+
100
+ = 1.24.0 =
101
+
102
+ - AdSense deprecated Link Units and might no longer fill them. So we removed them when creating new ads. [Learn more](https://wpadvancedads.com/adsense-link-units/)
103
+ - enable AdSense Auto ads on AMP pages
104
+ - interpret WP blocks in the plain text ad type
105
+ - remove MailPoet warning since they are not retiring custom shortcodes after all
106
+ - convert jQuery shorthand functions to `.on()` and `.trigger()`
107
+ - made shortcode button work with WordPress 4.9
108
+ - allow to exclude conditions from the "new display condition" dropdown
109
+ - prevent AdSense earnings box from appearing on non AdSense ad page when AdSense connection is lost
110
+
111
+ = 1.23.2 =
112
+
113
+ - reverted erroneously removing plugin author index
114
+
115
+ = 1.23.1 =
116
+
117
+ - removed warning about iThemes Security since it is no longer causing the reported issue
118
+ - added correct icon to Advanced Ads block
119
+ - fixed escaping for AdSense Auto ads codes that use the deprecated "Disable Top Level" option
120
+ - fixed TinyMCE warning in dev console
121
+ - replaced `intval()` and `floatval()` with type-casting
122
+
123
+ = 1.23.0 =
124
+
125
+ - MailPoet is going to deprecate custom shortcodes. See [this section](https://wpadvancedads.com/mailpoet-newsletters/#Enable_MailPoet_support_in_Advanced_Ads) in case you are using Advanced Ads ads in your newsletters
126
+ - updated Google AdSense API to use web application verification
127
+ - prevent accidental public ad URLs. See [Making the Ads post type public](https://wpadvancedads.com/manual/making-the-ad-post-type-public/) if you want to query ads via a dedicated URL
128
+ - allow to reserve only width or height for plain, rich content and group ad types
129
+
130
+ = 1.22.2 =
131
+
132
+ - fix shortcode button within Classic editor and Classic editor block
133
+
134
+ = 1.22.1 =
135
+
136
+ - removed "Disable shortcode button" setting after it became obsolete in 1.22.0
137
+ - added the `advanced-ads-disable-shortcode-button` filter to disable the shortcode button
138
+ - removed ads.txt-related warnings when the option is disabled
139
+ - fixed issue with loading of shortcode button in editors that disabled custom buttons, e.g., Elementor
140
+ - fixed JavaScript warnings in Elementor editor
141
+
142
+ = 1.22.0 =
143
+
144
+ - made dashboard layout compatible with WordPress 5.6
145
+ - removed irrelevant AdSense warnings
146
+ - allow filtering of data-attributes for encoded ads if privacy module is enabled
147
+ - added `advanced-ads-ad-edit-show-placement-injection` filter to allow removing the placement-injection box on the ad edit screen
148
+ - added `advanced-ads-unhide-meta-boxes` filter to allow adding of meta box ids that should always be visible on ad edit pages
149
+ - added `advanced-ads-ad-option-{$field}` filter for ad options
150
+ - 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}`
151
+ - removed public URLs for single ads on some installations
152
+ - fixed old icon in the menu
153
+ - fixed Internet Explorer 11 incompatibility
154
+ - fixed possible error in TinyMCE editor caused by ad blockers
155
+
156
+ = 1.21.1 =
157
+
158
+ - fixed pagination on the ad list page
159
+ - fix Google AdSense non-personalized ads
160
+
161
+ = 1.21.0 =
162
+
163
+ - enable Position options for Sidebar placements
164
+ - increased default weight for ads imported to a group from 1 to 5 which is mostly relevant when selling ads to existing placements
165
+ - Ad Health: added body classes that explain plugin behavior at given moment
166
+ - ads.txt: prevented converting special characters into HTML entities
167
+ - show ad overview list even if all ads were moved to trash
168
+ - fixed error when specific ACF function does not exist
169
+ - fixed option to disable ads also on the "Posts page" as set in the WordPress Reading settings
170
+
171
+ = 1.20.3 =
172
+
173
+ - whitelist field groups created by Advanced Custom Fields on the ad edit page
174
+ - prevent including AdSense Auto ads code when the Borlabs Cookie is already adding it
175
+ - prevented adding unneeded escape characters to ads.txt file
176
+ - added compatibility with Funding Choices when consent is not needed
177
+
178
+ = 1.20.2 =
179
+
180
+ - fixed displaying image ads if privacy method is set to custom cookie
181
+ - fixed scroll to last edited placement with non-English letters
182
+ - fixed minor UI issues
183
+
184
+ = 1.20.1 =
185
+
186
+ - don't escape top anchor ads code as a whole, user input has already been escaped
187
+
188
+ = 1.20.0 =
189
+
190
+ - integrate with TCF 2.0 compatible consent management platforms, e.g., Quantcast Choices
191
+ - improve timezone methods `Advanced_Ads_Utils::get_wp_timezone()` and `Advanced_Ads_Utils::get_timezone_name()`
192
+ - Divi theme: made content injection work with the "Unlimited ad injection" setting disabled
193
+ - added missing spaces to image ad tags to fix Cache-Busting issue
194
+ - made ad centering work when right and left margin are set
195
+ - add ad health check if __tcfapi responds but the privacy module is either not enabled or not set to TCF 2.0
196
+ - remove duplicate lines from the ads.txt file
197
+ - fixed layout issues that happens due to the JNews theme
198
+
199
+ = 1.19.1 =
200
+
201
+ - apply WordPress lazy loading for images to images in ad content
202
+ - layout fixes for WordPress 5.5
203
+
204
+ = 1.19.0 =
205
+
206
+ - placements are now ordered by type on the Placements page. You can still choose ordering by name
207
+ - the "custom" option of the Content placement now comes with a picker to select the position in the frontend
208
+ - WPML: placements pages show ads according to the selected language
209
+ - WPML: display the ad in the original language if a translated ad is missing unless the publisher chooses to hide it instead
210
+ - prevented injection of ads into captions of "image" blocks
211
+ - improved bot check
212
+ - fixed layout of expiry data fields
213
+ - fixed broken check for the Responsive add-on
214
+
215
+ = 1.18.0 =
216
+
217
+ * inject ads automatically based on div, table, quotes, iframe, and other HTML tags
218
+ * define your own injection rules using the new "custom" option for the Content placement
219
+ * hide Shortcode button in TinyMCE editor by default for new users
220
+ * added `advanced-ads-options` filter for main plugin options
221
+ * prevent automatic ad injection into paragraphs within blockquotes
222
+ * hide placement options after publishing an ad translated with WPML
223
+ * disallowed ad insertion into the header of the WP File Manager's admin page
224
+
225
+ = 1.17.12 =
226
+
227
+ * set default name for ads where none was given
228
+ * fixed issue where long option markup could break the group page
229
+ * made placements of type other than "Header Code" work with "Thrive Theme Builder" theme
230
+
231
+ = 1.17.11 =
232
+
233
+ * added Datanyze and Ecosia to bots list
234
+ * linked to [Google Ad Manager Integration](https://wpadvancedads.com/add-ons/google-ad-manager/)
235
+ * fixed Layout Key field for AdSense ads not saving new values
236
+ * fixed error that broke the wizard when the URL field of image ads contained a wrong value
237
+ * fixed links to manuals
238
+ * fixed unneeded notification shown when ads are disabled on 404 pages
239
+
240
+ = 1.17.10 =
241
+
242
+ * fixed escaped HTML tag in Ad Planning column
243
+ * fixed possible JavaScript error caused by Ad Health checks
244
+ * fixed possible third-party conflict causing the ad group filter to throw an exception
245
+ * removed unneeded notification shown when ads are disabled on 404 pages
246
+
247
+ = 1.17.9 =
248
+
249
+ * fixed warning about missing `the_content` filter in WordPress 5.4
250
+ * fixed public warning if the WordPres `widget` function is called with wrong parameters
251
+ * fixed wrong usage of get_current_user
252
+
253
+ = 1.17.8 =
254
+
255
+ * WPML: placements now deliver also ads translated with WPML when only one of the language versions was assigned to them
256
+ * fixed delete option in placement form
257
+
258
+ = 1.17.7 =
259
+
260
+ * fixed index value of content placements not showing up in the form while saved and working correctly
261
+ * recovered compatibility with the "Render Blocking JS" option of the WP Fastest Cache plugin
262
+
263
+ = 1.17.6 =
264
+
265
+ * improved coding style in backend templates
266
+ * prepared for option to allow minimum number of words between ads in Advanced Ads Pro
267
+ * hide notice that warns if the "Disable ads in REST API" option was selected
268
+ * Renad theme: fixed a bug that caused menu item to point to incorrect url instead of theme options
269
+
270
+ = 1.17.5 =
271
+
272
+ * fixed ads being injected multiple times when using the Newspaper theme or multiple the_content filters
273
+
274
+ = 1.17.4 =
275
+
276
+ * added option and Display Condition to disable ads in content served through the REST API
277
+ * made error notices less obstrusive
278
+ * code style optimizations
279
+ * fixed ad groups form on ad edit page
280
+ * fixed potential conflict with autoloader
281
+
282
+ = 1.17.3 =
283
+
284
+ * prevented content injection into specific elements where ads cause issues
285
+ * assign `advads-stop-injection` class to any element into which you don’t want to automatically inject ads
286
+ * fixed possible cURL error when checking existing ads.txt file locally
287
+
288
+ = 1.17.2 =
289
+
290
+ * replaced autoloader
291
+ * fixed an issue where an expired ad removed HTML in the ad code
292
+
293
+ = 1.17.1 =
294
+
295
+ * fixed failing upload of new image ads
296
+ * fixed Google Ad Manager debug link also showing up when other Google Publisher Tags are used
297
+
298
+ = 1.17 =
299
+
300
+ * improved AdSense ad unit list coming from the AdSense API
301
+ * improved "highlight ads" option in Ad Health
302
+ * show notice if AJAX calls are broken
303
+ * added `com.pl` as exception for placing ads.txt files in subdomains
304
+ * removed placeholder for AdSense ads in the Customizer and Elementor editor
305
+ * fix for WP Smush lazy load preventing image ads from showing at all
306
+
307
+ = 1.16.1 =
308
+
309
+ * fixed JavaScript that broke privacy module check in the frontend
310
+ * allow to change size of AdSense ads loaded from the AdSense account
311
+
312
+ = 1.16 =
313
+
314
+ * moved all users to the new content injection logic and removed opt-out option
315
+ * use new Auto ads code for everyone who didn’t enable the "Disable top anchor ads" option
316
+ * hide "Disable top anchor ads" option to users who didn’t enable it
317
+ * the Ad Admin user role can now also save the plugin settings
318
+ * hide Wizard for existing ads
319
+ * removed warning about WP Autoterms plugin after a fix by the plugin authors
320
+ * some work for Conditions to improve compatibility with an upcoming Pro feature
321
+ * fixed multiple wrappers occurred as result of using nested ads
322
+ * fixed missing index issue on 404 pages for logged-in admins
323
+ * fixed AJAX/PHP error 403 on Settings page
324
+ * fixed layout issue that happened when "If>So Dynamic Content" plugin was active
325
+ * prevented Ad label from taking height of fixed sized AdSense ads
classes/EDD_SL_Plugin_Updater.php CHANGED
@@ -1,10 +1,15 @@
1
  <?php
2
 
 
 
 
 
 
3
  /**
4
  * Allows plugins to use their own update API.
5
  *
6
- * @author Easy Digital Downloads
7
- * @version 1.9.0
8
  */
9
  class ADVADS_SL_Plugin_Updater {
10
 
@@ -16,54 +21,54 @@ class ADVADS_SL_Plugin_Updater {
16
  private $version = '';
17
  private $wp_override = false;
18
  private $beta = false;
19
- private $health_check_timeout = 5;
20
 
21
  /**
22
  * Class constructor.
23
  *
24
- * @param string $_api_url The URL pointing to the custom API endpoint.
25
- * @param string $_plugin_file Path to the plugin file.
26
- * @param array $_api_data Optional data to send with API calls.
27
- *
28
  * @uses hook()
29
  *
30
- * @uses plugin_basename()
 
 
31
  */
32
  public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
33
 
34
  global $edd_plugin_data;
35
 
36
- $this->api_url = trailingslashit( $_api_url );
37
- $this->api_data = $_api_data;
38
- $this->plugin_file = $_plugin_file;
39
- $this->name = plugin_basename( $_plugin_file );
40
- $this->slug = basename( $_plugin_file, '.php' );
41
- $this->version = $_api_data['version'];
42
- $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
43
- $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
 
44
 
45
  $edd_plugin_data[ $this->slug ] = $this->api_data;
46
 
47
  /**
48
  * Fires after the $edd_plugin_data is setup.
49
  *
50
- * @param array $edd_plugin_data Array of EDD SL plugin data.
51
- *
52
  * @since x.x.x
53
  *
 
54
  */
55
  do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
56
 
57
  // Set up hooks.
58
  $this->init();
 
59
  }
60
 
61
  /**
62
  * Set up WordPress filters to hook into WP's update process.
63
  *
64
- * @return void
65
  * @uses add_filter()
66
  *
 
67
  */
68
  public function init() {
69
 
@@ -71,6 +76,7 @@ class ADVADS_SL_Plugin_Updater {
71
  add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
72
  add_action( 'after_plugin_row', array( $this, 'show_update_notification' ), 10, 2 );
73
  add_action( 'admin_init', array( $this, 'show_changelog' ) );
 
74
  }
75
 
76
  /**
@@ -81,11 +87,10 @@ class ADVADS_SL_Plugin_Updater {
81
  * It is reassembled from parts of the native WordPress plugin update code.
82
  * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
83
  *
84
- * @param array $_transient_data Update array build by WordPress.
85
- *
86
- * @return array Modified update array with custom plugin data.
87
  * @uses api_request()
88
  *
 
 
89
  */
90
  public function check_update( $_transient_data ) {
91
 
@@ -148,8 +153,8 @@ class ADVADS_SL_Plugin_Updater {
148
  /**
149
  * Show the update notification on multisite subsites.
150
  *
151
- * @param string $file
152
- * @param array $plugin
153
  */
154
  public function show_update_notification( $file, $plugin ) {
155
 
@@ -158,7 +163,8 @@ class ADVADS_SL_Plugin_Updater {
158
  return;
159
  }
160
 
161
- if ( ! current_user_can( 'update_plugins' ) ) {
 
162
  return;
163
  }
164
 
@@ -219,17 +225,22 @@ class ADVADS_SL_Plugin_Updater {
219
  esc_html( $plugin['Name'] )
220
  );
221
 
222
- if ( empty( $update_cache->response[ $this->name ]->package ) && ! empty( $changelog_link ) ) {
 
 
 
 
223
  printf(
224
  /* translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate. */
225
- __( ' %1$sView version %2$s details%3$s.', 'advanced-ads' ),
226
  '<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
227
  esc_html( $update_cache->response[ $this->name ]->new_version ),
228
  '</a>'
229
  );
230
  } elseif ( ! empty( $changelog_link ) ) {
 
231
  printf(
232
- __( ' %1$sView version %2$s details%3$s or %4$supdate now%5$s.', 'advanced-ads' ),
233
  '<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
234
  esc_html( $update_cache->response[ $this->name ]->new_version ),
235
  '</a>',
@@ -265,24 +276,25 @@ class ADVADS_SL_Plugin_Updater {
265
  /**
266
  * Updates information on the "View version x.x details" page with custom data.
267
  *
268
- * @param mixed $_data
269
- * @param string $_action
270
- * @param object $_args
271
- *
272
- * @return object $_data
273
  * @uses api_request()
274
  *
 
 
 
 
275
  */
276
  public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
277
 
278
  if ( 'plugin_information' !== $_action ) {
279
 
280
  return $_data;
 
281
  }
282
 
283
  if ( ! isset( $_args->slug ) || ( $_args->slug !== $this->slug ) ) {
284
 
285
  return $_data;
 
286
  }
287
 
288
  $to_send = array(
@@ -346,11 +358,11 @@ class ADVADS_SL_Plugin_Updater {
346
  * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
347
  * decoding, they are objects. This method allows us to pass in the object and return an associative array.
348
  *
 
 
349
  * @param stdClass $data
350
  *
351
  * @return array
352
- * @since 3.6.5
353
- *
354
  */
355
  private function convert_object_to_array( $data ) {
356
  if ( ! is_array( $data ) && ! is_object( $data ) ) {
@@ -367,9 +379,8 @@ class ADVADS_SL_Plugin_Updater {
367
  /**
368
  * Disable SSL verification in order to prevent download update failures
369
  *
370
- * @param array $args
371
- * @param string $url
372
- *
373
  * @return object $array
374
  */
375
  public function http_request_args( $args, $url ) {
@@ -377,66 +388,81 @@ class ADVADS_SL_Plugin_Updater {
377
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
378
  $args['sslverify'] = $this->verify_ssl();
379
  }
380
-
381
  return $args;
 
382
  }
383
 
384
  /**
385
  * Calls the API and, if successfull, returns the object delivered by the API.
386
  *
387
- * @param string $_action The requested action.
388
- * @param array $_data Parameters for the API action.
389
- *
390
- * @return false|object
391
  * @uses get_bloginfo()
392
  * @uses wp_remote_post()
393
  * @uses is_wp_error()
394
  *
 
 
 
395
  */
396
  private function api_request( $_action, $_data ) {
 
397
 
398
- global $edd_plugin_url_available;
399
-
400
- // Do a quick status check on this domain if we haven't already checked it.
401
- $store_hash = md5( $this->api_url );
402
- if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
403
- $test_url_parts = wp_parse_url( $this->api_url );
404
-
405
- $scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme'] : 'http';
406
- $host = ! empty( $test_url_parts['host'] ) ? $test_url_parts['host'] : '';
407
- $port = ! empty( $test_url_parts['port'] ) ? ':' . $test_url_parts['port'] : '';
408
 
409
- if ( empty( $host ) ) {
410
- $edd_plugin_url_available[ $store_hash ] = false;
411
- } else {
412
- $test_url = $scheme . '://' . $host . $port;
413
- $response = wp_remote_get(
414
- $test_url,
415
- array(
416
- 'timeout' => $this->health_check_timeout,
417
- 'sslverify' => $this->verify_ssl(),
418
- )
419
- );
420
- $edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
421
- }
422
  }
423
 
424
- if ( false === $edd_plugin_url_available[ $store_hash ] ) {
425
  return false;
426
  }
427
 
428
- $data = array_merge( $this->api_data, $_data );
 
429
 
430
- if ( $data['slug'] !== $this->slug ) {
431
- return;
 
 
 
 
 
 
 
 
 
 
 
432
  }
433
 
434
- // Don't allow a plugin to ping itself
435
- if ( trailingslashit( home_url() ) === $this->api_url ) {
 
 
 
 
 
436
  return false;
437
  }
438
 
439
- return $this->get_version_from_remote();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  }
441
 
442
  /**
@@ -494,9 +520,9 @@ class ADVADS_SL_Plugin_Updater {
494
  /**
495
  * Filters the parameters sent in the API request.
496
  *
497
- * @param array $api_params The array of data sent in the request.
498
- * @param array $this- >api_data The array of data set up in the class constructor.
499
- * @param string $this- >plugin_file The full path and filename of the file.
500
  */
501
  $api_params = apply_filters( 'edd_sl_plugin_updater_api_params', $api_params, $this->api_data, $this->plugin_file );
502
 
@@ -509,7 +535,9 @@ class ADVADS_SL_Plugin_Updater {
509
  )
510
  );
511
 
512
- if ( is_wp_error( $request ) ) {
 
 
513
  return false;
514
  }
515
 
@@ -542,7 +570,6 @@ class ADVADS_SL_Plugin_Updater {
542
  * Get the version info from the cache, if it exists.
543
  *
544
  * @param string $cache_key
545
- *
546
  * @return object
547
  */
548
  public function get_cached_version_info( $cache_key = '' ) {
@@ -565,6 +592,7 @@ class ADVADS_SL_Plugin_Updater {
565
  }
566
 
567
  return $cache['value'];
 
568
  }
569
 
570
  /**
@@ -593,8 +621,8 @@ class ADVADS_SL_Plugin_Updater {
593
  /**
594
  * Returns if the SSL of the store should be verified.
595
  *
596
- * @return bool
597
  * @since 1.6.13
 
598
  */
599
  private function verify_ssl() {
600
  return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
@@ -603,8 +631,8 @@ class ADVADS_SL_Plugin_Updater {
603
  /**
604
  * Gets the unique key (option name) for a plugin.
605
  *
606
- * @return string
607
  * @since 1.9.0
 
608
  */
609
  private function get_cache_key() {
610
  $string = $this->slug . $this->api_data['license'] . $this->beta;
1
  <?php
2
 
3
+ // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
  /**
9
  * Allows plugins to use their own update API.
10
  *
11
+ * @author Easy Digital Downloads
12
+ * @version 1.9.1
13
  */
14
  class ADVADS_SL_Plugin_Updater {
15
 
21
  private $version = '';
22
  private $wp_override = false;
23
  private $beta = false;
24
+ private $failed_request_cache_key;
25
 
26
  /**
27
  * Class constructor.
28
  *
29
+ * @uses plugin_basename()
 
 
 
30
  * @uses hook()
31
  *
32
+ * @param string $_api_url The URL pointing to the custom API endpoint.
33
+ * @param string $_plugin_file Path to the plugin file.
34
+ * @param array $_api_data Optional data to send with API calls.
35
  */
36
  public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
37
 
38
  global $edd_plugin_data;
39
 
40
+ $this->api_url = trailingslashit( $_api_url );
41
+ $this->api_data = $_api_data;
42
+ $this->plugin_file = $_plugin_file;
43
+ $this->name = plugin_basename( $_plugin_file );
44
+ $this->slug = basename( $_plugin_file, '.php' );
45
+ $this->version = $_api_data['version'];
46
+ $this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
47
+ $this->beta = ! empty( $this->api_data['beta'] ) ? true : false;
48
+ $this->failed_request_cache_key = 'edd_sl_failed_http_' . md5( $this->api_url );
49
 
50
  $edd_plugin_data[ $this->slug ] = $this->api_data;
51
 
52
  /**
53
  * Fires after the $edd_plugin_data is setup.
54
  *
 
 
55
  * @since x.x.x
56
  *
57
+ * @param array $edd_plugin_data Array of EDD SL plugin data.
58
  */
59
  do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
60
 
61
  // Set up hooks.
62
  $this->init();
63
+
64
  }
65
 
66
  /**
67
  * Set up WordPress filters to hook into WP's update process.
68
  *
 
69
  * @uses add_filter()
70
  *
71
+ * @return void
72
  */
73
  public function init() {
74
 
76
  add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
77
  add_action( 'after_plugin_row', array( $this, 'show_update_notification' ), 10, 2 );
78
  add_action( 'admin_init', array( $this, 'show_changelog' ) );
79
+
80
  }
81
 
82
  /**
87
  * It is reassembled from parts of the native WordPress plugin update code.
88
  * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
89
  *
 
 
 
90
  * @uses api_request()
91
  *
92
+ * @param array $_transient_data Update array build by WordPress.
93
+ * @return array Modified update array with custom plugin data.
94
  */
95
  public function check_update( $_transient_data ) {
96
 
153
  /**
154
  * Show the update notification on multisite subsites.
155
  *
156
+ * @param string $file
157
+ * @param array $plugin
158
  */
159
  public function show_update_notification( $file, $plugin ) {
160
 
163
  return;
164
  }
165
 
166
+ // Allow single site admins to see that an update is available.
167
+ if ( ! current_user_can( 'activate_plugins' ) ) {
168
  return;
169
  }
170
 
225
  esc_html( $plugin['Name'] )
226
  );
227
 
228
+ if ( ! current_user_can( 'update_plugins' ) ) {
229
+ echo ' ';
230
+ esc_html_e( 'Contact your network administrator to install the update.', 'advanced-ads' );
231
+ } elseif ( empty( $update_cache->response[ $this->name ]->package ) && ! empty( $changelog_link ) ) {
232
+ echo ' ';
233
  printf(
234
  /* translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate. */
235
+ __( '%1$sView version %2$s details%3$s.', 'advanced-ads' ),
236
  '<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
237
  esc_html( $update_cache->response[ $this->name ]->new_version ),
238
  '</a>'
239
  );
240
  } elseif ( ! empty( $changelog_link ) ) {
241
+ echo ' ';
242
  printf(
243
+ __( '%1$sView version %2$s details%3$s or %4$supdate now%5$s.', 'advanced-ads' ),
244
  '<a target="_blank" class="thickbox open-plugin-details-modal" href="' . esc_url( $changelog_link ) . '">',
245
  esc_html( $update_cache->response[ $this->name ]->new_version ),
246
  '</a>',
276
  /**
277
  * Updates information on the "View version x.x details" page with custom data.
278
  *
 
 
 
 
 
279
  * @uses api_request()
280
  *
281
+ * @param mixed $_data
282
+ * @param string $_action
283
+ * @param object $_args
284
+ * @return object $_data
285
  */
286
  public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
287
 
288
  if ( 'plugin_information' !== $_action ) {
289
 
290
  return $_data;
291
+
292
  }
293
 
294
  if ( ! isset( $_args->slug ) || ( $_args->slug !== $this->slug ) ) {
295
 
296
  return $_data;
297
+
298
  }
299
 
300
  $to_send = array(
358
  * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
359
  * decoding, they are objects. This method allows us to pass in the object and return an associative array.
360
  *
361
+ * @since 3.6.5
362
+ *
363
  * @param stdClass $data
364
  *
365
  * @return array
 
 
366
  */
367
  private function convert_object_to_array( $data ) {
368
  if ( ! is_array( $data ) && ! is_object( $data ) ) {
379
  /**
380
  * Disable SSL verification in order to prevent download update failures
381
  *
382
+ * @param array $args
383
+ * @param string $url
 
384
  * @return object $array
385
  */
386
  public function http_request_args( $args, $url ) {
388
  if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
389
  $args['sslverify'] = $this->verify_ssl();
390
  }
 
391
  return $args;
392
+
393
  }
394
 
395
  /**
396
  * Calls the API and, if successfull, returns the object delivered by the API.
397
  *
 
 
 
 
398
  * @uses get_bloginfo()
399
  * @uses wp_remote_post()
400
  * @uses is_wp_error()
401
  *
402
+ * @param string $_action The requested action.
403
+ * @param array $_data Parameters for the API action.
404
+ * @return false|object|void
405
  */
406
  private function api_request( $_action, $_data ) {
407
+ $data = array_merge( $this->api_data, $_data );
408
 
409
+ if ( $data['slug'] !== $this->slug ) {
410
+ return;
411
+ }
 
 
 
 
 
 
 
412
 
413
+ // Don't allow a plugin to ping itself
414
+ if ( trailingslashit( home_url() ) === $this->api_url ) {
415
+ return false;
 
 
 
 
 
 
 
 
 
 
416
  }
417
 
418
+ if ( $this->request_recently_failed() ) {
419
  return false;
420
  }
421
 
422
+ return $this->get_version_from_remote();
423
+ }
424
 
425
+ /**
426
+ * Determines if a request has recently failed.
427
+ *
428
+ * @since 1.9.1
429
+ *
430
+ * @return bool
431
+ */
432
+ private function request_recently_failed() {
433
+ $failed_request_details = get_option( $this->failed_request_cache_key );
434
+
435
+ // Request has never failed.
436
+ if ( empty( $failed_request_details ) || ! is_numeric( $failed_request_details ) ) {
437
+ return false;
438
  }
439
 
440
+ /*
441
+ * Request previously failed, but the timeout has expired.
442
+ * This means we're allowed to try again.
443
+ */
444
+ if ( time() > $failed_request_details ) {
445
+ delete_option( $this->failed_request_cache_key );
446
+
447
  return false;
448
  }
449
 
450
+ return true;
451
+ }
452
+
453
+ /**
454
+ * Logs a failed HTTP request for this API URL.
455
+ * We set a timestamp for 1 hour from now. This prevents future API requests from being
456
+ * made to this domain for 1 hour. Once the timestamp is in the past, API requests
457
+ * will be allowed again. This way if the site is down for some reason we don't bombard
458
+ * it with failed API requests.
459
+ *
460
+ * @see EDD_SL_Plugin_Updater::request_recently_failed
461
+ *
462
+ * @since 1.9.1
463
+ */
464
+ private function log_failed_request() {
465
+ update_option( $this->failed_request_cache_key, strtotime( '+1 hour' ) );
466
  }
467
 
468
  /**
520
  /**
521
  * Filters the parameters sent in the API request.
522
  *
523
+ * @param array $api_params The array of data sent in the request.
524
+ * @param array $this->api_data The array of data set up in the class constructor.
525
+ * @param string $this->plugin_file The full path and filename of the file.
526
  */
527
  $api_params = apply_filters( 'edd_sl_plugin_updater_api_params', $api_params, $this->api_data, $this->plugin_file );
528
 
535
  )
536
  );
537
 
538
+ if ( is_wp_error( $request ) || ( 200 !== wp_remote_retrieve_response_code( $request ) ) ) {
539
+ $this->log_failed_request();
540
+
541
  return false;
542
  }
543
 
570
  * Get the version info from the cache, if it exists.
571
  *
572
  * @param string $cache_key
 
573
  * @return object
574
  */
575
  public function get_cached_version_info( $cache_key = '' ) {
592
  }
593
 
594
  return $cache['value'];
595
+
596
  }
597
 
598
  /**
621
  /**
622
  * Returns if the SSL of the store should be verified.
623
  *
 
624
  * @since 1.6.13
625
+ * @return bool
626
  */
627
  private function verify_ssl() {
628
  return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
631
  /**
632
  * Gets the unique key (option name) for a plugin.
633
  *
 
634
  * @since 1.9.0
635
+ * @return string
636
  */
637
  private function get_cache_key() {
638
  $string = $this->slug . $this->api_data['license'] . $this->beta;
classes/ad.php CHANGED
@@ -966,7 +966,10 @@ class Advanced_Ads_Ad {
966
  $wrapper_element = ! empty( $this->args['inline_wrapper_element'] ) ? 'span' : 'div';
967
 
968
  // build the box
969
- $wrapper = '<' . $wrapper_element . Advanced_Ads_Utils::build_html_attributes( $wrapper_options ) . '>';
 
 
 
970
  $wrapper .= $this->label;
971
  $wrapper .= apply_filters( 'advanced-ads-output-wrapper-before-content', '', $this );
972
  $wrapper .= $ad_content;
966
  $wrapper_element = ! empty( $this->args['inline_wrapper_element'] ) ? 'span' : 'div';
967
 
968
  // build the box
969
+ $wrapper = '<' . $wrapper_element . Advanced_Ads_Utils::build_html_attributes( array_merge(
970
+ $wrapper_options,
971
+ isset( $this->output['wrapper_attrs'] ) ? $this->output['wrapper_attrs'] : array()
972
+ ) ) . '>';
973
  $wrapper .= $this->label;
974
  $wrapper .= apply_filters( 'advanced-ads-output-wrapper-before-content', '', $this );
975
  $wrapper .= $ad_content;
classes/ad_group.php CHANGED
@@ -286,26 +286,17 @@ class Advanced_Ads_Group {
286
  }
287
 
288
  // load ads
289
- $ads = $this->load_all_ads();
290
- if ( ! is_array( $ads ) || $ads === array() ) {
291
- return false;
292
- }
293
 
294
  // get ad weights serving as an order here
295
  $weights = $this->get_ad_weights();
296
  asort($weights);
297
 
298
- // if ads and weights don’t have the same keys, update weights array
299
- if ( (count( $weights ) == 0 && count( $ads ) > 0) || count( $weights ) != count( $ads ) || array_diff_key( $weights, $ads ) != array()
300
- || array_diff_key( $ads, $weights ) != array() ) {
301
- $this->update_ad_weights();
302
- $weights = $this->ad_weights;
303
- }
304
-
305
- // remove ads with 0 ad weight
306
- foreach( $weights as $_ad_id => $_ad_weight ){
307
- if( $_ad_weight === 0 ){
308
- unset( $weights[ $_ad_id ] );
309
  }
310
  }
311
 
@@ -339,7 +330,8 @@ class Advanced_Ads_Group {
339
  * @since 1.0.0
340
  * @update 1.1.0 load only public ads
341
  * @update allow to cache groups for few minutes
342
- * @return arr $ads array with ad (post) objects
 
343
  */
344
  private function load_all_ads() {
345
 
@@ -516,79 +508,6 @@ class Advanced_Ads_Group {
516
  update_option( 'advads-ad-groups', $groups );
517
  }
518
 
519
- /**
520
- * Save ad group weight (into global ad weight array)
521
- *
522
- * @since 1.0.0
523
- * @param arr|str $weights array with ad weights (key: ad id; value: weight)
524
- */
525
- public function save_ad_weights($weights = '') {
526
-
527
- // allow only arrays and empty string
528
- if ( ! is_array( $weights ) && $weights !== '' ) {
529
- return; }
530
-
531
- $global_weights = get_option( 'advads-ad-weights', array() );
532
-
533
- $global_weights[$this->id] = $this->sanitize_ad_weights( $weights );
534
-
535
- /**
536
- * Save ad weights in frontend only, if contanst is not set
537
- * always save in admin
538
- * use the constant to prevent accidental overriding of ad settings in the frontend as happened on very large sites
539
- */
540
- if( !defined( 'ADVANCED_ADS_DISABLE_FRONTEND_AD_WEIGHT_UPDATE' ) || is_admin() ){
541
- update_option( 'advads-ad-weights', $global_weights );
542
- }
543
-
544
- // refresh ad weights after update to avoid conflict
545
- $this->ad_weights = $global_weights[$this->id];
546
- }
547
-
548
- /**
549
- * Update ad weight based on current ads for the group and ad weight
550
- *
551
- * @since 1.0.0
552
- */
553
- private function update_ad_weights(){
554
- $ads = $this->get_all_ads();
555
- $weights = $this->get_ad_weights();
556
-
557
- $new_weights = array();
558
- // use only ads assigned to the group
559
- foreach ( $ads as $_ad ){
560
- if ( isset($weights[$_ad->ID]) ){
561
- $new_weights[$_ad->ID] = $weights[$_ad->ID];
562
- } else {
563
- // if no weight is given, use default value
564
- $new_weights[$_ad->ID] = self::MAX_AD_GROUP_DEFAULT_WEIGHT;
565
- }
566
- }
567
-
568
- $this->save_ad_weights( $new_weights );
569
- }
570
-
571
- /**
572
- * Sanitize ad weights
573
- *
574
- * @since 1.0.0
575
- * @param arr $weights ad weights array with (key: ad id; value: weight)
576
- */
577
- public function sanitize_ad_weights($weights = array()) {
578
-
579
- if ( ! is_array( $weights ) ) {
580
- return ''; }
581
-
582
- $sanitized_weights = array();
583
- foreach ( $weights as $_ad_id => $_weight ) {
584
- $_ad_id = absint( $_ad_id );
585
- $_weight = absint( $_weight );
586
- $sanitized_weights[$_ad_id] = $_weight;
587
- }
588
-
589
- return $sanitized_weights;
590
- }
591
-
592
  /**
593
  * Delete all the ad weights for a group by id
594
  *
@@ -618,6 +537,12 @@ class Advanced_Ads_Group {
618
  $this->wrapper['class'] = $this->ad_args['output']['class'];
619
  }
620
 
 
 
 
 
 
 
621
  if ( ! empty( $this->ad_args['placement_position'] ) ) {
622
  switch ( $this->ad_args['placement_position'] ) {
623
  case 'left' :
286
  }
287
 
288
  // load ads
289
+ $ads = $this->load_all_ads();
290
+ $ad_ids = array_keys( $ads );
 
 
291
 
292
  // get ad weights serving as an order here
293
  $weights = $this->get_ad_weights();
294
  asort($weights);
295
 
296
+ // remove ads with 0 ad weight and unavailable ads (e.g. drafts).
297
+ foreach ( $weights as $ad_id => $ad_weight ) {
298
+ if ( $ad_weight === 0 || ! in_array( $ad_id, $ad_ids, true ) ) {
299
+ unset( $weights[ $ad_id ] );
 
 
 
 
 
 
 
300
  }
301
  }
302
 
330
  * @since 1.0.0
331
  * @update 1.1.0 load only public ads
332
  * @update allow to cache groups for few minutes
333
+ *
334
+ * @return WP_Post[] $ads array with ad (post) objects
335
  */
336
  private function load_all_ads() {
337
 
508
  update_option( 'advads-ad-groups', $groups );
509
  }
510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511
  /**
512
  * Delete all the ad weights for a group by id
513
  *
537
  $this->wrapper['class'] = $this->ad_args['output']['class'];
538
  }
539
 
540
+ if ( isset( $this->ad_args['output']['wrapper_attrs'] ) && is_array( $this->ad_args['output']['wrapper_attrs'] ) ) {
541
+ foreach ( $this->ad_args['output']['wrapper_attrs'] as $key => $value ) {
542
+ $this->wrapper[$key] = $value;
543
+ }
544
+ }
545
+
546
  if ( ! empty( $this->ad_args['placement_position'] ) ) {
547
  switch ( $this->ad_args['placement_position'] ) {
548
  case 'left' :
classes/ad_placements.php CHANGED
@@ -433,7 +433,9 @@ class Advanced_Ads_Placements {
433
  $advads = Advanced_Ads::get_instance();
434
  $name = isset( $placement['name'] ) ? $placement['name'] : $id;
435
 
436
- if ( ! isset( $args['global_output'] ) || $args['global_output'] ) {
 
 
437
  $advads->current_ads[] = array(
438
  'type' => 'placement',
439
  'id' => $id,
@@ -441,8 +443,6 @@ class Advanced_Ads_Placements {
441
  );
442
  }
443
 
444
- $result = Advanced_Ads_Select::get_instance()->get_ad_by_method( (int) $_item[1], $_item[0], $args );
445
-
446
  return $result;
447
  }
448
 
433
  $advads = Advanced_Ads::get_instance();
434
  $name = isset( $placement['name'] ) ? $placement['name'] : $id;
435
 
436
+ $result = Advanced_Ads_Select::get_instance()->get_ad_by_method( (int) $_item[1], $_item[0], $args );
437
+
438
+ if ( $result && ( ! isset( $args['global_output'] ) || $args['global_output'] ) ) {
439
  $advads->current_ads[] = array(
440
  'type' => 'placement',
441
  'id' => $id,
443
  );
444
  }
445
 
 
 
446
  return $result;
447
  }
448
 
classes/checks.php CHANGED
@@ -277,7 +277,6 @@ class Advanced_Ads_Checks {
277
  'ADVANCED_ADS_DISABLE_ANALYTICS_ANONYMIZE_IP',
278
  'ADVANCED_ADS_DISABLE_CHANGE',
279
  'ADVANCED_ADS_DISABLE_CODE_HIGHLIGHTING',
280
- 'ADVANCED_ADS_DISABLE_FRONTEND_AD_WEIGHT_UPDATE',
281
  'ADVANCED_ADS_DISABLE_SHORTCODE_BUTTON',
282
  'ADVANCED_ADS_DISALLOW_PHP',
283
  'ADVANCED_ADS_ENABLE_REVISIONS',
277
  'ADVANCED_ADS_DISABLE_ANALYTICS_ANONYMIZE_IP',
278
  'ADVANCED_ADS_DISABLE_CHANGE',
279
  'ADVANCED_ADS_DISABLE_CODE_HIGHLIGHTING',
 
280
  'ADVANCED_ADS_DISABLE_SHORTCODE_BUTTON',
281
  'ADVANCED_ADS_DISALLOW_PHP',
282
  'ADVANCED_ADS_ENABLE_REVISIONS',
classes/utils.php CHANGED
@@ -68,7 +68,9 @@ class Advanced_Ads_Utils {
68
  if ( is_array( $_values ) ) {
69
  $_values_string = esc_attr( implode( ' ', $_values ) ); } else {
70
  $_values_string = esc_attr( $_values ); }
71
- $result .= " $_html_attr=\"$_values_string\"";
 
 
72
  }
73
  }
74
  return $result;
68
  if ( is_array( $_values ) ) {
69
  $_values_string = esc_attr( implode( ' ', $_values ) ); } else {
70
  $_values_string = esc_attr( $_values ); }
71
+ if ( $_values_string !== '' ) {
72
+ $result .= " $_html_attr=\"$_values_string\"";
73
+ }
74
  }
75
  }
76
  return $result;
classes/widget.php CHANGED
@@ -64,14 +64,12 @@ class Advanced_Ads_Widget extends WP_Widget {
64
 
65
  $before_widget = $this->maybe_replace_frontend_id( $before_widget, $instance );
66
 
67
- //phpcs:disable
68
  echo $before_widget;
69
  if ( ! empty( $title ) ) {
70
  echo $args['before_title'] . $title . $args['after_title'];
71
  }
72
  echo $output;
73
  echo $after_widget;
74
- //phpcs:enable
75
  }
76
 
77
  /**
@@ -181,15 +179,15 @@ class Advanced_Ads_Widget extends WP_Widget {
181
  */
182
  public static function widget_placements_for_select() {
183
  $select = array();
184
- $placements = Advanced_Ads::get_ad_placements_array();
185
 
186
  if ( is_array( $placements ) ) {
187
  ksort( $placements );
188
  }
189
 
190
- foreach ( $placements as $_placement_slug => $_placement ) {
191
- if ( isset( $_placement['type'] ) && 'sidebar_widget' === $_placement['type'] ) {
192
- $select['placements'][ 'placement_' . $_placement_slug ] = $_placement['name'];
193
  }
194
  }
195
 
64
 
65
  $before_widget = $this->maybe_replace_frontend_id( $before_widget, $instance );
66
 
 
67
  echo $before_widget;
68
  if ( ! empty( $title ) ) {
69
  echo $args['before_title'] . $title . $args['after_title'];
70
  }
71
  echo $output;
72
  echo $after_widget;
 
73
  }
74
 
75
  /**
179
  */
180
  public static function widget_placements_for_select() {
181
  $select = array();
182
+ $placements = Advanced_Ads::get_instance()->get_model()->get_ad_placements_array();
183
 
184
  if ( is_array( $placements ) ) {
185
  ksort( $placements );
186
  }
187
 
188
+ foreach ( $placements as $placement_slug => $placement ) {
189
+ if ( isset( $placement['type'] ) && in_array( $placement['type'], array( 'sidebar_widget', 'default' ), true ) ) {
190
+ $select['placements'][ 'placement_' . $placement_slug ] = $placement['name'];
191
  }
192
  }
193
 
languages/advanced-ads.pot CHANGED
@@ -2,20 +2,20 @@
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.29.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: 2021-10-14T12:39:27+02: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"
16
 
17
  #. Plugin Name of the plugin
18
- #: modules/gutenberg/includes/class-gutenberg.php:88
19
  msgid "Advanced Ads"
20
  msgstr ""
21
 
@@ -32,7 +32,7 @@ msgstr ""
32
  msgid "Thomas Maier, Advanced Ads GmbH"
33
  msgstr ""
34
 
35
- #: admin/class-advanced-ads-admin.php:216
36
  #: classes/display-conditions.php:317
37
  #: classes/visitor-conditions.php:311
38
  #: modules/gadsense/admin/views/external-ads-links.php:17
@@ -41,74 +41,74 @@ msgstr ""
41
  msgid "or"
42
  msgstr ""
43
 
44
- #: admin/class-advanced-ads-admin.php:217
45
  #: classes/display-conditions.php:317
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
  #: modules/gadsense/includes/class-adsense-report.php:159
56
  msgid "Today"
57
  msgstr ""
58
 
59
- #: admin/class-advanced-ads-admin.php:221
60
  #: modules/gadsense/includes/class-adsense-report.php:160
61
  msgid "Yesterday"
62
  msgstr ""
63
 
64
- #: admin/class-advanced-ads-admin.php:222
65
  #: modules/gadsense/includes/class-adsense-report.php:163
66
  msgid "This Month"
67
  msgstr ""
68
 
69
  #. translators: 1: The number of days.
70
- #: admin/class-advanced-ads-admin.php:224
71
  #: modules/gadsense/includes/class-adsense-report.php:162
72
  #: modules/gadsense/includes/class-adsense-report.php:165
73
  msgid "Last %1$d days"
74
  msgstr ""
75
 
76
- #: admin/class-advanced-ads-admin.php:227
77
  #: modules/gadsense/admin/views/adsense-report.php:24
78
  msgid "All"
79
  msgstr ""
80
 
81
- #: admin/class-advanced-ads-admin.php:228
82
  msgid "There were no results returned for this ad. Please make sure it is active, generating impressions and double check your ad parameters."
83
  msgstr ""
84
 
85
- #: admin/class-advanced-ads-admin.php:229
86
  msgid "Show inactive ads"
87
  msgstr ""
88
 
89
- #: admin/class-advanced-ads-admin.php:230
90
  msgid "Hide inactive ads"
91
  msgstr ""
92
 
93
- #: admin/class-advanced-ads-admin.php:232
94
  msgid "Permanently delete this placement?"
95
  msgstr ""
96
 
97
- #: admin/class-advanced-ads-admin.php:391
98
  #: admin/includes/class-menu.php:156
99
  #: admin/includes/class-menu.php:159
100
  #: admin/views/settings.php:29
101
  msgid "Support"
102
  msgstr ""
103
 
104
- #: admin/class-advanced-ads-admin.php:395
105
  #: admin/includes/class-overview-widgets.php:72
106
  msgid "Add-Ons"
107
  msgstr ""
108
 
109
  #. translators: %s is the URL to add a new review, https://wordpress.org/support/plugin/advanced-ads/reviews/#new-post
110
  #. translators: %s is a URL.
111
- #: admin/class-advanced-ads-admin.php:666
112
  #: admin/includes/class-overview-widgets.php:191
113
  msgid "Thank the developer with a &#9733;&#9733;&#9733;&#9733;&#9733; review on <a href=\"%s\" target=\"_blank\">wordpress.org</a>"
114
  msgstr ""
@@ -249,98 +249,98 @@ msgstr ""
249
  msgid "Learn how."
250
  msgstr ""
251
 
252
- #: admin/includes/class-ad-groups-list.php:172
253
  msgid "Ad weight"
254
  msgstr ""
255
 
256
  #. translators: %s is a date.
257
- #: admin/includes/class-ad-groups-list.php:184
258
  #: admin/views/ad-list-timing-column.php:21
259
  msgid "starts %s"
260
  msgstr ""
261
 
262
  #. translators: %s is a date.
263
  #. translators: %s is a time and date string.
264
- #: admin/includes/class-ad-groups-list.php:205
265
  #: admin/views/ad-list-timing-column.php:59
266
  msgid "expires %s"
267
  msgstr ""
268
 
269
  #. translators: %s is a date.
270
  #. translators: %s is a time and date string.
271
- #: admin/includes/class-ad-groups-list.php:208
272
  #: admin/views/ad-list-timing-column.php:70
273
  msgid "<strong>expired</strong> %s"
274
  msgstr ""
275
 
276
  #. translators: %d is a number.
277
- #: admin/includes/class-ad-groups-list.php:225
278
  msgid "show %d more ads"
279
  msgstr ""
280
 
281
- #: admin/includes/class-ad-groups-list.php:229
282
  msgid "all published ads are displayed"
283
  msgstr ""
284
 
285
  #. translators: %d is a number.
286
- #: admin/includes/class-ad-groups-list.php:232
287
  msgid "up to %d ads displayed"
288
  msgstr ""
289
 
290
- #: admin/includes/class-ad-groups-list.php:235
291
  msgid "No ads assigned"
292
  msgstr ""
293
 
294
- #: admin/includes/class-ad-groups-list.php:237
295
  msgid "Add some"
296
  msgstr ""
297
 
298
- #: admin/includes/class-ad-groups-list.php:315
299
  msgid "Random ads"
300
  msgstr ""
301
 
302
- #: admin/includes/class-ad-groups-list.php:316
303
  msgid "Display random ads based on ad weight"
304
  msgstr ""
305
 
306
- #: admin/includes/class-ad-groups-list.php:319
307
  msgid "Ordered ads"
308
  msgstr ""
309
 
310
- #: admin/includes/class-ad-groups-list.php:320
311
  msgid "Display ads with the highest ad weight first"
312
  msgstr ""
313
 
314
- #: admin/includes/class-ad-groups-list.php:339
315
  #: admin/views/placements.php:275
316
  #: modules/import-export/classes/import.php:153
317
  #: modules/import-export/classes/import.php:193
318
  #: modules/import-export/classes/import.php:595
319
- #: public/class-advanced-ads.php:792
320
  msgid "Edit"
321
  msgstr ""
322
 
323
- #: admin/includes/class-ad-groups-list.php:340
324
  #: admin/views/placements.php:306
325
  msgid "Usage"
326
  msgstr ""
327
 
328
- #: admin/includes/class-ad-groups-list.php:349
329
  #: admin/views/placements.php:10
330
  msgid "Delete"
331
  msgstr ""
332
 
333
- #: admin/includes/class-ad-groups-list.php:371
334
- #: admin/includes/class-ad-groups-list.php:441
335
  msgid "Invalid Ad Group"
336
  msgstr ""
337
 
338
- #: admin/includes/class-ad-groups-list.php:376
339
- #: admin/includes/class-ad-groups-list.php:446
340
  msgid "You don’t have permission to change the ad groups"
341
  msgstr ""
342
 
343
- #: admin/includes/class-ad-groups-list.php:410
344
  msgid "No ad group created"
345
  msgstr ""
346
 
@@ -395,48 +395,48 @@ msgstr[0] ""
395
  msgstr[1] ""
396
 
397
  #. Translators: %s is the time the ad was first saved.
398
- #: admin/includes/class-ad-type.php:659
399
  msgid "Ad created on %s"
400
  msgstr ""
401
 
402
- #: admin/includes/class-ad-type.php:851
403
- #: admin/includes/class-ad-type.php:852
404
  msgid "Ad updated."
405
  msgstr ""
406
 
407
  #. translators: %s: date and time of the revision
408
- #: admin/includes/class-ad-type.php:853
409
  msgid "Ad restored to revision from %s"
410
  msgstr ""
411
 
412
- #: admin/includes/class-ad-type.php:854
413
- #: admin/includes/class-ad-type.php:855
414
  msgid "Ad saved."
415
  msgstr ""
416
 
417
- #: admin/includes/class-ad-type.php:856
418
  msgid "Ad submitted."
419
  msgstr ""
420
 
421
  #. translators: %1$s is a date.
422
- #: admin/includes/class-ad-type.php:859
423
  msgid "Ad scheduled for: <strong>%1$s</strong>."
424
  msgstr ""
425
 
426
  #. translators: Publish box date format, see http://php.net/date.
427
- #: admin/includes/class-ad-type.php:861
428
  msgid "M j, Y @ G:i"
429
  msgstr ""
430
 
431
- #: admin/includes/class-ad-type.php:863
432
  msgid "Ad draft updated."
433
  msgstr ""
434
 
435
- #: admin/includes/class-ad-type.php:919
436
  msgid "You don’t have access to ads. Please deactivate and re-enable Advanced Ads again to fix this."
437
  msgstr ""
438
 
439
- #: admin/includes/class-ad-type.php:920
440
  #: classes/frontend_checks.php:503
441
  msgid "Get help"
442
  msgstr ""
@@ -533,17 +533,17 @@ msgstr ""
533
  msgid "Download failed. <a href=\"%s\" target=\"_blank\">Click here to learn why</a>."
534
  msgstr ""
535
 
536
- #: admin/includes/class-list-filters.php:143
537
  #: modules/gadsense/admin/admin.php:73
538
  #: modules/gadsense/admin/views/adsense-ad-parameters.php:109
539
  msgid "Responsive"
540
  msgstr ""
541
 
542
- #: admin/includes/class-list-filters.php:152
543
  msgid "expired"
544
  msgstr ""
545
 
546
- #: admin/includes/class-list-filters.php:156
547
  msgid "any expiry date"
548
  msgstr ""
549
 
@@ -559,24 +559,24 @@ msgstr ""
559
  #: admin/includes/class-shortcode-creator.php:184
560
  #: admin/views/ad-group-list-form-row.php:91
561
  #: admin/views/ad-group-list-header.php:16
562
- #: admin/views/placement-form.php:88
563
  #: admin/views/placements-item.php:26
564
- #: classes/widget.php:138
565
- #: modules/gutenberg/includes/class-gutenberg.php:89
566
  #: modules/import-export/views/page.php:23
567
- #: public/class-advanced-ads.php:788
568
  msgid "Ads"
569
  msgstr ""
570
 
571
  #: admin/includes/class-menu.php:112
572
- #: public/class-advanced-ads.php:791
573
  msgid "Add New Ad"
574
  msgstr ""
575
 
576
  #: admin/includes/class-menu.php:113
577
  #: admin/views/ad-group-list-ads.php:36
578
- #: public/class-advanced-ads.php:790
579
- #: public/class-advanced-ads.php:794
580
  msgid "New Ad"
581
  msgstr ""
582
 
@@ -595,8 +595,8 @@ msgstr ""
595
  #: admin/includes/class-menu.php:132
596
  #: admin/includes/class-shortcode-creator.php:198
597
  #: admin/views/placements.php:57
598
- #: classes/widget.php:124
599
- #: modules/gutenberg/includes/class-gutenberg.php:91
600
  #: modules/import-export/views/page.php:25
601
  msgid "Placements"
602
  msgstr ""
@@ -685,34 +685,34 @@ msgstr ""
685
  msgid "Disable"
686
  msgstr ""
687
 
688
- #: admin/includes/class-meta-box.php:422
689
  msgid "Ad Settings"
690
  msgstr ""
691
 
692
- #: admin/includes/class-meta-box.php:521
693
  #: admin/views/overview.php:8
694
  msgid "Ads Dashboard"
695
  msgstr ""
696
 
697
  #. translators: %1$d is the number of ads, %2$s and %3$s are URLs.
698
- #: admin/includes/class-meta-box.php:537
699
  msgid "%1$d ads – <a href=\"%2$s\">manage</a> - <a href=\"%3$s\">new</a>"
700
  msgstr ""
701
 
702
- #: admin/includes/class-meta-box.php:550
703
  msgid "Get the tutorial via email"
704
  msgstr ""
705
 
706
- #: admin/includes/class-meta-box.php:559
707
  msgid "Get AdSense tips via email"
708
  msgstr ""
709
 
710
- #: admin/includes/class-meta-box.php:568
711
  msgid "Visit our blog for more articles about ad optimization"
712
  msgstr ""
713
 
714
  #. translators: %s is our URL.
715
- #: admin/includes/class-meta-box.php:622
716
  msgid "Latest posts on wpadvancedads.com"
717
  msgstr ""
718
 
@@ -1016,16 +1016,16 @@ msgid "Advertisements"
1016
  msgstr ""
1017
 
1018
  #: admin/includes/class-shortcode-creator.php:182
1019
- #: classes/widget.php:122
1020
- #: modules/gutenberg/includes/class-gutenberg.php:87
1021
  msgid "--empty--"
1022
  msgstr ""
1023
 
1024
  #: admin/includes/class-shortcode-creator.php:191
1025
- #: admin/views/placement-form.php:81
1026
  #: admin/views/placements-item.php:14
1027
- #: classes/widget.php:131
1028
- #: modules/gutenberg/includes/class-gutenberg.php:90
1029
  msgid "Ad Groups"
1030
  msgstr ""
1031
 
@@ -1175,7 +1175,7 @@ msgstr ""
1175
  #: classes/ad-debug.php:118
1176
  #: classes/ad-debug.php:167
1177
  #: classes/ad-debug.php:169
1178
- #: public/class-advanced-ads.php:789
1179
  msgid "Ad"
1180
  msgstr ""
1181
 
@@ -1807,32 +1807,32 @@ msgstr ""
1807
  msgid "Choose a Name"
1808
  msgstr ""
1809
 
1810
- #: admin/views/placement-form.php:72
1811
- msgid "The name of the placement is only visible to you. Tip: choose a descriptive one, e.g. <em>Below Post Headline</em>."
1812
  msgstr ""
1813
 
1814
- #: admin/views/placement-form.php:74
1815
  msgid "Placement Name"
1816
  msgstr ""
1817
 
1818
- #: admin/views/placement-form.php:75
1819
  msgid "Please enter a name for your placement."
1820
  msgstr ""
1821
 
1822
- #: admin/views/placement-form.php:76
1823
  msgid "Choose the Ad or Group"
1824
  msgstr ""
1825
 
1826
- #: admin/views/placement-form.php:77
1827
  msgid "The ad or group that should be displayed."
1828
  msgstr ""
1829
 
1830
- #: admin/views/placement-form.php:79
1831
  #: admin/views/placements-item.php:12
1832
  msgid "--not selected--"
1833
  msgstr ""
1834
 
1835
- #: admin/views/placement-form.php:96
1836
  msgid "Save New Placement"
1837
  msgstr ""
1838
 
@@ -2023,6 +2023,14 @@ msgstr ""
2023
  msgid "Delivery"
2024
  msgstr ""
2025
 
 
 
 
 
 
 
 
 
2026
  #: admin/views/placements.php:139
2027
  msgid "show usage"
2028
  msgstr ""
@@ -2939,28 +2947,32 @@ msgid "days"
2939
  msgstr ""
2940
 
2941
  #. translators: the plugin name.
2942
- #: classes/EDD_SL_Plugin_Updater.php:218
2943
  msgid "There is a new version of %1$s available."
2944
  msgstr ""
2945
 
2946
- #. translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate.
2947
- #: classes/EDD_SL_Plugin_Updater.php:225
2948
- msgid " %1$sView version %2$s details%3$s."
2949
  msgstr ""
2950
 
2951
- #: classes/EDD_SL_Plugin_Updater.php:232
2952
- msgid " %1$sView version %2$s details%3$s or %4$supdate now%5$s."
 
2953
  msgstr ""
2954
 
2955
  #: classes/EDD_SL_Plugin_Updater.php:243
 
 
 
 
2956
  msgid "Update now."
2957
  msgstr ""
2958
 
2959
- #: classes/EDD_SL_Plugin_Updater.php:460
2960
  msgid "You do not have permission to install plugin updates"
2961
  msgstr ""
2962
 
2963
- #: classes/EDD_SL_Plugin_Updater.php:460
2964
  msgid "Error"
2965
  msgstr ""
2966
 
@@ -3151,7 +3163,7 @@ msgid "Closing the message"
3151
  msgstr ""
3152
 
3153
  #. translators: time zone name.
3154
- #: classes/utils.php:275
3155
  msgid "time of %s"
3156
  msgstr ""
3157
 
@@ -3228,7 +3240,7 @@ msgstr ""
3228
  msgid "Display Ads and Ad Groups."
3229
  msgstr ""
3230
 
3231
- #: classes/widget.php:116
3232
  msgid "Title:"
3233
  msgstr ""
3234
 
@@ -3256,71 +3268,72 @@ msgstr ""
3256
  msgid "Individual Posts, Pages and Public Post Types"
3257
  msgstr ""
3258
 
3259
- #: modules/ad-blocker/admin/admin.php:96
3260
  msgid "Ad blocker fix"
3261
  msgstr ""
3262
 
3263
- #: modules/ad-blocker/admin/admin.php:150
3264
  #: modules/ads-txt/admin/class-advanced-ads-ads-txt-admin.php:381
3265
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
3266
  msgstr ""
3267
 
3268
- #: modules/ad-blocker/admin/admin.php:165
3269
  msgid "The asset folder was rebuilt successfully"
3270
  msgstr ""
3271
 
3272
- #: modules/ad-blocker/admin/admin.php:206
3273
  msgid "There is no writable upload folder"
3274
  msgstr ""
3275
 
3276
- #: modules/ad-blocker/admin/admin.php:238
3277
  msgid "Unable to rename \"%s\" directory"
3278
  msgstr ""
3279
 
3280
- #: modules/ad-blocker/admin/admin.php:254
3281
- #: modules/ad-blocker/admin/admin.php:267
3282
- #: modules/ad-blocker/admin/admin.php:284
3283
  msgid "Unable to copy assets to the \"%s\" directory"
3284
  msgstr ""
3285
 
3286
- #: modules/ad-blocker/admin/admin.php:317
3287
- #: modules/ad-blocker/admin/admin.php:402
3288
  msgid "We do not have direct write access to the \"%s\" directory"
3289
  msgstr ""
3290
 
3291
- #: modules/ad-blocker/admin/admin.php:413
3292
  msgid "Unable to copy files to %s"
3293
  msgstr ""
3294
 
3295
- #: modules/ad-blocker/admin/views/rebuild_form.php:1
3296
  msgid "Ad blocker file folder"
3297
  msgstr ""
3298
 
3299
- #: modules/ad-blocker/admin/views/rebuild_form.php:10
3300
  msgid "Upload folder is not writable"
3301
  msgstr ""
3302
 
3303
- #: modules/ad-blocker/admin/views/rebuild_form.php:23
3304
  msgid "Asset path"
3305
  msgstr ""
3306
 
3307
- #: modules/ad-blocker/admin/views/rebuild_form.php:27
3308
  msgid "Asset URL"
3309
  msgstr ""
3310
 
3311
- #: modules/ad-blocker/admin/views/rebuild_form.php:31
3312
  msgid "Rename assets"
3313
  msgstr ""
3314
 
3315
- #: modules/ad-blocker/admin/views/rebuild_form.php:34
3316
  msgid "Check if you want to change the names of the assets"
3317
  msgstr ""
3318
 
3319
- #: modules/ad-blocker/admin/views/rebuild_form.php:43
3320
- msgid "Please, rebuild the asset folder. All assets will be located in <strong>%s</strong>"
 
3321
  msgstr ""
3322
 
3323
- #: modules/ad-blocker/admin/views/rebuild_form.php:46
3324
  msgid "Rebuild asset folder"
3325
  msgstr ""
3326
 
@@ -3684,6 +3697,10 @@ msgstr ""
3684
  msgid "Get the code for this ad"
3685
  msgstr ""
3686
 
 
 
 
 
3687
  #: modules/gadsense/admin/views/external-ads-list.php:97
3688
  msgid "Ad can't be imported, click for details"
3689
  msgstr ""
@@ -3725,7 +3742,6 @@ msgstr ""
3725
 
3726
  #. translators: AdSense ID.
3727
  #: modules/gadsense/includes/adsense-report-api.php:152
3728
- #: modules/gadsense/includes/adsense-report-api.php:161
3729
  msgid "Invalid response while retrieving report for \"%s\"."
3730
  msgstr ""
3731
 
@@ -4228,35 +4244,35 @@ msgstr ""
4228
  msgid "No Ad Group found"
4229
  msgstr ""
4230
 
4231
- #: public/class-advanced-ads.php:793
4232
  msgid "Edit Ad"
4233
  msgstr ""
4234
 
4235
- #: public/class-advanced-ads.php:795
4236
  msgid "View"
4237
  msgstr ""
4238
 
4239
- #: public/class-advanced-ads.php:796
4240
  msgid "View the Ad"
4241
  msgstr ""
4242
 
4243
- #: public/class-advanced-ads.php:797
4244
  msgid "Search Ads"
4245
  msgstr ""
4246
 
4247
- #: public/class-advanced-ads.php:798
4248
  msgid "No Ads found"
4249
  msgstr ""
4250
 
4251
- #: public/class-advanced-ads.php:799
4252
  msgid "No Ads found in Trash"
4253
  msgstr ""
4254
 
4255
- #: public/class-advanced-ads.php:800
4256
  msgid "Parent Ad"
4257
  msgstr ""
4258
 
4259
- #: public/class-advanced-ads.php:978
4260
  msgctxt "label above ads"
4261
  msgid "Advertisements"
4262
  msgstr ""
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.30.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: 2021-11-09T11:40:15+01: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"
16
 
17
  #. Plugin Name of the plugin
18
+ #: modules/gutenberg/includes/class-gutenberg.php:85
19
  msgid "Advanced Ads"
20
  msgstr ""
21
 
32
  msgid "Thomas Maier, Advanced Ads GmbH"
33
  msgstr ""
34
 
35
+ #: admin/class-advanced-ads-admin.php:214
36
  #: classes/display-conditions.php:317
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:215
45
  #: classes/display-conditions.php:317
46
  #: classes/visitor-conditions.php:311
47
  msgid "and"
48
  msgstr ""
49
 
50
+ #: admin/class-advanced-ads-admin.php:216
51
  msgid "After which paragraph?"
52
  msgstr ""
53
 
54
+ #: admin/class-advanced-ads-admin.php:218
55
  #: modules/gadsense/includes/class-adsense-report.php:159
56
  msgid "Today"
57
  msgstr ""
58
 
59
+ #: admin/class-advanced-ads-admin.php:219
60
  #: modules/gadsense/includes/class-adsense-report.php:160
61
  msgid "Yesterday"
62
  msgstr ""
63
 
64
+ #: admin/class-advanced-ads-admin.php:220
65
  #: modules/gadsense/includes/class-adsense-report.php:163
66
  msgid "This Month"
67
  msgstr ""
68
 
69
  #. translators: 1: The number of days.
70
+ #: admin/class-advanced-ads-admin.php:222
71
  #: modules/gadsense/includes/class-adsense-report.php:162
72
  #: modules/gadsense/includes/class-adsense-report.php:165
73
  msgid "Last %1$d days"
74
  msgstr ""
75
 
76
+ #: admin/class-advanced-ads-admin.php:225
77
  #: modules/gadsense/admin/views/adsense-report.php:24
78
  msgid "All"
79
  msgstr ""
80
 
81
+ #: admin/class-advanced-ads-admin.php:226
82
  msgid "There were no results returned for this ad. Please make sure it is active, generating impressions and double check your ad parameters."
83
  msgstr ""
84
 
85
+ #: admin/class-advanced-ads-admin.php:227
86
  msgid "Show inactive ads"
87
  msgstr ""
88
 
89
+ #: admin/class-advanced-ads-admin.php:228
90
  msgid "Hide inactive ads"
91
  msgstr ""
92
 
93
+ #: admin/class-advanced-ads-admin.php:230
94
  msgid "Permanently delete this placement?"
95
  msgstr ""
96
 
97
+ #: admin/class-advanced-ads-admin.php:389
98
  #: admin/includes/class-menu.php:156
99
  #: admin/includes/class-menu.php:159
100
  #: admin/views/settings.php:29
101
  msgid "Support"
102
  msgstr ""
103
 
104
+ #: admin/class-advanced-ads-admin.php:393
105
  #: admin/includes/class-overview-widgets.php:72
106
  msgid "Add-Ons"
107
  msgstr ""
108
 
109
  #. translators: %s is the URL to add a new review, https://wordpress.org/support/plugin/advanced-ads/reviews/#new-post
110
  #. translators: %s is a URL.
111
+ #: admin/class-advanced-ads-admin.php:664
112
  #: admin/includes/class-overview-widgets.php:191
113
  msgid "Thank the developer with a &#9733;&#9733;&#9733;&#9733;&#9733; review on <a href=\"%s\" target=\"_blank\">wordpress.org</a>"
114
  msgstr ""
249
  msgid "Learn how."
250
  msgstr ""
251
 
252
+ #: admin/includes/class-ad-groups-list.php:178
253
  msgid "Ad weight"
254
  msgstr ""
255
 
256
  #. translators: %s is a date.
257
+ #: admin/includes/class-ad-groups-list.php:190
258
  #: admin/views/ad-list-timing-column.php:21
259
  msgid "starts %s"
260
  msgstr ""
261
 
262
  #. translators: %s is a date.
263
  #. translators: %s is a time and date string.
264
+ #: admin/includes/class-ad-groups-list.php:211
265
  #: admin/views/ad-list-timing-column.php:59
266
  msgid "expires %s"
267
  msgstr ""
268
 
269
  #. translators: %s is a date.
270
  #. translators: %s is a time and date string.
271
+ #: admin/includes/class-ad-groups-list.php:214
272
  #: admin/views/ad-list-timing-column.php:70
273
  msgid "<strong>expired</strong> %s"
274
  msgstr ""
275
 
276
  #. translators: %d is a number.
277
+ #: admin/includes/class-ad-groups-list.php:231
278
  msgid "show %d more ads"
279
  msgstr ""
280
 
281
+ #: admin/includes/class-ad-groups-list.php:235
282
  msgid "all published ads are displayed"
283
  msgstr ""
284
 
285
  #. translators: %d is a number.
286
+ #: admin/includes/class-ad-groups-list.php:238
287
  msgid "up to %d ads displayed"
288
  msgstr ""
289
 
290
+ #: admin/includes/class-ad-groups-list.php:241
291
  msgid "No ads assigned"
292
  msgstr ""
293
 
294
+ #: admin/includes/class-ad-groups-list.php:243
295
  msgid "Add some"
296
  msgstr ""
297
 
298
+ #: admin/includes/class-ad-groups-list.php:321
299
  msgid "Random ads"
300
  msgstr ""
301
 
302
+ #: admin/includes/class-ad-groups-list.php:322
303
  msgid "Display random ads based on ad weight"
304
  msgstr ""
305
 
306
+ #: admin/includes/class-ad-groups-list.php:325
307
  msgid "Ordered ads"
308
  msgstr ""
309
 
310
+ #: admin/includes/class-ad-groups-list.php:326
311
  msgid "Display ads with the highest ad weight first"
312
  msgstr ""
313
 
314
+ #: admin/includes/class-ad-groups-list.php:345
315
  #: admin/views/placements.php:275
316
  #: modules/import-export/classes/import.php:153
317
  #: modules/import-export/classes/import.php:193
318
  #: modules/import-export/classes/import.php:595
319
+ #: public/class-advanced-ads.php:798
320
  msgid "Edit"
321
  msgstr ""
322
 
323
+ #: admin/includes/class-ad-groups-list.php:346
324
  #: admin/views/placements.php:306
325
  msgid "Usage"
326
  msgstr ""
327
 
328
+ #: admin/includes/class-ad-groups-list.php:355
329
  #: admin/views/placements.php:10
330
  msgid "Delete"
331
  msgstr ""
332
 
333
+ #: admin/includes/class-ad-groups-list.php:377
334
+ #: admin/includes/class-ad-groups-list.php:447
335
  msgid "Invalid Ad Group"
336
  msgstr ""
337
 
338
+ #: admin/includes/class-ad-groups-list.php:382
339
+ #: admin/includes/class-ad-groups-list.php:452
340
  msgid "You don’t have permission to change the ad groups"
341
  msgstr ""
342
 
343
+ #: admin/includes/class-ad-groups-list.php:416
344
  msgid "No ad group created"
345
  msgstr ""
346
 
395
  msgstr[1] ""
396
 
397
  #. Translators: %s is the time the ad was first saved.
398
+ #: admin/includes/class-ad-type.php:662
399
  msgid "Ad created on %s"
400
  msgstr ""
401
 
402
+ #: admin/includes/class-ad-type.php:854
403
+ #: admin/includes/class-ad-type.php:855
404
  msgid "Ad updated."
405
  msgstr ""
406
 
407
  #. translators: %s: date and time of the revision
408
+ #: admin/includes/class-ad-type.php:856
409
  msgid "Ad restored to revision from %s"
410
  msgstr ""
411
 
412
+ #: admin/includes/class-ad-type.php:857
413
+ #: admin/includes/class-ad-type.php:858
414
  msgid "Ad saved."
415
  msgstr ""
416
 
417
+ #: admin/includes/class-ad-type.php:859
418
  msgid "Ad submitted."
419
  msgstr ""
420
 
421
  #. translators: %1$s is a date.
422
+ #: admin/includes/class-ad-type.php:862
423
  msgid "Ad scheduled for: <strong>%1$s</strong>."
424
  msgstr ""
425
 
426
  #. translators: Publish box date format, see http://php.net/date.
427
+ #: admin/includes/class-ad-type.php:864
428
  msgid "M j, Y @ G:i"
429
  msgstr ""
430
 
431
+ #: admin/includes/class-ad-type.php:866
432
  msgid "Ad draft updated."
433
  msgstr ""
434
 
435
+ #: admin/includes/class-ad-type.php:922
436
  msgid "You don’t have access to ads. Please deactivate and re-enable Advanced Ads again to fix this."
437
  msgstr ""
438
 
439
+ #: admin/includes/class-ad-type.php:923
440
  #: classes/frontend_checks.php:503
441
  msgid "Get help"
442
  msgstr ""
533
  msgid "Download failed. <a href=\"%s\" target=\"_blank\">Click here to learn why</a>."
534
  msgstr ""
535
 
536
+ #: admin/includes/class-list-filters.php:142
537
  #: modules/gadsense/admin/admin.php:73
538
  #: modules/gadsense/admin/views/adsense-ad-parameters.php:109
539
  msgid "Responsive"
540
  msgstr ""
541
 
542
+ #: admin/includes/class-list-filters.php:151
543
  msgid "expired"
544
  msgstr ""
545
 
546
+ #: admin/includes/class-list-filters.php:155
547
  msgid "any expiry date"
548
  msgstr ""
549
 
559
  #: admin/includes/class-shortcode-creator.php:184
560
  #: admin/views/ad-group-list-form-row.php:91
561
  #: admin/views/ad-group-list-header.php:16
562
+ #: admin/views/placement-form.php:90
563
  #: admin/views/placements-item.php:26
564
+ #: classes/widget.php:136
565
+ #: modules/gutenberg/includes/class-gutenberg.php:86
566
  #: modules/import-export/views/page.php:23
567
+ #: public/class-advanced-ads.php:794
568
  msgid "Ads"
569
  msgstr ""
570
 
571
  #: admin/includes/class-menu.php:112
572
+ #: public/class-advanced-ads.php:797
573
  msgid "Add New Ad"
574
  msgstr ""
575
 
576
  #: admin/includes/class-menu.php:113
577
  #: admin/views/ad-group-list-ads.php:36
578
+ #: public/class-advanced-ads.php:796
579
+ #: public/class-advanced-ads.php:800
580
  msgid "New Ad"
581
  msgstr ""
582
 
595
  #: admin/includes/class-menu.php:132
596
  #: admin/includes/class-shortcode-creator.php:198
597
  #: admin/views/placements.php:57
598
+ #: classes/widget.php:122
599
+ #: modules/gutenberg/includes/class-gutenberg.php:88
600
  #: modules/import-export/views/page.php:25
601
  msgid "Placements"
602
  msgstr ""
685
  msgid "Disable"
686
  msgstr ""
687
 
688
+ #: admin/includes/class-meta-box.php:413
689
  msgid "Ad Settings"
690
  msgstr ""
691
 
692
+ #: admin/includes/class-meta-box.php:512
693
  #: admin/views/overview.php:8
694
  msgid "Ads Dashboard"
695
  msgstr ""
696
 
697
  #. translators: %1$d is the number of ads, %2$s and %3$s are URLs.
698
+ #: admin/includes/class-meta-box.php:528
699
  msgid "%1$d ads – <a href=\"%2$s\">manage</a> - <a href=\"%3$s\">new</a>"
700
  msgstr ""
701
 
702
+ #: admin/includes/class-meta-box.php:541
703
  msgid "Get the tutorial via email"
704
  msgstr ""
705
 
706
+ #: admin/includes/class-meta-box.php:550
707
  msgid "Get AdSense tips via email"
708
  msgstr ""
709
 
710
+ #: admin/includes/class-meta-box.php:559
711
  msgid "Visit our blog for more articles about ad optimization"
712
  msgstr ""
713
 
714
  #. translators: %s is our URL.
715
+ #: admin/includes/class-meta-box.php:613
716
  msgid "Latest posts on wpadvancedads.com"
717
  msgstr ""
718
 
1016
  msgstr ""
1017
 
1018
  #: admin/includes/class-shortcode-creator.php:182
1019
+ #: classes/widget.php:120
1020
+ #: modules/gutenberg/includes/class-gutenberg.php:84
1021
  msgid "--empty--"
1022
  msgstr ""
1023
 
1024
  #: admin/includes/class-shortcode-creator.php:191
1025
+ #: admin/views/placement-form.php:83
1026
  #: admin/views/placements-item.php:14
1027
+ #: classes/widget.php:129
1028
+ #: modules/gutenberg/includes/class-gutenberg.php:87
1029
  msgid "Ad Groups"
1030
  msgstr ""
1031
 
1175
  #: classes/ad-debug.php:118
1176
  #: classes/ad-debug.php:167
1177
  #: classes/ad-debug.php:169
1178
+ #: public/class-advanced-ads.php:795
1179
  msgid "Ad"
1180
  msgstr ""
1181
 
1807
  msgid "Choose a Name"
1808
  msgstr ""
1809
 
1810
+ #: admin/views/placement-form.php:73
1811
+ msgid "The name of the placement is only visible to you. Tip: choose a descriptive one, e.g. Below Post Headline."
1812
  msgstr ""
1813
 
1814
+ #: admin/views/placement-form.php:76
1815
  msgid "Placement Name"
1816
  msgstr ""
1817
 
1818
+ #: admin/views/placement-form.php:77
1819
  msgid "Please enter a name for your placement."
1820
  msgstr ""
1821
 
1822
+ #: admin/views/placement-form.php:78
1823
  msgid "Choose the Ad or Group"
1824
  msgstr ""
1825
 
1826
+ #: admin/views/placement-form.php:79
1827
  msgid "The ad or group that should be displayed."
1828
  msgstr ""
1829
 
1830
+ #: admin/views/placement-form.php:81
1831
  #: admin/views/placements-item.php:12
1832
  msgid "--not selected--"
1833
  msgstr ""
1834
 
1835
+ #: admin/views/placement-form.php:98
1836
  msgid "Save New Placement"
1837
  msgstr ""
1838
 
2023
  msgid "Delivery"
2024
  msgstr ""
2025
 
2026
+ #: admin/views/placements.php:81
2027
+ msgid "- show all types -"
2028
+ msgstr ""
2029
+
2030
+ #: admin/views/placements.php:88
2031
+ msgid "filter by name"
2032
+ msgstr ""
2033
+
2034
  #: admin/views/placements.php:139
2035
  msgid "show usage"
2036
  msgstr ""
2947
  msgstr ""
2948
 
2949
  #. translators: the plugin name.
2950
+ #: classes/EDD_SL_Plugin_Updater.php:224
2951
  msgid "There is a new version of %1$s available."
2952
  msgstr ""
2953
 
2954
+ #: classes/EDD_SL_Plugin_Updater.php:230
2955
+ msgid "Contact your network administrator to install the update."
 
2956
  msgstr ""
2957
 
2958
+ #. translators: 1. opening anchor tag, do not translate 2. the new plugin version 3. closing anchor tag, do not translate.
2959
+ #: classes/EDD_SL_Plugin_Updater.php:235
2960
+ msgid "%1$sView version %2$s details%3$s."
2961
  msgstr ""
2962
 
2963
  #: classes/EDD_SL_Plugin_Updater.php:243
2964
+ msgid "%1$sView version %2$s details%3$s or %4$supdate now%5$s."
2965
+ msgstr ""
2966
+
2967
+ #: classes/EDD_SL_Plugin_Updater.php:254
2968
  msgid "Update now."
2969
  msgstr ""
2970
 
2971
+ #: classes/EDD_SL_Plugin_Updater.php:486
2972
  msgid "You do not have permission to install plugin updates"
2973
  msgstr ""
2974
 
2975
+ #: classes/EDD_SL_Plugin_Updater.php:486
2976
  msgid "Error"
2977
  msgstr ""
2978
 
3163
  msgstr ""
3164
 
3165
  #. translators: time zone name.
3166
+ #: classes/utils.php:277
3167
  msgid "time of %s"
3168
  msgstr ""
3169
 
3240
  msgid "Display Ads and Ad Groups."
3241
  msgstr ""
3242
 
3243
+ #: classes/widget.php:114
3244
  msgid "Title:"
3245
  msgstr ""
3246
 
3268
  msgid "Individual Posts, Pages and Public Post Types"
3269
  msgstr ""
3270
 
3271
+ #: modules/ad-blocker/admin/admin.php:93
3272
  msgid "Ad blocker fix"
3273
  msgstr ""
3274
 
3275
+ #: modules/ad-blocker/admin/admin.php:135
3276
  #: modules/ads-txt/admin/class-advanced-ads-ads-txt-admin.php:381
3277
  msgid "Unable to connect to the filesystem. Please confirm your credentials."
3278
  msgstr ""
3279
 
3280
+ #: modules/ad-blocker/admin/admin.php:149
3281
  msgid "The asset folder was rebuilt successfully"
3282
  msgstr ""
3283
 
3284
+ #: modules/ad-blocker/admin/admin.php:194
3285
  msgid "There is no writable upload folder"
3286
  msgstr ""
3287
 
3288
+ #: modules/ad-blocker/admin/admin.php:226
3289
  msgid "Unable to rename \"%s\" directory"
3290
  msgstr ""
3291
 
3292
+ #: modules/ad-blocker/admin/admin.php:242
3293
+ #: modules/ad-blocker/admin/admin.php:255
3294
+ #: modules/ad-blocker/admin/admin.php:272
3295
  msgid "Unable to copy assets to the \"%s\" directory"
3296
  msgstr ""
3297
 
3298
+ #: modules/ad-blocker/admin/admin.php:305
3299
+ #: modules/ad-blocker/admin/admin.php:390
3300
  msgid "We do not have direct write access to the \"%s\" directory"
3301
  msgstr ""
3302
 
3303
+ #: modules/ad-blocker/admin/admin.php:401
3304
  msgid "Unable to copy files to %s"
3305
  msgstr ""
3306
 
3307
+ #: modules/ad-blocker/admin/views/rebuild_form.php:12
3308
  msgid "Ad blocker file folder"
3309
  msgstr ""
3310
 
3311
+ #: modules/ad-blocker/admin/views/rebuild_form.php:21
3312
  msgid "Upload folder is not writable"
3313
  msgstr ""
3314
 
3315
+ #: modules/ad-blocker/admin/views/rebuild_form.php:32
3316
  msgid "Asset path"
3317
  msgstr ""
3318
 
3319
+ #: modules/ad-blocker/admin/views/rebuild_form.php:36
3320
  msgid "Asset URL"
3321
  msgstr ""
3322
 
3323
+ #: modules/ad-blocker/admin/views/rebuild_form.php:40
3324
  msgid "Rename assets"
3325
  msgstr ""
3326
 
3327
+ #: modules/ad-blocker/admin/views/rebuild_form.php:44
3328
  msgid "Check if you want to change the names of the assets"
3329
  msgstr ""
3330
 
3331
+ #. translators: placeholder is path to folder in uploads dir
3332
+ #: modules/ad-blocker/admin/views/rebuild_form.php:58
3333
+ msgid "Please, rebuild the asset folder. All assets will be located in %s"
3334
  msgstr ""
3335
 
3336
+ #: modules/ad-blocker/admin/views/rebuild_form.php:67
3337
  msgid "Rebuild asset folder"
3338
  msgstr ""
3339
 
3697
  msgid "Get the code for this ad"
3698
  msgstr ""
3699
 
3700
+ #: modules/gadsense/admin/views/external-ads-list.php:93
3701
+ msgid "Load"
3702
+ msgstr ""
3703
+
3704
  #: modules/gadsense/admin/views/external-ads-list.php:97
3705
  msgid "Ad can't be imported, click for details"
3706
  msgstr ""
3742
 
3743
  #. translators: AdSense ID.
3744
  #: modules/gadsense/includes/adsense-report-api.php:152
 
3745
  msgid "Invalid response while retrieving report for \"%s\"."
3746
  msgstr ""
3747
 
4244
  msgid "No Ad Group found"
4245
  msgstr ""
4246
 
4247
+ #: public/class-advanced-ads.php:799
4248
  msgid "Edit Ad"
4249
  msgstr ""
4250
 
4251
+ #: public/class-advanced-ads.php:801
4252
  msgid "View"
4253
  msgstr ""
4254
 
4255
+ #: public/class-advanced-ads.php:802
4256
  msgid "View the Ad"
4257
  msgstr ""
4258
 
4259
+ #: public/class-advanced-ads.php:803
4260
  msgid "Search Ads"
4261
  msgstr ""
4262
 
4263
+ #: public/class-advanced-ads.php:804
4264
  msgid "No Ads found"
4265
  msgstr ""
4266
 
4267
+ #: public/class-advanced-ads.php:805
4268
  msgid "No Ads found in Trash"
4269
  msgstr ""
4270
 
4271
+ #: public/class-advanced-ads.php:806
4272
  msgid "Parent Ad"
4273
  msgstr ""
4274
 
4275
+ #: public/class-advanced-ads.php:984
4276
  msgctxt "label above ads"
4277
  msgid "Advertisements"
4278
  msgstr ""
lib/composer/ClassLoader.php CHANGED
@@ -37,26 +37,80 @@ namespace AdvancedAds\Autoload;
37
  *
38
  * @author Fabien Potencier <fabien@symfony.com>
39
  * @author Jordi Boggiano <j.boggiano@seld.be>
40
- * @see http://www.php-fig.org/psr/psr-0/
41
- * @see http://www.php-fig.org/psr/psr-4/
42
  */
43
  class ClassLoader
44
  {
 
 
 
45
  // PSR-4
 
 
 
 
46
  private $prefixLengthsPsr4 = array();
 
 
 
 
47
  private $prefixDirsPsr4 = array();
 
 
 
 
48
  private $fallbackDirsPsr4 = array();
49
 
50
  // PSR-0
 
 
 
 
51
  private $prefixesPsr0 = array();
 
 
 
 
52
  private $fallbackDirsPsr0 = array();
53
 
 
54
  private $useIncludePath = false;
 
 
 
 
 
55
  private $classMap = array();
 
 
56
  private $classMapAuthoritative = false;
 
 
 
 
 
57
  private $missingClasses = array();
 
 
58
  private $apcuPrefix;
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  public function getPrefixes()
61
  {
62
  if (!empty($this->prefixesPsr0)) {
@@ -66,28 +120,47 @@ class ClassLoader
66
  return array();
67
  }
68
 
 
 
 
 
69
  public function getPrefixesPsr4()
70
  {
71
  return $this->prefixDirsPsr4;
72
  }
73
 
 
 
 
 
74
  public function getFallbackDirs()
75
  {
76
  return $this->fallbackDirsPsr0;
77
  }
78
 
 
 
 
 
79
  public function getFallbackDirsPsr4()
80
  {
81
  return $this->fallbackDirsPsr4;
82
  }
83
 
 
 
 
 
84
  public function getClassMap()
85
  {
86
  return $this->classMap;
87
  }
88
 
89
  /**
90
- * @param array $classMap Class to filename map
 
 
 
91
  */
92
  public function addClassMap(array $classMap)
93
  {
@@ -102,9 +175,11 @@ class ClassLoader
102
  * Registers a set of PSR-0 directories for a given prefix, either
103
  * appending or prepending to the ones previously set for this prefix.
104
  *
105
- * @param string $prefix The prefix
106
- * @param array|string $paths The PSR-0 root directories
107
- * @param bool $prepend Whether to prepend the directories
 
 
108
  */
109
  public function add($prefix, $paths, $prepend = false)
110
  {
@@ -147,11 +222,13 @@ class ClassLoader
147
  * Registers a set of PSR-4 directories for a given namespace, either
148
  * appending or prepending to the ones previously set for this namespace.
149
  *
150
- * @param string $prefix The prefix/namespace, with trailing '\\'
151
- * @param array|string $paths The PSR-4 base directories
152
- * @param bool $prepend Whether to prepend the directories
153
  *
154
  * @throws \InvalidArgumentException
 
 
155
  */
156
  public function addPsr4($prefix, $paths, $prepend = false)
157
  {
@@ -195,8 +272,10 @@ class ClassLoader
195
  * Registers a set of PSR-0 directories for a given prefix,
196
  * replacing any others previously set for this prefix.
197
  *
198
- * @param string $prefix The prefix
199
- * @param array|string $paths The PSR-0 base directories
 
 
200
  */
201
  public function set($prefix, $paths)
202
  {
@@ -211,10 +290,12 @@ class ClassLoader
211
  * Registers a set of PSR-4 directories for a given namespace,
212
  * replacing any others previously set for this namespace.
213
  *
214
- * @param string $prefix The prefix/namespace, with trailing '\\'
215
- * @param array|string $paths The PSR-4 base directories
216
  *
217
  * @throws \InvalidArgumentException
 
 
218
  */
219
  public function setPsr4($prefix, $paths)
220
  {
@@ -234,6 +315,8 @@ class ClassLoader
234
  * Turns on searching the include path for class files.
235
  *
236
  * @param bool $useIncludePath
 
 
237
  */
238
  public function setUseIncludePath($useIncludePath)
239
  {
@@ -256,6 +339,8 @@ class ClassLoader
256
  * that have not been registered with the class map.
257
  *
258
  * @param bool $classMapAuthoritative
 
 
259
  */
260
  public function setClassMapAuthoritative($classMapAuthoritative)
261
  {
@@ -276,6 +361,8 @@ class ClassLoader
276
  * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
  *
278
  * @param string|null $apcuPrefix
 
 
279
  */
280
  public function setApcuPrefix($apcuPrefix)
281
  {
@@ -296,25 +383,44 @@ class ClassLoader
296
  * Registers this instance as an autoloader.
297
  *
298
  * @param bool $prepend Whether to prepend the autoloader or not
 
 
299
  */
300
  public function register($prepend = false)
301
  {
302
  spl_autoload_register(array($this, 'loadClass'), true, $prepend);
 
 
 
 
 
 
 
 
 
 
 
303
  }
304
 
305
  /**
306
  * Unregisters this instance as an autoloader.
 
 
307
  */
308
  public function unregister()
309
  {
310
  spl_autoload_unregister(array($this, 'loadClass'));
 
 
 
 
311
  }
312
 
313
  /**
314
  * Loads the given class or interface.
315
  *
316
  * @param string $class The name of the class
317
- * @return bool|null True if loaded, null otherwise
318
  */
319
  public function loadClass($class)
320
  {
@@ -323,6 +429,8 @@ class ClassLoader
323
 
324
  return true;
325
  }
 
 
326
  }
327
 
328
  /**
@@ -367,6 +475,21 @@ class ClassLoader
367
  return $file;
368
  }
369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  private function findFileWithExtension($class, $ext)
371
  {
372
  // PSR-4 lookup
@@ -438,6 +561,10 @@ class ClassLoader
438
  * Scope isolated include.
439
  *
440
  * Prevents access to $this/self from included files.
 
 
 
 
441
  */
442
  function includeFile($file)
443
  {
37
  *
38
  * @author Fabien Potencier <fabien@symfony.com>
39
  * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see https://www.php-fig.org/psr/psr-0/
41
+ * @see https://www.php-fig.org/psr/psr-4/
42
  */
43
  class ClassLoader
44
  {
45
+ /** @var ?string */
46
+ private $vendorDir;
47
+
48
  // PSR-4
49
+ /**
50
+ * @var array[]
51
+ * @psalm-var array<string, array<string, int>>
52
+ */
53
  private $prefixLengthsPsr4 = array();
54
+ /**
55
+ * @var array[]
56
+ * @psalm-var array<string, array<int, string>>
57
+ */
58
  private $prefixDirsPsr4 = array();
59
+ /**
60
+ * @var array[]
61
+ * @psalm-var array<string, string>
62
+ */
63
  private $fallbackDirsPsr4 = array();
64
 
65
  // PSR-0
66
+ /**
67
+ * @var array[]
68
+ * @psalm-var array<string, array<string, string[]>>
69
+ */
70
  private $prefixesPsr0 = array();
71
+ /**
72
+ * @var array[]
73
+ * @psalm-var array<string, string>
74
+ */
75
  private $fallbackDirsPsr0 = array();
76
 
77
+ /** @var bool */
78
  private $useIncludePath = false;
79
+
80
+ /**
81
+ * @var string[]
82
+ * @psalm-var array<string, string>
83
+ */
84
  private $classMap = array();
85
+
86
+ /** @var bool */
87
  private $classMapAuthoritative = false;
88
+
89
+ /**
90
+ * @var bool[]
91
+ * @psalm-var array<string, bool>
92
+ */
93
  private $missingClasses = array();
94
+
95
+ /** @var ?string */
96
  private $apcuPrefix;
97
 
98
+ /**
99
+ * @var self[]
100
+ */
101
+ private static $registeredLoaders = array();
102
+
103
+ /**
104
+ * @param ?string $vendorDir
105
+ */
106
+ public function __construct($vendorDir = null)
107
+ {
108
+ $this->vendorDir = $vendorDir;
109
+ }
110
+
111
+ /**
112
+ * @return string[]
113
+ */
114
  public function getPrefixes()
115
  {
116
  if (!empty($this->prefixesPsr0)) {
120
  return array();
121
  }
122
 
123
+ /**
124
+ * @return array[]
125
+ * @psalm-return array<string, array<int, string>>
126
+ */
127
  public function getPrefixesPsr4()
128
  {
129
  return $this->prefixDirsPsr4;
130
  }
131
 
132
+ /**
133
+ * @return array[]
134
+ * @psalm-return array<string, string>
135
+ */
136
  public function getFallbackDirs()
137
  {
138
  return $this->fallbackDirsPsr0;
139
  }
140
 
141
+ /**
142
+ * @return array[]
143
+ * @psalm-return array<string, string>
144
+ */
145
  public function getFallbackDirsPsr4()
146
  {
147
  return $this->fallbackDirsPsr4;
148
  }
149
 
150
+ /**
151
+ * @return string[] Array of classname => path
152
+ * @psalm-var array<string, string>
153
+ */
154
  public function getClassMap()
155
  {
156
  return $this->classMap;
157
  }
158
 
159
  /**
160
+ * @param string[] $classMap Class to filename map
161
+ * @psalm-param array<string, string> $classMap
162
+ *
163
+ * @return void
164
  */
165
  public function addClassMap(array $classMap)
166
  {
175
  * Registers a set of PSR-0 directories for a given prefix, either
176
  * appending or prepending to the ones previously set for this prefix.
177
  *
178
+ * @param string $prefix The prefix
179
+ * @param string[]|string $paths The PSR-0 root directories
180
+ * @param bool $prepend Whether to prepend the directories
181
+ *
182
+ * @return void
183
  */
184
  public function add($prefix, $paths, $prepend = false)
185
  {
222
  * Registers a set of PSR-4 directories for a given namespace, either
223
  * appending or prepending to the ones previously set for this namespace.
224
  *
225
+ * @param string $prefix The prefix/namespace, with trailing '\\'
226
+ * @param string[]|string $paths The PSR-4 base directories
227
+ * @param bool $prepend Whether to prepend the directories
228
  *
229
  * @throws \InvalidArgumentException
230
+ *
231
+ * @return void
232
  */
233
  public function addPsr4($prefix, $paths, $prepend = false)
234
  {
272
  * Registers a set of PSR-0 directories for a given prefix,
273
  * replacing any others previously set for this prefix.
274
  *
275
+ * @param string $prefix The prefix
276
+ * @param string[]|string $paths The PSR-0 base directories
277
+ *
278
+ * @return void
279
  */
280
  public function set($prefix, $paths)
281
  {
290
  * Registers a set of PSR-4 directories for a given namespace,
291
  * replacing any others previously set for this namespace.
292
  *
293
+ * @param string $prefix The prefix/namespace, with trailing '\\'
294
+ * @param string[]|string $paths The PSR-4 base directories
295
  *
296
  * @throws \InvalidArgumentException
297
+ *
298
+ * @return void
299
  */
300
  public function setPsr4($prefix, $paths)
301
  {
315
  * Turns on searching the include path for class files.
316
  *
317
  * @param bool $useIncludePath
318
+ *
319
+ * @return void
320
  */
321
  public function setUseIncludePath($useIncludePath)
322
  {
339
  * that have not been registered with the class map.
340
  *
341
  * @param bool $classMapAuthoritative
342
+ *
343
+ * @return void
344
  */
345
  public function setClassMapAuthoritative($classMapAuthoritative)
346
  {
361
  * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
362
  *
363
  * @param string|null $apcuPrefix
364
+ *
365
+ * @return void
366
  */
367
  public function setApcuPrefix($apcuPrefix)
368
  {
383
  * Registers this instance as an autoloader.
384
  *
385
  * @param bool $prepend Whether to prepend the autoloader or not
386
+ *
387
+ * @return void
388
  */
389
  public function register($prepend = false)
390
  {
391
  spl_autoload_register(array($this, 'loadClass'), true, $prepend);
392
+
393
+ if (null === $this->vendorDir) {
394
+ return;
395
+ }
396
+
397
+ if ($prepend) {
398
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
399
+ } else {
400
+ unset(self::$registeredLoaders[$this->vendorDir]);
401
+ self::$registeredLoaders[$this->vendorDir] = $this;
402
+ }
403
  }
404
 
405
  /**
406
  * Unregisters this instance as an autoloader.
407
+ *
408
+ * @return void
409
  */
410
  public function unregister()
411
  {
412
  spl_autoload_unregister(array($this, 'loadClass'));
413
+
414
+ if (null !== $this->vendorDir) {
415
+ unset(self::$registeredLoaders[$this->vendorDir]);
416
+ }
417
  }
418
 
419
  /**
420
  * Loads the given class or interface.
421
  *
422
  * @param string $class The name of the class
423
+ * @return true|null True if loaded, null otherwise
424
  */
425
  public function loadClass($class)
426
  {
429
 
430
  return true;
431
  }
432
+
433
+ return null;
434
  }
435
 
436
  /**
475
  return $file;
476
  }
477
 
478
+ /**
479
+ * Returns the currently registered loaders indexed by their corresponding vendor directories.
480
+ *
481
+ * @return self[]
482
+ */
483
+ public static function getRegisteredLoaders()
484
+ {
485
+ return self::$registeredLoaders;
486
+ }
487
+
488
+ /**
489
+ * @param string $class
490
+ * @param string $ext
491
+ * @return string|false
492
+ */
493
  private function findFileWithExtension($class, $ext)
494
  {
495
  // PSR-4 lookup
561
  * Scope isolated include.
562
  *
563
  * Prevents access to $this/self from included files.
564
+ *
565
+ * @param string $file
566
+ * @return void
567
+ * @private
568
  */
569
  function includeFile($file)
570
  {
lib/composer/autoload_classmap.php CHANGED
@@ -52,6 +52,7 @@ return array(
52
  'Advanced_Ads_Utils' => $baseDir . '/classes/utils.php',
53
  'Advanced_Ads_Visitor_Conditions' => $baseDir . '/classes/visitor-conditions.php',
54
  'Advanced_Ads_Widget' => $baseDir . '/classes/widget.php',
 
55
  'Yoast_I18n_WordPressOrg_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php',
56
  'Yoast_I18n_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-v3.php',
57
  );
52
  'Advanced_Ads_Utils' => $baseDir . '/classes/utils.php',
53
  'Advanced_Ads_Visitor_Conditions' => $baseDir . '/classes/visitor-conditions.php',
54
  'Advanced_Ads_Widget' => $baseDir . '/classes/widget.php',
55
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
56
  'Yoast_I18n_WordPressOrg_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php',
57
  'Yoast_I18n_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-v3.php',
58
  );
lib/composer/autoload_real.php CHANGED
@@ -22,13 +22,15 @@ class ComposerAutoloaderInit_advanced_ads
22
  return self::$loader;
23
  }
24
 
 
 
25
  spl_autoload_register(array('ComposerAutoloaderInit_advanced_ads', 'loadClassLoader'), true, true);
26
- self::$loader = $loader = new \AdvancedAds\Autoload\ClassLoader();
27
  spl_autoload_unregister(array('ComposerAutoloaderInit_advanced_ads', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
- require_once __DIR__ . '/autoload_static.php';
32
 
33
  call_user_func(\AdvancedAds\Autoload\ComposerStaticInit_advanced_ads::getInitializer($loader));
34
  } else {
22
  return self::$loader;
23
  }
24
 
25
+ require __DIR__ . '/platform_check.php';
26
+
27
  spl_autoload_register(array('ComposerAutoloaderInit_advanced_ads', 'loadClassLoader'), true, true);
28
+ self::$loader = $loader = new \AdvancedAds\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
29
  spl_autoload_unregister(array('ComposerAutoloaderInit_advanced_ads', 'loadClassLoader'));
30
 
31
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
32
  if ($useStaticLoader) {
33
+ require __DIR__ . '/autoload_static.php';
34
 
35
  call_user_func(\AdvancedAds\Autoload\ComposerStaticInit_advanced_ads::getInitializer($loader));
36
  } else {
lib/composer/autoload_static.php CHANGED
@@ -53,6 +53,7 @@ class ComposerStaticInit_advanced_ads
53
  'Advanced_Ads_Utils' => __DIR__ . '/../..' . '/classes/utils.php',
54
  'Advanced_Ads_Visitor_Conditions' => __DIR__ . '/../..' . '/classes/visitor-conditions.php',
55
  'Advanced_Ads_Widget' => __DIR__ . '/../..' . '/classes/widget.php',
 
56
  'Yoast_I18n_WordPressOrg_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php',
57
  'Yoast_I18n_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-v3.php',
58
  );
53
  'Advanced_Ads_Utils' => __DIR__ . '/../..' . '/classes/utils.php',
54
  'Advanced_Ads_Visitor_Conditions' => __DIR__ . '/../..' . '/classes/visitor-conditions.php',
55
  'Advanced_Ads_Widget' => __DIR__ . '/../..' . '/classes/widget.php',
56
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
57
  'Yoast_I18n_WordPressOrg_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php',
58
  'Yoast_I18n_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-v3.php',
59
  );
modules/ad-blocker/admin/admin.php CHANGED
@@ -62,9 +62,6 @@ class Advanced_Ads_Ad_Blocker_Admin {
62
  $this->options = Advanced_Ads_Ad_Blocker::get_instance()->options();
63
  $this->upload_dir = $this->options['upload_dir'];
64
 
65
- // add rebuild asset form
66
- add_filter( 'advanced-ads-settings-tab-after-form', array( $this, 'add_asset_rebuild_form_wrap' ) );
67
-
68
  add_action( 'admin_init', array( $this, 'process_auto_update' ) );
69
 
70
  $this->error_messages = new WP_Error();
@@ -104,32 +101,23 @@ class Advanced_Ads_Ad_Blocker_Admin {
104
  * Render setting to enable/disable adblocker.
105
  */
106
  public function render_settings_use_adblocker() {
107
- $advads_options = Advanced_Ads::get_instance()->options();
108
  $is_main_site = is_main_site( get_current_blog_id() );
109
- $checked = ( ! empty( $advads_options['use-adblocker'] ) ) ? 1 : 0;
110
 
111
  include ADVADS_AB_BASE_PATH . 'admin/views/setting-use-adblocker.php';
112
- }
113
 
114
- /**
115
- * Render the ad-blocker rebuild assets form wrapper with rebuild assets form inside
116
- *
117
- * @param str $_setting_tab_id - id of the tab
118
- */
119
- public function add_asset_rebuild_form_wrap( $_setting_tab_id ) {
120
- if ( $_setting_tab_id == 'general' ) {
121
- $advads_options = Advanced_Ads::get_instance()->options();
122
- $use_adblocker = isset( $advads_options['use-adblocker'] );
123
- ?>
124
- <div id="advads-adblocker-wrapper" <?php if ( ! $use_adblocker ) { echo 'style="display:none"'; } ?>>
125
- <?php
126
- // not ajax yet, print the form
127
- $button_attrs = array( 'disabled' => 'disabled', 'autocomplete' => 'off' );
128
- include ADVADS_AB_BASE_PATH . 'admin/views/rebuild_form.php';
129
- ?>
130
- </div>
131
  <?php
132
- }
 
 
 
 
 
 
 
133
  }
134
 
135
  /**
@@ -141,12 +129,9 @@ class Advanced_Ads_Ad_Blocker_Admin {
141
  $success = false;
142
  $message = '';
143
 
144
- if ( ! isset( $_POST['advads_ab_form_submit'] ) ) { return; }
145
- check_ajax_referer( 'advads_ab_form_nonce', 'security' );
146
-
147
  $fs_connect = Advanced_Ads_Filesystem::get_instance()->fs_connect( $this->upload_dir['basedir'] );
148
 
149
- if ( false === $fs_connect || is_wp_error( $fs_connect ) ) {
150
  $message = __( 'Unable to connect to the filesystem. Please confirm your credentials.', 'advanced-ads' );
151
 
152
  if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
@@ -158,7 +143,6 @@ class Advanced_Ads_Ad_Blocker_Admin {
158
  } else {
159
  $output = $this->process_form();
160
  if ( is_wp_error( $output ) ) {
161
- $success = false;
162
  $message = $output->get_error_message();
163
  } else {
164
  $success = true;
@@ -166,13 +150,17 @@ class Advanced_Ads_Ad_Blocker_Admin {
166
  }
167
  }
168
 
 
 
 
 
169
  include ADVADS_AB_BASE_PATH . 'admin/views/rebuild_form.php';
170
  }
171
 
172
  /**
173
  * Perform processing of the rebuild_form, sent by user
174
  *
175
- * @return true on success, WP_Error in case of error
176
  **/
177
  private function process_form() {
178
  // at this point we do not need ftp/ssh credentials anymore
@@ -185,7 +173,7 @@ class Advanced_Ads_Ad_Blocker_Admin {
185
  Advanced_Ads::log( __METHOD__ . ': ' . $error_message );
186
  }
187
 
188
- return $this->error_messages; // WP_Error object
189
  }
190
 
191
  return true;
62
  $this->options = Advanced_Ads_Ad_Blocker::get_instance()->options();
63
  $this->upload_dir = $this->options['upload_dir'];
64
 
 
 
 
65
  add_action( 'admin_init', array( $this, 'process_auto_update' ) );
66
 
67
  $this->error_messages = new WP_Error();
101
  * Render setting to enable/disable adblocker.
102
  */
103
  public function render_settings_use_adblocker() {
 
104
  $is_main_site = is_main_site( get_current_blog_id() );
105
+ $checked = ! empty( Advanced_Ads::get_instance()->options()['use-adblocker'] );
106
 
107
  include ADVADS_AB_BASE_PATH . 'admin/views/setting-use-adblocker.php';
 
108
 
109
+ // add the rebuild form directly after the settings
110
+ ?>
111
+ <div id="advads-adblocker-wrapper" <?php echo( $checked ? '' : 'style="display: none;"' ); ?>>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  <?php
113
+ $button_disabled = true;
114
+ $upload_dir = $this->upload_dir;
115
+ $options = $this->options;
116
+
117
+ include ADVADS_AB_BASE_PATH . 'admin/views/rebuild_form.php';
118
+ ?>
119
+ </div>
120
+ <?php
121
  }
122
 
123
  /**
129
  $success = false;
130
  $message = '';
131
 
 
 
 
132
  $fs_connect = Advanced_Ads_Filesystem::get_instance()->fs_connect( $this->upload_dir['basedir'] );
133
 
134
+ if ( $fs_connect === false || is_wp_error( $fs_connect ) ) {
135
  $message = __( 'Unable to connect to the filesystem. Please confirm your credentials.', 'advanced-ads' );
136
 
137
  if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
143
  } else {
144
  $output = $this->process_form();
145
  if ( is_wp_error( $output ) ) {
 
146
  $message = $output->get_error_message();
147
  } else {
148
  $success = true;
150
  }
151
  }
152
 
153
+ $upload_dir = $this->upload_dir;
154
+ $button_disabled = false;
155
+ $options = Advanced_Ads_Ad_Blocker::get_instance()->options( true );
156
+
157
  include ADVADS_AB_BASE_PATH . 'admin/views/rebuild_form.php';
158
  }
159
 
160
  /**
161
  * Perform processing of the rebuild_form, sent by user
162
  *
163
+ * @return true|WP_Error true on success, WP_Error in case of error
164
  **/
165
  private function process_form() {
166
  // at this point we do not need ftp/ssh credentials anymore
173
  Advanced_Ads::log( __METHOD__ . ': ' . $error_message );
174
  }
175
 
176
+ return $this->error_messages;
177
  }
178
 
179
  return true;
modules/ad-blocker/admin/views/rebuild_form.php CHANGED
@@ -1,49 +1,70 @@
1
- <h3 class="title"><?php _e( 'Ad blocker file folder', 'advanced-ads' ); ?></h3>
2
  <?php
3
- $button_attrs = ( isset( $button_attrs ) ) ? $button_attrs : array();
 
 
 
 
 
 
 
 
4
 
5
- if ( ! empty( $message ) && isset( $success ) ): ?>
6
- <div class="<?php echo $success ? 'updated' : 'error'; ?> notice is-dismissible"><p><?php echo $message;?></p></div>
7
- <?php endif;
8
 
9
- if ( ! $this->upload_dir ): ?>
10
- <p class="advads-notice-inline advads-error"><?php esc_html_e( 'Upload folder is not writable', 'advanced-ads' ); ?></p>
11
- <?php
12
- else: ?>
13
- <form id="advanced-ads-rebuild-assets-form" method="post" action="">
14
- <input type="hidden" name="advads_ab_form_submit" value="true">
15
- <?php wp_nonce_field( 'advads_ab_form_nonce', 'security' );
16
- if ( ! empty( $this->options['folder_name'] ) && ! empty( $this->options['module_can_work'] ) ): ?>
17
- <table class="form-table">
18
- <tbody>
19
- <?php
20
- $folder = trailingslashit( $this->upload_dir['basedir'] ) . $this->options['folder_name'];
21
- $url = trailingslashit( $this->upload_dir['baseurl'] ) . $this->options['folder_name']; ?>
22
- <tr>
23
- <th scope="row"><?php _e( 'Asset path', 'advanced-ads' ); ?></th>
24
- <td><?php echo $folder; ?></td>
25
- </tr>
26
- <tr>
27
- <th scope="row"><?php _e( 'Asset URL', 'advanced-ads' ); ?></th>
28
- <td><?php echo $url; ?></td>
29
- </tr>
30
- <tr>
31
- <th scope="row"><?php _e( 'Rename assets', 'advanced-ads' ); ?></th>
32
- <td>
33
- <input type="checkbox" name="advads_ab_assign_new_folder">
34
- <p class="description"><?php _e( 'Check if you want to change the names of the assets', 'advanced-ads' ); ?></p>
35
- </td>
36
- </tr>
37
- </tbody>
38
- </table>
39
- <?php
40
- else: ?>
41
- <p><?php
42
- $folder = ! empty( $this->options['folder_name'] ) ? trailingslashit( $this->upload_dir['basedir'] ) . $this->options['folder_name'] : $this->upload_dir['basedir'];
43
- printf( __( 'Please, rebuild the asset folder. All assets will be located in <strong>%s</strong>', 'advanced-ads' ), $folder ); ?></p>
44
- <?php
45
- endif;
46
- submit_button( __( 'Rebuild asset folder', 'advanced-ads' ), 'primary', 'submit', true, $button_attrs ); ?>
47
- </form>
48
- <?php
49
- endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
+ /**
3
+ * Ad blocker fix rebuild template
4
+ *
5
+ * @var array $upload_dir wp_upload_dir response
6
+ * @var string $message Response message
7
+ * @var bool|null $success Whether request was successful
8
+ * @var bool $button_disabled If button should have disabled attribute.
9
+ */
10
+ ?>
11
 
12
+ <h3 class="title"><?php esc_html_e( 'Ad blocker file folder', 'advanced-ads' ); ?></h3>
 
 
13
 
14
+ <?php if ( ! empty( $message ) && isset( $success ) ) : ?>
15
+ <div class="<?php echo $success ? '' : 'error'; ?> advads-notice notice is-dismissible">
16
+ <p><?php echo esc_html( $message ); ?></p>
17
+ </div>
18
+ <?php endif; ?>
19
+
20
+ <?php if ( ! empty( $upload_dir['error'] ) ) : ?>
21
+ <p class="advads-notice-inline advads-error"><?php esc_html_e( 'Upload folder is not writable', 'advanced-ads' ); ?></p>
22
+ <?php
23
+ return;
24
+ endif;
25
+ ?>
26
+
27
+ <div id="advanced-ads-rebuild-assets-form">
28
+ <?php if ( ! empty( $options['folder_name'] ) && ! empty( $options['module_can_work'] ) ) : ?>
29
+ <table class="form-table" role="presentation">
30
+ <tbody>
31
+ <tr>
32
+ <th scope="row"><?php esc_html_e( 'Asset path', 'advanced-ads' ); ?></th>
33
+ <td><?php echo esc_html( trailingslashit( $upload_dir['basedir'] ) . $options['folder_name'] ); ?></td>
34
+ </tr>
35
+ <tr>
36
+ <th scope="row"><?php esc_html_e( 'Asset URL', 'advanced-ads' ); ?></th>
37
+ <td><?php echo esc_html( trailingslashit( $upload_dir['baseurl'] ) . $options['folder_name'] ); ?></td>
38
+ </tr>
39
+ <tr>
40
+ <th scope="row"><?php esc_html_e( 'Rename assets', 'advanced-ads' ); ?></th>
41
+ <td>
42
+ <label>
43
+ <input type="checkbox" name="advads_ab_assign_new_folder">
44
+ <?php esc_html_e( 'Check if you want to change the names of the assets', 'advanced-ads' ); ?>
45
+ </label>
46
+ </td>
47
+ </tr>
48
+ </tbody>
49
+ </table>
50
+ <?php else : ?>
51
+ <p>
52
+ <?php
53
+ $folder = ! empty( $options['folder_name'] )
54
+ ? trailingslashit( $upload_dir['basedir'] ) . $options['folder_name']
55
+ : $upload_dir['basedir'];
56
+ printf(
57
+ /* translators: placeholder is path to folder in uploads dir */
58
+ esc_html__( 'Please, rebuild the asset folder. All assets will be located in %s', 'advanced-ads' ),
59
+ sprintf( '<strong>%s</strong>', esc_attr( $folder ) )
60
+ );
61
+ ?>
62
+ </p>
63
+ <?php endif; ?>
64
+
65
+ <p class="submit">
66
+ <button type="button" class="button button-primary" id="advads-adblocker-rebuild" <?php echo( $button_disabled ? 'disabled' : '' ); ?>>
67
+ <?php esc_html_e( 'Rebuild asset folder', 'advanced-ads' ); ?>
68
+ </button>
69
+ </p>
70
+ </div>
modules/ad-blocker/classes/plugin.php CHANGED
@@ -105,10 +105,12 @@ class Advanced_Ads_Ad_Blocker {
105
  /**
106
  * Return module options
107
  *
108
- * @return array $options
 
 
109
  */
110
- public function options() {
111
- if ( ! isset( $this->options ) ) {
112
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
113
  global $current_site;
114
  // Switch to main blog.
105
  /**
106
  * Return module options
107
  *
108
+ * @param bool $force Whether the options should be fetched regardless if it has already been done. Is needed in AJAX calls.
109
+ *
110
+ * @return array
111
  */
112
+ public function options( $force = false ) {
113
+ if ( ! isset( $this->options ) || $force ) {
114
  if ( function_exists( 'is_multisite' ) && is_multisite() ) {
115
  global $current_site;
116
  // Switch to main blog.
modules/gadsense/admin/views/external-ads-list.php CHANGED
@@ -90,7 +90,7 @@ if ( ! isset( $ad_units ) ) {
90
  <?php echo esc_attr( Advanced_Ads_AdSense_MAPI::format_ad_data( $unit, 'type' ) ); ?>
91
  <?php else : ?>
92
  <button type="button" class="button-secondary button-small" title="<?php esc_attr_e( 'Get the code for this ad', 'advanced-ads' ); ?>">
93
- <span style="line-height: 26px;" class="dashicons dashicons-update"></span> <?php esc_html_e( 'Load', 'advanced ads' ); ?>
94
  </button>
95
  <?php endif; ?>
96
  <?php elseif ( empty( $unit->code ) ) : ?>
90
  <?php echo esc_attr( Advanced_Ads_AdSense_MAPI::format_ad_data( $unit, 'type' ) ); ?>
91
  <?php else : ?>
92
  <button type="button" class="button-secondary button-small" title="<?php esc_attr_e( 'Get the code for this ad', 'advanced-ads' ); ?>">
93
+ <span style="line-height: 26px;" class="dashicons dashicons-update"></span> <?php esc_html_e( 'Load', 'advanced-ads' ); ?>
94
  </button>
95
  <?php endif; ?>
96
  <?php elseif ( empty( $unit->code ) ) : ?>
modules/gadsense/includes/adsense-report-api.php CHANGED
@@ -145,16 +145,7 @@ class Advanced_Ads_AdSense_Report_Api {
145
 
146
  $response_body = json_decode( $response['body'], true );
147
 
148
- if ( $response_body === null ) {
149
- return array(
150
- 'status' => false,
151
- // translators: AdSense ID.
152
- 'msg' => sprintf( esc_html__( 'Invalid response while retrieving report for "%s".', 'advanced-ads' ), $this->publisher_id ),
153
- 'raw' => $response['body'],
154
- );
155
- }
156
-
157
- if ( ! isset( $response_body['totalMatchedRows'] ) ) {
158
  return array(
159
  'status' => false,
160
  // translators: AdSense ID.
145
 
146
  $response_body = json_decode( $response['body'], true );
147
 
148
+ if ( ! isset( $response_body['startDate'] ) ) {
 
 
 
 
 
 
 
 
 
149
  return array(
150
  'status' => false,
151
  // translators: AdSense ID.
modules/gadsense/public/public.php CHANGED
@@ -143,7 +143,17 @@ class Advanced_Ads_AdSense_Public {
143
  * Handle AdSense AMP code
144
  */
145
  public function inject_amp_code() {
146
-
 
 
 
 
 
 
 
 
 
 
147
  // The is_amp_endpoint function is used for multiple plugins.
148
  if ( function_exists( 'is_amp_endpoint' ) ) {
149
  $adsense_data = Advanced_Ads_AdSense_Data::get_instance();
143
  * Handle AdSense AMP code
144
  */
145
  public function inject_amp_code() {
146
+ // for non-AMP pages we do this on the `template_redirect` hook, this has not fired yet.
147
+ Advanced_Ads::get_instance()->set_disabled_constant();
148
+
149
+ if (
150
+ // check if ads are disabled.
151
+ ( defined( 'ADVADS_ADS_DISABLED' ) && ADVADS_ADS_DISABLED )
152
+ // check if this an AMP page, we're inside `wp` action so it's safe to use.
153
+ || ( ! function_exists( 'advads_is_amp' ) || ! advads_is_amp() )
154
+ ) {
155
+ return;
156
+ }
157
  // The is_amp_endpoint function is used for multiple plugins.
158
  if ( function_exists( 'is_amp_endpoint' ) ) {
159
  $adsense_data = Advanced_Ads_AdSense_Data::get_instance();
modules/gutenberg/includes/class-gutenberg.php CHANGED
@@ -48,14 +48,13 @@ class Advanced_Ads_Gutenberg {
48
  wp_register_script(
49
  ADVADS_BASE . '/gutenberg-ad',
50
  ADVADS_BASE_URL . 'modules/gutenberg/js/advanced-ads.block.js',
51
- array( 'wp-blocks', 'wp-element' )
52
  );
53
 
54
  $model = Advanced_Ads::get_instance()->get_model();
55
 
56
  $all_ads = Advanced_Ads::get_ads( array( 'post_status' => array( 'publish' ), 'orderby' => 'title', 'order' => 'ASC' ) );
57
  $all_groups = $model->get_ad_groups();
58
- $all_placements = Advanced_Ads::get_ad_placements_array();
59
 
60
  $ads = array();
61
  $groups = array();
@@ -69,16 +68,14 @@ class Advanced_Ads_Gutenberg {
69
  $groups[] = array( 'id' => $gr->term_id, 'name' => $gr->name );
70
  }
71
 
72
- if ( is_array( $all_placements ) ) {
73
- ksort( $all_placements );
74
- }
75
-
76
- foreach( $all_placements as $key => $value ) {
77
- if ( 'sidebar_widget' == $value['type'] ) {
78
  $placements[] = array( 'id' => $key, 'name' => $value['name'] );
79
  }
80
  }
81
 
 
 
82
  if ( empty( $placements ) ) {
83
  $placements = false;
84
  }
@@ -112,6 +109,8 @@ class Advanced_Ads_Gutenberg {
112
 
113
  /**
114
  * Server side rendering for single ad block
 
 
115
  */
116
  public static function render_ad_selector( $attr ) {
117
  ob_start();
@@ -121,39 +120,22 @@ class Advanced_Ads_Gutenberg {
121
  return '';
122
  }
123
 
124
- // the item is an ad
125
- if ( 0 === strpos( $attr['itemID'], 'ad_' ) ) {
126
-
127
- $id = substr( $attr['itemID'], 3 );
128
-
129
- // add CSS classes to the wrapper via filter
130
- if ( isset( $attr['className'] ) ) {
131
- echo get_ad( absint( $id ), array( 'output' => array( 'class' => explode( ' ', $attr['className'] ) ) ) );
132
- } else {
133
- the_ad( absint( $id ) );
134
- }
135
 
 
 
 
136
  } elseif ( 0 === strpos( $attr['itemID'], 'group_' ) ) {
137
-
138
- $id = substr( $attr['itemID'], 6 );
139
-
140
- if ( isset( $attr['className'] ) ) {
141
- echo get_ad_group( $id, array( 'output' => array( 'class' => explode( ' ', $attr['className'] ) ) ) );
142
- } else {
143
- the_ad_group( $id );
144
- }
145
-
146
  } elseif ( 0 === strpos( $attr['itemID'], 'place_' ) ) {
147
-
148
- $id = substr( $attr['itemID'], 6 );
149
-
150
- if ( isset( $attr['className'] ) ) {
151
- echo get_ad_placement( $id, array( 'output' => array( 'class' => explode( ' ', $attr['className'] ) ) ) );
152
- } else {
153
- the_ad_placement( $id );
154
- }
155
-
156
  }
 
157
 
158
  return ob_get_clean();
159
  }
48
  wp_register_script(
49
  ADVADS_BASE . '/gutenberg-ad',
50
  ADVADS_BASE_URL . 'modules/gutenberg/js/advanced-ads.block.js',
51
+ array( 'wp-dom-ready', 'wp-blocks', 'wp-element' )
52
  );
53
 
54
  $model = Advanced_Ads::get_instance()->get_model();
55
 
56
  $all_ads = Advanced_Ads::get_ads( array( 'post_status' => array( 'publish' ), 'orderby' => 'title', 'order' => 'ASC' ) );
57
  $all_groups = $model->get_ad_groups();
 
58
 
59
  $ads = array();
60
  $groups = array();
68
  $groups[] = array( 'id' => $gr->term_id, 'name' => $gr->name );
69
  }
70
 
71
+ foreach ( Advanced_Ads::get_instance()->get_model()->get_ad_placements_array() as $key => $value ) {
72
+ if ( in_array( $value['type'], array( 'sidebar_widget', 'default' ), true ) ) {
 
 
 
 
73
  $placements[] = array( 'id' => $key, 'name' => $value['name'] );
74
  }
75
  }
76
 
77
+ ksort( $placements );
78
+
79
  if ( empty( $placements ) ) {
80
  $placements = false;
81
  }
109
 
110
  /**
111
  * Server side rendering for single ad block
112
+ *
113
+ * @param array $attr Block's attributes.
114
  */
115
  public static function render_ad_selector( $attr ) {
116
  ob_start();
120
  return '';
121
  }
122
 
123
+ $output = array(
124
+ 'output' => array(
125
+ 'class' => explode( ' ', isset( $attr['className'] ) ? $attr['className'] : '' ),
126
+ 'wrapper_attrs' => array( 'data-fixed_widget' => isset( $attr['fixed_widget'] ) ? $attr['fixed_widget'] : '' ),
127
+ ),
128
+ );
 
 
 
 
 
129
 
130
+ // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- we can't escape ad output without potentially breaking ads
131
+ if ( 0 === strpos( $attr['itemID'], 'ad_' ) ) {
132
+ echo get_ad( absint( substr( $attr['itemID'], 3 ) ), $output );
133
  } elseif ( 0 === strpos( $attr['itemID'], 'group_' ) ) {
134
+ echo get_ad_group( substr( $attr['itemID'], 6 ), $output );
 
 
 
 
 
 
 
 
135
  } elseif ( 0 === strpos( $attr['itemID'], 'place_' ) ) {
136
+ echo get_ad_placement( substr( $attr['itemID'], 6 ), $output );
 
 
 
 
 
 
 
 
137
  }
138
+ // phpcs:enable
139
 
140
  return ob_get_clean();
141
  }
modules/gutenberg/js/advanced-ads.block.js CHANGED
@@ -1,194 +1,198 @@
1
- ;(function(wp){
2
-
3
- /**
4
- * Shortcut variables
5
- */
6
- var el = wp.element.createElement,
7
- registerBlockType = wp.blocks.registerBlockType;
8
-
9
- /**
10
- * Custom SVG icon
11
- * could move to a separated file if we need it in other places, too
12
- *
13
- * @source https://gist.github.com/zgordon/e837e29f77c343d29ebb7290a1a75eea
14
- */
15
- const advadsIconEl = el(
16
- 'svg',
17
- {
18
- width: "24px",
19
- height: "24px",
20
- viewBox: "1.396 3276 24 24",
21
- xmlns: "http://www.w3.org/2000/svg",
22
- x: "0px",
23
- y: "0px"
24
- },
25
- el(
26
- 'g',
27
- {},
28
  el(
29
- 'path',
30
- {
31
- fill: "#1C1B3A",
32
- d: "M18.602,3286.2v8.53H6.677v-11.925h8.53c-0.355-0.804-0.545-1.684-0.545-2.625s0.205-1.82,0.545-2.625 h-2.57H1.406v18.266l0.6,0.6l-0.6-0.6c0,2.304,1.875,4.179,4.18,4.179l0,0h7.05h11.216v-13.821 c-0.805,0.355-1.705,0.566-2.645,0.566C20.286,3286.745,19.406,3286.541,18.602,3286.2z"
33
- }
 
 
 
 
 
34
  ),
35
- el( 'circle', { fill: "#0E75A4", cx: "21.206", cy: "3280.179", r: "4.18" } )
36
- ),
37
- );
38
 
39
- /**
40
- * Register the single ad block type
41
- */
42
- registerBlockType( 'advads/gblock', {
43
 
44
- title: advadsGutenberg.i18n.advads,
45
 
46
- icon: advadsIconEl,
47
 
48
- category: 'common',
49
 
50
- attributes: {
51
- className: {
52
- type: 'string',
53
- },
54
- itemID: {
55
- type: 'string',
 
56
  },
57
- },
58
 
59
- // todo: make the keywords translatable
60
- keywords: [ 'advert', 'adsense', 'banner' ],
61
 
62
- edit: function( props ) {
63
 
64
- var itemID = props.attributes.itemID;
65
 
66
- /**
67
- * Update property on submit
68
- */
69
- function setItemID( event ) {
70
- var selected = event.target.querySelector( 'option:checked' );
71
- props.setAttributes( { itemID: selected.value } );
72
- event.preventDefault();
73
- }
74
 
75
- // the form children elements
76
- var children = [];
77
 
78
- // argument list (in array form) for the children creation
79
- var args = [];
80
- var ads = [];
81
- var groups = [];
82
- var placements = [];
83
 
84
- args.push( 'select' );
85
- args.push( { value: itemID, onChange: setItemID } );
86
- args.push( el( 'option', null, advadsGutenberg.i18n['--empty--'] ) );
87
 
88
- for ( var adID in advadsGutenberg.ads ) {
89
- if ( 'undefined' == typeof advadsGutenberg.ads[adID].id ) continue;
90
- ads.push( el( 'option', {value: 'ad_' + advadsGutenberg.ads[adID].id}, advadsGutenberg.ads[adID].title ) );
91
- }
92
 
93
- for ( var GID in advadsGutenberg.groups ) {
94
- if ( 'undefined' == typeof advadsGutenberg.groups[GID].id ) continue;
95
- groups.push( el( 'option', {value: 'group_' + advadsGutenberg.groups[GID]['id'] }, advadsGutenberg.groups[GID]['name'] ) );
96
 
97
- }
98
 
99
- if ( advadsGutenberg.placements ) {
100
- for ( var pid in advadsGutenberg.placements ) {
101
- if ( 'undefined' == typeof advadsGutenberg.placements[pid].id ) continue;
102
- placements.push( el( 'option', {value: 'place_' + advadsGutenberg.placements[pid]['id']}, advadsGutenberg.placements[pid]['name'] ) );
 
103
  }
104
- }
105
 
106
- if ( advadsGutenberg.placements ) {
107
- args.push( el( 'optgroup', {label: advadsGutenberg.i18n['placements']}, placements ) );
108
- }
109
 
110
- args.push( el( 'optgroup', {label: advadsGutenberg.i18n['adGroups']}, groups ) );
111
 
112
- args.push( el( 'optgroup', {label: advadsGutenberg.i18n['ads']}, ads ) );
113
 
114
- // add a <label /> first and style it.
115
- children.push( el( 'div', {className: 'components-placeholder__label'}, advadsIconEl, el( 'label', {style: {display: 'block'}}, advadsGutenberg.i18n.advads ) ) );
116
 
117
- if ( itemID && advadsGutenberg.i18n['--empty--'] != itemID ) {
118
 
119
- var url = '#';
120
- if ( 0 === itemID.indexOf( 'place_' ) ) {
121
- url = advadsGutenberg.editLinks.placement;
122
- } else if ( 0 === itemID.indexOf( 'group_' ) ) {
123
- url = advadsGutenberg.editLinks.group;
124
- } else if ( 0 === itemID.indexOf( 'ad_' ) ) {
125
- var _adID = itemID.substr(3);
126
- url = advadsGutenberg.editLinks.ad.replace( '%ID%', _adID );
127
- }
128
 
129
- children.push(
130
- el(
131
- 'div',
132
- {className: 'components-placeholder__fieldset'},
133
- // then add the <select /> input with its own children
134
- el.apply( null, args ),
135
  el(
136
- 'a',
137
- {
138
- class: 'dashicons dashicons-external',
139
- style: {
140
- margin: 5
141
- },
142
- href: url,
143
- target: '_blank'
144
- }
 
 
 
 
 
 
145
  )
146
- )
147
- );
148
- } else {
149
- children.push( el.apply( null, args ) );
150
- }
151
- // return the complete form
152
- return el( 'form', { className: 'components-placeholder is-large', onSubmit: setItemID }, children );
153
-
154
- },
155
-
156
- save: function() {
157
- // server side rendering
158
- return null;
159
- },
160
-
161
- // Transforms legacy widget to Advanced Ads block.
162
- transforms: {
163
- from: [{
164
- type: 'block',
165
- blocks: ['core/legacy-widget'],
166
- isMatch: function ( attributes ) {
167
- if ( ! attributes.instance || ! attributes.instance.raw ) {
168
- // Can't transform if raw instance is not shown in REST API.
169
- return false;
170
- }
171
- return attributes.idBase === 'advads_ad_widget';
172
- },
173
- transform: function ( attributes ) {
174
- var instance = attributes.instance.raw;
175
- var transformedBlock = wp.blocks.createBlock( 'advads/gblock', {
176
- name: instance.name,
177
- itemID: instance.item_id
178
- } );
179
- if ( ! instance.title ) {
180
- return transformedBlock;
181
- }
182
- return [
183
- wp.blocks.createBlock( 'core/heading', {
184
- content: instance.title
185
- } ),
186
- transformedBlock
187
- ];
188
  }
189
- }]
190
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
- } );
193
 
194
- })(window.wp);
 
1
+ (() => {
2
+ window.wp.domReady(() => { init(window.wp); })
3
+
4
+ function init(wp){
5
+
6
+ /**
7
+ * Shortcut variables
8
+ */
9
+ var el = wp.element.createElement,
10
+ registerBlockType = wp.blocks.registerBlockType;
11
+
12
+ /**
13
+ * Custom SVG icon
14
+ * could move to a separated file if we need it in other places, too
15
+ *
16
+ * @source https://gist.github.com/zgordon/e837e29f77c343d29ebb7290a1a75eea
17
+ */
18
+ const advadsIconEl = el(
19
+ 'svg',
20
+ {
21
+ width: "24px",
22
+ height: "24px",
23
+ viewBox: "1.396 3276 24 24",
24
+ xmlns: "http://www.w3.org/2000/svg",
25
+ x: "0px",
26
+ y: "0px"
27
+ },
28
  el(
29
+ 'g',
30
+ {},
31
+ el(
32
+ 'path',
33
+ {
34
+ fill: "#1C1B3A",
35
+ d: "M18.602,3286.2v8.53H6.677v-11.925h8.53c-0.355-0.804-0.545-1.684-0.545-2.625s0.205-1.82,0.545-2.625 h-2.57H1.406v18.266l0.6,0.6l-0.6-0.6c0,2.304,1.875,4.179,4.18,4.179l0,0h7.05h11.216v-13.821 c-0.805,0.355-1.705,0.566-2.645,0.566C20.286,3286.745,19.406,3286.541,18.602,3286.2z"
36
+ }
37
+ ),
38
+ el( 'circle', { fill: "#0E75A4", cx: "21.206", cy: "3280.179", r: "4.18" } )
39
  ),
40
+ );
 
 
41
 
42
+ /**
43
+ * Register the single ad block type
44
+ */
45
+ registerBlockType( 'advads/gblock', {
46
 
47
+ title: advadsGutenberg.i18n.advads,
48
 
49
+ icon: advadsIconEl,
50
 
51
+ category: 'common',
52
 
53
+ attributes: {
54
+ className: {
55
+ type: 'string',
56
+ },
57
+ itemID: {
58
+ type: 'string',
59
+ },
60
  },
 
61
 
62
+ // todo: make the keywords translatable
63
+ keywords: [ 'advert', 'adsense', 'banner' ],
64
 
65
+ edit: function( props ) {
66
 
67
+ var itemID = props.attributes.itemID;
68
 
69
+ /**
70
+ * Update property on submit
71
+ */
72
+ function setItemID( event ) {
73
+ var selected = event.target.querySelector( 'option:checked' );
74
+ props.setAttributes( { itemID: selected.value } );
75
+ event.preventDefault();
76
+ }
77
 
78
+ // the form children elements
79
+ var children = [];
80
 
81
+ // argument list (in array form) for the children creation
82
+ var args = [];
83
+ var ads = [];
84
+ var groups = [];
85
+ var placements = [];
86
 
87
+ args.push( 'select' );
88
+ args.push( { value: itemID, onChange: setItemID } );
89
+ args.push( el( 'option', null, advadsGutenberg.i18n['--empty--'] ) );
90
 
91
+ for ( var adID in advadsGutenberg.ads ) {
92
+ if ( 'undefined' == typeof advadsGutenberg.ads[adID].id ) continue;
93
+ ads.push( el( 'option', {value: 'ad_' + advadsGutenberg.ads[adID].id}, advadsGutenberg.ads[adID].title ) );
94
+ }
95
 
96
+ for ( var GID in advadsGutenberg.groups ) {
97
+ if ( 'undefined' == typeof advadsGutenberg.groups[GID].id ) continue;
98
+ groups.push( el( 'option', {value: 'group_' + advadsGutenberg.groups[GID]['id'] }, advadsGutenberg.groups[GID]['name'] ) );
99
 
100
+ }
101
 
102
+ if ( advadsGutenberg.placements ) {
103
+ for ( var pid in advadsGutenberg.placements ) {
104
+ if ( 'undefined' == typeof advadsGutenberg.placements[pid].id ) continue;
105
+ placements.push( el( 'option', {value: 'place_' + advadsGutenberg.placements[pid]['id']}, advadsGutenberg.placements[pid]['name'] ) );
106
+ }
107
  }
 
108
 
109
+ if ( advadsGutenberg.placements ) {
110
+ args.push( el( 'optgroup', {label: advadsGutenberg.i18n['placements']}, placements ) );
111
+ }
112
 
113
+ args.push( el( 'optgroup', {label: advadsGutenberg.i18n['adGroups']}, groups ) );
114
 
115
+ args.push( el( 'optgroup', {label: advadsGutenberg.i18n['ads']}, ads ) );
116
 
117
+ // add a <label /> first and style it.
118
+ children.push( el( 'div', {className: 'components-placeholder__label'}, advadsIconEl, el( 'label', {style: {display: 'block'}}, advadsGutenberg.i18n.advads ) ) );
119
 
120
+ if ( itemID && advadsGutenberg.i18n['--empty--'] != itemID ) {
121
 
122
+ var url = '#';
123
+ if ( 0 === itemID.indexOf( 'place_' ) ) {
124
+ url = advadsGutenberg.editLinks.placement;
125
+ } else if ( 0 === itemID.indexOf( 'group_' ) ) {
126
+ url = advadsGutenberg.editLinks.group;
127
+ } else if ( 0 === itemID.indexOf( 'ad_' ) ) {
128
+ var _adID = itemID.substr(3);
129
+ url = advadsGutenberg.editLinks.ad.replace( '%ID%', _adID );
130
+ }
131
 
132
+ children.push(
 
 
 
 
 
133
  el(
134
+ 'div',
135
+ {className: 'components-placeholder__fieldset'},
136
+ // then add the <select /> input with its own children
137
+ el.apply( null, args ),
138
+ el(
139
+ 'a',
140
+ {
141
+ class: 'dashicons dashicons-external',
142
+ style: {
143
+ margin: 5
144
+ },
145
+ href: url,
146
+ target: '_blank'
147
+ }
148
+ )
149
  )
150
+ );
151
+ } else {
152
+ children.push( el.apply( null, args ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
+ // return the complete form
155
+ return el( 'form', { className: 'components-placeholder is-large', onSubmit: setItemID }, children );
156
+
157
+ },
158
+
159
+ save: function() {
160
+ // server side rendering
161
+ return null;
162
+ },
163
+
164
+ // Transforms legacy widget to Advanced Ads block.
165
+ transforms: {
166
+ from: [{
167
+ type: 'block',
168
+ blocks: ['core/legacy-widget'],
169
+ isMatch: function ( attributes ) {
170
+ if ( ! attributes.instance || ! attributes.instance.raw ) {
171
+ // Can't transform if raw instance is not shown in REST API.
172
+ return false;
173
+ }
174
+ return attributes.idBase === 'advads_ad_widget';
175
+ },
176
+ transform: function ( attributes ) {
177
+ var instance = attributes.instance.raw;
178
+ var transformedBlock = wp.blocks.createBlock( 'advads/gblock', {
179
+ name: instance.name,
180
+ itemID: instance.item_id
181
+ } );
182
+ if ( ! instance.title ) {
183
+ return transformedBlock;
184
+ }
185
+ return [
186
+ wp.blocks.createBlock( 'core/heading', {
187
+ content: instance.title
188
+ } ),
189
+ transformedBlock
190
+ ];
191
+ }
192
+ }]
193
+ }
194
 
195
+ } );
196
 
197
+ }
198
+ })();
public/class-advanced-ads.php CHANGED
@@ -773,9 +773,15 @@ class Advanced_Ads {
773
  'show_admin_column' => true,
774
  'query_var' => false,
775
  'rewrite' => false,
 
 
 
 
 
 
776
  );
777
 
778
- return $args;
779
  }
780
 
781
  /**
773
  'show_admin_column' => true,
774
  'query_var' => false,
775
  'rewrite' => false,
776
+ 'capabilities' => array(
777
+ 'manage_terms' => 'advanced_ads_edit_ads',
778
+ 'edit_terms' => 'advanced_ads_edit_ads',
779
+ 'delete_terms' => 'advanced_ads_edit_ads',
780
+ 'assign_terms' => 'advanced_ads_edit_ads',
781
+ ),
782
  );
783
 
784
+ return apply_filters( 'advanced-ads-group-taxonomy-params', $args );
785
  }
786
 
787
  /**
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: ads, ad manager, ad rotation, adsense, banner
4
  Requires at least: 4.9
5
  Tested up to: 5.8
6
  Requires PHP: 5.6
7
- Stable tag: 1.29.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -322,305 +322,23 @@ Yes. You can use plenty of [hooks](https://wpadvancedads.com/codex/) to customiz
322
 
323
  == Changelog ==
324
 
325
- = 1.29.1 =
326
-
327
- - Fix: ensure `Advanced_Ads_Adsense_Report_Helper` JavaScript global is defined
328
- - Fix: hide AdSense setting submit button if there is no publisher ID
329
- - Fix: show error message when no AdSense account data found
330
-
331
- = 1.29.0 =
332
-
333
- - Improvement: update AdSense API to V2
334
- - Improvement: unify layout of backend notices
335
- - Improvement: move some descriptions into tooltips
336
- - Improvement: move ad blocker fix options to the related setting
337
- - Fix: correct uppercase CSS rule for labels in backend
338
- - Fix: remove usage link for every type except manual placement
339
- - Fix: correct sorting of placements by type on placement list page
340
- - Fix: bad language in Analytics Adblock Counter option
341
-
342
- = 1.28.0 =
343
-
344
- - Improvement: add an `inline` attribute to the `the_ad` shortcode that allows the user to change the wrapper from `div` to `span`
345
- - Improvement: update plugin updater class
346
- - Improvement: rename "Item" option into "Ad / Group" to clarify its purpose
347
- - Improvement: show a link to create a new ad on the placement page
348
- - Improvement: show content placements first when creating a new one
349
- - Improvement: remove welcome panel on ad edit screen
350
- - Improvement: rename last button in the wizard to "Save" to highlight that this is the last step
351
- - Fix: wrap `advanced_ads_ready_queue` in an IIEF to prevent naming collisions
352
-
353
- = 1.27.0 =
354
-
355
- - Improvement: prevent issues with functionality from other plugins that delay JavaScript execution (WP Rocket, Complianz, et al.).
356
- - Improvement: unify the layout of the Next buttons in the ad Wizard
357
- - Improvement: add the updated AdSense code. Added a filter to continue using the old AdSense code. [Learn more](https://wpadvancedads.com/adsense-crossorigin-attribute-performance)
358
- - Improvement: update Ad Block Counter to work with Google Analytics 4 properties
359
- - Fix: ensure Ad Admin can save AdSense, Privacy, and License settings
360
- - Fix: prevent error when "Remove data on uninstall" option is set due to uninitialised constants
361
- - Fix: ad edit button for ads delivered using groups
362
- - Fix: improve compatibility with PHP 8 by removing default values from required function parameters
363
-
364
- = 1.26.0 =
365
-
366
- - overwrite existing options when importing new options
367
- - add possibility to export privacy, ads.txt and Google AdSense options
368
- - remove duplicate inline styles for placements with passive cache-busting and activated TCF 2.0 privacy option
369
- - adjust the Advanced Ads block layout to the default WordPress block layout
370
- - add migration from Advanced Ads widget to Advanced Ads block
371
- - fix saving of additional CSS class in Advanced Ads block
372
- - make placement deletion confirmation dialogue translatable
373
- - add WebP as allowed image media type for exports
374
-
375
- = 1.25.1 =
376
-
377
- - fixed a bug that prevented removing placement conditions
378
- - trim `inline-css` to remove duplicate spaces
379
- - check if `inline-css` index exists in ad options to prevent undefined index notice
380
- - move `Advanced_Ads_Inline_Css` class from singleton to one instance per ad, to fix issues with `inline-css` not being added
381
- - fixed ad edit button visibility in frontend when ad label was activated
382
-
383
- = 1.25.0 =
384
-
385
- - show ad label event when ad wrapper is now shown
386
- - add filter `advanced-ads-ajax-ad-select-arguments` to modify arguments of AJAX ad selection
387
- - display ads on BuddyPress pages when no ads allowed on 404 pages
388
- - Ad blocker fix: do not copy assets from "vendor" and "lib" folders
389
- - Ad blocker fix: compare assets based on `filemtime` instead of `filesize`
390
- - bump minimal require WP core version to 4.9
391
- - allow to add a replacement for AdSense page-level code
392
-
393
- = 1.24.2 =
394
-
395
- - fix authenticated (i.e. logged-in) DOM-based XSS vulnerability while creating jQuery object from user input in Safari and IE
396
-
397
- = 1.24.1 =
398
-
399
- - fix compatibilty with WP prior to 5.0
400
-
401
- = 1.24.0 =
402
-
403
- - AdSense deprecated Link Units and might no longer fill them. So we removed them when creating new ads. [Learn more](https://wpadvancedads.com/adsense-link-units/)
404
- - enable AdSense Auto ads on AMP pages
405
- - interpret WP blocks in the plain text ad type
406
- - remove MailPoet warning since they are not retiring custom shortcodes after all
407
- - convert jQuery shorthand functions to `.on()` and `.trigger()`
408
- - made shortcode button work with WordPress 4.9
409
- - allow to exclude conditions from the "new display condition" dropdown
410
- - prevent AdSense earnings box from appearing on non AdSense ad page when AdSense connection is lost
411
-
412
- = 1.23.2 =
413
-
414
- - reverted erroneously removing plugin author index
415
-
416
- = 1.23.1 =
417
-
418
- - removed warning about iThemes Security since it is no longer causing the reported issue
419
- - added correct icon to Advanced Ads block
420
- - fixed escaping for AdSense Auto ads codes that use the deprecated "Disable Top Level" option
421
- - fixed TinyMCE warning in dev console
422
- - replaced `intval()` and `floatval()` with type-casting
423
-
424
- = 1.23.0 =
425
-
426
- - MailPoet is going to deprecate custom shortcodes. See [this section](https://wpadvancedads.com/mailpoet-newsletters/#Enable_MailPoet_support_in_Advanced_Ads) in case you are using Advanced Ads ads in your newsletters
427
- - updated Google AdSense API to use web application verification
428
- - prevent accidental public ad URLs. See [Making the Ads post type public](https://wpadvancedads.com/manual/making-the-ad-post-type-public/) if you want to query ads via a dedicated URL
429
- - allow to reserve only width or height for plain, rich content and group ad types
430
-
431
- = 1.22.2 =
432
-
433
- - fix shortcode button within Classic editor and Classic editor block
434
-
435
- = 1.22.1 =
436
-
437
- - removed "Disable shortcode button" setting after it became obsolete in 1.22.0
438
- - added the `advanced-ads-disable-shortcode-button` filter to disable the shortcode button
439
- - removed ads.txt-related warnings when the option is disabled
440
- - fixed issue with loading of shortcode button in editors that disabled custom buttons, e.g., Elementor
441
- - fixed JavaScript warnings in Elementor editor
442
-
443
- = 1.22.0 =
444
-
445
- - made dashboard layout compatible with WordPress 5.6
446
- - removed irrelevant AdSense warnings
447
- - allow filtering of data-attributes for encoded ads if privacy module is enabled
448
- - added `advanced-ads-ad-edit-show-placement-injection` filter to allow removing the placement-injection box on the ad edit screen
449
- - added `advanced-ads-unhide-meta-boxes` filter to allow adding of meta box ids that should always be visible on ad edit pages
450
- - added `advanced-ads-ad-option-{$field}` filter for ad options
451
- - 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}`
452
- - removed public URLs for single ads on some installations
453
- - fixed old icon in the menu
454
- - fixed Internet Explorer 11 incompatibility
455
- - fixed possible error in TinyMCE editor caused by ad blockers
456
-
457
- = 1.21.1 =
458
-
459
- - fixed pagination on the ad list page
460
- - fix Google AdSense non-personalized ads
461
-
462
- = 1.21.0 =
463
-
464
- - enable Position options for Sidebar placements
465
- - increased default weight for ads imported to a group from 1 to 5 which is mostly relevant when selling ads to existing placements
466
- - Ad Health: added body classes that explain plugin behavior at given moment
467
- - ads.txt: prevented converting special characters into HTML entities
468
- - show ad overview list even if all ads were moved to trash
469
- - fixed error when specific ACF function does not exist
470
- - fixed option to disable ads also on the "Posts page" as set in the WordPress Reading settings
471
-
472
- = 1.20.3 =
473
-
474
- - whitelist field groups created by Advanced Custom Fields on the ad edit page
475
- - prevent including AdSense Auto ads code when the Borlabs Cookie is already adding it
476
- - prevented adding unneeded escape characters to ads.txt file
477
- - added compatibility with Funding Choices when consent is not needed
478
-
479
- = 1.20.2 =
480
-
481
- - fixed displaying image ads if privacy method is set to custom cookie
482
- - fixed scroll to last edited placement with non-English letters
483
- - fixed minor UI issues
484
-
485
- = 1.20.1 =
486
-
487
- - don't escape top anchor ads code as a whole, user input has already been escaped
488
-
489
- = 1.20.0 =
490
-
491
- - integrate with TCF 2.0 compatible consent management platforms, e.g., Quantcast Choices
492
- - improve timezone methods `Advanced_Ads_Utils::get_wp_timezone()` and `Advanced_Ads_Utils::get_timezone_name()`
493
- - Divi theme: made content injection work with the "Unlimited ad injection" setting disabled
494
- - added missing spaces to image ad tags to fix Cache-Busting issue
495
- - made ad centering work when right and left margin are set
496
- - add ad health check if __tcfapi responds but the privacy module is either not enabled or not set to TCF 2.0
497
- - remove duplicate lines from the ads.txt file
498
- - fixed layout issues that happens due to the JNews theme
499
-
500
- = 1.19.1 =
501
-
502
- - apply WordPress lazy loading for images to images in ad content
503
- - layout fixes for WordPress 5.5
504
-
505
- = 1.19.0 =
506
-
507
- - placements are now ordered by type on the Placements page. You can still choose ordering by name
508
- - the "custom" option of the Content placement now comes with a picker to select the position in the frontend
509
- - WPML: placements pages show ads according to the selected language
510
- - WPML: display the ad in the original language if a translated ad is missing unless the publisher chooses to hide it instead
511
- - prevented injection of ads into captions of "image" blocks
512
- - improved bot check
513
- - fixed layout of expiry data fields
514
- - fixed broken check for the Responsive add-on
515
-
516
- = 1.18.0 =
517
-
518
- * inject ads automatically based on div, table, quotes, iframe, and other HTML tags
519
- * define your own injection rules using the new "custom" option for the Content placement
520
- * hide Shortcode button in TinyMCE editor by default for new users
521
- * added `advanced-ads-options` filter for main plugin options
522
- * prevent automatic ad injection into paragraphs within blockquotes
523
- * hide placement options after publishing an ad translated with WPML
524
- * disallowed ad insertion into the header of the WP File Manager's admin page
525
-
526
- = 1.17.12 =
527
-
528
- * set default name for ads where none was given
529
- * fixed issue where long option markup could break the group page
530
- * made placements of type other than "Header Code" work with "Thrive Theme Builder" theme
531
-
532
- = 1.17.11 =
533
-
534
- * added Datanyze and Ecosia to bots list
535
- * linked to [Google Ad Manager Integration](https://wpadvancedads.com/add-ons/google-ad-manager/)
536
- * fixed Layout Key field for AdSense ads not saving new values
537
- * fixed error that broke the wizard when the URL field of image ads contained a wrong value
538
- * fixed links to manuals
539
- * fixed unneeded notification shown when ads are disabled on 404 pages
540
-
541
- = 1.17.10 =
542
-
543
- * fixed escaped HTML tag in Ad Planning column
544
- * fixed possible JavaScript error caused by Ad Health checks
545
- * fixed possible third-party conflict causing the ad group filter to throw an exception
546
- * removed unneeded notification shown when ads are disabled on 404 pages
547
-
548
- = 1.17.9 =
549
-
550
- * fixed warning about missing `the_content` filter in WordPress 5.4
551
- * fixed public warning if the WordPres `widget` function is called with wrong parameters
552
- * fixed wrong usage of get_current_user
553
-
554
- = 1.17.8 =
555
-
556
- * WPML: placements now deliver also ads translated with WPML when only one of the language versions was assigned to them
557
- * fixed delete option in placement form
558
-
559
- = 1.17.7 =
560
-
561
- * fixed index value of content placements not showing up in the form while saved and working correctly
562
- * recovered compatibility with the "Render Blocking JS" option of the WP Fastest Cache plugin
563
-
564
- = 1.17.6 =
565
-
566
- * improved coding style in backend templates
567
- * prepared for option to allow minimum number of words between ads in Advanced Ads Pro
568
- * hide notice that warns if the "Disable ads in REST API" option was selected
569
- * Renad theme: fixed a bug that caused menu item to point to incorrect url instead of theme options
570
-
571
- = 1.17.5 =
572
-
573
- * fixed ads being injected multiple times when using the Newspaper theme or multiple the_content filters
574
-
575
- = 1.17.4 =
576
-
577
- * added option and Display Condition to disable ads in content served through the REST API
578
- * made error notices less obstrusive
579
- * code style optimizations
580
- * fixed ad groups form on ad edit page
581
- * fixed potential conflict with autoloader
582
-
583
- = 1.17.3 =
584
-
585
- * prevented content injection into specific elements where ads cause issues
586
- * assign `advads-stop-injection` class to any element into which you don’t want to automatically inject ads
587
- * fixed possible cURL error when checking existing ads.txt file locally
588
-
589
- = 1.17.2 =
590
-
591
- * replaced autoloader
592
- * fixed an issue where an expired ad removed HTML in the ad code
593
-
594
- = 1.17.1 =
595
-
596
- * fixed failing upload of new image ads
597
- * fixed Google Ad Manager debug link also showing up when other Google Publisher Tags are used
598
-
599
- = 1.17 =
600
-
601
- * improved AdSense ad unit list coming from the AdSense API
602
- * improved "highlight ads" option in Ad Health
603
- * show notice if AJAX calls are broken
604
- * added `com.pl` as exception for placing ads.txt files in subdomains
605
- * removed placeholder for AdSense ads in the Customizer and Elementor editor
606
- * fix for WP Smush lazy load preventing image ads from showing at all
607
-
608
- = 1.16.1 =
609
-
610
- * fixed JavaScript that broke privacy module check in the frontend
611
- * allow to change size of AdSense ads loaded from the AdSense account
612
-
613
- = 1.16 =
614
-
615
- * moved all users to the new content injection logic and removed opt-out option
616
- * use new Auto ads code for everyone who didn’t enable the "Disable top anchor ads" option
617
- * hide "Disable top anchor ads" option to users who didn’t enable it
618
- * the Ad Admin user role can now also save the plugin settings
619
- * hide Wizard for existing ads
620
- * removed warning about WP Autoterms plugin after a fix by the plugin authors
621
- * some work for Conditions to improve compatibility with an upcoming Pro feature
622
- * fixed multiple wrappers occurred as result of using nested ads
623
- * fixed missing index issue on 404 pages for logged-in admins
624
- * fixed AJAX/PHP error 403 on Settings page
625
- * fixed layout issue that happened when "If>So Dynamic Content" plugin was active
626
- * prevented Ad label from taking height of fixed sized AdSense ads
4
  Requires at least: 4.9
5
  Tested up to: 5.8
6
  Requires PHP: 5.6
7
+ Stable tag: 1.30.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
322
 
323
  == Changelog ==
324
 
325
+ = 1.30.0 =
326
+
327
+ - Improvement: add `advanced-ads-group-taxonomy-params` filter to change ad group taxonomy parameters
328
+ - Improvement: add "Manual Placements" to the Advanced Ads block and sidebar widget
329
+ - Improvement: update Black Friday promotion
330
+ - Fix: enable `Ad Admin` and `Ad Manager` to assign ads to groups from ad edit page and quick edit view
331
+ - Fix: disable unavailable ad types on the ad edit page
332
+ - Fix: improve AdSense auto ads code warning on ad edit page
333
+ - Fix: handle AdSense report API response for accounts without earnings
334
+ - Fix: remove `amp-auto-ads` element on non-AMP URLs
335
+ - Fix: honor disabling ads settings for AMP pages
336
+ - Fix: escape placement selectors for jQuery to allow adding conditions to multibyte placement names
337
+ - Fix: ensure correct text domain for translations
338
+ - Fix: make the ad list sortable in descending order
339
+ - Fix: remove hard-coded `orderby` and `order` for posts list
340
+ - Fix: prevent updating ad weights of non-published ads
341
+ - Fix: correct Display Conditions meta box video player
342
+ - Fix: remove escaped HTML tags in new placement form
343
+ - Fix: resolve a conflict with WPML where conditions were not displayed correctly on the placement page
344
+ - Fix: move placement of the ad blocker disguise settings