Version Description
- extended feed cache to 48 hours
- updated EDD add-on updater class
- display possible injection errors only, when WP_DEBUG is enabled
- fixed content injection when duplicate ids are found in content
- fixed JavaScript conflict that prevented Display Conditions from working
Download this release
Release Info
Developer | webzunft |
Plugin | Advanced Ads |
Version | 1.7.4.5 |
Comparing to | |
See all releases |
Code changes from version 1.7.4.4 to 1.7.4.5
- admin/assets/js/admin.js +24 -5
- admin/class-advanced-ads-admin.php +19 -4
- admin/views/ad-display-metabox.php +7 -3
- admin/views/ad-parameters-metabox.php +2 -1
- admin/views/ad-visitor-metabox.php +3 -1
- advanced-ads.php +2 -2
- classes/EDD_SL_Plugin_Updater.php +70 -29
- classes/ad_placements.php +6 -6
- classes/display-conditions.php +4 -4
- readme.txt +10 -2
admin/assets/js/admin.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
jQuery( document ).ready(function ($) {
|
2 |
-
if ( ! $.fn.
|
3 |
$( '.advads-jqueryui-error').show();
|
4 |
}
|
5 |
|
@@ -74,7 +74,7 @@ jQuery( document ).ready(function ($) {
|
|
74 |
});
|
75 |
|
76 |
// activate general buttons
|
77 |
-
if (
|
78 |
$( '.advads-buttonset' ).buttonset();
|
79 |
}
|
80 |
// activate accordions
|
@@ -164,7 +164,7 @@ jQuery( document ).ready(function ($) {
|
|
164 |
// is also called on every click
|
165 |
function advads_display_condition_option_not_selected(){
|
166 |
$( '.advads-conditions-not-selected' ).each(function(){
|
167 |
-
if( $( this ).siblings('
|
168 |
$( this ).hide();
|
169 |
} else {
|
170 |
$( this ).show();
|
@@ -173,12 +173,12 @@ jQuery( document ).ready(function ($) {
|
|
173 |
}
|
174 |
advads_display_condition_option_not_selected();
|
175 |
// update error messages when an item is clicked
|
176 |
-
$( document ).on( 'click', '.advads-conditions-terms-buttons
|
177 |
// needs a slight delay until the buttons are updated
|
178 |
window.setTimeout( advads_display_condition_option_not_selected, 200 );
|
179 |
});
|
180 |
// activate and toggle conditions connector option
|
181 |
-
$('.advads-conditions-connector input').
|
182 |
// dynamically change label
|
183 |
$(document).on('click', '.advads-conditions-connector input', function(){
|
184 |
if( $( this ).is(':checked' ) ){
|
@@ -721,3 +721,22 @@ function advads_ad_list_build_filters() {
|
|
721 |
.filter( ':even' ).addClass( 'advads-ad-list-even' ).removeClass( 'advads-ad-list-odd' );
|
722 |
});
|
723 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
jQuery( document ).ready(function ($) {
|
2 |
+
if ( ! $.fn.accordion || ! $.fn.tooltip || ! advads_use_ui_buttonset() ) {
|
3 |
$( '.advads-jqueryui-error').show();
|
4 |
}
|
5 |
|
74 |
});
|
75 |
|
76 |
// activate general buttons
|
77 |
+
if ( advads_use_ui_buttonset() ) {
|
78 |
$( '.advads-buttonset' ).buttonset();
|
79 |
}
|
80 |
// activate accordions
|
164 |
// is also called on every click
|
165 |
function advads_display_condition_option_not_selected(){
|
166 |
$( '.advads-conditions-not-selected' ).each(function(){
|
167 |
+
if( $( this ).siblings('input:checked').length ){
|
168 |
$( this ).hide();
|
169 |
} else {
|
170 |
$( this ).show();
|
173 |
}
|
174 |
advads_display_condition_option_not_selected();
|
175 |
// update error messages when an item is clicked
|
176 |
+
$( document ).on( 'click', '.advads-conditions-terms-buttons input[type="checkbox"], .advads-conditions-single input[type="checkbox"]', function(){
|
177 |
// needs a slight delay until the buttons are updated
|
178 |
window.setTimeout( advads_display_condition_option_not_selected, 200 );
|
179 |
});
|
180 |
// activate and toggle conditions connector option
|
181 |
+
$('.advads-conditions-connector input').advads_button();
|
182 |
// dynamically change label
|
183 |
$(document).on('click', '.advads-conditions-connector input', function(){
|
184 |
if( $( this ).is(':checked' ) ){
|
721 |
.filter( ':even' ).addClass( 'advads-ad-list-even' ).removeClass( 'advads-ad-list-odd' );
|
722 |
});
|
723 |
}
|
724 |
+
|
725 |
+
// Change JQueryUI names to fix name collision with other libraries, eg. Bootstrap
|
726 |
+
jQuery.fn.advads_button = jQuery.fn.button;
|
727 |
+
|
728 |
+
/**
|
729 |
+
* check if jQueryUI button/buttonset can be used
|
730 |
+
*/
|
731 |
+
var advads_use_ui_buttonset = ( function() {
|
732 |
+
var ret = null;
|
733 |
+
return function () {
|
734 |
+
if ( null === ret ) {
|
735 |
+
var needle = 'var g="string"==typeof f,h=c.call(arguments,1)'; //string from jquery-ui source code
|
736 |
+
ret = jQuery.fn.advads_button && jQuery.fn.buttonset && jQuery.fn.button.toString().indexOf( needle ) !== -1;
|
737 |
+
}
|
738 |
+
return ret;
|
739 |
+
};
|
740 |
+
})();
|
741 |
+
|
742 |
+
|
admin/class-advanced-ads-admin.php
CHANGED
@@ -208,7 +208,7 @@ class Advanced_Ads_Admin {
|
|
208 |
wp_enqueue_script( $this->plugin_slug . '-admin-global-script', plugins_url( 'assets/js/admin-global.js', __FILE__ ), array('jquery'), ADVADS_VERSION );
|
209 |
|
210 |
if( self::screen_belongs_to_advanced_ads() ){
|
211 |
-
wp_register_script( $this->plugin_slug . '-admin-script', plugins_url( 'assets/js/admin.js', __FILE__ ), array('jquery', 'jquery-ui-autocomplete'), ADVADS_VERSION );
|
212 |
wp_register_script( $this->plugin_slug . '-wizard-script', plugins_url( 'assets/js/wizard.js', __FILE__ ), array('jquery'), ADVADS_VERSION );
|
213 |
|
214 |
// jquery ui
|
@@ -1747,6 +1747,10 @@ class Advanced_Ads_Admin {
|
|
1747 |
// rss feed
|
1748 |
// $this->dashboard_widget_function_output('advads_dashboard_widget', $feed);
|
1749 |
self::dashboard_cached_rss_widget( 'advads_dashboard_widget', array('Advanced_Ads_Admin', 'dashboard_widget_function_output'), array('advads' => $feeds) );
|
|
|
|
|
|
|
|
|
1750 |
}
|
1751 |
|
1752 |
/**
|
@@ -1772,7 +1776,7 @@ class Advanced_Ads_Admin {
|
|
1772 |
if ( $callback && is_callable( $callback ) ) {
|
1773 |
ob_start();
|
1774 |
call_user_func_array( $callback, $feeds );
|
1775 |
-
set_transient( $cache_key, ob_get_flush(),
|
1776 |
}
|
1777 |
|
1778 |
return true;
|
@@ -1896,6 +1900,8 @@ class Advanced_Ads_Admin {
|
|
1896 |
if ( $body ){
|
1897 |
return $body;
|
1898 |
} else {
|
|
|
|
|
1899 |
return __( 'License couldn’t be activated. Please try again later.', 'advanced-ads' );
|
1900 |
}
|
1901 |
}
|
@@ -2134,6 +2140,16 @@ class Advanced_Ads_Admin {
|
|
2134 |
if( $add_ons === array() ) {
|
2135 |
return;
|
2136 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2137 |
|
2138 |
foreach( $add_ons as $_add_on_key => $_add_on ){
|
2139 |
|
@@ -2151,8 +2167,7 @@ class Advanced_Ads_Admin {
|
|
2151 |
continue;
|
2152 |
}
|
2153 |
|
2154 |
-
// retrieve our license key
|
2155 |
-
$licenses = get_option(ADVADS_SLUG . '-licenses', array());
|
2156 |
$license_key = isset($licenses[$_add_on_key]) ? $licenses[$_add_on_key] : '';
|
2157 |
|
2158 |
// setup the updater
|
208 |
wp_enqueue_script( $this->plugin_slug . '-admin-global-script', plugins_url( 'assets/js/admin-global.js', __FILE__ ), array('jquery'), ADVADS_VERSION );
|
209 |
|
210 |
if( self::screen_belongs_to_advanced_ads() ){
|
211 |
+
wp_register_script( $this->plugin_slug . '-admin-script', plugins_url( 'assets/js/admin.js', __FILE__ ), array( 'jquery', 'jquery-ui-autocomplete' , 'jquery-ui-button' ), ADVADS_VERSION );
|
212 |
wp_register_script( $this->plugin_slug . '-wizard-script', plugins_url( 'assets/js/wizard.js', __FILE__ ), array('jquery'), ADVADS_VERSION );
|
213 |
|
214 |
// jquery ui
|
1747 |
// rss feed
|
1748 |
// $this->dashboard_widget_function_output('advads_dashboard_widget', $feed);
|
1749 |
self::dashboard_cached_rss_widget( 'advads_dashboard_widget', array('Advanced_Ads_Admin', 'dashboard_widget_function_output'), array('advads' => $feeds) );
|
1750 |
+
|
1751 |
+
// add markup for utm variables
|
1752 |
+
// todo: move to js file
|
1753 |
+
?><script>jQuery('#advads_dashboard_widget .rss-widget a').each(function(){ this.href = this.href + '#utm_source=advanced-ads&utm_medium=rss-link&utm_campaign=dashboard'; })</script><?php
|
1754 |
}
|
1755 |
|
1756 |
/**
|
1776 |
if ( $callback && is_callable( $callback ) ) {
|
1777 |
ob_start();
|
1778 |
call_user_func_array( $callback, $feeds );
|
1779 |
+
set_transient( $cache_key, ob_get_flush(), 48 * HOUR_IN_SECONDS ); // Default lifetime in cache of 48 hours
|
1780 |
}
|
1781 |
|
1782 |
return true;
|
1900 |
if ( $body ){
|
1901 |
return $body;
|
1902 |
} else {
|
1903 |
+
error_log(print_r($response, true));
|
1904 |
+
// return print_r($response, true);
|
1905 |
return __( 'License couldn’t be activated. Please try again later.', 'advanced-ads' );
|
1906 |
}
|
1907 |
}
|
2140 |
if( $add_ons === array() ) {
|
2141 |
return;
|
2142 |
}
|
2143 |
+
|
2144 |
+
// check only every hour for updates to decrease load on store
|
2145 |
+
// ignore, if force-update was set
|
2146 |
+
if( ! isset( $_GET['force-check'] ) && get_transient( ADVADS_SLUG . '_add-on-updates-checked' ) ){
|
2147 |
+
return;
|
2148 |
+
}
|
2149 |
+
set_transient( ADVADS_SLUG . '_add-on-updates-checked', true, 3600 );
|
2150 |
+
|
2151 |
+
// load license keys
|
2152 |
+
$licenses = get_option(ADVADS_SLUG . '-licenses', array());
|
2153 |
|
2154 |
foreach( $add_ons as $_add_on_key => $_add_on ){
|
2155 |
|
2167 |
continue;
|
2168 |
}
|
2169 |
|
2170 |
+
// retrieve our license key
|
|
|
2171 |
$license_key = isset($licenses[$_add_on_key]) ? $licenses[$_add_on_key] : '';
|
2172 |
|
2173 |
// setup the updater
|
admin/views/ad-display-metabox.php
CHANGED
@@ -100,11 +100,15 @@ endif;
|
|
100 |
success: function (r, textStatus, XMLHttpRequest) {
|
101 |
// add
|
102 |
if (r) {
|
103 |
-
var connector = '<input type="checkbox" name="<?php echo Advanced_Ads_Display_Conditions::FORM_NAME; ?>[' + display_condition_index + '][connector]" checked="checked" value="or" id="advads-conditions-'+ display_condition_index +'-connector"><label for="advads-conditions-'+ display_condition_index +'-connector"><?php _e( 'or', 'advanced-ads' ); ?></label>';
|
104 |
var newline = '<tr><td class="advads-conditions-connector">'+connector+'</td><td class="advads-conditions-type" data-condition-type="'+ display_condition_type +'">' + display_condition_title + '</td><td>' + r + '</td><td><button type="button" class="advads-display-conditions-remove button">x</button></td></tr>';
|
105 |
$('#advads-display-conditions table tbody').append(newline);
|
106 |
-
|
107 |
-
|
|
|
|
|
|
|
|
|
108 |
// increase count
|
109 |
display_condition_index++;
|
110 |
$('#advads-display-conditions-index').val(display_condition_index);
|
100 |
success: function (r, textStatus, XMLHttpRequest) {
|
101 |
// add
|
102 |
if (r) {
|
103 |
+
var connector = '<input style="display:none;" type="checkbox" name="<?php echo Advanced_Ads_Display_Conditions::FORM_NAME; ?>[' + display_condition_index + '][connector]" checked="checked" value="or" id="advads-conditions-'+ display_condition_index +'-connector"><label for="advads-conditions-'+ display_condition_index +'-connector"><?php _e( 'or', 'advanced-ads' ); ?></label>';
|
104 |
var newline = '<tr><td class="advads-conditions-connector">'+connector+'</td><td class="advads-conditions-type" data-condition-type="'+ display_condition_type +'">' + display_condition_title + '</td><td>' + r + '</td><td><button type="button" class="advads-display-conditions-remove button">x</button></td></tr>';
|
105 |
$('#advads-display-conditions table tbody').append(newline);
|
106 |
+
if ( advads_use_ui_buttonset() ) {
|
107 |
+
$('#advads-display-conditions table tbody .advads-conditions-single.advads-buttonset').buttonset();
|
108 |
+
}
|
109 |
+
if ( jQuery.fn.advads_button ) {
|
110 |
+
$('#advads-display-conditions table tbody .advads-conditions-connector input').advads_button();
|
111 |
+
}
|
112 |
// increase count
|
113 |
display_condition_index++;
|
114 |
$('#advads-display-conditions-index').val(display_condition_index);
|
admin/views/ad-parameters-metabox.php
CHANGED
@@ -24,7 +24,8 @@ do_action( 'advanced-ads-ad-params-before', $ad, $types ); ?>
|
|
24 |
include ADVADS_BASE_PATH . 'admin/views/ad-parameters-size.php'; ?>
|
25 |
|
26 |
<?php
|
27 |
-
if (
|
|
|
28 |
<p class="advads-error-message">
|
29 |
<?php _e( 'The code of this ad might not work properly with the <em>Content</em> placement.', 'advanced-ads' );
|
30 |
?> <?php printf(__( 'Reach out to <a href="%s">support</a> to get help.', 'advanced-ads' ), admin_url('admin.php?page=advanced-ads-support') );
|
24 |
include ADVADS_BASE_PATH . 'admin/views/ad-parameters-size.php'; ?>
|
25 |
|
26 |
<?php
|
27 |
+
if ( defined ( 'WP_DEBUG' ) && WP_DEBUG &&
|
28 |
+
( $error = Advanced_Ads_Admin::get_instance()->check_ad_dom_is_not_valid( $ad ) ) ) : ?>
|
29 |
<p class="advads-error-message">
|
30 |
<?php _e( 'The code of this ad might not work properly with the <em>Content</em> placement.', 'advanced-ads' );
|
31 |
?> <?php printf(__( 'Reach out to <a href="%s">support</a> to get help.', 'advanced-ads' ), admin_url('admin.php?page=advanced-ads-support') );
|
admin/views/ad-visitor-metabox.php
CHANGED
@@ -68,7 +68,9 @@ jQuery( document ).ready(function ($) {
|
|
68 |
var connector = '<input type="checkbox" name="<?php echo Advanced_Ads_Visitor_Conditions::FORM_NAME; ?>[' + visitor_condition_index + '][connector]" value="or" id="advads-visitor-conditions-'+ visitor_condition_index +'-connector"><label for="advads-visitor-conditions-'+ visitor_condition_index +'-connector"><?php _e( 'and', 'advanced-ads' ); ?></label>';
|
69 |
var newline = '<tr><td class="advads-conditions-connector">'+connector+'</td><td>' + visitor_condition_title + '</td><td>' + r + '</td><td><button type="button" class="advads-visitor-conditions-remove button">x</button></td></tr>';
|
70 |
$( '#advads-visitor-conditions table tbody' ).append( newline );
|
71 |
-
|
|
|
|
|
72 |
// increase count
|
73 |
visitor_condition_index++;
|
74 |
$('#advads-visitor-conditions-index').val( visitor_condition_index );
|
68 |
var connector = '<input type="checkbox" name="<?php echo Advanced_Ads_Visitor_Conditions::FORM_NAME; ?>[' + visitor_condition_index + '][connector]" value="or" id="advads-visitor-conditions-'+ visitor_condition_index +'-connector"><label for="advads-visitor-conditions-'+ visitor_condition_index +'-connector"><?php _e( 'and', 'advanced-ads' ); ?></label>';
|
69 |
var newline = '<tr><td class="advads-conditions-connector">'+connector+'</td><td>' + visitor_condition_title + '</td><td>' + r + '</td><td><button type="button" class="advads-visitor-conditions-remove button">x</button></td></tr>';
|
70 |
$( '#advads-visitor-conditions table tbody' ).append( newline );
|
71 |
+
if ( jQuery.fn.advads_button ) {
|
72 |
+
$('#advads-visitor-conditions table tbody .advads-conditions-connector input').advads_button();
|
73 |
+
}
|
74 |
// increase count
|
75 |
visitor_condition_index++;
|
76 |
$('#advads-visitor-conditions-index').val( visitor_condition_index );
|
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.7.4.
|
16 |
* Author: Thomas Maier
|
17 |
* Author URI: http://webgilde.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, textdomain
|
40 |
define( 'ADVADS_SLUG', 'advanced-ads' );
|
41 |
define( 'ADVADS_URL', 'https://wpadvancedads.com/' );
|
42 |
-
define( 'ADVADS_VERSION', '1.7.4.
|
43 |
|
44 |
/*----------------------------------------------------------------------------*
|
45 |
* Autoloading, modules and functions
|
12 |
* Plugin Name: Advanced Ads
|
13 |
* Plugin URI: https://wpadvancedads.com
|
14 |
* Description: Manage and optimize your ads in WordPress
|
15 |
+
* Version: 1.7.4.5
|
16 |
* Author: Thomas Maier
|
17 |
* Author URI: http://webgilde.com
|
18 |
* Text Domain: advanced-ads
|
39 |
// general and global slug, e.g. to store options in WP, textdomain
|
40 |
define( 'ADVADS_SLUG', 'advanced-ads' );
|
41 |
define( 'ADVADS_URL', 'https://wpadvancedads.com/' );
|
42 |
+
define( 'ADVADS_VERSION', '1.7.4.5' );
|
43 |
|
44 |
/*----------------------------------------------------------------------------*
|
45 |
* Autoloading, modules and functions
|
classes/EDD_SL_Plugin_Updater.php
CHANGED
@@ -3,17 +3,21 @@
|
|
3 |
// uncomment this line for testing
|
4 |
//set_site_transient( 'update_plugins', null );
|
5 |
|
|
|
|
|
|
|
6 |
/**
|
7 |
* Allows plugins to use their own update API.
|
8 |
*
|
9 |
* @author Pippin Williamson
|
10 |
-
* @version 1.6
|
11 |
*/
|
12 |
class EDD_SL_Plugin_Updater {
|
13 |
private $api_url = '';
|
14 |
private $api_data = array();
|
15 |
private $name = '';
|
16 |
private $slug = '';
|
|
|
17 |
|
18 |
/**
|
19 |
* Class constructor.
|
@@ -24,18 +28,22 @@ class EDD_SL_Plugin_Updater {
|
|
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 |
-
* @return void
|
28 |
*/
|
29 |
-
function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
|
|
|
|
|
|
|
30 |
$this->api_url = trailingslashit( $_api_url );
|
31 |
$this->api_data = $_api_data;
|
32 |
$this->name = plugin_basename( $_plugin_file );
|
33 |
$this->slug = basename( $_plugin_file, '.php' );
|
34 |
$this->version = $_api_data['version'];
|
35 |
|
|
|
|
|
36 |
// Set up hooks.
|
37 |
$this->init();
|
38 |
-
|
39 |
}
|
40 |
|
41 |
/**
|
@@ -49,8 +57,10 @@ class EDD_SL_Plugin_Updater {
|
|
49 |
|
50 |
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
|
51 |
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
|
52 |
-
|
53 |
add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
|
|
|
|
|
54 |
}
|
55 |
|
56 |
/**
|
@@ -66,7 +76,7 @@ class EDD_SL_Plugin_Updater {
|
|
66 |
* @param array $_transient_data Update array build by WordPress.
|
67 |
* @return array Modified update array with custom plugin data.
|
68 |
*/
|
69 |
-
function check_update( $_transient_data ) {
|
70 |
|
71 |
global $pagenow;
|
72 |
|
@@ -84,8 +94,6 @@ class EDD_SL_Plugin_Updater {
|
|
84 |
|
85 |
if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
|
86 |
|
87 |
-
$this->did_check = true;
|
88 |
-
|
89 |
if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
|
90 |
|
91 |
$_transient_data->response[ $this->name ] = $version_info;
|
@@ -126,10 +134,12 @@ class EDD_SL_Plugin_Updater {
|
|
126 |
remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
|
127 |
|
128 |
$update_cache = get_site_transient( 'update_plugins' );
|
|
|
|
|
129 |
|
130 |
-
if (
|
131 |
|
132 |
-
$cache_key = md5( 'edd_plugin_' .sanitize_key( $this->name ) . '_version_info' );
|
133 |
$version_info = get_transient( $cache_key );
|
134 |
|
135 |
if( false === $version_info ) {
|
@@ -139,7 +149,6 @@ class EDD_SL_Plugin_Updater {
|
|
139 |
set_transient( $cache_key, $version_info, 3600 );
|
140 |
}
|
141 |
|
142 |
-
|
143 |
if( ! is_object( $version_info ) ) {
|
144 |
return;
|
145 |
}
|
@@ -174,21 +183,26 @@ class EDD_SL_Plugin_Updater {
|
|
174 |
|
175 |
if ( empty( $version_info->download_link ) ) {
|
176 |
printf(
|
177 |
-
__( 'There is a new version of %1$s available.
|
178 |
esc_html( $version_info->name ),
|
179 |
-
esc_url( $changelog_link ),
|
180 |
-
esc_html( $version_info->new_version )
|
|
|
181 |
);
|
182 |
} else {
|
183 |
printf(
|
184 |
-
__( 'There is a new version of %1$s available.
|
185 |
esc_html( $version_info->name ),
|
186 |
-
esc_url( $changelog_link ),
|
187 |
esc_html( $version_info->new_version ),
|
188 |
-
|
|
|
|
|
189 |
);
|
190 |
}
|
191 |
|
|
|
|
|
192 |
echo '</div></td></tr>';
|
193 |
}
|
194 |
}
|
@@ -204,7 +218,7 @@ class EDD_SL_Plugin_Updater {
|
|
204 |
* @param object $_args
|
205 |
* @return object $_data
|
206 |
*/
|
207 |
-
function plugins_api_filter( $_data, $_action = '', $_args = null ) {
|
208 |
|
209 |
|
210 |
if ( $_action != 'plugin_information' ) {
|
@@ -245,7 +259,7 @@ class EDD_SL_Plugin_Updater {
|
|
245 |
* @param string $url
|
246 |
* @return object $array
|
247 |
*/
|
248 |
-
function http_request_args( $args, $url ) {
|
249 |
// If it is an https request and we are performing a package download, disable ssl verification
|
250 |
if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
|
251 |
$args['sslverify'] = false;
|
@@ -262,7 +276,7 @@ class EDD_SL_Plugin_Updater {
|
|
262 |
*
|
263 |
* @param string $_action The requested action.
|
264 |
* @param array $_data Parameters for the API action.
|
265 |
-
* @return false
|
266 |
*/
|
267 |
private function api_request( $_action, $_data ) {
|
268 |
|
@@ -270,11 +284,9 @@ class EDD_SL_Plugin_Updater {
|
|
270 |
|
271 |
$data = array_merge( $this->api_data, $_data );
|
272 |
|
273 |
-
if ( $data['slug'] != $this->slug )
|
274 |
-
return;
|
275 |
-
|
276 |
-
if ( empty( $data['license'] ) )
|
277 |
return;
|
|
|
278 |
|
279 |
if( $this->api_url == home_url() ) {
|
280 |
return false; // Don't allow a plugin to ping itself
|
@@ -282,7 +294,7 @@ class EDD_SL_Plugin_Updater {
|
|
282 |
|
283 |
$api_params = array(
|
284 |
'edd_action' => 'get_version',
|
285 |
-
'license' => $data['license'],
|
286 |
'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
|
287 |
'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
|
288 |
'slug' => $data['slug'],
|
@@ -307,6 +319,7 @@ class EDD_SL_Plugin_Updater {
|
|
307 |
|
308 |
public function show_changelog() {
|
309 |
|
|
|
310 |
|
311 |
if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
|
312 |
return;
|
@@ -321,15 +334,43 @@ class EDD_SL_Plugin_Updater {
|
|
321 |
}
|
322 |
|
323 |
if( ! current_user_can( 'update_plugins' ) ) {
|
324 |
-
wp_die( __( 'You do not have permission to install plugin updates', '
|
325 |
}
|
326 |
|
327 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
|
329 |
-
if( $response && isset( $response->sections['changelog'] ) ) {
|
330 |
-
echo '<div style="background:#fff;padding:10px;">' . $response->sections['changelog'] . '</div>';
|
331 |
}
|
332 |
|
|
|
|
|
|
|
333 |
|
334 |
exit;
|
335 |
}
|
3 |
// uncomment this line for testing
|
4 |
//set_site_transient( 'update_plugins', null );
|
5 |
|
6 |
+
// Exit if accessed directly
|
7 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
8 |
+
|
9 |
/**
|
10 |
* Allows plugins to use their own update API.
|
11 |
*
|
12 |
* @author Pippin Williamson
|
13 |
+
* @version 1.6.3
|
14 |
*/
|
15 |
class EDD_SL_Plugin_Updater {
|
16 |
private $api_url = '';
|
17 |
private $api_data = array();
|
18 |
private $name = '';
|
19 |
private $slug = '';
|
20 |
+
private $version = '';
|
21 |
|
22 |
/**
|
23 |
* Class constructor.
|
28 |
* @param string $_api_url The URL pointing to the custom API endpoint.
|
29 |
* @param string $_plugin_file Path to the plugin file.
|
30 |
* @param array $_api_data Optional data to send with API calls.
|
|
|
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->name = plugin_basename( $_plugin_file );
|
39 |
$this->slug = basename( $_plugin_file, '.php' );
|
40 |
$this->version = $_api_data['version'];
|
41 |
|
42 |
+
$edd_plugin_data[ $this->slug ] = $this->api_data;
|
43 |
+
|
44 |
// Set up hooks.
|
45 |
$this->init();
|
46 |
+
|
47 |
}
|
48 |
|
49 |
/**
|
57 |
|
58 |
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
|
59 |
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
|
60 |
+
remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10, 2 );
|
61 |
add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
|
62 |
+
add_action( 'admin_init', array( $this, 'show_changelog' ) );
|
63 |
+
|
64 |
}
|
65 |
|
66 |
/**
|
76 |
* @param array $_transient_data Update array build by WordPress.
|
77 |
* @return array Modified update array with custom plugin data.
|
78 |
*/
|
79 |
+
public function check_update( $_transient_data ) {
|
80 |
|
81 |
global $pagenow;
|
82 |
|
94 |
|
95 |
if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
|
96 |
|
|
|
|
|
97 |
if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
|
98 |
|
99 |
$_transient_data->response[ $this->name ] = $version_info;
|
134 |
remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
|
135 |
|
136 |
$update_cache = get_site_transient( 'update_plugins' );
|
137 |
+
|
138 |
+
$update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();
|
139 |
|
140 |
+
if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
|
141 |
|
142 |
+
$cache_key = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' );
|
143 |
$version_info = get_transient( $cache_key );
|
144 |
|
145 |
if( false === $version_info ) {
|
149 |
set_transient( $cache_key, $version_info, 3600 );
|
150 |
}
|
151 |
|
|
|
152 |
if( ! is_object( $version_info ) ) {
|
153 |
return;
|
154 |
}
|
183 |
|
184 |
if ( empty( $version_info->download_link ) ) {
|
185 |
printf(
|
186 |
+
__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),
|
187 |
esc_html( $version_info->name ),
|
188 |
+
'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
|
189 |
+
esc_html( $version_info->new_version ),
|
190 |
+
'</a>'
|
191 |
);
|
192 |
} else {
|
193 |
printf(
|
194 |
+
__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),
|
195 |
esc_html( $version_info->name ),
|
196 |
+
'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
|
197 |
esc_html( $version_info->new_version ),
|
198 |
+
'</a>',
|
199 |
+
'<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
|
200 |
+
'</a>'
|
201 |
);
|
202 |
}
|
203 |
|
204 |
+
do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
|
205 |
+
|
206 |
echo '</div></td></tr>';
|
207 |
}
|
208 |
}
|
218 |
* @param object $_args
|
219 |
* @return object $_data
|
220 |
*/
|
221 |
+
public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
|
222 |
|
223 |
|
224 |
if ( $_action != 'plugin_information' ) {
|
259 |
* @param string $url
|
260 |
* @return object $array
|
261 |
*/
|
262 |
+
public function http_request_args( $args, $url ) {
|
263 |
// If it is an https request and we are performing a package download, disable ssl verification
|
264 |
if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
|
265 |
$args['sslverify'] = false;
|
276 |
*
|
277 |
* @param string $_action The requested action.
|
278 |
* @param array $_data Parameters for the API action.
|
279 |
+
* @return false|object
|
280 |
*/
|
281 |
private function api_request( $_action, $_data ) {
|
282 |
|
284 |
|
285 |
$data = array_merge( $this->api_data, $_data );
|
286 |
|
287 |
+
if ( $data['slug'] != $this->slug ) {
|
|
|
|
|
|
|
288 |
return;
|
289 |
+
}
|
290 |
|
291 |
if( $this->api_url == home_url() ) {
|
292 |
return false; // Don't allow a plugin to ping itself
|
294 |
|
295 |
$api_params = array(
|
296 |
'edd_action' => 'get_version',
|
297 |
+
'license' => ! empty( $data['license'] ) ? $data['license'] : '',
|
298 |
'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
|
299 |
'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
|
300 |
'slug' => $data['slug'],
|
319 |
|
320 |
public function show_changelog() {
|
321 |
|
322 |
+
global $edd_plugin_data;
|
323 |
|
324 |
if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
|
325 |
return;
|
334 |
}
|
335 |
|
336 |
if( ! current_user_can( 'update_plugins' ) ) {
|
337 |
+
wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
|
338 |
}
|
339 |
|
340 |
+
$data = $edd_plugin_data[ $_REQUEST['slug'] ];
|
341 |
+
$cache_key = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_version_info' );
|
342 |
+
$version_info = get_transient( $cache_key );
|
343 |
+
|
344 |
+
if( false === $version_info ) {
|
345 |
+
|
346 |
+
$api_params = array(
|
347 |
+
'edd_action' => 'get_version',
|
348 |
+
'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false,
|
349 |
+
'item_id' => isset( $data['item_id'] ) ? $data['item_id'] : false,
|
350 |
+
'slug' => $_REQUEST['slug'],
|
351 |
+
'author' => $data['author'],
|
352 |
+
'url' => home_url()
|
353 |
+
);
|
354 |
+
|
355 |
+
$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
|
356 |
+
|
357 |
+
if ( ! is_wp_error( $request ) ) {
|
358 |
+
$version_info = json_decode( wp_remote_retrieve_body( $request ) );
|
359 |
+
}
|
360 |
+
|
361 |
+
if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
|
362 |
+
$version_info->sections = maybe_unserialize( $version_info->sections );
|
363 |
+
} else {
|
364 |
+
$version_info = false;
|
365 |
+
}
|
366 |
+
|
367 |
+
set_transient( $cache_key, $version_info, 3600 );
|
368 |
|
|
|
|
|
369 |
}
|
370 |
|
371 |
+
if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
|
372 |
+
echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
|
373 |
+
}
|
374 |
|
375 |
exit;
|
376 |
}
|
classes/ad_placements.php
CHANGED
@@ -352,7 +352,6 @@ class Advanced_Ads_Placements {
|
|
352 |
libxml_use_internal_errors(true); // avoid notices and warnings - html is most likely malformed
|
353 |
$success = $dom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $content);
|
354 |
libxml_use_internal_errors(false);
|
355 |
-
libxml_clear_errors();
|
356 |
if ($success !== true) {
|
357 |
// -TODO handle cases were dom-parsing failed (at least inform user)
|
358 |
return $content;
|
@@ -429,10 +428,9 @@ class Advanced_Ads_Placements {
|
|
429 |
// $adContent = preg_replace('#(document.write[^<^)]+)</sc(.*)#', '$1<\/sc$2', $adContent); // too restrict, doesn’t work when beginning <script> tag is in the same line
|
430 |
$adDom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $adContent);
|
431 |
// log errors
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
libxml_use_internal_errors(false);
|
436 |
|
437 |
// inject
|
438 |
$node = apply_filters( 'advanced-ads-placement-content-injection-node', $paragraphs[$offset], $tag, $before );
|
@@ -457,10 +455,12 @@ class Advanced_Ads_Placements {
|
|
457 |
// append to body; -TODO using here that we only select direct children of the body tag
|
458 |
foreach ( $adDom->getElementsByTagName( 'body' )->item( 0 )->childNodes as $importedNode ) {
|
459 |
$importedNode = $dom->importNode( $importedNode, true );
|
460 |
-
$
|
461 |
}
|
462 |
}
|
463 |
}
|
|
|
|
|
464 |
}
|
465 |
|
466 |
// convert to text-representation
|
352 |
libxml_use_internal_errors(true); // avoid notices and warnings - html is most likely malformed
|
353 |
$success = $dom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $content);
|
354 |
libxml_use_internal_errors(false);
|
|
|
355 |
if ($success !== true) {
|
356 |
// -TODO handle cases were dom-parsing failed (at least inform user)
|
357 |
return $content;
|
428 |
// $adContent = preg_replace('#(document.write[^<^)]+)</sc(.*)#', '$1<\/sc$2', $adContent); // too restrict, doesn’t work when beginning <script> tag is in the same line
|
429 |
$adDom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wpCharset . '" /><body>' . $adContent);
|
430 |
// log errors
|
431 |
+
if ( defined ( 'WP_DEBUG' ) && WP_DEBUG && libxml_get_last_error() instanceof LibXMLError ){
|
432 |
+
Advanced_Ads::log( 'content injection error for placement "' . $placement_id . '": ' . print_r( libxml_get_last_error(), true ) );
|
433 |
+
}
|
|
|
434 |
|
435 |
// inject
|
436 |
$node = apply_filters( 'advanced-ads-placement-content-injection-node', $paragraphs[$offset], $tag, $before );
|
455 |
// append to body; -TODO using here that we only select direct children of the body tag
|
456 |
foreach ( $adDom->getElementsByTagName( 'body' )->item( 0 )->childNodes as $importedNode ) {
|
457 |
$importedNode = $dom->importNode( $importedNode, true );
|
458 |
+
$node->parentNode->appendChild( $importedNode );
|
459 |
}
|
460 |
}
|
461 |
}
|
462 |
+
|
463 |
+
libxml_use_internal_errors(false);
|
464 |
}
|
465 |
|
466 |
// convert to text-representation
|
classes/display-conditions.php
CHANGED
@@ -168,7 +168,7 @@ class Advanced_Ads_Display_Conditions {
|
|
168 |
|
169 |
$label = ( $value === 'or' ) ? __( 'or', 'advanced-ads' ) : __( 'and', 'advanced-ads' );
|
170 |
|
171 |
-
return '<input type="checkbox" name="' . self::FORM_NAME . '[' . $index . '][connector]' . '" value="or" id="advads-conditions-' .
|
172 |
$index . '-connector"' .
|
173 |
checked( 'or', $value, false )
|
174 |
.'><label for="advads-conditions-' . $index . '-connector">' . $label . '</label>';
|
@@ -209,7 +209,7 @@ class Advanced_Ads_Display_Conditions {
|
|
209 |
?><label class="button" for="advads-conditions-<?php echo $index; ?>-<?php echo $_type_id;
|
210 |
?>"><?php echo $_type->label; ?></label><input type="checkbox" id="advads-conditions-<?php echo $index; ?>-<?php echo $_type_id; ?>" name="<?php echo $name; ?>[value][]" <?php checked($_val, 1); ?> value="<?php echo $_type_id; ?>"><?php
|
211 |
}
|
212 |
-
?><p class="advads-conditions-not-selected advads-error-message"
|
213 |
}
|
214 |
|
215 |
/**
|
@@ -253,7 +253,7 @@ class Advanced_Ads_Display_Conditions {
|
|
253 |
?><label class="button ui-button" for="advads-conditions-<?php echo $index; ?>-<?php echo $_author->ID;
|
254 |
?>"><?php echo $_author->display_name; ?></label><input type="checkbox" id="advads-conditions-<?php echo $index; ?>-<?php echo $_author->ID; ?>" name="<?php echo $name; ?>[value][]" <?php checked($_val, 1); ?> value="<?php echo $_author->ID; ?>"><?php
|
255 |
}
|
256 |
-
?><p class="advads-conditions-not-selected advads-error-message"
|
257 |
}
|
258 |
|
259 |
/**
|
@@ -341,7 +341,7 @@ class Advanced_Ads_Display_Conditions {
|
|
341 |
$field_id = "advads-conditions-$index-$_term->term_id";
|
342 |
?><input type="checkbox" id="<?php echo $field_id; ?>" name="<?php echo $inputname; ?>" value="<?php echo $_term->term_id; ?>" <?php checked(in_array($_term->term_id, $checked), true); ?>><label for="<?php echo $field_id; ?>"><?php echo $_term->name; ?></label><?php
|
343 |
endforeach;
|
344 |
-
?><p class="advads-conditions-not-selected advads-error-message"
|
345 |
endif;
|
346 |
endif;
|
347 |
}
|
168 |
|
169 |
$label = ( $value === 'or' ) ? __( 'or', 'advanced-ads' ) : __( 'and', 'advanced-ads' );
|
170 |
|
171 |
+
return '<input style="display:none;" type="checkbox" name="' . self::FORM_NAME . '[' . $index . '][connector]' . '" value="or" id="advads-conditions-' .
|
172 |
$index . '-connector"' .
|
173 |
checked( 'or', $value, false )
|
174 |
.'><label for="advads-conditions-' . $index . '-connector">' . $label . '</label>';
|
209 |
?><label class="button" for="advads-conditions-<?php echo $index; ?>-<?php echo $_type_id;
|
210 |
?>"><?php echo $_type->label; ?></label><input type="checkbox" id="advads-conditions-<?php echo $index; ?>-<?php echo $_type_id; ?>" name="<?php echo $name; ?>[value][]" <?php checked($_val, 1); ?> value="<?php echo $_type_id; ?>"><?php
|
211 |
}
|
212 |
+
?><p class="advads-conditions-not-selected advads-error-message"><?php _ex( 'Please select some items.', 'Error message shown when no display condition term is selected', 'advanced-ads' ); ?></p></div><?php
|
213 |
}
|
214 |
|
215 |
/**
|
253 |
?><label class="button ui-button" for="advads-conditions-<?php echo $index; ?>-<?php echo $_author->ID;
|
254 |
?>"><?php echo $_author->display_name; ?></label><input type="checkbox" id="advads-conditions-<?php echo $index; ?>-<?php echo $_author->ID; ?>" name="<?php echo $name; ?>[value][]" <?php checked($_val, 1); ?> value="<?php echo $_author->ID; ?>"><?php
|
255 |
}
|
256 |
+
?><p class="advads-conditions-not-selected advads-error-message"><?php _ex( 'Please select some items.', 'Error message shown when no display condition term is selected', 'advanced-ads' ); ?></p></div><?php
|
257 |
}
|
258 |
|
259 |
/**
|
341 |
$field_id = "advads-conditions-$index-$_term->term_id";
|
342 |
?><input type="checkbox" id="<?php echo $field_id; ?>" name="<?php echo $inputname; ?>" value="<?php echo $_term->term_id; ?>" <?php checked(in_array($_term->term_id, $checked), true); ?>><label for="<?php echo $field_id; ?>"><?php echo $_term->name; ?></label><?php
|
343 |
endforeach;
|
344 |
+
?><p class="advads-conditions-not-selected advads-error-message"><?php _ex( 'Please select some items.', 'Error message shown when no display condition term is selected', 'advanced-ads' ); ?></p></div><?php
|
345 |
endif;
|
346 |
endif;
|
347 |
}
|
readme.txt
CHANGED
@@ -3,8 +3,8 @@ Contributors: webzunft
|
|
3 |
Donate link:https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RRRCEBGN3UT2
|
4 |
Tags: ads, ad, ad inserter, ad injection, ad manager, ads manager, ad widget, adrotate, adsense, advertise, advertisements, advertising, adverts, advert, amazon, banner, banners, buysellads, chitika, clickbank, dfp, doubleclick, geotarget, geolocation, geo location, google dfp, monetization, widget
|
5 |
Requires at least: WP 4.2, PHP 5.3
|
6 |
-
Tested up to: 4.5.
|
7 |
-
Stable tag: 1.7.4.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -203,6 +203,14 @@ There is no revenue share. Advanced Ads doesn’t alter your ad codes in a way t
|
|
203 |
|
204 |
== Changelog ==
|
205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
= 1.7.4.4 =
|
207 |
|
208 |
* linked first-ad tutorials above ad list if less than 3 ads created yet
|
3 |
Donate link:https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RRRCEBGN3UT2
|
4 |
Tags: ads, ad, ad inserter, ad injection, ad manager, ads manager, ad widget, adrotate, adsense, advertise, advertisements, advertising, adverts, advert, amazon, banner, banners, buysellads, chitika, clickbank, dfp, doubleclick, geotarget, geolocation, geo location, google dfp, monetization, widget
|
5 |
Requires at least: WP 4.2, PHP 5.3
|
6 |
+
Tested up to: 4.5.3
|
7 |
+
Stable tag: 1.7.4.5
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
203 |
|
204 |
== Changelog ==
|
205 |
|
206 |
+
= 1.7.4.5 =
|
207 |
+
|
208 |
+
* extended feed cache to 48 hours
|
209 |
+
* updated EDD add-on updater class
|
210 |
+
* display possible injection errors only, when WP_DEBUG is enabled
|
211 |
+
* fixed content injection when duplicate ids are found in content
|
212 |
+
* fixed JavaScript conflict that prevented Display Conditions from working
|
213 |
+
|
214 |
= 1.7.4.4 =
|
215 |
|
216 |
* linked first-ad tutorials above ad list if less than 3 ads created yet
|