Version Description
- prevented content injection into specific elements where ads cause issues
- assign
advads-stop-injection
class to any element into which you dont want to automatically inject ads - fixed possible cURL error when checking existing ads.txt file locally
Download this release
Release Info
Developer | webzunft |
Plugin | Advanced Ads |
Version | 1.17.3 |
Comparing to | |
See all releases |
Code changes from version 1.17.2 to 1.17.3
- admin/assets/css/admin.css +4 -4
- advanced-ads.php +2 -2
- classes/ad-ajax.php +91 -54
- classes/ad-health-notices.php +88 -79
- classes/ad-model.php +36 -28
- classes/ad.php +410 -327
- classes/ad_ajax_callbacks.php +258 -244
- classes/ad_placements.php +547 -312
- modules/ads-txt/includes/class-advanced-ads-ads-txt-utils.php +14 -1
- readme.txt +7 -1
admin/assets/css/admin.css
CHANGED
@@ -275,7 +275,7 @@ fieldset.advads-group-add-ad { margin-top: 1em; }
|
|
275 |
.advads-placements-new-form .advads-placement-type label .description { padding: 10px; }
|
276 |
.advads-placements-new-form .advads-error-message { display: none; }
|
277 |
.advads-placements-table { min-width: 80%; border-collapse: collapse; background: #fff; }
|
278 |
-
.advads-placements-table tbody tr { border-top: 1px solid #ddd; }
|
279 |
.advads-placements-table tbody tr td:first-child { width: 70px; }
|
280 |
.advads-placements-table tbody tr td:nth-child(2) { width: 140px; }
|
281 |
.advads-placements-table tbody tr td:nth-child(2) { font-size: 1.2em; }
|
@@ -364,7 +364,7 @@ tr:hover .on-hover { display: block; }
|
|
364 |
}
|
365 |
|
366 |
/**
|
367 |
-
* Connect to Google AdSense modal
|
368 |
*/
|
369 |
|
370 |
.gadsense-modal-error {
|
@@ -521,8 +521,8 @@ div.advads-stats-box div.advads-stats-box-main{
|
|
521 |
font-size: 18px;
|
522 |
}
|
523 |
div.advads-stats-dd-container {
|
524 |
-
position:relative;
|
525 |
-
float:right;
|
526 |
text-align:right;
|
527 |
}
|
528 |
div.advads-stats-dd-button{
|
275 |
.advads-placements-new-form .advads-placement-type label .description { padding: 10px; }
|
276 |
.advads-placements-new-form .advads-error-message { display: none; }
|
277 |
.advads-placements-table { min-width: 80%; border-collapse: collapse; background: #fff; }
|
278 |
+
.advads-placements-table > tbody > tr { border-top: 1px solid #ddd; }
|
279 |
.advads-placements-table tbody tr td:first-child { width: 70px; }
|
280 |
.advads-placements-table tbody tr td:nth-child(2) { width: 140px; }
|
281 |
.advads-placements-table tbody tr td:nth-child(2) { font-size: 1.2em; }
|
364 |
}
|
365 |
|
366 |
/**
|
367 |
+
* Connect to Google AdSense modal
|
368 |
*/
|
369 |
|
370 |
.gadsense-modal-error {
|
521 |
font-size: 18px;
|
522 |
}
|
523 |
div.advads-stats-dd-container {
|
524 |
+
position:relative;
|
525 |
+
float:right;
|
526 |
text-align:right;
|
527 |
}
|
528 |
div.advads-stats-dd-button{
|
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.17.
|
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.17.
|
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.17.3
|
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.17.3' );
|
43 |
|
44 |
// Autoloading, modules and functions.
|
45 |
|
classes/ad-ajax.php
CHANGED
@@ -7,8 +7,10 @@
|
|
7 |
*/
|
8 |
class Advanced_Ads_Ajax {
|
9 |
|
10 |
-
|
11 |
-
|
|
|
|
|
12 |
add_action( 'wp_ajax_advads_ad_select', array( $this, 'advads_ajax_ad_select' ) );
|
13 |
add_action( 'wp_ajax_nopriv_advads_ad_select', array( $this, 'advads_ajax_ad_select' ) );
|
14 |
add_action( 'wp_ajax_advads-ad-health-notice-push', array( $this, 'ad_health_notice_push' ) );
|
@@ -16,12 +18,21 @@ class Advanced_Ads_Ajax {
|
|
16 |
add_action( 'wp_ajax_advads-ad-frontend-notice-update', array( $this, 'frontend_notice_update' ) );
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
19 |
private static $instance;
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
return self::$instance;
|
@@ -31,65 +42,71 @@ class Advanced_Ads_Ajax {
|
|
31 |
* Simple wp ajax interface for ad selection.
|
32 |
*/
|
33 |
public function advads_ajax_ad_select() {
|
34 |
-
// set proper header
|
35 |
header( 'Content-Type: application/json; charset: utf-8' );
|
36 |
|
37 |
-
// allow modules / add ons to test (this is rather late but should happen before anything important is called)
|
38 |
do_action( 'advanced-ads-ajax-ad-select-init' );
|
39 |
|
40 |
-
$
|
41 |
-
if ( is_string( $
|
42 |
-
$
|
43 |
}
|
44 |
-
if (is_array($
|
45 |
-
Advanced_Ads::get_instance()->current_ads += $
|
46 |
}
|
47 |
|
48 |
-
$
|
49 |
-
if ( $
|
50 |
$response = array();
|
51 |
|
52 |
$requests_by_blog = array();
|
53 |
-
foreach ( (array) $
|
54 |
-
$blog_id
|
55 |
$requests_by_blog[ $blog_id ][] = $request;
|
56 |
}
|
57 |
foreach ( $requests_by_blog as $blog_id => $requests ) {
|
58 |
-
if (
|
|
|
|
|
59 |
|
60 |
foreach ( $requests as $request ) {
|
61 |
-
$result
|
62 |
$result['elementId'] = ! empty( $request['elementId'] ) ? $request['elementId'] : null;
|
63 |
-
$response[]
|
64 |
}
|
65 |
|
66 |
-
if (
|
|
|
|
|
67 |
}
|
68 |
|
69 |
-
echo
|
70 |
die();
|
71 |
}
|
72 |
|
73 |
$response = $this->select_one( $_REQUEST );
|
74 |
-
echo
|
75 |
die();
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
* Provides a single ad (ad, group, placement) given ID and selection method.
|
80 |
*
|
81 |
-
* @param $request
|
|
|
|
|
82 |
*/
|
83 |
private function select_one( $request ) {
|
84 |
-
// init handlers
|
85 |
-
$selector
|
86 |
-
$methods
|
87 |
-
$method
|
88 |
-
$id
|
89 |
$arguments = isset( $request['ad_args'] ) ? $request['ad_args'] : array();
|
90 |
-
if (is_string($arguments)) {
|
91 |
-
$arguments = stripslashes($arguments);
|
92 |
-
$arguments = json_decode($arguments, true);
|
93 |
}
|
94 |
if ( ! empty( $request['elementId'] ) ) {
|
95 |
$arguments['cache_busting_elementid'] = $request['elementId'];
|
@@ -98,41 +115,60 @@ class Advanced_Ads_Ajax {
|
|
98 |
$response = array();
|
99 |
if ( isset( $methods[ $method ] ) && isset( $id ) ) {
|
100 |
$advads = Advanced_Ads::get_instance();
|
101 |
-
$l
|
102 |
|
103 |
-
// build content
|
104 |
$content = $selector->get_ad_by_method( $id, $method, $arguments );
|
105 |
-
$
|
106 |
-
|
107 |
-
$r = array(
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
} else {
|
110 |
-
// report error
|
111 |
-
return array(
|
|
|
|
|
|
|
112 |
}
|
113 |
}
|
114 |
|
115 |
/**
|
116 |
* Push an Ad Health notice to the queue in the backend
|
117 |
*/
|
118 |
-
public function ad_health_notice_push(){
|
119 |
-
|
120 |
check_ajax_referer( 'advanced-ads-ad-health-ajax-nonce', 'nonce' );
|
121 |
-
|
122 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
123 |
return;
|
124 |
}
|
125 |
-
|
126 |
-
$key
|
127 |
-
$attr = ( !empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
128 |
-
|
129 |
// update or new entry?
|
130 |
-
if( isset( $attr['mode'] ) && 'update' === $attr['mode'] ){
|
131 |
Advanced_Ads_Ad_Health_Notices::get_instance()->update( $key, $attr );
|
132 |
} else {
|
133 |
Advanced_Ads_Ad_Health_Notices::get_instance()->add( $key, $attr );
|
134 |
-
}
|
135 |
-
|
136 |
die();
|
137 |
}
|
138 |
|
@@ -147,11 +183,12 @@ class Advanced_Ads_Ajax {
|
|
147 |
return;
|
148 |
}
|
149 |
|
150 |
-
$key
|
151 |
-
$attr = ( !empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
152 |
|
153 |
// update or new entry?
|
154 |
-
if( isset( $attr['mode'] ) && 'update' === $attr['mode'] ){
|
|
|
155 |
// Advanced_Ads_Frontend_Notices::get_instance()->update( $key, $attr );
|
156 |
} else {
|
157 |
Advanced_Ads_Frontend_Notices::get_instance()->update( $key, $attr );
|
7 |
*/
|
8 |
class Advanced_Ads_Ajax {
|
9 |
|
10 |
+
/**
|
11 |
+
* Advanced_Ads_Ajax constructor.
|
12 |
+
*/
|
13 |
+
private function __construct() {
|
14 |
add_action( 'wp_ajax_advads_ad_select', array( $this, 'advads_ajax_ad_select' ) );
|
15 |
add_action( 'wp_ajax_nopriv_advads_ad_select', array( $this, 'advads_ajax_ad_select' ) );
|
16 |
add_action( 'wp_ajax_advads-ad-health-notice-push', array( $this, 'ad_health_notice_push' ) );
|
18 |
add_action( 'wp_ajax_advads-ad-frontend-notice-update', array( $this, 'frontend_notice_update' ) );
|
19 |
}
|
20 |
|
21 |
+
/**
|
22 |
+
* Instance of Advanced_Ads_Ajax
|
23 |
+
*
|
24 |
+
* @var $instance
|
25 |
+
*/
|
26 |
private static $instance;
|
27 |
|
28 |
+
/**
|
29 |
+
* Instance getter
|
30 |
+
*
|
31 |
+
* @return Advanced_Ads_Ajax
|
32 |
+
*/
|
33 |
+
public static function get_instance() {
|
34 |
+
if ( ! isset( self::$instance ) ) {
|
35 |
+
self::$instance = new self();
|
36 |
}
|
37 |
|
38 |
return self::$instance;
|
42 |
* Simple wp ajax interface for ad selection.
|
43 |
*/
|
44 |
public function advads_ajax_ad_select() {
|
45 |
+
// set proper header.
|
46 |
header( 'Content-Type: application/json; charset: utf-8' );
|
47 |
|
48 |
+
// allow modules / add ons to test (this is rather late but should happen before anything important is called).
|
49 |
do_action( 'advanced-ads-ajax-ad-select-init' );
|
50 |
|
51 |
+
$ad_ids = isset( $_REQUEST['ad_ids'] ) ? $_REQUEST['ad_ids'] : null;
|
52 |
+
if ( is_string( $ad_ids ) ) {
|
53 |
+
$ad_ids = json_decode( $ad_ids, true );
|
54 |
}
|
55 |
+
if ( is_array( $ad_ids ) ) { // ads loaded previously and passed by query.
|
56 |
+
Advanced_Ads::get_instance()->current_ads += $ad_ids;
|
57 |
}
|
58 |
|
59 |
+
$defered_ads = isset( $_REQUEST['deferedAds'] ) ? $_REQUEST['deferedAds'] : null;
|
60 |
+
if ( $defered_ads ) { // load all ajax ads with a single request.
|
61 |
$response = array();
|
62 |
|
63 |
$requests_by_blog = array();
|
64 |
+
foreach ( (array) $defered_ads as $request ) {
|
65 |
+
$blog_id = isset( $request['blog_id'] ) ? $request['blog_id'] : get_current_blog_id();
|
66 |
$requests_by_blog[ $blog_id ][] = $request;
|
67 |
}
|
68 |
foreach ( $requests_by_blog as $blog_id => $requests ) {
|
69 |
+
if ( get_current_blog_id() !== $blog_id ) {
|
70 |
+
Advanced_Ads::get_instance()->switch_to_blog( $blog_id );
|
71 |
+
}
|
72 |
|
73 |
foreach ( $requests as $request ) {
|
74 |
+
$result = $this->select_one( $request );
|
75 |
$result['elementId'] = ! empty( $request['elementId'] ) ? $request['elementId'] : null;
|
76 |
+
$response[] = $result;
|
77 |
}
|
78 |
|
79 |
+
if ( get_current_blog_id() !== $blog_id ) {
|
80 |
+
Advanced_Ads::get_instance()->restore_current_blog();
|
81 |
+
}
|
82 |
}
|
83 |
|
84 |
+
echo wp_json_encode( $response );
|
85 |
die();
|
86 |
}
|
87 |
|
88 |
$response = $this->select_one( $_REQUEST );
|
89 |
+
echo wp_json_encode( $response );
|
90 |
die();
|
91 |
}
|
92 |
|
93 |
/**
|
94 |
* Provides a single ad (ad, group, placement) given ID and selection method.
|
95 |
*
|
96 |
+
* @param array $request request.
|
97 |
+
*
|
98 |
+
* @return array
|
99 |
*/
|
100 |
private function select_one( $request ) {
|
101 |
+
// init handlers.
|
102 |
+
$selector = Advanced_Ads_Select::get_instance();
|
103 |
+
$methods = $selector->get_methods();
|
104 |
+
$method = isset( $request['ad_method'] ) ? (string) $request['ad_method'] : null;
|
105 |
+
$id = isset( $request['ad_id'] ) ? (string) $request['ad_id'] : null;
|
106 |
$arguments = isset( $request['ad_args'] ) ? $request['ad_args'] : array();
|
107 |
+
if ( is_string( $arguments ) ) {
|
108 |
+
$arguments = stripslashes( $arguments );
|
109 |
+
$arguments = json_decode( $arguments, true );
|
110 |
}
|
111 |
if ( ! empty( $request['elementId'] ) ) {
|
112 |
$arguments['cache_busting_elementid'] = $request['elementId'];
|
115 |
$response = array();
|
116 |
if ( isset( $methods[ $method ] ) && isset( $id ) ) {
|
117 |
$advads = Advanced_Ads::get_instance();
|
118 |
+
$l = count( $advads->current_ads );
|
119 |
|
120 |
+
// build content.
|
121 |
$content = $selector->get_ad_by_method( $id, $method, $arguments );
|
122 |
+
$ad_ids = array_slice( $advads->current_ads, $l ); // ads loaded by this request.
|
123 |
+
|
124 |
+
$r = array(
|
125 |
+
'status' => 'success',
|
126 |
+
'item' => $content,
|
127 |
+
'id' => $id,
|
128 |
+
'method' => $method,
|
129 |
+
'ads' => $ad_ids,
|
130 |
+
'blog_id' => get_current_blog_id(),
|
131 |
+
);
|
132 |
+
|
133 |
+
return apply_filters(
|
134 |
+
'advanced-ads-cache-busting-item',
|
135 |
+
$r,
|
136 |
+
array(
|
137 |
+
'id' => $id,
|
138 |
+
'method' => $method,
|
139 |
+
'args' => $arguments,
|
140 |
+
)
|
141 |
+
);
|
142 |
} else {
|
143 |
+
// report error.
|
144 |
+
return array(
|
145 |
+
'status' => 'error',
|
146 |
+
'message' => 'No valid ID or METHOD found.',
|
147 |
+
);
|
148 |
}
|
149 |
}
|
150 |
|
151 |
/**
|
152 |
* Push an Ad Health notice to the queue in the backend
|
153 |
*/
|
154 |
+
public function ad_health_notice_push() {
|
155 |
+
|
156 |
check_ajax_referer( 'advanced-ads-ad-health-ajax-nonce', 'nonce' );
|
157 |
+
|
158 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
159 |
return;
|
160 |
}
|
161 |
+
|
162 |
+
$key = ( ! empty( $_REQUEST['key'] ) ) ? esc_attr( $_REQUEST['key'] ) : false;
|
163 |
+
$attr = ( ! empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
164 |
+
|
165 |
// update or new entry?
|
166 |
+
if ( isset( $attr['mode'] ) && 'update' === $attr['mode'] ) {
|
167 |
Advanced_Ads_Ad_Health_Notices::get_instance()->update( $key, $attr );
|
168 |
} else {
|
169 |
Advanced_Ads_Ad_Health_Notices::get_instance()->add( $key, $attr );
|
170 |
+
}
|
171 |
+
|
172 |
die();
|
173 |
}
|
174 |
|
183 |
return;
|
184 |
}
|
185 |
|
186 |
+
$key = ( ! empty( $_REQUEST['key'] ) ) ? esc_attr( $_REQUEST['key'] ) : false;
|
187 |
+
$attr = ( ! empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
188 |
|
189 |
// update or new entry?
|
190 |
+
if ( isset( $attr['mode'] ) && 'update' === $attr['mode'] ) {
|
191 |
+
die();
|
192 |
// Advanced_Ads_Frontend_Notices::get_instance()->update( $key, $attr );
|
193 |
} else {
|
194 |
Advanced_Ads_Frontend_Notices::get_instance()->update( $key, $attr );
|
classes/ad-health-notices.php
CHANGED
@@ -172,7 +172,7 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
172 |
if ( isset( $_notice['closed'] ) ) {
|
173 |
// remove notice when timeout expired – was closed longer ago than timeout set in the notice options.
|
174 |
if ( empty( $notice_array['timeout'] )
|
175 |
-
|
176 |
$this->remove( $_key );
|
177 |
} else {
|
178 |
// just ignore notice if timeout is still valid.
|
@@ -194,7 +194,6 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
194 |
add_filter( 'removable_query_args', array( $this, 'remove_query_vars_after_notice_update' ) );
|
195 |
}
|
196 |
|
197 |
-
|
198 |
// load hidden notices.
|
199 |
$this->ignore = $this->get_valid_ignored();
|
200 |
|
@@ -237,7 +236,7 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
237 |
|
238 |
// run only daily unless we are on an Advanced Ads related page.
|
239 |
if ( ! Advanced_Ads_Admin::screen_belongs_to_advanced_ads()
|
240 |
-
|
241 |
return;
|
242 |
}
|
243 |
|
@@ -325,12 +324,12 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
325 |
* Add a notice to the queue
|
326 |
*
|
327 |
* @param string $notice_key notice key to be added to the notice array.
|
328 |
-
* @param array
|
329 |
*
|
330 |
-
*
|
331 |
-
*
|
332 |
-
*
|
333 |
-
*
|
334 |
*/
|
335 |
public function add( $notice_key, $atts = array() ) {
|
336 |
|
@@ -342,10 +341,10 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
342 |
// add string to key.
|
343 |
if ( ! empty( $atts['append_key'] ) ) {
|
344 |
$orig_notice_key = $notice_key;
|
345 |
-
$notice_key
|
346 |
}
|
347 |
|
348 |
-
$notice_key
|
349 |
$options_before = $options = $this->options();
|
350 |
|
351 |
// load notices from "queue".
|
@@ -403,10 +402,10 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
403 |
* Updating an existing notice or add it, if it doesn’t exist, yet
|
404 |
*
|
405 |
* @param string $notice_key notice key to be added to the notice array.
|
406 |
-
* @param array
|
407 |
*
|
408 |
-
*
|
409 |
-
*
|
410 |
*/
|
411 |
public function update( $notice_key, $atts = array() ) {
|
412 |
|
@@ -416,8 +415,9 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
416 |
}
|
417 |
|
418 |
// check if the notice already exists.
|
419 |
-
$notice_key
|
420 |
-
$
|
|
|
421 |
|
422 |
// load notices from "queue".
|
423 |
$notices = isset( $options['notices'] ) ? $options['notices'] : array();
|
@@ -500,9 +500,10 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
500 |
}
|
501 |
|
502 |
// get notices from options.
|
503 |
-
$
|
|
|
504 |
if ( ! isset( $options['notices'] )
|
505 |
-
|
506 |
|| ! isset( $options['notices'][ $notice_key ] ) ) {
|
507 |
return;
|
508 |
}
|
@@ -533,7 +534,8 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
533 |
}
|
534 |
|
535 |
// get options.
|
536 |
-
$
|
|
|
537 |
$ignored = isset( $options['ignore'] ) && is_array( $options['ignore'] ) ? $options['ignore'] : array();
|
538 |
|
539 |
// adds notice key to ignore array if it doesn’t exist already.
|
@@ -559,7 +561,8 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
559 |
public function unignore() {
|
560 |
|
561 |
// get options.
|
562 |
-
$
|
|
|
563 |
|
564 |
// empty ignore value.
|
565 |
$options['ignore'] = array();
|
@@ -592,64 +595,66 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
592 |
* Display notices in a list
|
593 |
*
|
594 |
* @param string $type which type of notice to show; default: 'problem'.
|
595 |
-
*
|
596 |
*/
|
597 |
public function display( $type = 'problem' ) {
|
598 |
|
599 |
// iterate through notices.
|
600 |
?>
|
601 |
-
<ul class="advads-ad-health-notices advads-ad-health-notices-<?php echo $type; ?>"
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
|
|
|
|
|
|
653 |
}
|
654 |
|
655 |
/**
|
@@ -765,7 +770,7 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
765 |
$notice_array = $this->get_notice_array_for_key( $_key );
|
766 |
|
767 |
if ( isset( $notice_array['type'] ) && $type === $notice_array['type']
|
768 |
-
|
769 |
$notices_by_type[ $_key ] = $_notice;
|
770 |
}
|
771 |
}
|
@@ -824,18 +829,24 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
824 |
* Add notification when an ad expires based on the expiry date
|
825 |
*
|
826 |
* @param integer $ad_id ID of the ad.
|
827 |
-
* @param object
|
828 |
*/
|
829 |
public function ad_expired( $ad_id, $ad ) {
|
830 |
$id = ! empty( $ad_id ) ? absint( $ad_id ) : 0;
|
831 |
-
$this->update(
|
|
|
|
|
|
|
|
|
|
|
|
|
832 |
}
|
833 |
|
834 |
/**
|
835 |
* Get AdSense error link
|
836 |
* this is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link() which might not be available all the time
|
837 |
*
|
838 |
-
* @param string $code error code
|
839 |
*
|
840 |
* @return string link
|
841 |
*/
|
@@ -849,14 +860,12 @@ class Advanced_Ads_Ad_Health_Notices {
|
|
849 |
}
|
850 |
|
851 |
// is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link().
|
852 |
-
|
853 |
// translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag.
|
854 |
esc_attr__( 'Learn more about AdSense account issues %1$shere%2$s.', 'advanced-ads' ),
|
855 |
'<a href="' . ADVADS_URL . 'adsense-errors/#utm_source=advanced-ads&utm_medium=link&utm_campaign=adsense-error' . $code . '" target="_blank">',
|
856 |
'</a>'
|
857 |
);
|
858 |
-
|
859 |
-
return $link;
|
860 |
}
|
861 |
|
862 |
/**
|
172 |
if ( isset( $_notice['closed'] ) ) {
|
173 |
// remove notice when timeout expired – was closed longer ago than timeout set in the notice options.
|
174 |
if ( empty( $notice_array['timeout'] )
|
175 |
+
|| ( ( $time - $_notice['closed'] ) > $notice_array['timeout'] ) ) {
|
176 |
$this->remove( $_key );
|
177 |
} else {
|
178 |
// just ignore notice if timeout is still valid.
|
194 |
add_filter( 'removable_query_args', array( $this, 'remove_query_vars_after_notice_update' ) );
|
195 |
}
|
196 |
|
|
|
197 |
// load hidden notices.
|
198 |
$this->ignore = $this->get_valid_ignored();
|
199 |
|
236 |
|
237 |
// run only daily unless we are on an Advanced Ads related page.
|
238 |
if ( ! Advanced_Ads_Admin::screen_belongs_to_advanced_ads()
|
239 |
+
&& get_transient( self::DAILY_CHECK_TRANSIENT_NAME ) ) {
|
240 |
return;
|
241 |
}
|
242 |
|
324 |
* Add a notice to the queue
|
325 |
*
|
326 |
* @param string $notice_key notice key to be added to the notice array.
|
327 |
+
* @param array $atts additional attributes.
|
328 |
*
|
329 |
+
* attributes
|
330 |
+
* - append_key string attached to the key; enables to create multiple messages for one original key
|
331 |
+
* - append_text text added to the default message
|
332 |
+
* - ad_id ID of an ad, attaches the link to the ad edit page to the message
|
333 |
*/
|
334 |
public function add( $notice_key, $atts = array() ) {
|
335 |
|
341 |
// add string to key.
|
342 |
if ( ! empty( $atts['append_key'] ) ) {
|
343 |
$orig_notice_key = $notice_key;
|
344 |
+
$notice_key .= $atts['append_key'];
|
345 |
}
|
346 |
|
347 |
+
$notice_key = esc_attr( $notice_key );
|
348 |
$options_before = $options = $this->options();
|
349 |
|
350 |
// load notices from "queue".
|
402 |
* Updating an existing notice or add it, if it doesn’t exist, yet
|
403 |
*
|
404 |
* @param string $notice_key notice key to be added to the notice array.
|
405 |
+
* @param array $atts additional attributes.
|
406 |
*
|
407 |
+
* attributes:
|
408 |
+
* - append_text – text added to the default message
|
409 |
*/
|
410 |
public function update( $notice_key, $atts = array() ) {
|
411 |
|
415 |
}
|
416 |
|
417 |
// check if the notice already exists.
|
418 |
+
$notice_key = esc_attr( $notice_key );
|
419 |
+
$options = $this->options();
|
420 |
+
$options_before = $options;
|
421 |
|
422 |
// load notices from "queue".
|
423 |
$notices = isset( $options['notices'] ) ? $options['notices'] : array();
|
500 |
}
|
501 |
|
502 |
// get notices from options.
|
503 |
+
$options = $this->options();
|
504 |
+
$options_before = $options;
|
505 |
if ( ! isset( $options['notices'] )
|
506 |
+
|| ! is_array( $options['notices'] )
|
507 |
|| ! isset( $options['notices'][ $notice_key ] ) ) {
|
508 |
return;
|
509 |
}
|
534 |
}
|
535 |
|
536 |
// get options.
|
537 |
+
$options = $this->options();
|
538 |
+
$options_before = $options;
|
539 |
$ignored = isset( $options['ignore'] ) && is_array( $options['ignore'] ) ? $options['ignore'] : array();
|
540 |
|
541 |
// adds notice key to ignore array if it doesn’t exist already.
|
561 |
public function unignore() {
|
562 |
|
563 |
// get options.
|
564 |
+
$options = $this->options();
|
565 |
+
$options_before = $options;
|
566 |
|
567 |
// empty ignore value.
|
568 |
$options['ignore'] = array();
|
595 |
* Display notices in a list
|
596 |
*
|
597 |
* @param string $type which type of notice to show; default: 'problem'.
|
|
|
598 |
*/
|
599 |
public function display( $type = 'problem' ) {
|
600 |
|
601 |
// iterate through notices.
|
602 |
?>
|
603 |
+
<ul class="advads-ad-health-notices advads-ad-health-notices-<?php echo esc_attr( $type ); ?>">
|
604 |
+
<?php
|
605 |
+
|
606 |
+
// failsafe in case this is not an array.
|
607 |
+
if ( ! is_array( $this->notices ) ) {
|
608 |
+
return;
|
609 |
+
}
|
610 |
+
|
611 |
+
foreach ( $this->notices as $_notice_key => $_notice ) {
|
612 |
+
|
613 |
+
$notice_array = $this->get_notice_array_for_key( $_notice_key );
|
614 |
+
|
615 |
+
// remove the notice if key doesn’t exist anymore.
|
616 |
+
if ( array() === $notice_array ) {
|
617 |
+
$this->remove( $_notice_key );
|
618 |
+
}
|
619 |
+
|
620 |
+
$notice_type = isset( $notice_array['type'] ) ? $notice_array['type'] : 'problem';
|
621 |
+
|
622 |
+
// skip if type is not correct.
|
623 |
+
if ( $notice_type !== $type ) {
|
624 |
+
continue;
|
625 |
+
}
|
626 |
+
|
627 |
+
if ( ! empty( $_notice['text'] ) ) {
|
628 |
+
$text = $_notice['text'];
|
629 |
+
} elseif ( isset( $notice_array['text'] ) ) {
|
630 |
+
$text = $notice_array['text'];
|
631 |
+
} else {
|
632 |
+
continue;
|
633 |
+
}
|
634 |
+
|
635 |
+
// attach "append_text".
|
636 |
+
if ( ! empty( $_notice['append_text'] ) ) {
|
637 |
+
$text .= $_notice['append_text'];
|
638 |
+
}
|
639 |
+
|
640 |
+
// attach "get help" link.
|
641 |
+
if ( ! empty( $_notice['get_help_link'] ) ) {
|
642 |
+
$text .= $this->get_help_link( $_notice['get_help_link'] );
|
643 |
+
} elseif ( isset( $notice_array['get_help_link'] ) ) {
|
644 |
+
$text .= $this->get_help_link( $notice_array['get_help_link'] );
|
645 |
+
}
|
646 |
+
|
647 |
+
$can_hide = ( ! isset( $notice_array['can_hide'] ) || true === $notice_array['can_hide'] ) ? true : false;
|
648 |
+
$hide = ( ! isset( $notice_array['hide'] ) || true === $notice_array['hide'] ) ? true : false;
|
649 |
+
$is_hidden = in_array( $_notice_key, $this->ignore, true ) ? true : false;
|
650 |
+
$date = isset( $_notice['time'] ) ? date_i18n( get_option( 'date_format' ), $_notice['time'] ) : false;
|
651 |
+
|
652 |
+
include ADVADS_BASE_PATH . '/admin/views/overview-notice-row.php';
|
653 |
+
}
|
654 |
+
|
655 |
+
?>
|
656 |
+
</ul>
|
657 |
+
<?php
|
658 |
}
|
659 |
|
660 |
/**
|
770 |
$notice_array = $this->get_notice_array_for_key( $_key );
|
771 |
|
772 |
if ( isset( $notice_array['type'] ) && $type === $notice_array['type']
|
773 |
+
&& ( ! isset( $this->ignore ) || false === array_search( $_key, $this->ignore, true ) ) ) {
|
774 |
$notices_by_type[ $_key ] = $_notice;
|
775 |
}
|
776 |
}
|
829 |
* Add notification when an ad expires based on the expiry date
|
830 |
*
|
831 |
* @param integer $ad_id ID of the ad.
|
832 |
+
* @param object $ad ad object.
|
833 |
*/
|
834 |
public function ad_expired( $ad_id, $ad ) {
|
835 |
$id = ! empty( $ad_id ) ? absint( $ad_id ) : 0;
|
836 |
+
$this->update(
|
837 |
+
'ad_expired',
|
838 |
+
array(
|
839 |
+
'append_key' => $id,
|
840 |
+
'ad_id' => $id,
|
841 |
+
)
|
842 |
+
);
|
843 |
}
|
844 |
|
845 |
/**
|
846 |
* Get AdSense error link
|
847 |
* this is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link() which might not be available all the time
|
848 |
*
|
849 |
+
* @param string $code error code.
|
850 |
*
|
851 |
* @return string link
|
852 |
*/
|
860 |
}
|
861 |
|
862 |
// is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link().
|
863 |
+
return sprintf(
|
864 |
// translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag.
|
865 |
esc_attr__( 'Learn more about AdSense account issues %1$shere%2$s.', 'advanced-ads' ),
|
866 |
'<a href="' . ADVADS_URL . 'adsense-errors/#utm_source=advanced-ads&utm_medium=link&utm_campaign=adsense-error' . $code . '" target="_blank">',
|
867 |
'</a>'
|
868 |
);
|
|
|
|
|
869 |
}
|
870 |
|
871 |
/**
|
classes/ad-model.php
CHANGED
@@ -17,35 +17,42 @@ class Advanced_Ads_Model {
|
|
17 |
const OBJECT_CACHE_TTL = 720; // 12 Minutes
|
18 |
|
19 |
/**
|
|
|
20 |
*
|
21 |
* @var wpdb
|
22 |
*/
|
23 |
protected $db;
|
24 |
|
25 |
/**
|
|
|
26 |
*
|
27 |
* @var array
|
28 |
*/
|
29 |
protected $ad_conditions;
|
30 |
|
31 |
/**
|
|
|
32 |
*
|
33 |
* @var array
|
34 |
*/
|
35 |
protected $ad_placements;
|
36 |
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
39 |
$this->db = $wpdb;
|
40 |
-
}
|
41 |
-
|
42 |
/**
|
|
|
43 |
*
|
44 |
* @return array
|
45 |
*/
|
46 |
-
public function get_ad_conditions()
|
47 |
-
|
48 |
-
if ( ! isset(self::$ad_conditions) ) {
|
49 |
$this->ad_conditions = include ADVADS_BASE_PATH . 'includes/array_ad_conditions.php';
|
50 |
}
|
51 |
|
@@ -62,56 +69,57 @@ class Advanced_Ads_Model {
|
|
62 |
* @return array|false The blog ids, false if no matches.
|
63 |
*/
|
64 |
public function get_blog_ids() {
|
65 |
-
// get an array of blog ids
|
66 |
$sql = "SELECT blog_id FROM $this->db->blogs WHERE archived = '0' AND spam = '0' AND deleted = '0'";
|
67 |
|
68 |
return $this->db->get_col( $sql );
|
69 |
}
|
70 |
|
71 |
/**
|
72 |
-
*
|
73 |
*
|
74 |
* @since 1.1.0
|
75 |
-
* @param
|
76 |
-
* @return
|
77 |
*/
|
78 |
-
public function get_ads($args = array()){
|
79 |
-
// add default WP_Query arguments
|
80 |
-
$args['post_type']
|
81 |
$args['posts_per_page'] = -1;
|
82 |
-
if ( empty($args['post_status']) ) {
|
|
|
83 |
$ads = new WP_Query( $args );
|
84 |
|
85 |
return $ads->posts;
|
86 |
}
|
87 |
|
88 |
/**
|
89 |
-
*
|
90 |
*
|
91 |
* @since 1.1.0
|
92 |
-
* @param
|
93 |
-
* @return
|
94 |
* @link http://codex.wordpress.org/Function_Reference/get_terms
|
95 |
*/
|
96 |
-
public function get_ad_groups($args = array()){
|
97 |
-
$args['hide_empty'] = isset($args['hide_empty']) ? $args['hide_empty'] : false; // display groups without any ads
|
98 |
|
99 |
return get_terms( Advanced_Ads::AD_GROUP_TAXONOMY, $args );
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
-
*
|
104 |
*
|
105 |
* @since 1.1.0
|
106 |
-
* @return
|
107 |
*/
|
108 |
-
public function get_ad_placements_array(){
|
109 |
-
|
110 |
if ( ! isset( $this->ad_placements ) ) {
|
111 |
$this->ad_placements = get_option( 'advads-ads-placements', array() );
|
112 |
|
113 |
-
// load default array if not saved yet
|
114 |
-
if ( ! is_array( $this->ad_placements ) ){
|
115 |
$this->ad_placements = array();
|
116 |
}
|
117 |
|
@@ -129,9 +137,9 @@ class Advanced_Ads_Model {
|
|
129 |
}
|
130 |
|
131 |
/**
|
132 |
-
*
|
133 |
*
|
134 |
-
* @param
|
135 |
*/
|
136 |
public function update_ad_placements_array( $ad_placements ) {
|
137 |
update_option( 'advads-ads-placements', $ad_placements );
|
17 |
const OBJECT_CACHE_TTL = 720; // 12 Minutes
|
18 |
|
19 |
/**
|
20 |
+
* WordPress database object.
|
21 |
*
|
22 |
* @var wpdb
|
23 |
*/
|
24 |
protected $db;
|
25 |
|
26 |
/**
|
27 |
+
* General ad conditions.
|
28 |
*
|
29 |
* @var array
|
30 |
*/
|
31 |
protected $ad_conditions;
|
32 |
|
33 |
/**
|
34 |
+
* Placements
|
35 |
*
|
36 |
* @var array
|
37 |
*/
|
38 |
protected $ad_placements;
|
39 |
|
40 |
+
/**
|
41 |
+
* Advanced_Ads_Model constructor.
|
42 |
+
*
|
43 |
+
* @param wpdb $wpdb WordPress database access.
|
44 |
+
*/
|
45 |
+
public function __construct( wpdb $wpdb ) {
|
46 |
$this->db = $wpdb;
|
47 |
+
}
|
48 |
+
|
49 |
/**
|
50 |
+
* Load ad conditions.
|
51 |
*
|
52 |
* @return array
|
53 |
*/
|
54 |
+
public function get_ad_conditions() {
|
55 |
+
if ( ! isset( self::$ad_conditions ) ) {
|
|
|
56 |
$this->ad_conditions = include ADVADS_BASE_PATH . 'includes/array_ad_conditions.php';
|
57 |
}
|
58 |
|
69 |
* @return array|false The blog ids, false if no matches.
|
70 |
*/
|
71 |
public function get_blog_ids() {
|
72 |
+
// get an array of blog ids.
|
73 |
$sql = "SELECT blog_id FROM $this->db->blogs WHERE archived = '0' AND spam = '0' AND deleted = '0'";
|
74 |
|
75 |
return $this->db->get_col( $sql );
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
+
* Load all ads based on WP_Query conditions
|
80 |
*
|
81 |
* @since 1.1.0
|
82 |
+
* @param array $args WP_Query arguments that are more specific that default.
|
83 |
+
* @return array $ads array with post objects.
|
84 |
*/
|
85 |
+
public function get_ads( $args = array() ) {
|
86 |
+
// add default WP_Query arguments.
|
87 |
+
$args['post_type'] = Advanced_Ads::POST_TYPE_SLUG;
|
88 |
$args['posts_per_page'] = -1;
|
89 |
+
if ( empty( $args['post_status'] ) ) {
|
90 |
+
$args['post_status'] = array( 'publish', 'future' ); }
|
91 |
$ads = new WP_Query( $args );
|
92 |
|
93 |
return $ads->posts;
|
94 |
}
|
95 |
|
96 |
/**
|
97 |
+
* Load all ad groups
|
98 |
*
|
99 |
* @since 1.1.0
|
100 |
+
* @param array $args array with options.
|
101 |
+
* @return array array with ad groups
|
102 |
* @link http://codex.wordpress.org/Function_Reference/get_terms
|
103 |
*/
|
104 |
+
public function get_ad_groups( $args = array() ) {
|
105 |
+
$args['hide_empty'] = isset( $args['hide_empty'] ) ? $args['hide_empty'] : false; // display groups without any ads.
|
106 |
|
107 |
return get_terms( Advanced_Ads::AD_GROUP_TAXONOMY, $args );
|
108 |
}
|
109 |
|
110 |
/**
|
111 |
+
* Get the array with ad placements
|
112 |
*
|
113 |
* @since 1.1.0
|
114 |
+
* @return array $ad_placements
|
115 |
*/
|
116 |
+
public function get_ad_placements_array() {
|
117 |
+
|
118 |
if ( ! isset( $this->ad_placements ) ) {
|
119 |
$this->ad_placements = get_option( 'advads-ads-placements', array() );
|
120 |
|
121 |
+
// load default array if not saved yet.
|
122 |
+
if ( ! is_array( $this->ad_placements ) ) {
|
123 |
$this->ad_placements = array();
|
124 |
}
|
125 |
|
137 |
}
|
138 |
|
139 |
/**
|
140 |
+
* Update the array with ad placements
|
141 |
*
|
142 |
+
* @param array $ad_placements array with placements.
|
143 |
*/
|
144 |
public function update_ad_placements_array( $ad_placements ) {
|
145 |
update_option( 'advads-ads-placements', $ad_placements );
|
classes/ad.php
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
/**
|
4 |
* Advanced Ads Ad.
|
5 |
*
|
@@ -7,25 +6,25 @@
|
|
7 |
* @author Thomas Maier <support@wpadvancedads.com>
|
8 |
* @license GPL-2.0+
|
9 |
* @link https://wpadvancedads.com
|
10 |
-
* @copyright 2013 Thomas Maier, Advanced Ads GmbH
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
-
*
|
15 |
*
|
16 |
* @package Advanced_Ads_Ad
|
17 |
* @author Thomas Maier <support@wpadvancedads.com>
|
18 |
* @deprecated since version 1.5.3 (May 6th 2015)
|
19 |
* might still be needed if some old add-ons are running somewhere
|
20 |
*/
|
21 |
-
if( ! class_exists
|
22 |
-
|
23 |
|
24 |
-
|
25 |
}
|
26 |
|
27 |
/**
|
28 |
-
*
|
29 |
*
|
30 |
* @package Advanced_Ads_Ad
|
31 |
* @author Thomas Maier <support@wpadvancedads.com>
|
@@ -33,117 +32,161 @@ if( ! class_exists ( 'Advads_Ad', false ) ){
|
|
33 |
class Advanced_Ads_Ad {
|
34 |
|
35 |
/**
|
36 |
-
*
|
|
|
|
|
37 |
*/
|
38 |
public $id = 0;
|
39 |
|
40 |
/**
|
41 |
-
*
|
|
|
|
|
42 |
*/
|
43 |
public $is_ad = false;
|
44 |
|
45 |
/**
|
46 |
-
*
|
|
|
|
|
47 |
*/
|
48 |
public $type = 'content';
|
49 |
|
50 |
/**
|
51 |
-
*
|
|
|
|
|
52 |
*/
|
53 |
public $width = 0;
|
54 |
|
55 |
/**
|
56 |
-
*
|
57 |
*
|
58 |
-
* @
|
59 |
*/
|
60 |
public $url = '';
|
61 |
|
62 |
/**
|
63 |
-
*
|
|
|
|
|
64 |
*/
|
65 |
public $height = 0;
|
66 |
|
67 |
/**
|
68 |
-
*
|
|
|
|
|
69 |
*/
|
70 |
protected $type_obj;
|
71 |
|
72 |
/**
|
73 |
-
*
|
|
|
|
|
74 |
*
|
75 |
-
*
|
76 |
*/
|
77 |
public $content = '';
|
78 |
|
79 |
/**
|
80 |
-
*
|
|
|
|
|
81 |
*/
|
82 |
public $conditions = array();
|
83 |
|
84 |
/**
|
85 |
-
*
|
|
|
|
|
86 |
*/
|
87 |
-
public $status =
|
88 |
|
89 |
/**
|
90 |
-
*
|
|
|
|
|
91 |
*/
|
92 |
protected $options = array();
|
93 |
|
94 |
/**
|
95 |
-
*
|
|
|
|
|
96 |
*/
|
97 |
-
static $options_meta_field = 'advanced_ads_ad_options';
|
98 |
|
99 |
/**
|
100 |
-
*
|
|
|
|
|
101 |
*/
|
102 |
public $args = array();
|
103 |
|
104 |
/**
|
105 |
-
*
|
106 |
-
*
|
|
|
|
|
107 |
*/
|
108 |
public $wrapper = array();
|
109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
/**
|
111 |
* Displayed above the ad.
|
|
|
|
|
112 |
*/
|
113 |
protected $label = '';
|
114 |
|
115 |
/**
|
116 |
-
*
|
117 |
*
|
118 |
-
* @param int
|
119 |
-
* @param
|
120 |
*/
|
121 |
-
public function __construct($id, $args = array()) {
|
122 |
-
$id
|
123 |
-
$this->id
|
124 |
$this->args = is_array( $args ) ? $args : array();
|
125 |
|
126 |
-
// whether the ad will be tracked
|
127 |
$this->global_output = isset( $this->args['global_output'] ) ? (bool) $this->args['global_output'] : true;
|
128 |
|
129 |
-
if ( ! empty($id) ) {
|
|
|
|
|
130 |
|
131 |
-
// dynamically add sanitize filters for condition types
|
132 |
$_types = array();
|
133 |
// -TODO use model
|
134 |
$advanced_ads_ad_conditions = Advanced_Ads::get_ad_conditions();
|
135 |
foreach ( $advanced_ads_ad_conditions as $_condition ) {
|
136 |
-
// add unique
|
137 |
-
$_types[$_condition['type']] = false;
|
138 |
}
|
139 |
-
// iterate types
|
140 |
foreach ( array_keys( $_types ) as $_type ) {
|
141 |
// -TODO might be faster to use __call() method or isset()-test class method array
|
142 |
-
$method_name = 'sanitize_condition_'. $_type;
|
143 |
if ( method_exists( $this, $method_name ) ) {
|
144 |
-
add_filter( 'advanced-ads-sanitize-condition-' . $_type, array($this, $method_name), 10, 1 );
|
145 |
} elseif ( function_exists( 'advads_sanitize_condition_' . $_type ) ) {
|
146 |
-
// check for public function to sanitize this
|
147 |
add_filter( 'advanced-ads-sanitize-condition-' . $_type, 'advads_sanitize_condition_' . $_type, 10, 1 );
|
148 |
|
149 |
}
|
@@ -151,98 +194,106 @@ class Advanced_Ads_Ad {
|
|
151 |
}
|
152 |
|
153 |
/**
|
154 |
-
*
|
155 |
*
|
156 |
-
* @
|
|
|
|
|
157 |
*/
|
158 |
-
private function load($id = 0){
|
159 |
|
160 |
$_data = get_post( $id );
|
161 |
-
if ( $_data
|
|
|
|
|
162 |
|
163 |
-
// return, if not an ad
|
164 |
-
if ( $_data->post_type
|
165 |
return false;
|
166 |
} else {
|
167 |
$this->is_ad = true;
|
168 |
}
|
169 |
|
170 |
-
|
171 |
-
$this->type = $this->options( 'type' );
|
172 |
$this->title = $_data->post_title;
|
173 |
/* load ad type object */
|
174 |
$types = Advanced_Ads::get_instance()->ad_types;
|
175 |
-
if ( isset($types[$this->type]) ){
|
176 |
-
$this->type_obj = $types[$this->type];
|
177 |
} else {
|
178 |
-
$this->type_obj = new Advanced_Ads_Ad_Type_Abstract;
|
179 |
-
}
|
180 |
-
$this->url
|
181 |
-
$this->width
|
182 |
-
$this->height
|
183 |
-
$this->conditions
|
184 |
-
$this->description
|
185 |
-
$this->output
|
186 |
-
$this->status
|
187 |
-
$this->expiry_date
|
188 |
-
$this->is_head_placement
|
189 |
$this->args['is_top_level'] = ! isset( $this->args['is_top_level'] );
|
190 |
-
|
191 |
-
// load content based on ad type
|
192 |
-
$this->content = $this->type_obj->load_content( $_data );
|
193 |
|
|
|
|
|
194 |
|
195 |
if ( ! $this->is_head_placement ) {
|
196 |
$this->maybe_create_label();
|
197 |
$this->wrapper = $this->load_wrapper_options();
|
198 |
|
199 |
-
// set wrapper conditions
|
200 |
$this->wrapper = apply_filters( 'advanced-ads-set-wrapper', $this->wrapper, $this );
|
201 |
-
// add unique wrapper id
|
202 |
if ( is_array( $this->wrapper )
|
203 |
-
|
204 |
-
|
205 |
-
// create unique id if not yet given
|
206 |
$this->wrapper['id'] = $this->create_wrapper_id();
|
207 |
}
|
208 |
}
|
209 |
}
|
210 |
|
211 |
/**
|
212 |
-
*
|
|
|
|
|
|
|
213 |
*
|
214 |
-
* @param string $field post meta key to be returned
|
215 |
* @return mixed meta field content
|
216 |
-
* @since 1.0.0
|
217 |
* @todo check against default values
|
218 |
*/
|
219 |
public function options( $field = '', $default = null ) {
|
220 |
// retrieve options, if not given yet
|
221 |
// -TODO may execute multiple times (if empty); bad design and risk to access unintialised data with direct access to $this->options property.
|
222 |
-
if ( $this->options
|
223 |
-
//
|
224 |
$meta = get_post_meta( $this->id, self::$options_meta_field, true );
|
225 |
if ( $meta ) {
|
226 |
-
// merge meta with arguments given on ad load
|
227 |
$this->options = Advanced_Ads_Utils::merge_deep_array( array( $meta, $this->args ) );
|
228 |
} else {
|
229 |
-
// load arguments given on ad load
|
230 |
$this->options = $this->args;
|
231 |
}
|
232 |
|
233 |
if ( isset( $this->options['change-ad'] ) ) {
|
234 |
-
// some options was provided by the user
|
235 |
-
$this->options = Advanced_Ads_Utils::merge_deep_array(
|
|
|
|
|
|
|
|
|
|
|
236 |
}
|
237 |
}
|
238 |
-
|
239 |
-
// return specific option
|
240 |
-
if ( $field
|
241 |
-
if ( isset($this->options[$field]) ) {
|
242 |
-
return $this->options[$field];
|
243 |
}
|
244 |
-
} else { // return all options
|
245 |
-
if ( ! empty($this->options) ) {
|
246 |
return $this->options;
|
247 |
}
|
248 |
}
|
@@ -251,89 +302,108 @@ class Advanced_Ads_Ad {
|
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
-
*
|
|
|
|
|
|
|
255 |
*
|
256 |
* @since 1.1.0
|
257 |
-
* @param string $option name of the option
|
258 |
-
* @param mixed $value value of the option
|
259 |
*/
|
260 |
-
public function set_option($option = '', $value = ''){
|
261 |
-
if ( $option
|
|
|
|
|
262 |
|
263 |
-
// get current options
|
264 |
$options = $this->options();
|
265 |
|
266 |
-
// set options
|
267 |
-
$options[$option] = $value;
|
268 |
|
269 |
-
// save options
|
270 |
$this->options = $options;
|
271 |
|
272 |
}
|
273 |
|
274 |
|
275 |
/**
|
276 |
-
*
|
|
|
|
|
277 |
*
|
278 |
-
* @since 1.0.0
|
279 |
-
* @param array $output_options output options
|
280 |
* @return string $output ad output
|
|
|
281 |
*/
|
282 |
-
public function output( $output_options = array() ){
|
283 |
-
if ( ! $this->is_ad ) {
|
|
|
|
|
284 |
|
285 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
|
287 |
-
// switch between normal and debug mode
|
288 |
-
// check if debug output should only be displayed to admins
|
289 |
-
$user_can_manage_ads = current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') );
|
290 |
-
if( isset( $this->output['debugmode'] )
|
291 |
-
&& ( $user_can_manage_ads || ( ! $user_can_manage_ads && ! defined('ADVANCED_ADS_AD_DEBUG_FOR_ADMIN_ONLY') ) ) ){
|
292 |
-
$debug = new Advanced_Ads_Ad_Debug;
|
293 |
return $debug->prepare_debug_output( $this );
|
294 |
} else {
|
295 |
-
|
296 |
}
|
297 |
|
298 |
-
// add the ad to the global output array
|
299 |
$advads = Advanced_Ads::get_instance();
|
300 |
if ( $output_options['global_output'] ) {
|
301 |
-
$new_ad = array(
|
|
|
|
|
|
|
|
|
|
|
302 |
// if ( method_exists( 'Advanced_Ads_Tracking_Plugin' , 'check_ad_tracking_enabled' ) ) {
|
303 |
// if ( class_exists( 'Advanced_Ads_Tracking_Plugin', false ) ) {
|
304 |
-
if ( defined( 'AAT_VERSION' ) && -1 < version_compare( AAT_VERSION, '1.4.2' ) ) {
|
305 |
-
|
306 |
$new_ad['tracking_enabled'] = Advanced_Ads_Tracking_Plugin::get_instance()->check_ad_tracking_enabled( $this );
|
307 |
-
|
308 |
$tracking_options = Advanced_Ads_Tracking_Plugin::get_instance()->options();
|
309 |
-
if ( isset( $tracking_options['method'] ) && 'frontend'
|
310 |
$new_ad['placement_id'] = $this->output['placement_id'];
|
311 |
}
|
312 |
-
|
313 |
}
|
314 |
-
|
315 |
$advads->current_ads[] = $new_ad;
|
316 |
}
|
317 |
-
|
318 |
-
// action when output is created
|
319 |
do_action( 'advanced-ads-output', $this, $output, $output_options );
|
320 |
-
|
321 |
return apply_filters( 'advanced-ads-output-final', $output, $this, $output_options );
|
322 |
}
|
323 |
|
324 |
/**
|
325 |
-
*
|
|
|
|
|
326 |
*
|
327 |
-
* @since 1.0.0
|
328 |
-
* @param array $check_options check options
|
329 |
* @return bool $can_display true if can be displayed in frontend
|
|
|
330 |
*/
|
331 |
public function can_display( $check_options = array() ) {
|
332 |
-
$check_options = wp_parse_args(
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
}
|
338 |
|
339 |
// Check If the current ad is requested using a shortcode placed in the content of the current ad.
|
@@ -341,14 +411,14 @@ class Advanced_Ads_Ad {
|
|
341 |
return false;
|
342 |
}
|
343 |
|
344 |
-
// force ad display if debug mode is enabled
|
345 |
-
if( isset( $this->output['debugmode'] ) && ! $check_options['ignore_debugmode'] ) {
|
346 |
-
|
347 |
}
|
348 |
-
|
349 |
if ( ! $check_options['passive_cache_busting'] ) {
|
350 |
-
// don’t display ads that are not published or private for users not logged in
|
351 |
-
if ( $this->status
|
352 |
return false;
|
353 |
}
|
354 |
|
@@ -356,60 +426,63 @@ class Advanced_Ads_Ad {
|
|
356 |
return false;
|
357 |
}
|
358 |
} else {
|
359 |
-
if ( $this->status
|
360 |
return false;
|
361 |
}
|
362 |
}
|
363 |
|
364 |
-
// add own conditions to flag output as possible or not
|
365 |
$can_display = apply_filters( 'advanced-ads-can-display', true, $this, $check_options );
|
366 |
|
367 |
return $can_display;
|
368 |
}
|
369 |
|
370 |
/**
|
371 |
-
*
|
372 |
*
|
373 |
-
* @since 1.1.0
|
374 |
* @return bool $can_display true if can be displayed in frontend based on visitor settings
|
|
|
375 |
*/
|
376 |
-
public function can_display_by_visitor(){
|
377 |
if ( ! empty( $this->options['wp_the_query']['is_feed'] ) ) {
|
378 |
return true;
|
379 |
}
|
380 |
|
381 |
-
|
382 |
-
if ( ( empty($this->options['visitors']) ||
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
|
|
|
|
387 |
|
388 |
if ( isset( $this->options['visitors'] ) && is_array( $this->options['visitors'] ) ) {
|
389 |
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
|
|
|
|
411 |
}
|
412 |
-
}
|
413 |
}
|
414 |
|
415 |
/**
|
@@ -418,18 +491,24 @@ class Advanced_Ads_Ad {
|
|
418 |
* @deprecated since version 1.5.4
|
419 |
*/
|
420 |
|
421 |
-
if ( empty($this->options['visitor']) ||
|
422 |
-
|
|
|
|
|
423 |
$visitor_conditions = $this->options( 'visitor' );
|
424 |
|
425 |
-
// check mobile condition
|
426 |
-
if ( isset($visitor_conditions['mobile']) ){
|
427 |
-
switch ( $visitor_conditions['mobile'] ){
|
428 |
-
case 'only'
|
429 |
-
if ( ! wp_is_mobile() ) {
|
|
|
|
|
430 |
break;
|
431 |
-
case 'no'
|
432 |
-
if ( wp_is_mobile() ) {
|
|
|
|
|
433 |
break;
|
434 |
}
|
435 |
}
|
@@ -438,26 +517,31 @@ class Advanced_Ads_Ad {
|
|
438 |
}
|
439 |
|
440 |
/**
|
441 |
-
*
|
442 |
*
|
443 |
-
* @since 1.3.15
|
444 |
* @return bool $can_display true if can be displayed in frontend based on expiry date
|
|
|
445 |
*/
|
446 |
-
public function can_display_by_expiry_date(){
|
447 |
|
448 |
-
// if expiry_date is not set, null is returned
|
449 |
$ad_expiry_date = (int) $this->options( 'expiry_date' );
|
450 |
|
451 |
if ( $ad_expiry_date <= 0 || $ad_expiry_date > time() ) {
|
452 |
return true;
|
453 |
}
|
454 |
|
455 |
-
// set status to 'draft' if the ad is expired
|
456 |
-
if ( $this->status
|
457 |
-
|
458 |
-
|
459 |
-
wp_update_post(
|
460 |
-
|
|
|
|
|
|
|
|
|
|
|
461 |
/**
|
462 |
* Run when an ad expires
|
463 |
*/
|
@@ -468,39 +552,39 @@ class Advanced_Ads_Ad {
|
|
468 |
}
|
469 |
|
470 |
/**
|
471 |
-
*
|
472 |
* takes values from the current state
|
473 |
*/
|
474 |
-
public function save(){
|
475 |
global $wpdb;
|
476 |
|
477 |
-
// remove slashes from content
|
478 |
$this->content = $this->prepare_content_to_save();
|
479 |
|
480 |
-
$where = array('ID' => $this->id);
|
481 |
$wpdb->update( $wpdb->posts, array( 'post_content' => $this->content ), $where );
|
482 |
|
483 |
-
// clean post from object cache
|
484 |
clean_post_cache( $this->id );
|
485 |
|
486 |
// sanitize conditions
|
487 |
-
// see sanitize_conditions function for example on using this filter
|
488 |
$conditions = self::sanitize_conditions_on_save( $this->conditions );
|
489 |
|
490 |
-
// save other options to post meta field
|
491 |
$options = $this->options();
|
492 |
|
493 |
$options['type'] = $this->type;
|
494 |
-
$options['url']
|
495 |
// Inform the tracking add-on about the new url.
|
496 |
-
unset
|
497 |
-
$options['width']
|
498 |
-
$options['height']
|
499 |
-
$options['conditions']
|
500 |
$options['expiry_date'] = $this->expiry_date;
|
501 |
$options['description'] = $this->description;
|
502 |
|
503 |
-
// sanitize container ID option
|
504 |
$options['output']['wrapper-id'] = sanitize_key( $options['output']['wrapper-id'] );
|
505 |
|
506 |
// filter to manipulate options or add more to be saved
|
@@ -513,7 +597,7 @@ class Advanced_Ads_Ad {
|
|
513 |
* Save ad options.
|
514 |
* Meant to be used from the outside of an ad.
|
515 |
*
|
516 |
-
* @param int
|
517 |
* @param array $options ad options.
|
518 |
*/
|
519 |
public static function save_ad_options( $ad_id, array $options ) {
|
@@ -527,7 +611,7 @@ class Advanced_Ads_Ad {
|
|
527 |
}
|
528 |
|
529 |
/**
|
530 |
-
*
|
531 |
*
|
532 |
* @return string $content ad content
|
533 |
* @since 1.0.0
|
@@ -537,48 +621,49 @@ class Advanced_Ads_Ad {
|
|
537 |
$content = $this->content;
|
538 |
|
539 |
// load ad type specific parameter filter
|
540 |
-
// @todo this is just a hotfix for type_obj not set, yet the cause is still unknown
|
541 |
-
if(is_object( $this->type_obj )){
|
542 |
-
|
543 |
}
|
544 |
-
// apply a custom filter by ad type
|
545 |
$content = apply_filters( 'advanced-ads-pre-ad-save-' . $this->type, $content );
|
546 |
|
547 |
return $content;
|
548 |
}
|
549 |
|
550 |
/**
|
551 |
-
*
|
552 |
*
|
553 |
-
* @return
|
554 |
*/
|
555 |
public function prepare_parameters_to_save() {
|
556 |
|
557 |
$parameters = $this->parameters;
|
558 |
-
// load ad type specific parameter filter
|
559 |
$parameters = $this->type_obj->sanitize_parameters( $parameters );
|
560 |
|
561 |
-
// apply native WP filter for content fields
|
562 |
return $parameters;
|
563 |
}
|
564 |
|
565 |
/**
|
566 |
-
*
|
567 |
*
|
|
|
568 |
*/
|
569 |
public function prepare_frontend_output() {
|
570 |
$options = $this->options();
|
571 |
|
572 |
if ( isset( $options['change-ad']['content'] ) ) {
|
573 |
-
// output was provided by the user
|
574 |
$output = $options['change-ad']['content'];
|
575 |
} else {
|
576 |
-
// load ad type specific content filter
|
577 |
$output = $this->type_obj->prepare_output( $this );
|
578 |
}
|
579 |
|
580 |
-
// don’t deliver anything, if main ad content is empty
|
581 |
-
if ( $output
|
582 |
return;
|
583 |
}
|
584 |
|
@@ -590,49 +675,51 @@ class Advanced_Ads_Ad {
|
|
590 |
$output = $this->label . $output;
|
591 |
}
|
592 |
|
593 |
-
// build wrapper around the ad
|
594 |
$output = $this->add_wrapper( $output );
|
595 |
|
596 |
-
// add a clearfix, if set
|
597 |
-
if ( ( isset($this->output['clearfix'] ) && $this->output['clearfix'] )
|
598 |
-
|
599 |
$output .= '<br style="clear: both; display: block; float: none;"/>';
|
600 |
}
|
601 |
}
|
602 |
-
|
603 |
|
604 |
-
// apply a custom filter by ad type
|
605 |
$output = apply_filters( 'advanced-ads-ad-output', $output, $this );
|
606 |
|
607 |
return $output;
|
608 |
}
|
609 |
|
610 |
/**
|
611 |
-
*
|
|
|
|
|
612 |
*
|
613 |
-
* @param array $conditions conditions array send via the dashboard form for an ad
|
614 |
* @return array with sanitized conditions
|
615 |
* @since 1.0.0
|
616 |
*/
|
617 |
-
public function sanitize_conditions_on_save($conditions = array()){
|
618 |
|
619 |
global $advanced_ads_ad_conditions;
|
620 |
|
621 |
-
if ( ! is_array( $conditions ) ||
|
|
|
|
|
622 |
|
623 |
-
foreach ( $conditions as $_key => $_condition ){
|
624 |
-
if (
|
625 |
// sanitize single post conditions
|
626 |
-
if ( empty($_condition['ids']) ){ // remove, if empty
|
627 |
$_condition['include'] = array();
|
628 |
$_condition['exclude'] = array();
|
629 |
-
} elseif( isset( $_condition['method'] ) ) {
|
630 |
-
switch ( $_condition['method'] ){
|
631 |
-
case
|
632 |
$_condition['include'] = $_condition['ids'];
|
633 |
$_condition['exclude'] = array();
|
634 |
break;
|
635 |
-
case
|
636 |
$_condition['include'] = array();
|
637 |
$_condition['exclude'] = $_condition['ids'];
|
638 |
break;
|
@@ -640,104 +727,111 @@ class Advanced_Ads_Ad {
|
|
640 |
}
|
641 |
} else {
|
642 |
if ( ! is_array( $_condition ) ) {
|
643 |
-
$_condition = trim( $_condition );
|
|
|
644 |
if ( $_condition == '' ) {
|
645 |
-
$conditions[$_key] = $_condition;
|
646 |
continue;
|
647 |
}
|
648 |
}
|
649 |
-
$type = ! empty($advanced_ads_ad_conditions[$_key]['type']) ? $advanced_ads_ad_conditions[$_key]['type'] : 0;
|
650 |
-
if ( empty($type) ) {
|
|
|
|
|
651 |
|
652 |
-
// dynamically apply filters for each condition used
|
653 |
-
$conditions[$_key] = apply_filters( 'advanced-ads-sanitize-condition-' . $type, $_condition );
|
654 |
}
|
|
|
655 |
return $conditions;
|
656 |
}
|
657 |
|
658 |
/**
|
659 |
-
*
|
|
|
|
|
660 |
*
|
661 |
-
* @pararm array/string $cond input string/array
|
662 |
* @return array/string $cond sanitized string/array
|
663 |
*/
|
664 |
-
public static function sanitize_condition_idfield($cond = ''){
|
665 |
-
// strip anything that is not comma or number
|
666 |
|
667 |
-
if ( is_array( $cond ) ){
|
668 |
-
foreach ( $cond as $_key => $_cond ){
|
669 |
-
$cond[$_key] = preg_replace( '#[^0-9,]#', '', $_cond );
|
670 |
}
|
671 |
} else {
|
672 |
$cond = preg_replace( '#[^0-9,]#', '', $cond );
|
673 |
}
|
|
|
674 |
return $cond;
|
675 |
}
|
676 |
|
677 |
/**
|
678 |
-
*
|
679 |
*
|
680 |
-
* @
|
681 |
-
*
|
|
|
682 |
*/
|
683 |
-
public static function sanitize_condition_radio($string = ''){
|
684 |
-
// only allow 0, 1 and empty
|
685 |
-
return
|
686 |
}
|
687 |
|
688 |
/**
|
689 |
-
*
|
690 |
*
|
691 |
-
* @
|
692 |
-
*
|
|
|
693 |
*/
|
694 |
-
public static function sanitize_condition_textvalues($cond = ''){
|
695 |
-
// strip anything that is not comma, alphanumeric, minus and underscore
|
696 |
-
if ( is_array( $cond ) ){
|
697 |
-
foreach ( $cond as $_key => $_cond ){
|
698 |
-
$cond[$_key] = preg_replace( '#[^0-9,A-Za-z-_]#', '', $_cond );
|
699 |
}
|
700 |
} else {
|
701 |
$cond = preg_replace( '#[^0-9,A-Za-z-_]#', '', $cond );
|
702 |
}
|
|
|
703 |
return $cond;
|
704 |
}
|
705 |
|
706 |
/**
|
707 |
-
*
|
708 |
*
|
|
|
709 |
* @since 1.3
|
710 |
-
* @return arr $wrapper options array ready to be use in add_wrapper() function
|
711 |
*/
|
712 |
-
protected function load_wrapper_options(){
|
713 |
$wrapper = array();
|
714 |
|
715 |
-
|
716 |
-
|
717 |
-
$position = ! empty( $this->output['position'] ) ? $this->output['position'] : '';
|
718 |
$use_placement_pos = false;
|
719 |
|
720 |
if ( $this->args['is_top_level'] ) {
|
721 |
-
if ( isset($this->output['class'] ) && is_array( $this->output['class'] ) ) {
|
722 |
$wrapper['class'] = $this->output['class'];
|
723 |
}
|
724 |
if ( ! empty( $this->args['placement_position'] ) ) {
|
725 |
// If not group, Set placement position instead of ad position.
|
726 |
$use_placement_pos = true;
|
727 |
-
$position
|
728 |
}
|
729 |
}
|
730 |
|
731 |
switch ( $position ) {
|
732 |
-
case 'left'
|
733 |
$wrapper['style']['float'] = 'left';
|
734 |
break;
|
735 |
-
case 'right'
|
736 |
$wrapper['style']['float'] = 'right';
|
737 |
break;
|
738 |
-
case 'center'
|
739 |
-
if ( ! empty
|
740 |
-
$wrapper['style']['margin-left']
|
741 |
$wrapper['style']['margin-right'] = 'auto';
|
742 |
|
743 |
if ( $use_placement_pos ) {
|
@@ -747,38 +841,37 @@ class Advanced_Ads_Ad {
|
|
747 |
$wrapper['style']['text-align'] = 'center';
|
748 |
}
|
749 |
|
750 |
-
// add css rule after wrapper to center the ad
|
751 |
-
// add_filter( 'advanced-ads-output-wrapper-after-content', array( $this, 'center_ad_content' ), 10, 2 );
|
752 |
break;
|
753 |
-
case 'clearfix'
|
754 |
$wrapper['style']['clear'] = 'both';
|
755 |
break;
|
756 |
}
|
757 |
|
758 |
-
// add manual classes
|
759 |
-
if ( isset($this->output['wrapper-class']) && '' !== $this->output['wrapper-class'] ) {
|
760 |
$classes = explode( ' ', $this->output['wrapper-class'] );
|
761 |
|
762 |
-
foreach( $classes as $_class ){
|
763 |
$wrapper['class'][] = sanitize_text_field( $_class );
|
764 |
}
|
765 |
}
|
766 |
|
767 |
-
if ( ! empty($this->output['margin']['top']) ) {
|
768 |
$wrapper['style']['margin-top'] = intval( $this->output['margin']['top'] ) . 'px';
|
769 |
}
|
770 |
-
if ( ! empty($this->output['margin']['right']) ) {
|
771 |
$wrapper['style']['margin-right'] = intval( $this->output['margin']['right'] ) . 'px';
|
772 |
}
|
773 |
-
if ( ! empty($this->output['margin']['bottom']) ) {
|
774 |
$wrapper['style']['margin-bottom'] = intval( $this->output['margin']['bottom'] ) . 'px';
|
775 |
}
|
776 |
-
if ( ! empty($this->output['margin']['left']) ) {
|
777 |
$wrapper['style']['margin-left'] = intval( $this->output['margin']['left'] ) . 'px';
|
778 |
}
|
779 |
|
780 |
-
if ( ! empty
|
781 |
-
$wrapper['style']['width']
|
782 |
$wrapper['style']['height'] = intval( $this->height ) . 'px';
|
783 |
}
|
784 |
|
@@ -786,37 +879,40 @@ class Advanced_Ads_Ad {
|
|
786 |
$wrapper['style']['clear'] = 'both';
|
787 |
}
|
788 |
|
789 |
-
|
790 |
return $wrapper;
|
791 |
}
|
792 |
|
793 |
/**
|
794 |
-
*
|
|
|
|
|
795 |
*
|
|
|
796 |
* @since 1.1.4
|
797 |
-
* @param str $ad_content content of the ad
|
798 |
-
* @return str $wrapper ad within the wrapper
|
799 |
*/
|
800 |
-
protected function add_wrapper($ad_content = ''){
|
801 |
$wrapper_options = apply_filters( 'advanced-ads-output-wrapper-options', $this->wrapper, $this );
|
802 |
|
803 |
if ( ( ! isset( $this->output['wrapper-id'] ) || '' === $this->output['wrapper-id'] )
|
804 |
-
|
|
|
|
|
805 |
|
806 |
-
// create unique id if not yet given
|
807 |
-
if ( empty($wrapper_options['id']) ){
|
808 |
-
$
|
|
|
809 |
}
|
810 |
-
|
811 |
-
// add edit button for users with the appropriate rights
|
812 |
-
if( ! defined( 'ADVANCED_ADS_DISABLE_EDIT_BAR' ) && current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ){
|
813 |
ob_start();
|
814 |
include ADVADS_BASE_PATH . 'public/views/ad-edit-bar.php';
|
815 |
$ad_content = ob_get_clean() . $ad_content;
|
816 |
}
|
817 |
-
|
818 |
// build the box
|
819 |
-
$wrapper
|
820 |
$wrapper .= apply_filters( 'advanced-ads-output-wrapper-before-content', '', $this );
|
821 |
$wrapper .= $ad_content;
|
822 |
$wrapper .= apply_filters( 'advanced-ads-output-wrapper-after-content', '', $this );
|
@@ -826,36 +922,16 @@ class Advanced_Ads_Ad {
|
|
826 |
}
|
827 |
|
828 |
/**
|
829 |
-
*
|
830 |
-
*
|
831 |
-
* @since 1.6.9.5
|
832 |
-
* @param str $output additional output in wrapper after content
|
833 |
-
* @param obj $ad Advanced_Ads_Ad object
|
834 |
-
* @return str $output
|
835 |
-
*
|
836 |
-
*/
|
837 |
-
/*public function center_ad_content( $output, Advanced_Ads_Ad $ad ){
|
838 |
-
|
839 |
-
// no additional check needed, because the hook is only called when the ad is centered
|
840 |
-
if( isset( $ad->wrapper['id'] )){
|
841 |
-
// does not work with most div elements, so actually not used now
|
842 |
-
$output .= '<style type="text/css">#'. $ad->wrapper['id'] . ' img, #'. $ad->wrapper['id'] . ' div { display: inline !important; }</style>';
|
843 |
-
}
|
844 |
-
|
845 |
-
return $output;
|
846 |
-
}*/
|
847 |
-
|
848 |
-
/**
|
849 |
-
* create a random wrapper id
|
850 |
*
|
851 |
-
* @since 1.1.4
|
852 |
* @return string $id random id string
|
|
|
853 |
*/
|
854 |
-
private function create_wrapper_id(){
|
855 |
|
856 |
-
if( isset( $this->output['wrapper-id'] )){
|
857 |
$id = sanitize_key( $this->output['wrapper-id'] );
|
858 |
-
if( '' !== $id ){
|
859 |
return $id;
|
860 |
}
|
861 |
}
|
@@ -871,9 +947,8 @@ class Advanced_Ads_Ad {
|
|
871 |
public function maybe_create_label() {
|
872 |
$placement_state = isset( $this->args['ad_label'] ) ? $this->args['ad_label'] : 'default';
|
873 |
|
874 |
-
|
875 |
-
|
876 |
-
) {
|
877 |
$this->label = $label;
|
878 |
}
|
879 |
}
|
@@ -892,12 +967,20 @@ class Advanced_Ads_Ad {
|
|
892 |
// If this is not the ad edit page.
|
893 |
if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
|
894 |
// Remove placeholders.
|
895 |
-
$this->url = str_replace(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
896 |
}
|
897 |
}
|
|
|
898 |
return $this->url;
|
899 |
}
|
900 |
|
901 |
-
|
902 |
-
|
903 |
}
|
1 |
<?php
|
|
|
2 |
/**
|
3 |
* Advanced Ads Ad.
|
4 |
*
|
6 |
* @author Thomas Maier <support@wpadvancedads.com>
|
7 |
* @license GPL-2.0+
|
8 |
* @link https://wpadvancedads.com
|
9 |
+
* @copyright 2013-2020 Thomas Maier, Advanced Ads GmbH
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* An ad object
|
14 |
*
|
15 |
* @package Advanced_Ads_Ad
|
16 |
* @author Thomas Maier <support@wpadvancedads.com>
|
17 |
* @deprecated since version 1.5.3 (May 6th 2015)
|
18 |
* might still be needed if some old add-ons are running somewhere
|
19 |
*/
|
20 |
+
if ( ! class_exists( 'Advads_Ad', false ) ) {
|
21 |
+
class Advads_Ad extends Advanced_Ads_Ad {
|
22 |
|
23 |
+
}
|
24 |
}
|
25 |
|
26 |
/**
|
27 |
+
* An ad object
|
28 |
*
|
29 |
* @package Advanced_Ads_Ad
|
30 |
* @author Thomas Maier <support@wpadvancedads.com>
|
32 |
class Advanced_Ads_Ad {
|
33 |
|
34 |
/**
|
35 |
+
* Id of the post type for this ad
|
36 |
+
*
|
37 |
+
* @var int $id
|
38 |
*/
|
39 |
public $id = 0;
|
40 |
|
41 |
/**
|
42 |
+
* True, if this is an Advanced Ads Ad post type
|
43 |
+
*
|
44 |
+
* @var bool $is_ad
|
45 |
*/
|
46 |
public $is_ad = false;
|
47 |
|
48 |
/**
|
49 |
+
* Ad type
|
50 |
+
*
|
51 |
+
* @var string $type ad type.
|
52 |
*/
|
53 |
public $type = 'content';
|
54 |
|
55 |
/**
|
56 |
+
* Ad width
|
57 |
+
*
|
58 |
+
* @var int $width width of the ad.
|
59 |
*/
|
60 |
public $width = 0;
|
61 |
|
62 |
/**
|
63 |
+
* Target url
|
64 |
*
|
65 |
+
* @var string $url ad URL parameter.
|
66 |
*/
|
67 |
public $url = '';
|
68 |
|
69 |
/**
|
70 |
+
* Ad height
|
71 |
+
*
|
72 |
+
* @var int $height height of the ad.
|
73 |
*/
|
74 |
public $height = 0;
|
75 |
|
76 |
/**
|
77 |
+
* Object of current ad type
|
78 |
+
*
|
79 |
+
* @var object $type_obj object of the current ad type.
|
80 |
*/
|
81 |
protected $type_obj;
|
82 |
|
83 |
/**
|
84 |
+
* Content of the ad
|
85 |
+
*
|
86 |
+
* Only needed for ad types using the post content field
|
87 |
*
|
88 |
+
* @var string $content content of the ad.
|
89 |
*/
|
90 |
public $content = '';
|
91 |
|
92 |
/**
|
93 |
+
* Conditions of the ad display
|
94 |
+
*
|
95 |
+
* @var array $conditions display and visitor conditions.
|
96 |
*/
|
97 |
public $conditions = array();
|
98 |
|
99 |
/**
|
100 |
+
* Status of the ad (e.g. publish, pending)
|
101 |
+
*
|
102 |
+
* @var string $status status of the ad.
|
103 |
*/
|
104 |
+
public $status = '';
|
105 |
|
106 |
/**
|
107 |
+
* Array with meta field options aka parameters
|
108 |
+
*
|
109 |
+
* @var array $options ad options.
|
110 |
*/
|
111 |
protected $options = array();
|
112 |
|
113 |
/**
|
114 |
+
* Name of the meta field to save options to
|
115 |
+
*
|
116 |
+
* @var string $options_meta_field under which post meta key the ad options are stored.
|
117 |
*/
|
118 |
+
public static $options_meta_field = 'advanced_ads_ad_options';
|
119 |
|
120 |
/**
|
121 |
+
* Additional arguments set when ad is loaded, overwrites or extends options
|
122 |
+
*
|
123 |
+
* @var array $args
|
124 |
*/
|
125 |
public $args = array();
|
126 |
|
127 |
/**
|
128 |
+
* Multidimensional array contains information about the wrapper
|
129 |
+
* Each possible html attribute is an array with possible multiple elements
|
130 |
+
*
|
131 |
+
* @var array $wrapper options of the ad wrapper.
|
132 |
*/
|
133 |
public $wrapper = array();
|
134 |
|
135 |
+
/**
|
136 |
+
* Will the ad be tracked?
|
137 |
+
*
|
138 |
+
* @var mixed $global_output
|
139 |
+
*/
|
140 |
+
public $global_output;
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Title of the ad
|
144 |
+
*
|
145 |
+
* @var string $title
|
146 |
+
*/
|
147 |
+
public $title = '';
|
148 |
+
|
149 |
/**
|
150 |
* Displayed above the ad.
|
151 |
+
*
|
152 |
+
* @var string $label ad label.
|
153 |
*/
|
154 |
protected $label = '';
|
155 |
|
156 |
/**
|
157 |
+
* Init ad object
|
158 |
*
|
159 |
+
* @param int $id id of the ad.
|
160 |
+
* @param array $args additional arguments.
|
161 |
*/
|
162 |
+
public function __construct( $id, $args = array() ) {
|
163 |
+
$id = absint( $id );
|
164 |
+
$this->id = $id;
|
165 |
$this->args = is_array( $args ) ? $args : array();
|
166 |
|
167 |
+
// whether the ad will be tracked.
|
168 |
$this->global_output = isset( $this->args['global_output'] ) ? (bool) $this->args['global_output'] : true;
|
169 |
|
170 |
+
if ( ! empty( $id ) ) {
|
171 |
+
$this->load( $id );
|
172 |
+
}
|
173 |
|
174 |
+
// dynamically add sanitize filters for condition types.
|
175 |
$_types = array();
|
176 |
// -TODO use model
|
177 |
$advanced_ads_ad_conditions = Advanced_Ads::get_ad_conditions();
|
178 |
foreach ( $advanced_ads_ad_conditions as $_condition ) {
|
179 |
+
// add unique.
|
180 |
+
$_types[ $_condition['type'] ] = false;
|
181 |
}
|
182 |
+
// iterate types.
|
183 |
foreach ( array_keys( $_types ) as $_type ) {
|
184 |
// -TODO might be faster to use __call() method or isset()-test class method array
|
185 |
+
$method_name = 'sanitize_condition_' . $_type;
|
186 |
if ( method_exists( $this, $method_name ) ) {
|
187 |
+
add_filter( 'advanced-ads-sanitize-condition-' . $_type, array( $this, $method_name ), 10, 1 );
|
188 |
} elseif ( function_exists( 'advads_sanitize_condition_' . $_type ) ) {
|
189 |
+
// check for public function to sanitize this.
|
190 |
add_filter( 'advanced-ads-sanitize-condition-' . $_type, 'advads_sanitize_condition_' . $_type, 10, 1 );
|
191 |
|
192 |
}
|
194 |
}
|
195 |
|
196 |
/**
|
197 |
+
* Load an ad object by id based on its ad type
|
198 |
*
|
199 |
+
* @param int $id ad id.
|
200 |
+
*
|
201 |
+
* @return bool false if ad could not be loaded.
|
202 |
*/
|
203 |
+
private function load( $id = 0 ) {
|
204 |
|
205 |
$_data = get_post( $id );
|
206 |
+
if ( null === $_data ) {
|
207 |
+
return false;
|
208 |
+
}
|
209 |
|
210 |
+
// return, if not an ad.
|
211 |
+
if ( Advanced_Ads::POST_TYPE_SLUG !== $_data->post_type ) {
|
212 |
return false;
|
213 |
} else {
|
214 |
$this->is_ad = true;
|
215 |
}
|
216 |
|
217 |
+
$this->type = $this->options( 'type' );
|
|
|
218 |
$this->title = $_data->post_title;
|
219 |
/* load ad type object */
|
220 |
$types = Advanced_Ads::get_instance()->ad_types;
|
221 |
+
if ( isset( $types[ $this->type ] ) ) {
|
222 |
+
$this->type_obj = $types[ $this->type ];
|
223 |
} else {
|
224 |
+
$this->type_obj = new Advanced_Ads_Ad_Type_Abstract();
|
225 |
+
}
|
226 |
+
$this->url = $this->get_url();
|
227 |
+
$this->width = absint( $this->options( 'width' ) );
|
228 |
+
$this->height = absint( $this->options( 'height' ) );
|
229 |
+
$this->conditions = $this->options( 'conditions' );
|
230 |
+
$this->description = $this->options( 'description' );
|
231 |
+
$this->output = $this->options( 'output' );
|
232 |
+
$this->status = $_data->post_status;
|
233 |
+
$this->expiry_date = $this->options( 'expiry_date' );
|
234 |
+
$this->is_head_placement = isset( $this->args['placement_type'] ) && 'header' === $this->args['placement_type'];
|
235 |
$this->args['is_top_level'] = ! isset( $this->args['is_top_level'] );
|
|
|
|
|
|
|
236 |
|
237 |
+
// load content based on ad type.
|
238 |
+
$this->content = $this->type_obj->load_content( $_data );
|
239 |
|
240 |
if ( ! $this->is_head_placement ) {
|
241 |
$this->maybe_create_label();
|
242 |
$this->wrapper = $this->load_wrapper_options();
|
243 |
|
244 |
+
// set wrapper conditions.
|
245 |
$this->wrapper = apply_filters( 'advanced-ads-set-wrapper', $this->wrapper, $this );
|
246 |
+
// add unique wrapper id.
|
247 |
if ( is_array( $this->wrapper )
|
248 |
+
&& array() !== $this->wrapper
|
249 |
+
&& ! isset( $this->wrapper['id'] ) ) {
|
250 |
+
// create unique id if not yet given.
|
251 |
$this->wrapper['id'] = $this->create_wrapper_id();
|
252 |
}
|
253 |
}
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
+
* Get options from meta field and return specific field
|
258 |
+
*
|
259 |
+
* @param string $field post meta key to be returned.
|
260 |
+
* @param array $default default options.
|
261 |
*
|
|
|
262 |
* @return mixed meta field content
|
|
|
263 |
* @todo check against default values
|
264 |
*/
|
265 |
public function options( $field = '', $default = null ) {
|
266 |
// retrieve options, if not given yet
|
267 |
// -TODO may execute multiple times (if empty); bad design and risk to access unintialised data with direct access to $this->options property.
|
268 |
+
if ( array() === $this->options ) {
|
269 |
+
// may return false.
|
270 |
$meta = get_post_meta( $this->id, self::$options_meta_field, true );
|
271 |
if ( $meta ) {
|
272 |
+
// merge meta with arguments given on ad load.
|
273 |
$this->options = Advanced_Ads_Utils::merge_deep_array( array( $meta, $this->args ) );
|
274 |
} else {
|
275 |
+
// load arguments given on ad load.
|
276 |
$this->options = $this->args;
|
277 |
}
|
278 |
|
279 |
if ( isset( $this->options['change-ad'] ) ) {
|
280 |
+
// some options was provided by the user.
|
281 |
+
$this->options = Advanced_Ads_Utils::merge_deep_array(
|
282 |
+
array(
|
283 |
+
$this->options,
|
284 |
+
$this->options['change-ad'],
|
285 |
+
)
|
286 |
+
);
|
287 |
}
|
288 |
}
|
289 |
+
|
290 |
+
// return specific option.
|
291 |
+
if ( '' !== $field ) {
|
292 |
+
if ( isset( $this->options[ $field ] ) ) {
|
293 |
+
return $this->options[ $field ];
|
294 |
}
|
295 |
+
} else { // return all options.
|
296 |
+
if ( ! empty( $this->options ) ) {
|
297 |
return $this->options;
|
298 |
}
|
299 |
}
|
302 |
}
|
303 |
|
304 |
/**
|
305 |
+
* Set an option of the ad
|
306 |
+
*
|
307 |
+
* @param string $option name of the option.
|
308 |
+
* @param mixed $value value of the option.
|
309 |
*
|
310 |
* @since 1.1.0
|
|
|
|
|
311 |
*/
|
312 |
+
public function set_option( $option = '', $value = '' ) {
|
313 |
+
if ( '' === $option ) {
|
314 |
+
return;
|
315 |
+
}
|
316 |
|
317 |
+
// get current options.
|
318 |
$options = $this->options();
|
319 |
|
320 |
+
// set options.
|
321 |
+
$options[ $option ] = $value;
|
322 |
|
323 |
+
// save options.
|
324 |
$this->options = $options;
|
325 |
|
326 |
}
|
327 |
|
328 |
|
329 |
/**
|
330 |
+
* Return ad content for frontend output
|
331 |
+
*
|
332 |
+
* @param array $output_options output options.
|
333 |
*
|
|
|
|
|
334 |
* @return string $output ad output
|
335 |
+
* @since 1.0.0
|
336 |
*/
|
337 |
+
public function output( $output_options = array() ) {
|
338 |
+
if ( ! $this->is_ad ) {
|
339 |
+
return '';
|
340 |
+
}
|
341 |
|
342 |
+
$this->global_output = isset( $output_options['global_output'] ) ? $output_options['global_output'] : $this->global_output;
|
343 |
+
$output_options['global_output'] = $this->global_output;
|
344 |
+
|
345 |
+
// switch between normal and debug mode.
|
346 |
+
// check if debug output should only be displayed to admins.
|
347 |
+
$user_can_manage_ads = current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) );
|
348 |
+
if ( isset( $this->output['debugmode'] )
|
349 |
+
&& ( $user_can_manage_ads || ( ! $user_can_manage_ads && ! defined( 'ADVANCED_ADS_AD_DEBUG_FOR_ADMIN_ONLY' ) ) ) ) {
|
350 |
+
$debug = new Advanced_Ads_Ad_Debug();
|
351 |
|
|
|
|
|
|
|
|
|
|
|
|
|
352 |
return $debug->prepare_debug_output( $this );
|
353 |
} else {
|
354 |
+
$output = $this->prepare_frontend_output();
|
355 |
}
|
356 |
|
357 |
+
// add the ad to the global output array.
|
358 |
$advads = Advanced_Ads::get_instance();
|
359 |
if ( $output_options['global_output'] ) {
|
360 |
+
$new_ad = array(
|
361 |
+
'type' => 'ad',
|
362 |
+
'id' => $this->id,
|
363 |
+
'title' => $this->title,
|
364 |
+
'output' => $output,
|
365 |
+
);
|
366 |
// if ( method_exists( 'Advanced_Ads_Tracking_Plugin' , 'check_ad_tracking_enabled' ) ) {
|
367 |
// if ( class_exists( 'Advanced_Ads_Tracking_Plugin', false ) ) {
|
368 |
+
if ( defined( 'AAT_VERSION' ) && - 1 < version_compare( AAT_VERSION, '1.4.2' ) ) {
|
369 |
+
|
370 |
$new_ad['tracking_enabled'] = Advanced_Ads_Tracking_Plugin::get_instance()->check_ad_tracking_enabled( $this );
|
371 |
+
|
372 |
$tracking_options = Advanced_Ads_Tracking_Plugin::get_instance()->options();
|
373 |
+
if ( isset( $tracking_options['method'] ) && 'frontend' === $tracking_options['method'] && isset( $this->output['placement_id'] ) ) {
|
374 |
$new_ad['placement_id'] = $this->output['placement_id'];
|
375 |
}
|
|
|
376 |
}
|
377 |
+
|
378 |
$advads->current_ads[] = $new_ad;
|
379 |
}
|
380 |
+
|
381 |
+
// action when output is created.
|
382 |
do_action( 'advanced-ads-output', $this, $output, $output_options );
|
383 |
+
|
384 |
return apply_filters( 'advanced-ads-output-final', $output, $this, $output_options );
|
385 |
}
|
386 |
|
387 |
/**
|
388 |
+
* Check if the ad can be displayed in frontend due to its own conditions
|
389 |
+
*
|
390 |
+
* @param array $check_options check options.
|
391 |
*
|
|
|
|
|
392 |
* @return bool $can_display true if can be displayed in frontend
|
393 |
+
* @since 1.0.0
|
394 |
*/
|
395 |
public function can_display( $check_options = array() ) {
|
396 |
+
$check_options = wp_parse_args(
|
397 |
+
$check_options,
|
398 |
+
array(
|
399 |
+
'passive_cache_busting' => false,
|
400 |
+
'ignore_debugmode' => false,
|
401 |
+
)
|
402 |
+
);
|
403 |
+
|
404 |
+
// prevent ad to show up through wp_head, if this is not a header placement.
|
405 |
+
if ( doing_action( 'wp_head' ) && isset( $this->options['placement_type'] ) && 'header' !== $this->options['placement_type'] ) {
|
406 |
+
return false;
|
407 |
}
|
408 |
|
409 |
// Check If the current ad is requested using a shortcode placed in the content of the current ad.
|
411 |
return false;
|
412 |
}
|
413 |
|
414 |
+
// force ad display if debug mode is enabled.
|
415 |
+
if ( isset( $this->output['debugmode'] ) && ! $check_options['ignore_debugmode'] ) {
|
416 |
+
return true;
|
417 |
}
|
418 |
+
|
419 |
if ( ! $check_options['passive_cache_busting'] ) {
|
420 |
+
// don’t display ads that are not published or private for users not logged in.
|
421 |
+
if ( 'publish' !== $this->status && ! ( 'private' === $this->status && is_user_logged_in() ) ) {
|
422 |
return false;
|
423 |
}
|
424 |
|
426 |
return false;
|
427 |
}
|
428 |
} else {
|
429 |
+
if ( 'publish' !== $this->status || ! $this->can_display_by_expiry_date() ) {
|
430 |
return false;
|
431 |
}
|
432 |
}
|
433 |
|
434 |
+
// add own conditions to flag output as possible or not.
|
435 |
$can_display = apply_filters( 'advanced-ads-can-display', true, $this, $check_options );
|
436 |
|
437 |
return $can_display;
|
438 |
}
|
439 |
|
440 |
/**
|
441 |
+
* Check visitor conditions
|
442 |
*
|
|
|
443 |
* @return bool $can_display true if can be displayed in frontend based on visitor settings
|
444 |
+
* @since 1.1.0
|
445 |
*/
|
446 |
+
public function can_display_by_visitor() {
|
447 |
if ( ! empty( $this->options['wp_the_query']['is_feed'] ) ) {
|
448 |
return true;
|
449 |
}
|
450 |
|
451 |
+
// check old "visitor" and new "visitors" conditions.
|
452 |
+
if ( ( empty( $this->options['visitors'] ) ||
|
453 |
+
! is_array( $this->options['visitors'] ) )
|
454 |
+
&& ( empty( $this->options['visitor'] ) ||
|
455 |
+
! is_array( $this->options['visitor'] )
|
456 |
+
) ) {
|
457 |
+
return true;
|
458 |
+
}
|
459 |
|
460 |
if ( isset( $this->options['visitors'] ) && is_array( $this->options['visitors'] ) ) {
|
461 |
|
462 |
+
$visitor_conditions = $this->options['visitors'];
|
463 |
+
|
464 |
+
$last_result = false;
|
465 |
+
$length = count( $visitor_conditions );
|
466 |
+
|
467 |
+
for ( $i = 0; $i < $length; ++ $i ) {
|
468 |
+
$_condition = current( $visitor_conditions );
|
469 |
+
// ignore OR if last result was true.
|
470 |
+
if ( $last_result && isset( $_condition['connector'] ) && 'or' === $_condition['connector'] ) {
|
471 |
+
next( $visitor_conditions );
|
472 |
+
continue;
|
473 |
+
}
|
474 |
+
$result = Advanced_Ads_Visitor_Conditions::frontend_check( $_condition, $this );
|
475 |
+
$last_result = $result;
|
476 |
+
if ( ! $result ) {
|
477 |
+
// return false only, if the next condition doesn’t have an OR operator.
|
478 |
+
$next = next( $visitor_conditions );
|
479 |
+
if ( ! isset( $next['connector'] ) || 'or' !== $next['connector'] ) {
|
480 |
+
return false;
|
481 |
+
}
|
482 |
+
} else {
|
483 |
+
next( $visitor_conditions );
|
484 |
+
}
|
485 |
}
|
|
|
486 |
}
|
487 |
|
488 |
/**
|
491 |
* @deprecated since version 1.5.4
|
492 |
*/
|
493 |
|
494 |
+
if ( empty( $this->options['visitor'] ) ||
|
495 |
+
! is_array( $this->options['visitor'] ) ) {
|
496 |
+
return true;
|
497 |
+
}
|
498 |
$visitor_conditions = $this->options( 'visitor' );
|
499 |
|
500 |
+
// check mobile condition.
|
501 |
+
if ( isset( $visitor_conditions['mobile'] ) ) {
|
502 |
+
switch ( $visitor_conditions['mobile'] ) {
|
503 |
+
case 'only':
|
504 |
+
if ( ! wp_is_mobile() ) {
|
505 |
+
return false;
|
506 |
+
}
|
507 |
break;
|
508 |
+
case 'no':
|
509 |
+
if ( wp_is_mobile() ) {
|
510 |
+
return false;
|
511 |
+
}
|
512 |
break;
|
513 |
}
|
514 |
}
|
517 |
}
|
518 |
|
519 |
/**
|
520 |
+
* Check expiry date
|
521 |
*
|
|
|
522 |
* @return bool $can_display true if can be displayed in frontend based on expiry date
|
523 |
+
* @since 1.3.15
|
524 |
*/
|
525 |
+
public function can_display_by_expiry_date() {
|
526 |
|
527 |
+
// if expiry_date is not set, null is returned.
|
528 |
$ad_expiry_date = (int) $this->options( 'expiry_date' );
|
529 |
|
530 |
if ( $ad_expiry_date <= 0 || $ad_expiry_date > time() ) {
|
531 |
return true;
|
532 |
}
|
533 |
|
534 |
+
// set status to 'draft' if the ad is expired.
|
535 |
+
if ( 'draft' !== $this->status ) {
|
536 |
+
// removing the kses filters here so that expiring ads don’t lose HTML or other code.
|
537 |
+
kses_remove_filters();
|
538 |
+
wp_update_post(
|
539 |
+
array(
|
540 |
+
'ID' => $this->id,
|
541 |
+
'post_status' => 'draft',
|
542 |
+
)
|
543 |
+
);
|
544 |
+
kses_init_filters();
|
545 |
/**
|
546 |
* Run when an ad expires
|
547 |
*/
|
552 |
}
|
553 |
|
554 |
/**
|
555 |
+
* Save an ad to the database
|
556 |
* takes values from the current state
|
557 |
*/
|
558 |
+
public function save() {
|
559 |
global $wpdb;
|
560 |
|
561 |
+
// remove slashes from content.
|
562 |
$this->content = $this->prepare_content_to_save();
|
563 |
|
564 |
+
$where = array( 'ID' => $this->id );
|
565 |
$wpdb->update( $wpdb->posts, array( 'post_content' => $this->content ), $where );
|
566 |
|
567 |
+
// clean post from object cache.
|
568 |
clean_post_cache( $this->id );
|
569 |
|
570 |
// sanitize conditions
|
571 |
+
// see sanitize_conditions function for example on using this filter.
|
572 |
$conditions = self::sanitize_conditions_on_save( $this->conditions );
|
573 |
|
574 |
+
// save other options to post meta field.
|
575 |
$options = $this->options();
|
576 |
|
577 |
$options['type'] = $this->type;
|
578 |
+
$options['url'] = $this->url;
|
579 |
// Inform the tracking add-on about the new url.
|
580 |
+
unset( $options['tracking']['link'] );
|
581 |
+
$options['width'] = $this->width;
|
582 |
+
$options['height'] = $this->height;
|
583 |
+
$options['conditions'] = $conditions;
|
584 |
$options['expiry_date'] = $this->expiry_date;
|
585 |
$options['description'] = $this->description;
|
586 |
|
587 |
+
// sanitize container ID option.
|
588 |
$options['output']['wrapper-id'] = sanitize_key( $options['output']['wrapper-id'] );
|
589 |
|
590 |
// filter to manipulate options or add more to be saved
|
597 |
* Save ad options.
|
598 |
* Meant to be used from the outside of an ad.
|
599 |
*
|
600 |
+
* @param int $ad_id post ID of the ad.
|
601 |
* @param array $options ad options.
|
602 |
*/
|
603 |
public static function save_ad_options( $ad_id, array $options ) {
|
611 |
}
|
612 |
|
613 |
/**
|
614 |
+
* Native filter for content field before being saved
|
615 |
*
|
616 |
* @return string $content ad content
|
617 |
* @since 1.0.0
|
621 |
$content = $this->content;
|
622 |
|
623 |
// load ad type specific parameter filter
|
624 |
+
// @todo this is just a hotfix for type_obj not set, yet the cause is still unknown.
|
625 |
+
if ( is_object( $this->type_obj ) ) {
|
626 |
+
$content = $this->type_obj->sanitize_content( $content );
|
627 |
}
|
628 |
+
// apply a custom filter by ad type.
|
629 |
$content = apply_filters( 'advanced-ads-pre-ad-save-' . $this->type, $content );
|
630 |
|
631 |
return $content;
|
632 |
}
|
633 |
|
634 |
/**
|
635 |
+
* Native filter for ad parameters before being saved
|
636 |
*
|
637 |
+
* @return array $parameters sanitized parameters.
|
638 |
*/
|
639 |
public function prepare_parameters_to_save() {
|
640 |
|
641 |
$parameters = $this->parameters;
|
642 |
+
// load ad type specific parameter filter.
|
643 |
$parameters = $this->type_obj->sanitize_parameters( $parameters );
|
644 |
|
645 |
+
// apply native WP filter for content fields.
|
646 |
return $parameters;
|
647 |
}
|
648 |
|
649 |
/**
|
650 |
+
* Prepare ads output
|
651 |
*
|
652 |
+
* @return string.
|
653 |
*/
|
654 |
public function prepare_frontend_output() {
|
655 |
$options = $this->options();
|
656 |
|
657 |
if ( isset( $options['change-ad']['content'] ) ) {
|
658 |
+
// output was provided by the user.
|
659 |
$output = $options['change-ad']['content'];
|
660 |
} else {
|
661 |
+
// load ad type specific content filter.
|
662 |
$output = $this->type_obj->prepare_output( $this );
|
663 |
}
|
664 |
|
665 |
+
// don’t deliver anything, if main ad content is empty.
|
666 |
+
if ( empty( $output ) ) {
|
667 |
return;
|
668 |
}
|
669 |
|
675 |
$output = $this->label . $output;
|
676 |
}
|
677 |
|
678 |
+
// build wrapper around the ad.
|
679 |
$output = $this->add_wrapper( $output );
|
680 |
|
681 |
+
// add a clearfix, if set.
|
682 |
+
if ( ( isset( $this->output['clearfix'] ) && $this->output['clearfix'] )
|
683 |
+
|| ( ! empty( $this->args['is_top_level'] ) && ! empty( $this->args['placement_clearfix'] ) ) ) {
|
684 |
$output .= '<br style="clear: both; display: block; float: none;"/>';
|
685 |
}
|
686 |
}
|
|
|
687 |
|
688 |
+
// apply a custom filter by ad type.
|
689 |
$output = apply_filters( 'advanced-ads-ad-output', $output, $this );
|
690 |
|
691 |
return $output;
|
692 |
}
|
693 |
|
694 |
/**
|
695 |
+
* Sanitize ad display conditions when saving the ad
|
696 |
+
*
|
697 |
+
* @param array $conditions conditions array send via the dashboard form for an ad.
|
698 |
*
|
|
|
699 |
* @return array with sanitized conditions
|
700 |
* @since 1.0.0
|
701 |
*/
|
702 |
+
public function sanitize_conditions_on_save( $conditions = array() ) {
|
703 |
|
704 |
global $advanced_ads_ad_conditions;
|
705 |
|
706 |
+
if ( ! is_array( $conditions ) || array() === $conditions ) {
|
707 |
+
return array();
|
708 |
+
}
|
709 |
|
710 |
+
foreach ( $conditions as $_key => $_condition ) {
|
711 |
+
if ( 'postids' === $_key ) {
|
712 |
// sanitize single post conditions
|
713 |
+
if ( empty( $_condition['ids'] ) ) { // remove, if empty.
|
714 |
$_condition['include'] = array();
|
715 |
$_condition['exclude'] = array();
|
716 |
+
} elseif ( isset( $_condition['method'] ) ) {
|
717 |
+
switch ( $_condition['method'] ) {
|
718 |
+
case 'include':
|
719 |
$_condition['include'] = $_condition['ids'];
|
720 |
$_condition['exclude'] = array();
|
721 |
break;
|
722 |
+
case 'exclude':
|
723 |
$_condition['include'] = array();
|
724 |
$_condition['exclude'] = $_condition['ids'];
|
725 |
break;
|
727 |
}
|
728 |
} else {
|
729 |
if ( ! is_array( $_condition ) ) {
|
730 |
+
$_condition = trim( $_condition );
|
731 |
+
}
|
732 |
if ( $_condition == '' ) {
|
733 |
+
$conditions[ $_key ] = $_condition;
|
734 |
continue;
|
735 |
}
|
736 |
}
|
737 |
+
$type = ! empty( $advanced_ads_ad_conditions[ $_key ]['type'] ) ? $advanced_ads_ad_conditions[ $_key ]['type'] : 0;
|
738 |
+
if ( empty( $type ) ) {
|
739 |
+
continue;
|
740 |
+
}
|
741 |
|
742 |
+
// dynamically apply filters for each condition used.
|
743 |
+
$conditions[ $_key ] = apply_filters( 'advanced-ads-sanitize-condition-' . $type, $_condition );
|
744 |
}
|
745 |
+
|
746 |
return $conditions;
|
747 |
}
|
748 |
|
749 |
/**
|
750 |
+
* Sanitize id input field(s) for pattern /1,2,3,4/
|
751 |
+
*
|
752 |
+
* @param mixed $cond input string/array.
|
753 |
*
|
|
|
754 |
* @return array/string $cond sanitized string/array
|
755 |
*/
|
756 |
+
public static function sanitize_condition_idfield( $cond = '' ) {
|
757 |
+
// strip anything that is not comma or number.
|
758 |
|
759 |
+
if ( is_array( $cond ) ) {
|
760 |
+
foreach ( $cond as $_key => $_cond ) {
|
761 |
+
$cond[ $_key ] = preg_replace( '#[^0-9,]#', '', $_cond );
|
762 |
}
|
763 |
} else {
|
764 |
$cond = preg_replace( '#[^0-9,]#', '', $cond );
|
765 |
}
|
766 |
+
|
767 |
return $cond;
|
768 |
}
|
769 |
|
770 |
/**
|
771 |
+
* Sanitize radio input field
|
772 |
*
|
773 |
+
* @param string $string input string.
|
774 |
+
*
|
775 |
+
* @return string $string sanitized string.
|
776 |
*/
|
777 |
+
public static function sanitize_condition_radio( $string = '' ) {
|
778 |
+
// only allow 0, 1 and empty.
|
779 |
+
return preg_replace( '#[^01]#', '', $string );
|
780 |
}
|
781 |
|
782 |
/**
|
783 |
+
* Sanitize comma seperated text input field
|
784 |
*
|
785 |
+
* @param mixed $cond input string/array.
|
786 |
+
*
|
787 |
+
* @return array/string $cond sanitized string/array.
|
788 |
*/
|
789 |
+
public static function sanitize_condition_textvalues( $cond = '' ) {
|
790 |
+
// strip anything that is not comma, alphanumeric, minus and underscore.
|
791 |
+
if ( is_array( $cond ) ) {
|
792 |
+
foreach ( $cond as $_key => $_cond ) {
|
793 |
+
$cond[ $_key ] = preg_replace( '#[^0-9,A-Za-z-_]#', '', $_cond );
|
794 |
}
|
795 |
} else {
|
796 |
$cond = preg_replace( '#[^0-9,A-Za-z-_]#', '', $cond );
|
797 |
}
|
798 |
+
|
799 |
return $cond;
|
800 |
}
|
801 |
|
802 |
/**
|
803 |
+
* Load wrapper options set with the ad
|
804 |
*
|
805 |
+
* @return array $wrapper options array ready to be use in add_wrapper() function.
|
806 |
* @since 1.3
|
|
|
807 |
*/
|
808 |
+
protected function load_wrapper_options() {
|
809 |
$wrapper = array();
|
810 |
|
811 |
+
$position = ! empty( $this->output['position'] ) ? $this->output['position'] : '';
|
|
|
|
|
812 |
$use_placement_pos = false;
|
813 |
|
814 |
if ( $this->args['is_top_level'] ) {
|
815 |
+
if ( isset( $this->output['class'] ) && is_array( $this->output['class'] ) ) {
|
816 |
$wrapper['class'] = $this->output['class'];
|
817 |
}
|
818 |
if ( ! empty( $this->args['placement_position'] ) ) {
|
819 |
// If not group, Set placement position instead of ad position.
|
820 |
$use_placement_pos = true;
|
821 |
+
$position = $this->args['placement_position'];
|
822 |
}
|
823 |
}
|
824 |
|
825 |
switch ( $position ) {
|
826 |
+
case 'left':
|
827 |
$wrapper['style']['float'] = 'left';
|
828 |
break;
|
829 |
+
case 'right':
|
830 |
$wrapper['style']['float'] = 'right';
|
831 |
break;
|
832 |
+
case 'center':
|
833 |
+
if ( ! empty( $this->output['add_wrapper_sizes'] ) ) {
|
834 |
+
$wrapper['style']['margin-left'] = 'auto';
|
835 |
$wrapper['style']['margin-right'] = 'auto';
|
836 |
|
837 |
if ( $use_placement_pos ) {
|
841 |
$wrapper['style']['text-align'] = 'center';
|
842 |
}
|
843 |
|
844 |
+
// add css rule after wrapper to center the ad.
|
|
|
845 |
break;
|
846 |
+
case 'clearfix':
|
847 |
$wrapper['style']['clear'] = 'both';
|
848 |
break;
|
849 |
}
|
850 |
|
851 |
+
// add manual classes.
|
852 |
+
if ( isset( $this->output['wrapper-class'] ) && '' !== $this->output['wrapper-class'] ) {
|
853 |
$classes = explode( ' ', $this->output['wrapper-class'] );
|
854 |
|
855 |
+
foreach ( $classes as $_class ) {
|
856 |
$wrapper['class'][] = sanitize_text_field( $_class );
|
857 |
}
|
858 |
}
|
859 |
|
860 |
+
if ( ! empty( $this->output['margin']['top'] ) ) {
|
861 |
$wrapper['style']['margin-top'] = intval( $this->output['margin']['top'] ) . 'px';
|
862 |
}
|
863 |
+
if ( ! empty( $this->output['margin']['right'] ) ) {
|
864 |
$wrapper['style']['margin-right'] = intval( $this->output['margin']['right'] ) . 'px';
|
865 |
}
|
866 |
+
if ( ! empty( $this->output['margin']['bottom'] ) ) {
|
867 |
$wrapper['style']['margin-bottom'] = intval( $this->output['margin']['bottom'] ) . 'px';
|
868 |
}
|
869 |
+
if ( ! empty( $this->output['margin']['left'] ) ) {
|
870 |
$wrapper['style']['margin-left'] = intval( $this->output['margin']['left'] ) . 'px';
|
871 |
}
|
872 |
|
873 |
+
if ( ! empty( $this->output['add_wrapper_sizes'] ) ) {
|
874 |
+
$wrapper['style']['width'] = intval( $this->width ) . 'px';
|
875 |
$wrapper['style']['height'] = intval( $this->height ) . 'px';
|
876 |
}
|
877 |
|
879 |
$wrapper['style']['clear'] = 'both';
|
880 |
}
|
881 |
|
|
|
882 |
return $wrapper;
|
883 |
}
|
884 |
|
885 |
/**
|
886 |
+
* Add a wrapper arount the ad content if wrapper information are given
|
887 |
+
*
|
888 |
+
* @param string $ad_content content of the ad.
|
889 |
*
|
890 |
+
* @return string $wrapper ad within the wrapper
|
891 |
* @since 1.1.4
|
|
|
|
|
892 |
*/
|
893 |
+
protected function add_wrapper( $ad_content = '' ) {
|
894 |
$wrapper_options = apply_filters( 'advanced-ads-output-wrapper-options', $this->wrapper, $this );
|
895 |
|
896 |
if ( ( ! isset( $this->output['wrapper-id'] ) || '' === $this->output['wrapper-id'] )
|
897 |
+
&& array() === $wrapper_options || ! is_array( $wrapper_options ) ) {
|
898 |
+
return $ad_content;
|
899 |
+
}
|
900 |
|
901 |
+
// create unique id if not yet given.
|
902 |
+
if ( empty( $wrapper_options['id'] ) ) {
|
903 |
+
$wrapper_options['id'] = $this->create_wrapper_id();
|
904 |
+
$this->wrapper['id'] = $wrapper_options['id'];
|
905 |
}
|
906 |
+
|
907 |
+
// add edit button for users with the appropriate rights.
|
908 |
+
if ( ! defined( 'ADVANCED_ADS_DISABLE_EDIT_BAR' ) && current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
909 |
ob_start();
|
910 |
include ADVADS_BASE_PATH . 'public/views/ad-edit-bar.php';
|
911 |
$ad_content = ob_get_clean() . $ad_content;
|
912 |
}
|
913 |
+
|
914 |
// build the box
|
915 |
+
$wrapper = '<div' . Advanced_Ads_Utils::build_html_attributes( $wrapper_options ) . '>';
|
916 |
$wrapper .= apply_filters( 'advanced-ads-output-wrapper-before-content', '', $this );
|
917 |
$wrapper .= $ad_content;
|
918 |
$wrapper .= apply_filters( 'advanced-ads-output-wrapper-after-content', '', $this );
|
922 |
}
|
923 |
|
924 |
/**
|
925 |
+
* Create a random wrapper id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
926 |
*
|
|
|
927 |
* @return string $id random id string
|
928 |
+
* @since 1.1.4
|
929 |
*/
|
930 |
+
private function create_wrapper_id() {
|
931 |
|
932 |
+
if ( isset( $this->output['wrapper-id'] ) ) {
|
933 |
$id = sanitize_key( $this->output['wrapper-id'] );
|
934 |
+
if ( '' !== $id ) {
|
935 |
return $id;
|
936 |
}
|
937 |
}
|
947 |
public function maybe_create_label() {
|
948 |
$placement_state = isset( $this->args['ad_label'] ) ? $this->args['ad_label'] : 'default';
|
949 |
|
950 |
+
$label = Advanced_Ads::get_instance()->get_label( $placement_state );
|
951 |
+
if ( 'group' !== $this->type && $label ) {
|
|
|
952 |
$this->label = $label;
|
953 |
}
|
954 |
}
|
967 |
// If this is not the ad edit page.
|
968 |
if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
|
969 |
// Remove placeholders.
|
970 |
+
$this->url = str_replace(
|
971 |
+
array(
|
972 |
+
'[POST_ID]',
|
973 |
+
'[POST_SLUG]',
|
974 |
+
'[CAT_SLUG]',
|
975 |
+
'[AD_ID]',
|
976 |
+
),
|
977 |
+
'',
|
978 |
+
$this->url
|
979 |
+
);
|
980 |
}
|
981 |
}
|
982 |
+
|
983 |
return $this->url;
|
984 |
}
|
985 |
|
|
|
|
|
986 |
}
|
classes/ad_ajax_callbacks.php
CHANGED
@@ -18,10 +18,12 @@
|
|
18 |
*/
|
19 |
class Advanced_Ads_Ad_Ajax_Callbacks {
|
20 |
|
|
|
|
|
|
|
21 |
public function __construct() {
|
22 |
|
23 |
-
//
|
24 |
-
//add_action( 'wp_ajax_load_content_editor', array( $this, 'load_content_editor' ) );
|
25 |
add_action( 'wp_ajax_load_ad_parameters_metabox', array( $this, 'load_ad_parameters_metabox' ) );
|
26 |
add_action( 'wp_ajax_load_visitor_conditions_metabox', array( $this, 'load_visitor_condition' ) );
|
27 |
add_action( 'wp_ajax_load_display_conditions_metabox', array( $this, 'load_display_condition' ) );
|
@@ -45,33 +47,34 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
45 |
}
|
46 |
|
47 |
/**
|
48 |
-
*
|
49 |
*
|
50 |
* @since 1.0.0
|
51 |
*/
|
52 |
public function load_ad_parameters_metabox() {
|
53 |
-
|
54 |
-
check_ajax_referer('advanced-ads-admin-ajax-nonce', 'nonce');
|
55 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
56 |
return;
|
57 |
}
|
58 |
|
59 |
-
$types
|
60 |
$type_string = $_REQUEST['ad_type'];
|
61 |
-
$ad_id
|
62 |
-
if ( empty($ad_id) ) {
|
|
|
63 |
|
64 |
$ad = new Advanced_Ads_Ad( $ad_id );
|
65 |
|
66 |
-
if ( ! empty($types[$type_string]) && method_exists( $types[$type_string], 'render_parameters' ) ) {
|
67 |
$type = $types[ $type_string ];
|
68 |
$type->render_parameters( $ad );
|
69 |
|
70 |
-
$types_without_size = array('dummy');
|
71 |
-
|
72 |
-
if ( ! in_array($type_string, $types_without_size) ) {
|
73 |
-
|
74 |
-
|
75 |
}
|
76 |
|
77 |
die();
|
@@ -79,107 +82,112 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
79 |
}
|
80 |
|
81 |
/**
|
82 |
-
*
|
83 |
*
|
84 |
* @since 1.5.4
|
85 |
*/
|
86 |
public function load_visitor_condition() {
|
87 |
-
|
88 |
-
check_ajax_referer('advanced-ads-admin-ajax-nonce', 'nonce');
|
89 |
-
|
90 |
-
if( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
91 |
-
|
92 |
}
|
93 |
|
94 |
-
// get visitor condition types
|
95 |
$visitor_conditions = Advanced_Ads_Visitor_Conditions::get_instance()->conditions;
|
96 |
-
$condition
|
97 |
-
$condition['type']
|
98 |
-
$index
|
99 |
|
100 |
$form_name = isset( $_POST['form_name'] ) ? $_POST['form_name'] : Advanced_Ads_Visitor_Conditions::FORM_NAME;
|
101 |
|
102 |
-
if( isset( $visitor_conditions[$condition['type']] ) ) {
|
103 |
-
|
104 |
} else {
|
105 |
-
|
106 |
}
|
107 |
|
108 |
if ( method_exists( $metabox[0], $metabox[1] ) ) {
|
109 |
-
call_user_func( array($metabox[0], $metabox[1]), $condition, $index, $form_name );
|
110 |
}
|
111 |
|
112 |
die();
|
113 |
}
|
|
|
114 |
/**
|
115 |
-
*
|
116 |
*
|
117 |
* @since 1.7
|
118 |
*/
|
119 |
public function load_display_condition() {
|
120 |
-
|
121 |
-
check_ajax_referer('advanced-ads-admin-ajax-nonce', 'nonce');
|
122 |
-
|
123 |
-
if( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
124 |
-
|
125 |
}
|
126 |
|
127 |
-
// get display condition types
|
128 |
-
$conditions
|
129 |
-
$condition
|
130 |
$condition['type'] = isset( $_POST['type'] ) ? $_POST['type'] : '';
|
131 |
-
$index
|
132 |
|
133 |
$form_name = isset( $_POST['form_name'] ) ? $_POST['form_name'] : Advanced_Ads_Display_Conditions::FORM_NAME;
|
134 |
|
135 |
-
if( isset( $conditions[$condition['type']] ) ) {
|
136 |
-
|
137 |
} else {
|
138 |
-
|
139 |
}
|
140 |
|
141 |
if ( method_exists( $metabox[0], $metabox[1] ) ) {
|
142 |
-
call_user_func( array($metabox[0], $metabox[1]), $condition, $index, $form_name );
|
143 |
}
|
144 |
|
145 |
die();
|
146 |
}
|
147 |
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
180 |
|
181 |
/**
|
182 |
-
*
|
183 |
*
|
184 |
* @since 1.5.3
|
185 |
*/
|
@@ -202,27 +210,27 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
202 |
die();
|
203 |
}
|
204 |
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
) {
|
217 |
-
|
218 |
-
|
219 |
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
|
224 |
/**
|
225 |
-
*
|
226 |
*
|
227 |
* @since 1.5.3
|
228 |
*/
|
@@ -232,79 +240,87 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
232 |
|
233 |
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_see_interface' ) ) || empty( $_POST['notice'] )
|
234 |
) {
|
235 |
-
wp_send_json_error(
|
236 |
-
|
237 |
-
|
|
|
|
|
|
|
|
|
238 |
}
|
239 |
|
240 |
-
wp_send_json_success(
|
241 |
}
|
242 |
|
243 |
/**
|
244 |
-
*
|
245 |
*
|
246 |
* @since 1.5.7
|
247 |
*/
|
248 |
-
public function activate_license(){
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
|
253 |
-
|
254 |
-
|
255 |
|
256 |
-
|
|
|
257 |
|
258 |
-
|
|
|
|
|
259 |
|
260 |
-
|
261 |
}
|
262 |
-
|
263 |
/**
|
264 |
-
*
|
265 |
*
|
266 |
* @since 1.6.11
|
267 |
*/
|
268 |
-
public function deactivate_license(){
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
|
273 |
-
|
274 |
-
|
275 |
|
276 |
-
|
|
|
277 |
|
278 |
-
|
|
|
|
|
279 |
|
280 |
-
|
281 |
}
|
282 |
|
283 |
/**
|
284 |
-
*
|
285 |
-
*
|
286 |
*/
|
287 |
-
public function adblock_rebuild_assets(){
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
}
|
298 |
|
299 |
/**
|
300 |
-
*
|
301 |
-
*
|
302 |
*/
|
303 |
-
public function post_search(){
|
304 |
-
|
305 |
-
check_ajax_referer('advanced-ads-admin-ajax-nonce', 'nonce');
|
306 |
-
|
307 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
308 |
return;
|
309 |
}
|
310 |
|
@@ -313,24 +329,25 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
313 |
|
314 |
wp_ajax_wp_link_ajax();
|
315 |
}
|
316 |
-
|
317 |
/**
|
318 |
-
*
|
319 |
-
*
|
320 |
* @since 1.7.3
|
321 |
*/
|
322 |
-
public function inject_placement(){
|
323 |
-
|
324 |
-
check_ajax_referer('advanced-ads-admin-ajax-nonce', 'nonce');
|
325 |
-
|
326 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads') ) ) {
|
327 |
die();
|
328 |
}
|
329 |
-
|
330 |
$ad_id = absint( $_REQUEST['ad_id'] );
|
331 |
-
if ( empty( $ad_id ) ) {
|
332 |
-
|
333 |
-
|
|
|
334 |
if ( isset( $_REQUEST['placement_slug'] ) ) {
|
335 |
$xml_array[] = '<placements type="array">';
|
336 |
$xml_array[] = '<item key="0" type="array">';
|
@@ -344,163 +361,160 @@ class Advanced_Ads_Ad_Ajax_Callbacks {
|
|
344 |
|
345 |
Advanced_Ads_Import::get_instance()->import( $xml );
|
346 |
if ( count( Advanced_Ads_Import::get_instance()->imported_data['placements'] ) ) {
|
347 |
-
// if the ad was assigned
|
348 |
-
echo $_REQUEST['placement_slug'];
|
349 |
};
|
350 |
die();
|
351 |
}
|
352 |
|
353 |
-
|
354 |
-
|
355 |
|
356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
|
358 |
-
$item = 'ad_' . $ad_id;
|
359 |
-
|
360 |
-
$options = array();
|
361 |
-
|
362 |
-
// check type
|
363 |
-
$placement_types = Advanced_Ads_Placements::get_placement_types();
|
364 |
-
if( ! isset( $placement_types[ $type ] ) ){
|
365 |
-
die();
|
366 |
-
}
|
367 |
-
|
368 |
-
$title = $placement_types[ $type ]['title'];
|
369 |
-
|
370 |
-
$new_placement = array(
|
371 |
-
'type' => $type,
|
372 |
-
'item' => $item,
|
373 |
-
'name' => $title,
|
374 |
-
);
|
375 |
-
|
376 |
-
// set content specific options
|
377 |
-
if( 'post_content' === $type ){
|
378 |
-
$index = isset( $_REQUEST['options']['index'] ) ? absint( $_REQUEST['options']['index'] ) : 1;
|
379 |
-
$new_placement['options'] = array(
|
380 |
-
'position' => 'after',
|
381 |
-
'index' => $index,
|
382 |
-
'tag' => 'p'
|
383 |
-
);
|
384 |
-
}
|
385 |
-
|
386 |
$slug = Advanced_Ads_Placements::save_new_placement( $new_placement );
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
}
|
392 |
-
|
393 |
/**
|
394 |
-
*
|
395 |
-
*
|
396 |
* @since 1.7.4
|
397 |
*/
|
398 |
-
public function save_wizard_state(){
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
|
|
|
|
|
|
|
|
|
|
411 |
die();
|
412 |
-
}
|
413 |
-
|
414 |
-
update_user_meta( $user_id, 'advanced-ads-hide-wizard', $state );
|
415 |
-
|
416 |
-
die();
|
417 |
}
|
418 |
|
419 |
/**
|
420 |
* Enable Adsense Auto ads, previously "Page-Level ads"
|
421 |
*/
|
422 |
-
public function adsense_enable_pla(){
|
423 |
|
424 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
425 |
|
426 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') ) ) {
|
427 |
return;
|
428 |
}
|
429 |
|
430 |
-
$options
|
431 |
$options['page-level-enabled'] = true;
|
432 |
update_option( GADSENSE_OPT_NAME, $options );
|
433 |
-
|
434 |
}
|
435 |
-
|
436 |
/**
|
437 |
* Display list of Ad Health notices
|
438 |
*/
|
439 |
-
public function ad_health_notice_display(){
|
440 |
-
|
441 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
442 |
-
|
443 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') ) ) {
|
444 |
return;
|
445 |
}
|
446 |
-
|
447 |
Advanced_Ads_Ad_Health_Notices::get_instance()->render_widget();
|
448 |
die();
|
449 |
}
|
450 |
-
|
451 |
/**
|
452 |
* Push an Ad Health notice to the queue
|
453 |
*/
|
454 |
-
public function ad_health_notice_push(){
|
455 |
-
|
456 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
457 |
-
|
458 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') ) ) {
|
459 |
return;
|
460 |
}
|
461 |
-
|
462 |
-
$key
|
463 |
-
$attr = ( !empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
464 |
-
|
465 |
// update or new entry?
|
466 |
-
if( isset( $attr['mode'] ) && 'update' === $attr['mode'] ){
|
467 |
Advanced_Ads_Ad_Health_Notices::get_instance()->update( $key, $attr );
|
468 |
} else {
|
469 |
Advanced_Ads_Ad_Health_Notices::get_instance()->add( $key, $attr );
|
470 |
-
}
|
471 |
-
|
472 |
die();
|
473 |
}
|
474 |
-
|
475 |
/**
|
476 |
* Hide Ad Health notice
|
477 |
*/
|
478 |
-
public function ad_health_notice_hide(){
|
479 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
480 |
-
|
481 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') ) ) {
|
482 |
return;
|
483 |
}
|
484 |
-
|
485 |
-
$notice_key = ( !empty( $_REQUEST['notice'] ) ) ? esc_attr( $_REQUEST['notice'] ) : false;
|
486 |
-
|
487 |
Advanced_Ads_Ad_Health_Notices::get_instance()->hide( $notice_key );
|
488 |
die();
|
489 |
}
|
490 |
-
|
491 |
/**
|
492 |
* Show all ignored notices of a given type
|
493 |
*/
|
494 |
-
public function ad_health_notice_unignore(){
|
495 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
496 |
-
|
497 |
-
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options') ) ) {
|
498 |
return;
|
499 |
}
|
500 |
-
|
501 |
-
// $notice_key = ( !empty( $_REQUEST['type'] ) ) ? esc_attr( $_REQUEST['type'] ) : false;
|
502 |
-
|
503 |
-
// Advanced_Ads_Ad_Health_Notices::get_instance()->unignore_by_type( $notice_key );
|
504 |
Advanced_Ads_Ad_Health_Notices::get_instance()->unignore();
|
505 |
die();
|
506 |
}
|
18 |
*/
|
19 |
class Advanced_Ads_Ad_Ajax_Callbacks {
|
20 |
|
21 |
+
/**
|
22 |
+
* Advanced_Ads_Ad_Ajax_Callbacks constructor.
|
23 |
+
*/
|
24 |
public function __construct() {
|
25 |
|
26 |
+
// admin only!
|
|
|
27 |
add_action( 'wp_ajax_load_ad_parameters_metabox', array( $this, 'load_ad_parameters_metabox' ) );
|
28 |
add_action( 'wp_ajax_load_visitor_conditions_metabox', array( $this, 'load_visitor_condition' ) );
|
29 |
add_action( 'wp_ajax_load_display_conditions_metabox', array( $this, 'load_display_condition' ) );
|
47 |
}
|
48 |
|
49 |
/**
|
50 |
+
* Load content of the ad parameter metabox
|
51 |
*
|
52 |
* @since 1.0.0
|
53 |
*/
|
54 |
public function load_ad_parameters_metabox() {
|
55 |
+
|
56 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
57 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
58 |
return;
|
59 |
}
|
60 |
|
61 |
+
$types = Advanced_Ads::get_instance()->ad_types;
|
62 |
$type_string = $_REQUEST['ad_type'];
|
63 |
+
$ad_id = absint( $_REQUEST['ad_id'] );
|
64 |
+
if ( empty( $ad_id ) ) {
|
65 |
+
die(); }
|
66 |
|
67 |
$ad = new Advanced_Ads_Ad( $ad_id );
|
68 |
|
69 |
+
if ( ! empty( $types[ $type_string ] ) && method_exists( $types[ $type_string ], 'render_parameters' ) ) {
|
70 |
$type = $types[ $type_string ];
|
71 |
$type->render_parameters( $ad );
|
72 |
|
73 |
+
$types_without_size = array( 'dummy' );
|
74 |
+
$types_without_size = apply_filters( 'advanced-ads-types-without-size', $types_without_size );
|
75 |
+
if ( ! in_array( $type_string, $types_without_size ) ) {
|
76 |
+
include ADVADS_BASE_PATH . 'admin/views/ad-parameters-size.php';
|
77 |
+
}
|
78 |
}
|
79 |
|
80 |
die();
|
82 |
}
|
83 |
|
84 |
/**
|
85 |
+
* Load interface for single visitor condition
|
86 |
*
|
87 |
* @since 1.5.4
|
88 |
*/
|
89 |
public function load_visitor_condition() {
|
90 |
+
|
91 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
92 |
+
|
93 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
94 |
+
return;
|
95 |
}
|
96 |
|
97 |
+
// get visitor condition types.
|
98 |
$visitor_conditions = Advanced_Ads_Visitor_Conditions::get_instance()->conditions;
|
99 |
+
$condition = array();
|
100 |
+
$condition['type'] = isset( $_POST['type'] ) ? $_POST['type'] : '';
|
101 |
+
$index = isset( $_POST['index'] ) ? $_POST['index'] : 0;
|
102 |
|
103 |
$form_name = isset( $_POST['form_name'] ) ? $_POST['form_name'] : Advanced_Ads_Visitor_Conditions::FORM_NAME;
|
104 |
|
105 |
+
if ( isset( $visitor_conditions[ $condition['type'] ] ) ) {
|
106 |
+
$metabox = $visitor_conditions[ $condition['type'] ]['metabox'];
|
107 |
} else {
|
108 |
+
die();
|
109 |
}
|
110 |
|
111 |
if ( method_exists( $metabox[0], $metabox[1] ) ) {
|
112 |
+
call_user_func( array( $metabox[0], $metabox[1] ), $condition, $index, $form_name );
|
113 |
}
|
114 |
|
115 |
die();
|
116 |
}
|
117 |
+
|
118 |
/**
|
119 |
+
* Load interface for single display condition
|
120 |
*
|
121 |
* @since 1.7
|
122 |
*/
|
123 |
public function load_display_condition() {
|
124 |
+
|
125 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
126 |
+
|
127 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
128 |
+
return;
|
129 |
}
|
130 |
|
131 |
+
// get display condition types.
|
132 |
+
$conditions = Advanced_Ads_Display_Conditions::get_instance()->conditions;
|
133 |
+
$condition = array();
|
134 |
$condition['type'] = isset( $_POST['type'] ) ? $_POST['type'] : '';
|
135 |
+
$index = isset( $_POST['index'] ) ? $_POST['index'] : 0;
|
136 |
|
137 |
$form_name = isset( $_POST['form_name'] ) ? $_POST['form_name'] : Advanced_Ads_Display_Conditions::FORM_NAME;
|
138 |
|
139 |
+
if ( isset( $conditions[ $condition['type'] ] ) ) {
|
140 |
+
$metabox = $conditions[ $condition['type'] ]['metabox'];
|
141 |
} else {
|
142 |
+
die();
|
143 |
}
|
144 |
|
145 |
if ( method_exists( $metabox[0], $metabox[1] ) ) {
|
146 |
+
call_user_func( array( $metabox[0], $metabox[1] ), $condition, $index, $form_name );
|
147 |
}
|
148 |
|
149 |
die();
|
150 |
}
|
151 |
|
152 |
+
/**
|
153 |
+
* Search terms belonging to a specific taxonomy
|
154 |
+
*
|
155 |
+
* @since 1.4.7
|
156 |
+
*/
|
157 |
+
public function search_terms() {
|
158 |
+
|
159 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
160 |
+
|
161 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
162 |
+
return;
|
163 |
+
}
|
164 |
+
|
165 |
+
$args = array();
|
166 |
+
$taxonomy = $_POST['tax'];
|
167 |
+
$args = array(
|
168 |
+
'hide_empty' => false,
|
169 |
+
'number' => 20,
|
170 |
+
);
|
171 |
+
|
172 |
+
if ( ! isset( $_POST['search'] ) || '' === $_POST['search'] ) {
|
173 |
+
die();
|
174 |
+
}
|
175 |
+
|
176 |
+
// if search is an id, search for the term id, else do a full text search.
|
177 |
+
if ( 0 !== absint( $_POST['search'] ) && strlen( $_POST['search'] ) === strlen( absint( $_POST['search'] ) ) ) {
|
178 |
+
$args['include'] = array( absint( $_POST['search'] ) );
|
179 |
+
} else {
|
180 |
+
$args['search'] = $_POST['search'];
|
181 |
+
}
|
182 |
+
|
183 |
+
$results = get_terms( $taxonomy, $args );
|
184 |
+
echo wp_json_encode( $results );
|
185 |
+
echo "\n";
|
186 |
+
die();
|
187 |
+
}
|
188 |
|
189 |
/**
|
190 |
+
* Close a notice for good
|
191 |
*
|
192 |
* @since 1.5.3
|
193 |
*/
|
210 |
die();
|
211 |
}
|
212 |
|
213 |
+
/**
|
214 |
+
* Hide a notice for some time (7 days right now)
|
215 |
+
*
|
216 |
+
* @since 1.8.17
|
217 |
+
*/
|
218 |
+
public function hide_notice() {
|
219 |
+
|
220 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
221 |
+
|
222 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) )
|
223 |
+
|| empty( $_POST['notice'] )
|
224 |
) {
|
225 |
+
die();
|
226 |
+
}
|
227 |
|
228 |
+
Advanced_Ads_Admin_Notices::get_instance()->hide_notice( $_POST['notice'] );
|
229 |
+
die();
|
230 |
+
}
|
231 |
|
232 |
/**
|
233 |
+
* Subscribe to newsletter
|
234 |
*
|
235 |
* @since 1.5.3
|
236 |
*/
|
240 |
|
241 |
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_see_interface' ) ) || empty( $_POST['notice'] )
|
242 |
) {
|
243 |
+
wp_send_json_error(
|
244 |
+
array(
|
245 |
+
// translators: %s is a URL.
|
246 |
+
'message' => sprintf( __( 'An error occurred. Please use <a href="%s" target="_blank">this form</a> to sign up.', 'advanced-ads' ), 'http://eepurl.com/bk4z4P' ),
|
247 |
+
),
|
248 |
+
400
|
249 |
+
);
|
250 |
}
|
251 |
|
252 |
+
wp_send_json_success( array( 'message' => Advanced_Ads_Admin_Notices::get_instance()->subscribe( $_POST['notice'] ) ) );
|
253 |
}
|
254 |
|
255 |
/**
|
256 |
+
* Activate license of an add-on
|
257 |
*
|
258 |
* @since 1.5.7
|
259 |
*/
|
260 |
+
public function activate_license() {
|
261 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
262 |
+
return;
|
263 |
+
}
|
264 |
|
265 |
+
// check nonce.
|
266 |
+
check_ajax_referer( 'advads_ajax_license_nonce', 'security' );
|
267 |
|
268 |
+
if ( ! isset( $_POST['addon'] ) || '' === $_POST['addon'] ) {
|
269 |
+
die(); }
|
270 |
|
271 |
+
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
272 |
+
echo Advanced_Ads_Admin_Licenses::get_instance()->activate_license( $_POST['addon'], $_POST['pluginname'], $_POST['optionslug'], $_POST['license'] );
|
273 |
+
// phpcs:enable
|
274 |
|
275 |
+
die();
|
276 |
}
|
277 |
+
|
278 |
/**
|
279 |
+
* Deactivate license of an add-on
|
280 |
*
|
281 |
* @since 1.6.11
|
282 |
*/
|
283 |
+
public function deactivate_license() {
|
284 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
285 |
+
return;
|
286 |
+
}
|
287 |
|
288 |
+
// check nonce.
|
289 |
+
check_ajax_referer( 'advads_ajax_license_nonce', 'security' );
|
290 |
|
291 |
+
if ( ! isset( $_POST['addon'] ) || '' === $_POST['addon'] ) {
|
292 |
+
die(); }
|
293 |
|
294 |
+
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
295 |
+
echo Advanced_Ads_Admin_Licenses::get_instance()->deactivate_license( $_POST['addon'], $_POST['pluginname'], $_POST['optionslug'] );
|
296 |
+
// phpcs:enable
|
297 |
|
298 |
+
die();
|
299 |
}
|
300 |
|
301 |
/**
|
302 |
+
* Rebuild assets for ad-blocker module
|
|
|
303 |
*/
|
304 |
+
public function adblock_rebuild_assets() {
|
305 |
+
|
306 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
307 |
+
|
308 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
309 |
+
return;
|
310 |
+
}
|
311 |
+
|
312 |
+
Advanced_Ads_Ad_Blocker_Admin::get_instance()->add_asset_rebuild_form();
|
313 |
+
die();
|
314 |
}
|
315 |
|
316 |
/**
|
317 |
+
* Post search (used in Display conditions)
|
|
|
318 |
*/
|
319 |
+
public function post_search() {
|
320 |
+
|
321 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
322 |
+
|
323 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
324 |
return;
|
325 |
}
|
326 |
|
329 |
|
330 |
wp_ajax_wp_link_ajax();
|
331 |
}
|
332 |
+
|
333 |
/**
|
334 |
+
* Inject an ad and a placement
|
335 |
+
*
|
336 |
* @since 1.7.3
|
337 |
*/
|
338 |
+
public function inject_placement() {
|
339 |
+
|
340 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
341 |
+
|
342 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
343 |
die();
|
344 |
}
|
345 |
+
|
346 |
$ad_id = absint( $_REQUEST['ad_id'] );
|
347 |
+
if ( empty( $ad_id ) ) {
|
348 |
+
die(); }
|
349 |
+
|
350 |
+
// use existing placement.
|
351 |
if ( isset( $_REQUEST['placement_slug'] ) ) {
|
352 |
$xml_array[] = '<placements type="array">';
|
353 |
$xml_array[] = '<item key="0" type="array">';
|
361 |
|
362 |
Advanced_Ads_Import::get_instance()->import( $xml );
|
363 |
if ( count( Advanced_Ads_Import::get_instance()->imported_data['placements'] ) ) {
|
364 |
+
// if the ad was assigned.
|
365 |
+
echo esc_attr( $_REQUEST['placement_slug'] );
|
366 |
};
|
367 |
die();
|
368 |
}
|
369 |
|
370 |
+
// create new placement.
|
371 |
+
$placements = Advanced_Ads::get_instance()->get_model()->get_ad_placements_array();
|
372 |
|
373 |
+
$type = esc_attr( $_REQUEST['placement_type'] );
|
374 |
+
|
375 |
+
$item = 'ad_' . $ad_id;
|
376 |
+
|
377 |
+
$options = array();
|
378 |
+
|
379 |
+
// check type.
|
380 |
+
$placement_types = Advanced_Ads_Placements::get_placement_types();
|
381 |
+
if ( ! isset( $placement_types[ $type ] ) ) {
|
382 |
+
die();
|
383 |
+
}
|
384 |
+
|
385 |
+
$title = $placement_types[ $type ]['title'];
|
386 |
+
|
387 |
+
$new_placement = array(
|
388 |
+
'type' => $type,
|
389 |
+
'item' => $item,
|
390 |
+
'name' => $title,
|
391 |
+
);
|
392 |
+
|
393 |
+
// set content specific options.
|
394 |
+
if ( 'post_content' === $type ) {
|
395 |
+
$index = isset( $_REQUEST['options']['index'] ) ? absint( $_REQUEST['options']['index'] ) : 1;
|
396 |
+
$new_placement['options'] = array(
|
397 |
+
'position' => 'after',
|
398 |
+
'index' => $index,
|
399 |
+
'tag' => 'p',
|
400 |
+
);
|
401 |
+
}
|
402 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
$slug = Advanced_Ads_Placements::save_new_placement( $new_placement );
|
404 |
+
// return potential slug.
|
405 |
+
echo esc_attr( $slug );
|
406 |
+
|
407 |
+
die();
|
408 |
}
|
409 |
+
|
410 |
/**
|
411 |
+
* Save ad wizard state for each user individually
|
412 |
+
*
|
413 |
* @since 1.7.4
|
414 |
*/
|
415 |
+
public function save_wizard_state() {
|
416 |
+
|
417 |
+
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
418 |
+
|
419 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
|
420 |
+
return;
|
421 |
+
}
|
422 |
+
|
423 |
+
$state = ( isset( $_REQUEST['hide_wizard'] ) && 'true' === $_REQUEST['hide_wizard'] ) ? 'true' : 'false';
|
424 |
+
|
425 |
+
// get current user.
|
426 |
+
$user_id = get_current_user_id();
|
427 |
+
if ( ! $user_id ) {
|
428 |
+
die();
|
429 |
+
}
|
430 |
+
|
431 |
+
update_user_meta( $user_id, 'advanced-ads-hide-wizard', $state );
|
432 |
+
|
433 |
die();
|
|
|
|
|
|
|
|
|
|
|
434 |
}
|
435 |
|
436 |
/**
|
437 |
* Enable Adsense Auto ads, previously "Page-Level ads"
|
438 |
*/
|
439 |
+
public function adsense_enable_pla() {
|
440 |
|
441 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
442 |
|
443 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
444 |
return;
|
445 |
}
|
446 |
|
447 |
+
$options = get_option( GADSENSE_OPT_NAME, array() );
|
448 |
$options['page-level-enabled'] = true;
|
449 |
update_option( GADSENSE_OPT_NAME, $options );
|
450 |
+
die();
|
451 |
}
|
452 |
+
|
453 |
/**
|
454 |
* Display list of Ad Health notices
|
455 |
*/
|
456 |
+
public function ad_health_notice_display() {
|
457 |
+
|
458 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
459 |
+
|
460 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
461 |
return;
|
462 |
}
|
463 |
+
|
464 |
Advanced_Ads_Ad_Health_Notices::get_instance()->render_widget();
|
465 |
die();
|
466 |
}
|
467 |
+
|
468 |
/**
|
469 |
* Push an Ad Health notice to the queue
|
470 |
*/
|
471 |
+
public function ad_health_notice_push() {
|
472 |
+
|
473 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
474 |
+
|
475 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
476 |
return;
|
477 |
}
|
478 |
+
|
479 |
+
$key = ( ! empty( $_REQUEST['key'] ) ) ? esc_attr( $_REQUEST['key'] ) : false;
|
480 |
+
$attr = ( ! empty( $_REQUEST['attr'] ) && is_array( $_REQUEST['attr'] ) ) ? $_REQUEST['attr'] : array();
|
481 |
+
|
482 |
// update or new entry?
|
483 |
+
if ( isset( $attr['mode'] ) && 'update' === $attr['mode'] ) {
|
484 |
Advanced_Ads_Ad_Health_Notices::get_instance()->update( $key, $attr );
|
485 |
} else {
|
486 |
Advanced_Ads_Ad_Health_Notices::get_instance()->add( $key, $attr );
|
487 |
+
}
|
488 |
+
|
489 |
die();
|
490 |
}
|
491 |
+
|
492 |
/**
|
493 |
* Hide Ad Health notice
|
494 |
*/
|
495 |
+
public function ad_health_notice_hide() {
|
496 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
497 |
+
|
498 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
499 |
return;
|
500 |
}
|
501 |
+
|
502 |
+
$notice_key = ( ! empty( $_REQUEST['notice'] ) ) ? esc_attr( $_REQUEST['notice'] ) : false;
|
503 |
+
|
504 |
Advanced_Ads_Ad_Health_Notices::get_instance()->hide( $notice_key );
|
505 |
die();
|
506 |
}
|
507 |
+
|
508 |
/**
|
509 |
* Show all ignored notices of a given type
|
510 |
*/
|
511 |
+
public function ad_health_notice_unignore() {
|
512 |
check_ajax_referer( 'advanced-ads-admin-ajax-nonce', 'nonce' );
|
513 |
+
|
514 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) ) ) {
|
515 |
return;
|
516 |
}
|
517 |
+
|
|
|
|
|
|
|
518 |
Advanced_Ads_Ad_Health_Notices::get_instance()->unignore();
|
519 |
die();
|
520 |
}
|
classes/ad_placements.php
CHANGED
@@ -11,125 +11,159 @@
|
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
-
*
|
15 |
*
|
16 |
* @since 1.1.0
|
17 |
* @package Advanced_Ads_Placements
|
18 |
* @author Thomas Maier <support@wpadvancedads.com>
|
19 |
*/
|
20 |
class Advanced_Ads_Placements {
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
private static $ads_for_placeholders = array();
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
private static $replacements = array(
|
24 |
'gcse:search' => 'gcse__search', // Google custom search namespaced tags.
|
25 |
);
|
26 |
|
27 |
/**
|
28 |
-
*
|
29 |
*
|
|
|
30 |
* @since 1.2.1
|
31 |
-
* @return arr $types array with placement types
|
32 |
*/
|
33 |
public static function get_placement_types() {
|
34 |
$types = array(
|
35 |
-
'default'
|
36 |
-
'title'
|
37 |
'description' => __( 'Manual placement to use as function or shortcode.', 'advanced-ads' ),
|
38 |
-
'image'
|
39 |
-
'options'
|
|
|
|
|
|
|
40 |
),
|
41 |
-
|
42 |
-
|
|
|
43 |
'description' => __( 'Injected in Header (before closing </head> Tag, often not visible).', 'advanced-ads' ),
|
44 |
-
'image'
|
45 |
-
|
46 |
-
'footer'
|
47 |
-
'title'
|
48 |
'description' => __( 'Injected in Footer (before closing </body> Tag).', 'advanced-ads' ),
|
49 |
-
'image'
|
50 |
-
'options'
|
51 |
-
|
52 |
-
'post_top'
|
53 |
-
'title'
|
54 |
'description' => __( 'Injected before the post content.', 'advanced-ads' ),
|
55 |
-
'image'
|
56 |
-
'options'
|
|
|
|
|
|
|
|
|
57 |
),
|
58 |
-
|
59 |
-
|
|
|
60 |
'description' => __( 'Injected after the post content.', 'advanced-ads' ),
|
61 |
-
'image'
|
62 |
-
'options'
|
|
|
|
|
|
|
|
|
63 |
),
|
64 |
-
|
65 |
-
|
|
|
66 |
'description' => __( 'Injected into the content. You can choose the paragraph after which the ad content is displayed.', 'advanced-ads' ),
|
67 |
-
'image'
|
68 |
-
'options'
|
|
|
|
|
|
|
|
|
69 |
),
|
|
|
70 |
'sidebar_widget' => array(
|
71 |
-
'title'
|
72 |
'description' => __( 'Create a sidebar widget with an ad. Can be placed and used like any other widget.', 'advanced-ads' ),
|
73 |
-
'image'
|
74 |
-
'options'
|
|
|
|
|
75 |
),
|
|
|
76 |
);
|
|
|
77 |
return apply_filters( 'advanced-ads-placement-types', $types );
|
78 |
}
|
79 |
|
80 |
/**
|
81 |
-
|
82 |
*
|
83 |
* @since 1.5.2
|
84 |
-
|
85 |
-
static function update_placements(){
|
86 |
|
87 |
-
// check user permissions
|
88 |
-
if( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_placements') ) ) {
|
89 |
return;
|
90 |
}
|
91 |
-
|
92 |
$success = null;
|
93 |
-
|
94 |
-
// add hook of last opened placement settings to URL
|
95 |
-
$hook = !empty( $_POST['advads-last-edited-placement'] ) ? '#single-placement-' . $_POST['advads-last-edited-placement'] : '';
|
96 |
|
97 |
-
|
|
|
|
|
|
|
98 |
$success = self::save_new_placement( $_POST['advads']['placement'] );
|
99 |
}
|
100 |
-
// save placement data
|
101 |
-
if ( isset($_POST['advads']['placements']) && check_admin_referer( 'advads-placement', 'advads_placement' )){
|
102 |
$success = self::save_placements( $_POST['advads']['placements'] );
|
103 |
}
|
104 |
|
105 |
$success = apply_filters( 'advanced-ads-update-placements', $success );
|
106 |
|
107 |
-
if(isset($success)){
|
108 |
$message = $success ? 'updated' : 'error';
|
109 |
-
wp_redirect( esc_url_raw( add_query_arg(array('message' => $message) ) ) . $hook );
|
110 |
}
|
111 |
}
|
112 |
|
113 |
/**
|
114 |
-
*
|
|
|
|
|
115 |
*
|
116 |
-
* @since 1.1.0
|
117 |
-
* @param array $new_placement
|
118 |
* @return mixed slug if saved; false if not
|
|
|
119 |
*/
|
120 |
-
public static function save_new_placement($new_placement) {
|
121 |
-
// load placements // -TODO use model
|
122 |
$placements = Advanced_Ads::get_ad_placements_array();
|
123 |
|
124 |
-
// create slug
|
125 |
$new_placement['slug'] = sanitize_title( $new_placement['name'] );
|
126 |
|
127 |
if ( isset( $placements[ $new_placement['slug'] ] ) ) {
|
128 |
$i = 1;
|
129 |
-
// try to save placement until we found an empty slug
|
130 |
do {
|
131 |
$i ++;
|
132 |
-
if (
|
133 |
Advanced_Ads::log( 'endless loop when injecting placement' );
|
134 |
break;
|
135 |
}
|
@@ -139,146 +173,164 @@ class Advanced_Ads_Placements {
|
|
139 |
$new_placement['name'] .= ' ' . $i;
|
140 |
}
|
141 |
|
142 |
-
// check if slug already exists or is empty
|
143 |
-
if ( $new_placement['slug']
|
144 |
return false;
|
145 |
}
|
146 |
|
147 |
-
// make sure only allowed types are being saved
|
148 |
-
$placement_types
|
149 |
-
$new_placement['type'] = (isset($placement_types[$new_placement['type']])) ? $new_placement['type'] : 'default';
|
150 |
-
// escape name
|
151 |
$new_placement['name'] = esc_attr( $new_placement['name'] );
|
152 |
|
153 |
-
// add new place to all placements
|
154 |
-
$placements[$new_placement['slug']] = array(
|
155 |
'type' => $new_placement['type'],
|
156 |
'name' => $new_placement['name'],
|
157 |
-
'item' => $new_placement['item']
|
158 |
);
|
159 |
-
|
160 |
-
// add index options
|
161 |
-
if ( isset($new_placement['options']) ){
|
162 |
-
$placements[$new_placement['slug']]['options'] = $new_placement['options'];
|
163 |
-
if ( isset($placements[$new_placement['slug']]['options']['index']) ) {
|
164 |
-
$placements[$new_placement['slug']]['options']['index'] = absint( $placements[$new_placement['slug']]['options']['index'] );
|
165 |
-
|
166 |
-
|
167 |
-
|
|
|
168 |
Advanced_Ads::get_instance()->get_model()->update_ad_placements_array( $placements );
|
169 |
|
170 |
return $new_placement['slug'];
|
171 |
}
|
172 |
|
173 |
/**
|
174 |
-
*
|
|
|
|
|
175 |
*
|
176 |
-
* @since 1.1.0
|
177 |
-
* @param array $placement_items
|
178 |
* @return mixed true if saved; error message if not
|
|
|
179 |
*/
|
180 |
-
public static function save_placements($placement_items) {
|
181 |
|
182 |
-
// load placements // -TODO use model
|
183 |
$placements = Advanced_Ads::get_ad_placements_array();
|
184 |
|
185 |
foreach ( $placement_items as $_placement_slug => $_placement ) {
|
186 |
-
// remove the placement
|
187 |
-
if ( isset($_placement['delete']) ) {
|
188 |
-
unset($placements[$_placement_slug]);
|
189 |
continue;
|
190 |
}
|
191 |
-
// save item
|
192 |
-
if ( isset($_placement['item']) ) {
|
193 |
-
$placements[$_placement_slug]['item'] = $_placement['item'];
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
|
|
|
|
199 |
} else {
|
200 |
-
$placements[$_placement_slug]['options'] = array();
|
201 |
}
|
202 |
}
|
203 |
|
204 |
-
// save array
|
205 |
Advanced_Ads::get_instance()->get_model()->update_ad_placements_array( $placements );
|
206 |
|
207 |
return true;
|
208 |
}
|
209 |
|
210 |
/**
|
211 |
-
*
|
212 |
*
|
|
|
213 |
* @since 1.1
|
214 |
-
* @return arr $select items for select field
|
215 |
*/
|
216 |
public static function items_for_select() {
|
217 |
$select = array();
|
218 |
-
$model
|
219 |
|
220 |
-
// load all ad groups
|
221 |
$groups = $model->get_ad_groups();
|
222 |
foreach ( $groups as $_group ) {
|
223 |
-
$select['groups']['group_' . $_group->term_id] = $_group->name;
|
224 |
}
|
225 |
|
226 |
-
// load all ads
|
227 |
-
$ads = $model->get_ads(
|
|
|
|
|
|
|
|
|
|
|
228 |
foreach ( $ads as $_ad ) {
|
229 |
-
$select['ads']['ad_' . $_ad->ID] = $_ad->post_title;
|
230 |
}
|
231 |
|
232 |
return $select;
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
-
*
|
237 |
*
|
|
|
238 |
* @since 1.3.5
|
239 |
-
* @return arr $tags array with tags that can be used for content injection
|
240 |
*/
|
241 |
-
public static function tags_for_content_injection(){
|
242 |
-
$tags = apply_filters(
|
243 |
-
'
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
return $tags;
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
-
*
|
255 |
*
|
256 |
-
* @
|
257 |
-
* @param
|
258 |
-
*
|
|
|
259 |
*/
|
260 |
public static function output( $id = '', $args = array() ) {
|
261 |
-
// get placement data for the slug
|
262 |
-
if (
|
263 |
return;
|
264 |
}
|
265 |
|
266 |
$placements = Advanced_Ads::get_ad_placements_array();
|
267 |
-
$placement
|
268 |
|
269 |
if ( isset( $args['change-placement'] ) ) {
|
270 |
-
// some options was provided by the user
|
271 |
-
$placement = Advanced_Ads_Utils::merge_deep_array( array( $placement, $args['change-placement'] ) )
|
272 |
}
|
273 |
|
274 |
-
if ( isset( $placement['item'] ) && $placement['item']
|
275 |
$_item = explode( '_', $placement['item'] );
|
276 |
|
277 |
if ( ! isset( $_item[1] ) || empty( $_item[1] ) ) {
|
278 |
-
return
|
279 |
}
|
280 |
|
281 |
-
// inject options
|
282 |
if ( isset( $placement['options'] ) && is_array( $placement['options'] ) ) {
|
283 |
foreach ( $placement['options'] as $_k => $_v ) {
|
284 |
if ( ! isset( $args[ $_k ] ) ) {
|
@@ -287,20 +339,20 @@ class Advanced_Ads_Placements {
|
|
287 |
}
|
288 |
}
|
289 |
|
290 |
-
// inject placement type
|
291 |
if ( isset( $placement['type'] ) ) {
|
292 |
-
$args[
|
293 |
}
|
294 |
|
295 |
-
// options
|
296 |
$prefix = Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();
|
297 |
|
298 |
-
// return either ad or group content
|
299 |
switch ( $_item[0] ) {
|
300 |
case 'ad':
|
301 |
-
case Advanced_Ads_Select::AD
|
302 |
-
// create class from placement id (not if header injection)
|
303 |
-
if ( ! isset( $placement['type'] ) || $placement['type']
|
304 |
if ( ! isset( $args['output'] ) ) {
|
305 |
$args['output'] = array();
|
306 |
}
|
@@ -313,203 +365,212 @@ class Advanced_Ads_Placements {
|
|
313 |
}
|
314 |
}
|
315 |
|
316 |
-
// fix method id
|
317 |
$_item[0] = Advanced_Ads_Select::AD;
|
318 |
break;
|
319 |
|
320 |
-
// avoid loops (programmatical error)
|
321 |
-
case Advanced_Ads_Select::PLACEMENT
|
322 |
return;
|
323 |
|
324 |
-
case Advanced_Ads_Select::GROUP
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
default:
|
333 |
}
|
334 |
|
335 |
-
// create placement id for various features
|
336 |
$args['output']['placement_id'] = $id;
|
337 |
|
338 |
-
// add the placement to the global output array
|
339 |
$advads = Advanced_Ads::get_instance();
|
340 |
-
$name
|
341 |
|
342 |
if ( ! isset( $args['global_output'] ) || $args['global_output'] ) {
|
343 |
-
$advads->current_ads[] = array(
|
|
|
|
|
|
|
|
|
344 |
}
|
345 |
|
346 |
$result = Advanced_Ads_Select::get_instance()->get_ad_by_method( (int) $_item[1], $_item[0], $args );
|
347 |
|
348 |
return $result;
|
349 |
}
|
|
|
|
|
350 |
}
|
351 |
|
352 |
/**
|
353 |
-
*
|
354 |
*
|
|
|
|
|
|
|
|
|
|
|
355 |
* @since 1.2.1
|
356 |
-
* @param string $placement_id id of the placement
|
357 |
-
* @param arr $placement_opts placement options
|
358 |
-
* @param string $content
|
359 |
-
* @return type
|
360 |
-
* @link inspired by http://www.wpbeginner.com/wp-tutorials/how-to-insert-ads-within-your-post-content-in-wordpress/
|
361 |
*/
|
362 |
-
public static function &inject_in_content($placement_id, $placement_opts, &$content) {
|
363 |
if ( ! extension_loaded( 'dom' ) ) {
|
364 |
return $content;
|
365 |
}
|
366 |
|
367 |
-
// get plugin options
|
368 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
369 |
-
|
370 |
-
$wpCharset = get_bloginfo('charset');
|
371 |
-
// parse document as DOM (fragment - having only a part of an actual post given)
|
372 |
|
373 |
-
$
|
|
|
|
|
|
|
374 |
if ( ! $content_to_load ) {
|
375 |
return $content;
|
376 |
}
|
377 |
|
378 |
-
$dom = new DOMDocument('1.0', $
|
379 |
-
// may loose some fragments or add autop-like code
|
380 |
-
libxml_use_internal_errors(true); // avoid notices and warnings - html is most likely malformed
|
381 |
|
382 |
-
$success = $dom->loadHtml('<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $
|
383 |
-
libxml_use_internal_errors(false);
|
384 |
-
if ($success
|
385 |
// -TODO handle cases were dom-parsing failed (at least inform user)
|
386 |
return $content;
|
387 |
}
|
388 |
|
389 |
-
// parse arguments
|
390 |
-
$tag = isset($placement_opts['tag']) ? $placement_opts['tag'] : 'p';
|
391 |
-
$tag = preg_replace('/[^a-z0-9]/i', '', $tag); // simplify tag
|
392 |
|
393 |
-
// allow more complex xPath expression
|
394 |
$tag = apply_filters( 'advanced-ads-placement-content-injection-xpath', $tag, $placement_opts );
|
395 |
|
396 |
-
if (
|
397 |
$tag = 'p[not(descendant::img)]';
|
398 |
}
|
399 |
|
400 |
-
// select positions
|
401 |
-
$xpath = new DOMXPath($dom);
|
402 |
-
$items = $xpath->query('/html/body/' . $tag);
|
403 |
|
404 |
$options = array(
|
405 |
-
|
406 |
-
'paragraph_select_from_bottom' => isset($placement_opts['start_from_bottom']) && $placement_opts['start_from_bottom'],
|
407 |
-
// only has before and after
|
408 |
-
'before'
|
409 |
);
|
410 |
|
411 |
-
$options['paragraph_id'] = isset($placement_opts['index']) ? $placement_opts['index'] : 1;
|
412 |
$options['paragraph_id'] = max( 1, (int) $options['paragraph_id'] );
|
413 |
|
414 |
-
// if there are too few items at this level test nesting
|
415 |
-
$options['itemLimit'] =
|
416 |
|
417 |
-
// trigger such a high item limit that all elements will be considered
|
418 |
-
if( ! empty($plugin_options['content-injection-level-disabled'] ) ){
|
419 |
$options['itemLimit'] = 1000;
|
420 |
}
|
421 |
-
|
422 |
-
// allow hooks to change some options
|
423 |
$options = apply_filters(
|
424 |
'advanced-ads-placement-content-injection-options',
|
425 |
$options,
|
426 |
-
$tag
|
|
|
427 |
|
428 |
-
if ($items->length < $options['itemLimit'] ) {
|
429 |
-
$items = $xpath->query('/html/body/*/' . $tag);
|
430 |
}
|
431 |
-
// try third level
|
432 |
if ( $items->length < $options['itemLimit'] ) {
|
433 |
-
$items = $xpath->query('/html/body/*/*/' . $tag);
|
434 |
}
|
435 |
-
// try all levels as last resort
|
436 |
if ( $items->length < $options['itemLimit'] ) {
|
437 |
$items = $xpath->query( '//' . $tag );
|
438 |
}
|
439 |
-
|
440 |
-
// allow to select other elements
|
441 |
$items = apply_filters( 'advanced-ads-placement-content-injection-items', $items, $xpath, $tag );
|
442 |
|
443 |
-
// filter empty tags from items
|
444 |
-
$whitespaces = json_decode('"\t\n\r \u00A0"');
|
445 |
-
$paragraphs
|
446 |
-
foreach ($items as $item) {
|
447 |
-
if ( $options['allowEmpty'] || ( isset($item->textContent) && trim($item->textContent, $whitespaces) !== '' ) ) {
|
448 |
$paragraphs[] = $item;
|
449 |
}
|
450 |
}
|
451 |
|
452 |
-
$
|
|
|
|
|
|
|
453 |
|
454 |
-
if ($options['paragraph_count'] >= $options['paragraph_id']) {
|
455 |
-
$offset
|
456 |
-
$offsets
|
457 |
$did_inject = false;
|
458 |
|
459 |
foreach ( $offsets as $offset ) {
|
460 |
-
// inject
|
461 |
-
$node = apply_filters( 'advanced-ads-placement-content-injection-node', $paragraphs[$offset], $tag, $options['before'] );
|
462 |
|
463 |
-
$
|
464 |
|
465 |
-
if ( trim( $
|
466 |
continue;
|
467 |
}
|
468 |
|
469 |
-
|
|
|
470 |
|
471 |
// convert HTML to XML!
|
472 |
-
$
|
473 |
-
libxml_use_internal_errors(true);
|
474 |
-
$
|
475 |
-
// log errors
|
476 |
-
if ( defined
|
477 |
-
foreach( libxml_get_errors() as $_error ) {
|
478 |
-
// continue, if there is '&' symbol, but not HTML entity
|
479 |
if ( false === stripos( $_error->message, 'htmlParseEntityRef:' ) ) {
|
480 |
Advanced_Ads::log( 'possible content injection error for placement "' . $placement_id . '": ' . print_r( $_error, true ) );
|
481 |
}
|
482 |
}
|
483 |
}
|
484 |
|
485 |
-
|
486 |
if ( $options['before'] ) {
|
487 |
-
$
|
488 |
|
489 |
-
foreach ( $
|
490 |
$importedNode = $dom->importNode( $importedNode, true );
|
491 |
-
$
|
492 |
}
|
493 |
} else {
|
494 |
-
// append before next node or as last child to body
|
495 |
-
$
|
496 |
-
if (isset($
|
497 |
|
498 |
-
foreach ( $
|
499 |
$importedNode = $dom->importNode( $importedNode, true );
|
500 |
-
$
|
501 |
}
|
502 |
-
|
503 |
} else {
|
504 |
-
// append to body; -TODO using here that we only select direct children of the body tag
|
505 |
-
foreach ( $
|
506 |
$importedNode = $dom->importNode( $importedNode, true );
|
507 |
$node->parentNode->appendChild( $importedNode );
|
508 |
}
|
509 |
}
|
510 |
}
|
511 |
|
512 |
-
libxml_use_internal_errors(false);
|
513 |
$did_inject = true;
|
514 |
}
|
515 |
|
@@ -518,25 +579,33 @@ class Advanced_Ads_Placements {
|
|
518 |
}
|
519 |
|
520 |
$content_orig = $content;
|
521 |
-
// convert to text-representation
|
522 |
$content = $dom->saveHTML();
|
523 |
$content = self::prepare_output( $content, $content_orig );
|
524 |
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
// check if there are more elements without limitation
|
537 |
$all_items = $xpath->query( '//' . $tag );
|
538 |
-
|
539 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
540 |
add_filter( 'advanced-ads-ad-health-nodes', array( 'Advanced_Ads_Placements', 'add_ad_health_node' ) );
|
541 |
}
|
542 |
}
|
@@ -548,17 +617,18 @@ class Advanced_Ads_Placements {
|
|
548 |
* Get content to load.
|
549 |
*
|
550 |
* @param string $content Original content.
|
551 |
-
* @param $
|
|
|
552 |
* @return string $content Content to load.
|
553 |
*/
|
554 |
-
private static function get_content_to_load( $content, $
|
555 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
556 |
|
557 |
// Prevent removing closing tags in scripts.
|
558 |
-
$content_to_load= preg_replace( '/<script.*?<\/script>/', '<!--\0-->', $content);
|
559 |
|
560 |
-
// check which priority the wpautop filter has; might have been disabled on purpose
|
561 |
-
$wpautop_priority = has_filter( 'the_content', 'wpautop');
|
562 |
if ( $wpautop_priority && Advanced_Ads_Plugin::get_instance()->get_content_injection_priority() < $wpautop_priority ) {
|
563 |
$content_to_load = wpautop( $content_to_load );
|
564 |
}
|
@@ -569,23 +639,24 @@ class Advanced_Ads_Placements {
|
|
569 |
/**
|
570 |
* Filter ad content.
|
571 |
*
|
572 |
-
* @param string $
|
573 |
* @param string $tag_name tar before/after the content.
|
574 |
-
* @param array
|
575 |
-
*
|
|
|
576 |
*/
|
577 |
private static function filter_ad_content( $ad_content, $tag_name, $options ) {
|
578 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
579 |
|
580 |
-
//Inject placeholder.
|
581 |
-
$id
|
582 |
self::$ads_for_placeholders[] = array(
|
583 |
-
'id'
|
584 |
-
'tag'
|
585 |
'type' => $options['before'] ? 'before' : 'after',
|
586 |
-
'ad'
|
587 |
);
|
588 |
-
$ad_content
|
589 |
|
590 |
return $ad_content;
|
591 |
}
|
@@ -595,12 +666,13 @@ class Advanced_Ads_Placements {
|
|
595 |
*
|
596 |
* @param string $content Modified content.
|
597 |
* @param string $content_orig Original content.
|
|
|
598 |
* @return string $content Content to output.
|
599 |
*/
|
600 |
private static function prepare_output( $content, $content_orig ) {
|
601 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
602 |
|
603 |
-
$content
|
604 |
self::$ads_for_placeholders = array();
|
605 |
|
606 |
return $content;
|
@@ -610,53 +682,71 @@ class Advanced_Ads_Placements {
|
|
610 |
* Search for ad placeholders in the `$content` to determine positions at which to inject ads.
|
611 |
* Given the positions, inject ads into `$content_orig.
|
612 |
*
|
613 |
-
* @param string $content
|
614 |
* @param string $content_orig Unmodified post content.
|
615 |
-
* @param
|
616 |
-
* @param
|
617 |
-
*
|
|
|
618 |
* @return string $content
|
619 |
*/
|
620 |
private static function inject_ads( $content, $content_orig, $ads_for_placeholders ) {
|
621 |
-
$self_closing_tags = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
622 |
|
623 |
// It is not possible to append/prepend in self closing tags.
|
624 |
foreach ( $ads_for_placeholders as &$ad_content ) {
|
625 |
if ( ( 'prepend' === $ad_content['type'] || 'append' === $ad_content['type'] )
|
626 |
-
|
627 |
$ad_content['type'] = 'after';
|
628 |
}
|
629 |
}
|
630 |
unset( $ad_content );
|
631 |
usort( $ads_for_placeholders, array( 'Advanced_Ads_Placements', 'sort_ads_for_placehoders' ) );
|
632 |
|
633 |
-
|
634 |
// Add tags before/after which ad placehoders were injected.
|
635 |
foreach ( $ads_for_placeholders as $ad_content ) {
|
636 |
$tag = $ad_content['tag'];
|
637 |
|
638 |
-
switch( $ad_content['type'] ) {
|
639 |
-
|
640 |
-
|
641 |
-
$alts[] = "<${tag}[^>]*>";
|
642 |
-
break;
|
643 |
-
case 'after':
|
644 |
-
if ( in_array( $tag, $self_closing_tags, true ) ) {
|
645 |
$alts[] = "<${tag}[^>]*>";
|
646 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
$alts[] = "</${tag}>";
|
648 |
-
|
649 |
-
break;
|
650 |
-
case 'append':
|
651 |
-
$alts[] = "</${tag}>";
|
652 |
-
break;
|
653 |
}
|
654 |
-
|
655 |
}
|
656 |
-
$alts
|
657 |
$tag_regexp = implode( '|', $alts );
|
658 |
// Add ad placeholder.
|
659 |
-
$alts[]
|
660 |
$tag_and_placeholder_regexp = implode( '|', $alts );
|
661 |
|
662 |
preg_match_all( "#{$tag_and_placeholder_regexp}#i", $content, $tag_matches );
|
@@ -665,7 +755,7 @@ class Advanced_Ads_Placements {
|
|
665 |
// For each tag located before/after an ad placeholder, find its offset among the same tags.
|
666 |
foreach ( $tag_matches[0] as $r ) {
|
667 |
if ( preg_match( '/%advads_placeholder_(\d+)%/', $r, $result ) ) {
|
668 |
-
$id
|
669 |
$found_ad = false;
|
670 |
foreach ( $ads_for_placeholders as $n => $ad ) {
|
671 |
if ( (int) $ad['id'] === (int) $id ) {
|
@@ -677,26 +767,25 @@ class Advanced_Ads_Placements {
|
|
677 |
continue;
|
678 |
}
|
679 |
|
680 |
-
switch( $found_ad['type'] ) {
|
681 |
case 'before':
|
682 |
case 'append':
|
683 |
$ads_for_placeholders[ $n ]['offset'] = $count;
|
684 |
break;
|
685 |
case 'after':
|
686 |
case 'prepend':
|
687 |
-
$ads_for_placeholders[ $n ]['offset'] = $count -1;
|
688 |
break;
|
689 |
}
|
690 |
-
|
691 |
} else {
|
692 |
-
$count++;
|
693 |
}
|
694 |
}
|
695 |
|
696 |
// Find tags before/after which we need to inject ads.
|
697 |
preg_match_all( "#{$tag_regexp}#i", $content_orig, $orig_tag_matches, PREG_OFFSET_CAPTURE );
|
698 |
$new_content = '';
|
699 |
-
$pos
|
700 |
|
701 |
foreach ( $orig_tag_matches[0] as $n => $r ) {
|
702 |
$to_inject = array();
|
@@ -708,23 +797,24 @@ class Advanced_Ads_Placements {
|
|
708 |
}
|
709 |
|
710 |
foreach ( $to_inject as $item ) {
|
711 |
-
switch( $item['type'] ) {
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
}
|
721 |
|
722 |
$new_content .= substr( $content_orig, $pos, $found_pos - $pos );
|
723 |
-
$pos
|
724 |
$new_content .= $item['ad'];
|
725 |
}
|
726 |
}
|
727 |
$new_content .= substr( $content_orig, $pos );
|
|
|
728 |
return $new_content;
|
729 |
}
|
730 |
|
@@ -732,8 +822,9 @@ class Advanced_Ads_Placements {
|
|
732 |
/**
|
733 |
* Callback function for usort() to sort ads for placeholders.
|
734 |
*
|
735 |
-
* @param array $first
|
736 |
* @param array $second The second array to compare.
|
|
|
737 |
* @return int 0 if both objects equal. -1 if second array should come first, 1 otherwise.
|
738 |
*/
|
739 |
public static function sort_ads_for_placehoders( $first, $second ) {
|
@@ -741,43 +832,55 @@ class Advanced_Ads_Placements {
|
|
741 |
return 0;
|
742 |
}
|
743 |
|
744 |
-
$num = array(
|
|
|
|
|
|
|
|
|
|
|
745 |
|
746 |
-
return $num[ $first['type'] ] > $num[ $second['type'] ] ? 1 : -1;
|
747 |
}
|
748 |
|
749 |
/**
|
750 |
* Add a warning to 'Ad health'.
|
751 |
*
|
752 |
-
* @param array $nodes.
|
|
|
753 |
* @return array $nodes.
|
754 |
*/
|
755 |
public static function add_ad_health_node( $nodes ) {
|
756 |
-
$nodes[] = array(
|
757 |
-
'
|
758 |
-
'
|
759 |
-
|
|
|
|
|
760 |
/* translators: %s stands for the name of the "Disable level limitation" option and automatically translated as well */
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
'
|
766 |
-
|
767 |
-
|
768 |
-
|
|
|
|
|
|
|
769 |
return $nodes;
|
770 |
}
|
771 |
|
772 |
/**
|
773 |
-
*
|
|
|
|
|
774 |
*
|
775 |
-
* @since 1.6.9
|
776 |
-
* @param int $id placement id
|
777 |
* @return bool true if placement can be displayed
|
|
|
778 |
*/
|
779 |
-
static function can_display( $id = 0 ){
|
780 |
-
if ( ! isset($id) ||
|
781 |
return true;
|
782 |
}
|
783 |
|
@@ -788,7 +891,8 @@ class Advanced_Ads_Placements {
|
|
788 |
* Get the placements that includes the ad or group.
|
789 |
*
|
790 |
* @param string $type 'ad' or 'group'.
|
791 |
-
* @param int
|
|
|
792 |
* @return array
|
793 |
*/
|
794 |
public static function get_placements_by( $type, $id ) {
|
@@ -804,5 +908,136 @@ class Advanced_Ads_Placements {
|
|
804 |
return $result;
|
805 |
}
|
806 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
807 |
}
|
808 |
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
+
* Grouping placements functions
|
15 |
*
|
16 |
* @since 1.1.0
|
17 |
* @package Advanced_Ads_Placements
|
18 |
* @author Thomas Maier <support@wpadvancedads.com>
|
19 |
*/
|
20 |
class Advanced_Ads_Placements {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Gather placeholders which later are replaced by the ads
|
24 |
+
*
|
25 |
+
* @var array $ads_for_placeholders
|
26 |
+
*/
|
27 |
private static $ads_for_placeholders = array();
|
28 |
+
/**
|
29 |
+
* Temporarily change content during processing
|
30 |
+
*
|
31 |
+
* @var array $placements
|
32 |
+
*/
|
33 |
private static $replacements = array(
|
34 |
'gcse:search' => 'gcse__search', // Google custom search namespaced tags.
|
35 |
);
|
36 |
|
37 |
/**
|
38 |
+
* Get placement types
|
39 |
*
|
40 |
+
* @return array $types array with placement types
|
41 |
* @since 1.2.1
|
|
|
42 |
*/
|
43 |
public static function get_placement_types() {
|
44 |
$types = array(
|
45 |
+
'default' => array(
|
46 |
+
'title' => __( 'Manual Placement', 'advanced-ads' ),
|
47 |
'description' => __( 'Manual placement to use as function or shortcode.', 'advanced-ads' ),
|
48 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/manual.png',
|
49 |
+
'options' => array(
|
50 |
+
'show_position' => true,
|
51 |
+
'show_lazy_load' => true,
|
52 |
+
'amp' => true,
|
53 |
),
|
54 |
+
),
|
55 |
+
'header' => array(
|
56 |
+
'title' => __( 'Header Code', 'advanced-ads' ),
|
57 |
'description' => __( 'Injected in Header (before closing </head> Tag, often not visible).', 'advanced-ads' ),
|
58 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/header.png',
|
59 |
+
),
|
60 |
+
'footer' => array(
|
61 |
+
'title' => __( 'Footer Code', 'advanced-ads' ),
|
62 |
'description' => __( 'Injected in Footer (before closing </body> Tag).', 'advanced-ads' ),
|
63 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/footer.png',
|
64 |
+
'options' => array( 'amp' => true ),
|
65 |
+
),
|
66 |
+
'post_top' => array(
|
67 |
+
'title' => __( 'Before Content', 'advanced-ads' ),
|
68 |
'description' => __( 'Injected before the post content.', 'advanced-ads' ),
|
69 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-before.png',
|
70 |
+
'options' => array(
|
71 |
+
'show_position' => true,
|
72 |
+
'show_lazy_load' => true,
|
73 |
+
'uses_the_content' => true,
|
74 |
+
'amp' => true,
|
75 |
),
|
76 |
+
),
|
77 |
+
'post_bottom' => array(
|
78 |
+
'title' => __( 'After Content', 'advanced-ads' ),
|
79 |
'description' => __( 'Injected after the post content.', 'advanced-ads' ),
|
80 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-after.png',
|
81 |
+
'options' => array(
|
82 |
+
'show_position' => true,
|
83 |
+
'show_lazy_load' => true,
|
84 |
+
'uses_the_content' => true,
|
85 |
+
'amp' => true,
|
86 |
),
|
87 |
+
),
|
88 |
+
'post_content' => array(
|
89 |
+
'title' => __( 'Content', 'advanced-ads' ),
|
90 |
'description' => __( 'Injected into the content. You can choose the paragraph after which the ad content is displayed.', 'advanced-ads' ),
|
91 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/content-within.png',
|
92 |
+
'options' => array(
|
93 |
+
'show_position' => true,
|
94 |
+
'show_lazy_load' => true,
|
95 |
+
'uses_the_content' => true,
|
96 |
+
'amp' => true,
|
97 |
),
|
98 |
+
),
|
99 |
'sidebar_widget' => array(
|
100 |
+
'title' => __( 'Sidebar Widget', 'advanced-ads' ),
|
101 |
'description' => __( 'Create a sidebar widget with an ad. Can be placed and used like any other widget.', 'advanced-ads' ),
|
102 |
+
'image' => ADVADS_BASE_URL . 'admin/assets/img/placements/widget.png',
|
103 |
+
'options' => array(
|
104 |
+
'show_lazy_load' => true,
|
105 |
+
'amp' => true,
|
106 |
),
|
107 |
+
),
|
108 |
);
|
109 |
+
|
110 |
return apply_filters( 'advanced-ads-placement-types', $types );
|
111 |
}
|
112 |
|
113 |
/**
|
114 |
+
* Update placements if sent
|
115 |
*
|
116 |
* @since 1.5.2
|
117 |
+
*/
|
118 |
+
public static function update_placements() {
|
119 |
|
120 |
+
// check user permissions.
|
121 |
+
if ( ! current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_placements' ) ) ) {
|
122 |
return;
|
123 |
}
|
124 |
+
|
125 |
$success = null;
|
|
|
|
|
|
|
126 |
|
127 |
+
// add hook of last opened placement settings to URL.
|
128 |
+
$hook = ! empty( $_POST['advads-last-edited-placement'] ) ? '#single-placement-' . $_POST['advads-last-edited-placement'] : '';
|
129 |
+
|
130 |
+
if ( isset( $_POST['advads']['placement'] ) && check_admin_referer( 'advads-placement', 'advads_placement' ) ) {
|
131 |
$success = self::save_new_placement( $_POST['advads']['placement'] );
|
132 |
}
|
133 |
+
// save placement data.
|
134 |
+
if ( isset( $_POST['advads']['placements'] ) && check_admin_referer( 'advads-placement', 'advads_placement' ) ) {
|
135 |
$success = self::save_placements( $_POST['advads']['placements'] );
|
136 |
}
|
137 |
|
138 |
$success = apply_filters( 'advanced-ads-update-placements', $success );
|
139 |
|
140 |
+
if ( isset( $success ) ) {
|
141 |
$message = $success ? 'updated' : 'error';
|
142 |
+
wp_redirect( esc_url_raw( add_query_arg( array( 'message' => $message ) ) ) . $hook );
|
143 |
}
|
144 |
}
|
145 |
|
146 |
/**
|
147 |
+
* Save a new placement
|
148 |
+
*
|
149 |
+
* @param array $new_placement information about the new placement.
|
150 |
*
|
|
|
|
|
151 |
* @return mixed slug if saved; false if not
|
152 |
+
* @since 1.1.0
|
153 |
*/
|
154 |
+
public static function save_new_placement( $new_placement ) {
|
155 |
+
// load placements // -TODO use model.
|
156 |
$placements = Advanced_Ads::get_ad_placements_array();
|
157 |
|
158 |
+
// create slug.
|
159 |
$new_placement['slug'] = sanitize_title( $new_placement['name'] );
|
160 |
|
161 |
if ( isset( $placements[ $new_placement['slug'] ] ) ) {
|
162 |
$i = 1;
|
163 |
+
// try to save placement until we found an empty slug.
|
164 |
do {
|
165 |
$i ++;
|
166 |
+
if ( 100 === $i ) { // prevent endless loop, just in case.
|
167 |
Advanced_Ads::log( 'endless loop when injecting placement' );
|
168 |
break;
|
169 |
}
|
173 |
$new_placement['name'] .= ' ' . $i;
|
174 |
}
|
175 |
|
176 |
+
// check if slug already exists or is empty.
|
177 |
+
if ( '' === $new_placement['slug'] || isset( $placements[ $new_placement['slug'] ] ) || ! isset( $new_placement['type'] ) ) {
|
178 |
return false;
|
179 |
}
|
180 |
|
181 |
+
// make sure only allowed types are being saved.
|
182 |
+
$placement_types = self::get_placement_types();
|
183 |
+
$new_placement['type'] = ( isset( $placement_types[ $new_placement['type'] ] ) ) ? $new_placement['type'] : 'default';
|
184 |
+
// escape name.
|
185 |
$new_placement['name'] = esc_attr( $new_placement['name'] );
|
186 |
|
187 |
+
// add new place to all placements.
|
188 |
+
$placements[ $new_placement['slug'] ] = array(
|
189 |
'type' => $new_placement['type'],
|
190 |
'name' => $new_placement['name'],
|
191 |
+
'item' => $new_placement['item'],
|
192 |
);
|
193 |
+
|
194 |
+
// add index options.
|
195 |
+
if ( isset( $new_placement['options'] ) ) {
|
196 |
+
$placements[ $new_placement['slug'] ]['options'] = $new_placement['options'];
|
197 |
+
if ( isset( $placements[ $new_placement['slug'] ]['options']['index'] ) ) {
|
198 |
+
$placements[ $new_placement['slug'] ]['options']['index'] = absint( $placements[ $new_placement['slug'] ]['options']['index'] );
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
// save array.
|
203 |
Advanced_Ads::get_instance()->get_model()->update_ad_placements_array( $placements );
|
204 |
|
205 |
return $new_placement['slug'];
|
206 |
}
|
207 |
|
208 |
/**
|
209 |
+
* Save placements
|
210 |
+
*
|
211 |
+
* @param array $placement_items placements.
|
212 |
*
|
|
|
|
|
213 |
* @return mixed true if saved; error message if not
|
214 |
+
* @since 1.1.0
|
215 |
*/
|
216 |
+
public static function save_placements( $placement_items ) {
|
217 |
|
218 |
+
// load placements // -TODO use model.
|
219 |
$placements = Advanced_Ads::get_ad_placements_array();
|
220 |
|
221 |
foreach ( $placement_items as $_placement_slug => $_placement ) {
|
222 |
+
// remove the placement.
|
223 |
+
if ( isset( $_placement['delete'] ) ) {
|
224 |
+
unset( $placements[ $_placement_slug ] );
|
225 |
continue;
|
226 |
}
|
227 |
+
// save item.
|
228 |
+
if ( isset( $_placement['item'] ) ) {
|
229 |
+
$placements[ $_placement_slug ]['item'] = $_placement['item'];
|
230 |
+
}
|
231 |
+
// save item options.
|
232 |
+
if ( isset( $_placement['options'] ) ) {
|
233 |
+
$placements[ $_placement_slug ]['options'] = $_placement['options'];
|
234 |
+
if ( isset( $placements[ $_placement_slug ]['options']['index'] ) ) {
|
235 |
+
$placements[ $_placement_slug ]['options']['index'] = absint( $placements[ $_placement_slug ]['options']['index'] );
|
236 |
+
}
|
237 |
} else {
|
238 |
+
$placements[ $_placement_slug ]['options'] = array();
|
239 |
}
|
240 |
}
|
241 |
|
242 |
+
// save array.
|
243 |
Advanced_Ads::get_instance()->get_model()->update_ad_placements_array( $placements );
|
244 |
|
245 |
return true;
|
246 |
}
|
247 |
|
248 |
/**
|
249 |
+
* Get items for item select field
|
250 |
*
|
251 |
+
* @return array $select items for select field
|
252 |
* @since 1.1
|
|
|
253 |
*/
|
254 |
public static function items_for_select() {
|
255 |
$select = array();
|
256 |
+
$model = Advanced_Ads::get_instance()->get_model();
|
257 |
|
258 |
+
// load all ad groups.
|
259 |
$groups = $model->get_ad_groups();
|
260 |
foreach ( $groups as $_group ) {
|
261 |
+
$select['groups'][ 'group_' . $_group->term_id ] = $_group->name;
|
262 |
}
|
263 |
|
264 |
+
// load all ads.
|
265 |
+
$ads = $model->get_ads(
|
266 |
+
array(
|
267 |
+
'orderby' => 'title',
|
268 |
+
'order' => 'ASC',
|
269 |
+
)
|
270 |
+
);
|
271 |
foreach ( $ads as $_ad ) {
|
272 |
+
$select['ads'][ 'ad_' . $_ad->ID ] = $_ad->post_title;
|
273 |
}
|
274 |
|
275 |
return $select;
|
276 |
}
|
277 |
|
278 |
/**
|
279 |
+
* Get html tags for content injection
|
280 |
*
|
281 |
+
* @return array $tags array with tags that can be used for content injection
|
282 |
* @since 1.3.5
|
|
|
283 |
*/
|
284 |
+
public static function tags_for_content_injection() {
|
285 |
+
$tags = apply_filters(
|
286 |
+
'advanced-ads-tags-for-injection',
|
287 |
+
array(
|
288 |
+
// translators: %s is an html tag.
|
289 |
+
'p' => sprintf( __( 'paragraph (%s)', 'advanced-ads' ), '<p>' ),
|
290 |
+
// translators: %s is an html tag.
|
291 |
+
'pwithoutimg' => sprintf( __( 'paragraph without image (%s)', 'advanced-ads' ), '<p>' ),
|
292 |
+
// translators: %s is an html tag.
|
293 |
+
'h2' => sprintf( __( 'headline 2 (%s)', 'advanced-ads' ), '<h2>' ),
|
294 |
+
// translators: %s is an html tag.
|
295 |
+
'h3' => sprintf( __( 'headline 3 (%s)', 'advanced-ads' ), '<h3>' ),
|
296 |
+
// translators: %s is an html tag.
|
297 |
+
'h4' => sprintf( __( 'headline 4 (%s)', 'advanced-ads' ), '<h4>' ),
|
298 |
+
)
|
299 |
+
);
|
300 |
|
301 |
return $tags;
|
302 |
}
|
303 |
|
304 |
/**
|
305 |
+
* Return content of a placement
|
306 |
*
|
307 |
+
* @param string $id slug of the display.
|
308 |
+
* @param array $args optional arguments (passed to child).
|
309 |
+
*
|
310 |
+
* @return string
|
311 |
*/
|
312 |
public static function output( $id = '', $args = array() ) {
|
313 |
+
// get placement data for the slug.
|
314 |
+
if ( '' == $id ) {
|
315 |
return;
|
316 |
}
|
317 |
|
318 |
$placements = Advanced_Ads::get_ad_placements_array();
|
319 |
+
$placement = ( isset( $placements[ $id ] ) && is_array( $placements[ $id ] ) ) ? $placements[ $id ] : array();
|
320 |
|
321 |
if ( isset( $args['change-placement'] ) ) {
|
322 |
+
// some options was provided by the user.
|
323 |
+
$placement = Advanced_Ads_Utils::merge_deep_array( array( $placement, $args['change-placement'] ) );
|
324 |
}
|
325 |
|
326 |
+
if ( isset( $placement['item'] ) && '' !== $placement['item'] ) {
|
327 |
$_item = explode( '_', $placement['item'] );
|
328 |
|
329 |
if ( ! isset( $_item[1] ) || empty( $_item[1] ) ) {
|
330 |
+
return;
|
331 |
}
|
332 |
|
333 |
+
// inject options.
|
334 |
if ( isset( $placement['options'] ) && is_array( $placement['options'] ) ) {
|
335 |
foreach ( $placement['options'] as $_k => $_v ) {
|
336 |
if ( ! isset( $args[ $_k ] ) ) {
|
339 |
}
|
340 |
}
|
341 |
|
342 |
+
// inject placement type.
|
343 |
if ( isset( $placement['type'] ) ) {
|
344 |
+
$args['placement_type'] = $placement['type'];
|
345 |
}
|
346 |
|
347 |
+
// options.
|
348 |
$prefix = Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();
|
349 |
|
350 |
+
// return either ad or group content.
|
351 |
switch ( $_item[0] ) {
|
352 |
case 'ad':
|
353 |
+
case Advanced_Ads_Select::AD:
|
354 |
+
// create class from placement id (not if header injection).
|
355 |
+
if ( ! isset( $placement['type'] ) || 'header' !== $placement['type'] ) {
|
356 |
if ( ! isset( $args['output'] ) ) {
|
357 |
$args['output'] = array();
|
358 |
}
|
365 |
}
|
366 |
}
|
367 |
|
368 |
+
// fix method id.
|
369 |
$_item[0] = Advanced_Ads_Select::AD;
|
370 |
break;
|
371 |
|
372 |
+
// avoid loops (programmatical error).
|
373 |
+
case Advanced_Ads_Select::PLACEMENT:
|
374 |
return;
|
375 |
|
376 |
+
case Advanced_Ads_Select::GROUP:
|
377 |
+
$class = $prefix . $id;
|
378 |
+
if ( ( isset( $placement['type'] ) && $placement['type'] !== 'header' )
|
379 |
+
&& ( ! isset( $args['output']['class'] )
|
380 |
+
|| ! is_array( $args['output']['class'] )
|
381 |
+
|| ! in_array( $class, $args['output']['class'] ) ) ) {
|
382 |
+
$args['output']['class'][] = $class;
|
383 |
+
}
|
384 |
default:
|
385 |
}
|
386 |
|
387 |
+
// create placement id for various features.
|
388 |
$args['output']['placement_id'] = $id;
|
389 |
|
390 |
+
// add the placement to the global output array.
|
391 |
$advads = Advanced_Ads::get_instance();
|
392 |
+
$name = isset( $placement['name'] ) ? $placement['name'] : $id;
|
393 |
|
394 |
if ( ! isset( $args['global_output'] ) || $args['global_output'] ) {
|
395 |
+
$advads->current_ads[] = array(
|
396 |
+
'type' => 'placement',
|
397 |
+
'id' => $id,
|
398 |
+
'title' => $name,
|
399 |
+
);
|
400 |
}
|
401 |
|
402 |
$result = Advanced_Ads_Select::get_instance()->get_ad_by_method( (int) $_item[1], $_item[0], $args );
|
403 |
|
404 |
return $result;
|
405 |
}
|
406 |
+
|
407 |
+
return;
|
408 |
}
|
409 |
|
410 |
/**
|
411 |
+
* Inject ads directly into the content
|
412 |
*
|
413 |
+
* @param string $placement_id Id of the placement.
|
414 |
+
* @param array $placement_opts Placement options.
|
415 |
+
* @param string $content Content to inject placement into.
|
416 |
+
*
|
417 |
+
* @return string $content Content with injected placement.
|
418 |
* @since 1.2.1
|
|
|
|
|
|
|
|
|
|
|
419 |
*/
|
420 |
+
public static function &inject_in_content( $placement_id, $placement_opts, &$content ) {
|
421 |
if ( ! extension_loaded( 'dom' ) ) {
|
422 |
return $content;
|
423 |
}
|
424 |
|
425 |
+
// get plugin options.
|
426 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
|
|
|
|
|
|
427 |
|
428 |
+
$wp_charset = get_bloginfo( 'charset' );
|
429 |
+
// parse document as DOM (fragment - having only a part of an actual post given).
|
430 |
+
|
431 |
+
$content_to_load = self::get_content_to_load( $content, $wp_charset );
|
432 |
if ( ! $content_to_load ) {
|
433 |
return $content;
|
434 |
}
|
435 |
|
436 |
+
$dom = new DOMDocument( '1.0', $wp_charset );
|
437 |
+
// may loose some fragments or add autop-like code.
|
438 |
+
libxml_use_internal_errors( true ); // avoid notices and warnings - html is most likely malformed.
|
439 |
|
440 |
+
$success = $dom->loadHtml( '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wp_charset . '" /><body>' . $content_to_load );
|
441 |
+
libxml_use_internal_errors( false );
|
442 |
+
if ( true !== $success ) {
|
443 |
// -TODO handle cases were dom-parsing failed (at least inform user)
|
444 |
return $content;
|
445 |
}
|
446 |
|
447 |
+
// parse arguments.
|
448 |
+
$tag = isset( $placement_opts['tag'] ) ? $placement_opts['tag'] : 'p';
|
449 |
+
$tag = preg_replace( '/[^a-z0-9]/i', '', $tag ); // simplify tag.
|
450 |
|
451 |
+
// allow more complex xPath expression.
|
452 |
$tag = apply_filters( 'advanced-ads-placement-content-injection-xpath', $tag, $placement_opts );
|
453 |
|
454 |
+
if ( 'pwithoutimg' === $tag ) {
|
455 |
$tag = 'p[not(descendant::img)]';
|
456 |
}
|
457 |
|
458 |
+
// select positions.
|
459 |
+
$xpath = new DOMXPath( $dom );
|
460 |
+
$items = $xpath->query( '/html/body/' . $tag );
|
461 |
|
462 |
$options = array(
|
463 |
+
'allowEmpty' => false, // whether the tag can be empty to be counted.
|
464 |
+
'paragraph_select_from_bottom' => isset( $placement_opts['start_from_bottom'] ) && $placement_opts['start_from_bottom'],
|
465 |
+
// only has before and after.
|
466 |
+
'before' => isset( $placement_opts['position'] ) && 'before' === $placement_opts['position'],
|
467 |
);
|
468 |
|
469 |
+
$options['paragraph_id'] = isset( $placement_opts['index'] ) ? $placement_opts['index'] : 1;
|
470 |
$options['paragraph_id'] = max( 1, (int) $options['paragraph_id'] );
|
471 |
|
472 |
+
// if there are too few items at this level test nesting.
|
473 |
+
$options['itemLimit'] = 'p' === $tag ? 2 : 1;
|
474 |
|
475 |
+
// trigger such a high item limit that all elements will be considered.
|
476 |
+
if ( ! empty( $plugin_options['content-injection-level-disabled'] ) ) {
|
477 |
$options['itemLimit'] = 1000;
|
478 |
}
|
479 |
+
|
480 |
+
// allow hooks to change some options.
|
481 |
$options = apply_filters(
|
482 |
'advanced-ads-placement-content-injection-options',
|
483 |
$options,
|
484 |
+
$tag
|
485 |
+
);
|
486 |
|
487 |
+
if ( $items->length < $options['itemLimit'] ) {
|
488 |
+
$items = $xpath->query( '/html/body/*/' . $tag );
|
489 |
}
|
490 |
+
// try third level.
|
491 |
if ( $items->length < $options['itemLimit'] ) {
|
492 |
+
$items = $xpath->query( '/html/body/*/*/' . $tag );
|
493 |
}
|
494 |
+
// try all levels as last resort.
|
495 |
if ( $items->length < $options['itemLimit'] ) {
|
496 |
$items = $xpath->query( '//' . $tag );
|
497 |
}
|
498 |
+
|
499 |
+
// allow to select other elements.
|
500 |
$items = apply_filters( 'advanced-ads-placement-content-injection-items', $items, $xpath, $tag );
|
501 |
|
502 |
+
// filter empty tags from items.
|
503 |
+
$whitespaces = json_decode( '"\t\n\r \u00A0"' );
|
504 |
+
$paragraphs = array();
|
505 |
+
foreach ( $items as $item ) {
|
506 |
+
if ( $options['allowEmpty'] || ( isset( $item->textContent ) && trim( $item->textContent, $whitespaces ) !== '' ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
|
507 |
$paragraphs[] = $item;
|
508 |
}
|
509 |
}
|
510 |
|
511 |
+
$ancestors_to_limit = self::get_ancestors_to_limit( $xpath );
|
512 |
+
$paragraphs = self::filter_by_ancestors_to_limit( $paragraphs, $ancestors_to_limit );
|
513 |
+
|
514 |
+
$options['paragraph_count'] = count( $paragraphs );
|
515 |
|
516 |
+
if ( $options['paragraph_count'] >= $options['paragraph_id'] ) {
|
517 |
+
$offset = $options['paragraph_select_from_bottom'] ? $options['paragraph_count'] - $options['paragraph_id'] : $options['paragraph_id'] - 1;
|
518 |
+
$offsets = apply_filters( 'advanced-ads-placement-content-offsets', array( $offset ), $options, $placement_opts );
|
519 |
$did_inject = false;
|
520 |
|
521 |
foreach ( $offsets as $offset ) {
|
522 |
+
// inject.
|
523 |
+
$node = apply_filters( 'advanced-ads-placement-content-injection-node', $paragraphs[ $offset ], $tag, $options['before'] );
|
524 |
|
525 |
+
$ad_content = Advanced_Ads_Select::get_instance()->get_ad_by_method( $placement_id, 'placement', $placement_opts );
|
526 |
|
527 |
+
if ( trim( $ad_content, $whitespaces ) === '' ) {
|
528 |
continue;
|
529 |
}
|
530 |
|
531 |
+
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
|
532 |
+
$ad_content = self::filter_ad_content( $ad_content, $node->tagName, $options );
|
533 |
|
534 |
// convert HTML to XML!
|
535 |
+
$ad_dom = new DOMDocument( '1.0', $wp_charset );
|
536 |
+
libxml_use_internal_errors( true );
|
537 |
+
$ad_dom->loadHtml( '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=' . $wp_charset . '" /><body>' . $ad_content );
|
538 |
+
// log errors.
|
539 |
+
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && current_user_can( 'advanced_ads_manage_options' ) ) {
|
540 |
+
foreach ( libxml_get_errors() as $_error ) {
|
541 |
+
// continue, if there is '&' symbol, but not HTML entity.
|
542 |
if ( false === stripos( $_error->message, 'htmlParseEntityRef:' ) ) {
|
543 |
Advanced_Ads::log( 'possible content injection error for placement "' . $placement_id . '": ' . print_r( $_error, true ) );
|
544 |
}
|
545 |
}
|
546 |
}
|
547 |
|
|
|
548 |
if ( $options['before'] ) {
|
549 |
+
$ref_node = $node;
|
550 |
|
551 |
+
foreach ( $ad_dom->getElementsByTagName( 'body' )->item( 0 )->childNodes as $importedNode ) {
|
552 |
$importedNode = $dom->importNode( $importedNode, true );
|
553 |
+
$ref_node->parentNode->insertBefore( $importedNode, $ref_node );
|
554 |
}
|
555 |
} else {
|
556 |
+
// append before next node or as last child to body.
|
557 |
+
$ref_node = $node->nextSibling;
|
558 |
+
if ( isset( $ref_node ) ) {
|
559 |
|
560 |
+
foreach ( $ad_dom->getElementsByTagName( 'body' )->item( 0 )->childNodes as $importedNode ) {
|
561 |
$importedNode = $dom->importNode( $importedNode, true );
|
562 |
+
$ref_node->parentNode->insertBefore( $importedNode, $ref_node );
|
563 |
}
|
|
|
564 |
} else {
|
565 |
+
// append to body; -TODO using here that we only select direct children of the body tag.
|
566 |
+
foreach ( $ad_dom->getElementsByTagName( 'body' )->item( 0 )->childNodes as $importedNode ) {
|
567 |
$importedNode = $dom->importNode( $importedNode, true );
|
568 |
$node->parentNode->appendChild( $importedNode );
|
569 |
}
|
570 |
}
|
571 |
}
|
572 |
|
573 |
+
libxml_use_internal_errors( false );
|
574 |
$did_inject = true;
|
575 |
}
|
576 |
|
579 |
}
|
580 |
|
581 |
$content_orig = $content;
|
582 |
+
// convert to text-representation.
|
583 |
$content = $dom->saveHTML();
|
584 |
$content = self::prepare_output( $content, $content_orig );
|
585 |
|
586 |
+
/**
|
587 |
+
* Show a warning to ad admins in the Ad Health bar in the frontend, when
|
588 |
+
*
|
589 |
+
* * the level limitation was not disabled
|
590 |
+
* * could not inject one ad (as by use of `elseif` here)
|
591 |
+
* * but there are enough elements on the site, but just in sub-containers
|
592 |
+
*/
|
593 |
+
} elseif ( current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) )
|
594 |
+
&& empty( $plugin_options['content-injection-level-disabled'] ) ) {
|
595 |
+
|
596 |
+
// Check if there are more elements without limitation.
|
|
|
597 |
$all_items = $xpath->query( '//' . $tag );
|
598 |
+
|
599 |
+
$paragraphs = array();
|
600 |
+
foreach ( $all_items as $item ) {
|
601 |
+
if ( $options['allowEmpty'] || ( isset( $item->textContent ) && trim( $item->textContent, $whitespaces ) !== '' ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
|
602 |
+
$paragraphs[] = $item;
|
603 |
+
}
|
604 |
+
}
|
605 |
+
|
606 |
+
$paragraphs = self::filter_by_ancestors_to_limit( $paragraphs, $ancestors_to_limit );
|
607 |
+
if ( $options['paragraph_id'] <= count( $paragraphs ) ) {
|
608 |
+
// Add a warning to ad health.
|
609 |
add_filter( 'advanced-ads-ad-health-nodes', array( 'Advanced_Ads_Placements', 'add_ad_health_node' ) );
|
610 |
}
|
611 |
}
|
617 |
* Get content to load.
|
618 |
*
|
619 |
* @param string $content Original content.
|
620 |
+
* @param string $wp_charset blog charset.
|
621 |
+
*
|
622 |
* @return string $content Content to load.
|
623 |
*/
|
624 |
+
private static function get_content_to_load( $content, $wp_charset ) {
|
625 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
626 |
|
627 |
// Prevent removing closing tags in scripts.
|
628 |
+
$content_to_load = preg_replace( '/<script.*?<\/script>/', '<!--\0-->', $content );
|
629 |
|
630 |
+
// check which priority the wpautop filter has; might have been disabled on purpose.
|
631 |
+
$wpautop_priority = has_filter( 'the_content', 'wpautop' );
|
632 |
if ( $wpautop_priority && Advanced_Ads_Plugin::get_instance()->get_content_injection_priority() < $wpautop_priority ) {
|
633 |
$content_to_load = wpautop( $content_to_load );
|
634 |
}
|
639 |
/**
|
640 |
* Filter ad content.
|
641 |
*
|
642 |
+
* @param string $ad_content Ad content.
|
643 |
* @param string $tag_name tar before/after the content.
|
644 |
+
* @param array $options Injection options.
|
645 |
+
*
|
646 |
+
* @return string ad content.
|
647 |
*/
|
648 |
private static function filter_ad_content( $ad_content, $tag_name, $options ) {
|
649 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
650 |
|
651 |
+
// Inject placeholder.
|
652 |
+
$id = count( self::$ads_for_placeholders );
|
653 |
self::$ads_for_placeholders[] = array(
|
654 |
+
'id' => $id,
|
655 |
+
'tag' => $tag_name,
|
656 |
'type' => $options['before'] ? 'before' : 'after',
|
657 |
+
'ad' => $ad_content,
|
658 |
);
|
659 |
+
$ad_content = '%advads_placeholder_' . $id . '%';
|
660 |
|
661 |
return $ad_content;
|
662 |
}
|
666 |
*
|
667 |
* @param string $content Modified content.
|
668 |
* @param string $content_orig Original content.
|
669 |
+
*
|
670 |
* @return string $content Content to output.
|
671 |
*/
|
672 |
private static function prepare_output( $content, $content_orig ) {
|
673 |
$plugin_options = Advanced_Ads::get_instance()->options();
|
674 |
|
675 |
+
$content = self::inject_ads( $content, $content_orig, self::$ads_for_placeholders );
|
676 |
self::$ads_for_placeholders = array();
|
677 |
|
678 |
return $content;
|
682 |
* Search for ad placeholders in the `$content` to determine positions at which to inject ads.
|
683 |
* Given the positions, inject ads into `$content_orig.
|
684 |
*
|
685 |
+
* @param string $content Post content with injected ad placeholders.
|
686 |
* @param string $content_orig Unmodified post content.
|
687 |
+
* @param array $options Injection options.
|
688 |
+
* @param array $ads_for_placeholders Array of ads.
|
689 |
+
* Each ad contains placeholder id, before or after which tag to inject the ad, the ad content.
|
690 |
+
*
|
691 |
* @return string $content
|
692 |
*/
|
693 |
private static function inject_ads( $content, $content_orig, $ads_for_placeholders ) {
|
694 |
+
$self_closing_tags = array(
|
695 |
+
'area',
|
696 |
+
'base',
|
697 |
+
'basefont',
|
698 |
+
'bgsound',
|
699 |
+
'br',
|
700 |
+
'col',
|
701 |
+
'embed',
|
702 |
+
'frame',
|
703 |
+
'hr',
|
704 |
+
'img',
|
705 |
+
'input',
|
706 |
+
'keygen',
|
707 |
+
'link',
|
708 |
+
'meta',
|
709 |
+
'param',
|
710 |
+
'source',
|
711 |
+
'track',
|
712 |
+
'wbr',
|
713 |
+
);
|
714 |
|
715 |
// It is not possible to append/prepend in self closing tags.
|
716 |
foreach ( $ads_for_placeholders as &$ad_content ) {
|
717 |
if ( ( 'prepend' === $ad_content['type'] || 'append' === $ad_content['type'] )
|
718 |
+
&& in_array( $ad_content['tag'], $self_closing_tags, true ) ) {
|
719 |
$ad_content['type'] = 'after';
|
720 |
}
|
721 |
}
|
722 |
unset( $ad_content );
|
723 |
usort( $ads_for_placeholders, array( 'Advanced_Ads_Placements', 'sort_ads_for_placehoders' ) );
|
724 |
|
|
|
725 |
// Add tags before/after which ad placehoders were injected.
|
726 |
foreach ( $ads_for_placeholders as $ad_content ) {
|
727 |
$tag = $ad_content['tag'];
|
728 |
|
729 |
+
switch ( $ad_content['type'] ) {
|
730 |
+
case 'before':
|
731 |
+
case 'prepend':
|
|
|
|
|
|
|
|
|
732 |
$alts[] = "<${tag}[^>]*>";
|
733 |
+
break;
|
734 |
+
case 'after':
|
735 |
+
if ( in_array( $tag, $self_closing_tags, true ) ) {
|
736 |
+
$alts[] = "<${tag}[^>]*>";
|
737 |
+
} else {
|
738 |
+
$alts[] = "</${tag}>";
|
739 |
+
}
|
740 |
+
break;
|
741 |
+
case 'append':
|
742 |
$alts[] = "</${tag}>";
|
743 |
+
break;
|
|
|
|
|
|
|
|
|
744 |
}
|
|
|
745 |
}
|
746 |
+
$alts = array_unique( $alts );
|
747 |
$tag_regexp = implode( '|', $alts );
|
748 |
// Add ad placeholder.
|
749 |
+
$alts[] = '%advads_placeholder_(?:\d+)%';
|
750 |
$tag_and_placeholder_regexp = implode( '|', $alts );
|
751 |
|
752 |
preg_match_all( "#{$tag_and_placeholder_regexp}#i", $content, $tag_matches );
|
755 |
// For each tag located before/after an ad placeholder, find its offset among the same tags.
|
756 |
foreach ( $tag_matches[0] as $r ) {
|
757 |
if ( preg_match( '/%advads_placeholder_(\d+)%/', $r, $result ) ) {
|
758 |
+
$id = $result[1];
|
759 |
$found_ad = false;
|
760 |
foreach ( $ads_for_placeholders as $n => $ad ) {
|
761 |
if ( (int) $ad['id'] === (int) $id ) {
|
767 |
continue;
|
768 |
}
|
769 |
|
770 |
+
switch ( $found_ad['type'] ) {
|
771 |
case 'before':
|
772 |
case 'append':
|
773 |
$ads_for_placeholders[ $n ]['offset'] = $count;
|
774 |
break;
|
775 |
case 'after':
|
776 |
case 'prepend':
|
777 |
+
$ads_for_placeholders[ $n ]['offset'] = $count - 1;
|
778 |
break;
|
779 |
}
|
|
|
780 |
} else {
|
781 |
+
$count ++;
|
782 |
}
|
783 |
}
|
784 |
|
785 |
// Find tags before/after which we need to inject ads.
|
786 |
preg_match_all( "#{$tag_regexp}#i", $content_orig, $orig_tag_matches, PREG_OFFSET_CAPTURE );
|
787 |
$new_content = '';
|
788 |
+
$pos = 0;
|
789 |
|
790 |
foreach ( $orig_tag_matches[0] as $n => $r ) {
|
791 |
$to_inject = array();
|
797 |
}
|
798 |
|
799 |
foreach ( $to_inject as $item ) {
|
800 |
+
switch ( $item['type'] ) {
|
801 |
+
case 'before':
|
802 |
+
case 'append':
|
803 |
+
$found_pos = $r[1];
|
804 |
+
break;
|
805 |
+
case 'after':
|
806 |
+
case 'prepend':
|
807 |
+
$found_pos = $r[1] + strlen( $r[0] );
|
808 |
+
break;
|
809 |
}
|
810 |
|
811 |
$new_content .= substr( $content_orig, $pos, $found_pos - $pos );
|
812 |
+
$pos = $found_pos;
|
813 |
$new_content .= $item['ad'];
|
814 |
}
|
815 |
}
|
816 |
$new_content .= substr( $content_orig, $pos );
|
817 |
+
|
818 |
return $new_content;
|
819 |
}
|
820 |
|
822 |
/**
|
823 |
* Callback function for usort() to sort ads for placeholders.
|
824 |
*
|
825 |
+
* @param array $first The first array to compare.
|
826 |
* @param array $second The second array to compare.
|
827 |
+
*
|
828 |
* @return int 0 if both objects equal. -1 if second array should come first, 1 otherwise.
|
829 |
*/
|
830 |
public static function sort_ads_for_placehoders( $first, $second ) {
|
832 |
return 0;
|
833 |
}
|
834 |
|
835 |
+
$num = array(
|
836 |
+
'before' => 1,
|
837 |
+
'prepend' => 2,
|
838 |
+
'append' => 3,
|
839 |
+
'after' => 4,
|
840 |
+
);
|
841 |
|
842 |
+
return $num[ $first['type'] ] > $num[ $second['type'] ] ? 1 : - 1;
|
843 |
}
|
844 |
|
845 |
/**
|
846 |
* Add a warning to 'Ad health'.
|
847 |
*
|
848 |
+
* @param array $nodes .
|
849 |
+
*
|
850 |
* @return array $nodes.
|
851 |
*/
|
852 |
public static function add_ad_health_node( $nodes ) {
|
853 |
+
$nodes[] = array(
|
854 |
+
'type' => 1,
|
855 |
+
'data' => array(
|
856 |
+
'parent' => 'advanced_ads_ad_health',
|
857 |
+
'id' => 'advanced_ads_ad_health_the_content_not_enough_elements',
|
858 |
+
'title' => sprintf(
|
859 |
/* translators: %s stands for the name of the "Disable level limitation" option and automatically translated as well */
|
860 |
+
__( 'Set <em>%s</em> to show more ads', 'advanced-ads' ),
|
861 |
+
__( 'Disable level limitation', 'advanced-ads' )
|
862 |
+
),
|
863 |
+
'href' => admin_url( '/admin.php?page=advanced-ads-settings#top#general' ),
|
864 |
+
'meta' => array(
|
865 |
+
'class' => 'advanced_ads_ad_health_warning',
|
866 |
+
'target' => '_blank',
|
867 |
+
),
|
868 |
+
),
|
869 |
+
);
|
870 |
+
|
871 |
return $nodes;
|
872 |
}
|
873 |
|
874 |
/**
|
875 |
+
* Check if the placement can be displayed
|
876 |
+
*
|
877 |
+
* @param int $id placement id.
|
878 |
*
|
|
|
|
|
879 |
* @return bool true if placement can be displayed
|
880 |
+
* @since 1.6.9
|
881 |
*/
|
882 |
+
public static function can_display( $id = 0 ) {
|
883 |
+
if ( ! isset( $id ) || 0 === $id ) {
|
884 |
return true;
|
885 |
}
|
886 |
|
891 |
* Get the placements that includes the ad or group.
|
892 |
*
|
893 |
* @param string $type 'ad' or 'group'.
|
894 |
+
* @param int $id Id.
|
895 |
+
*
|
896 |
* @return array
|
897 |
*/
|
898 |
public static function get_placements_by( $type, $id ) {
|
908 |
return $result;
|
909 |
}
|
910 |
|
911 |
+
/**
|
912 |
+
* Get paths of ancestors that should not contain ads.
|
913 |
+
*
|
914 |
+
* @param object $xpath DOMXPath object.
|
915 |
+
*
|
916 |
+
* @return array Paths of ancestors.
|
917 |
+
*/
|
918 |
+
private static function get_ancestors_to_limit( $xpath ) {
|
919 |
+
$query = self::get_ancestors_to_limit_query();
|
920 |
+
if ( ! $query ) {
|
921 |
+
return array();
|
922 |
+
}
|
923 |
+
|
924 |
+
$node_list = $xpath->query( $query );
|
925 |
+
$ancestors_to_limit = array();
|
926 |
+
|
927 |
+
foreach ( $node_list as $a ) {
|
928 |
+
$ancestors_to_limit[] = $a->getNodePath();
|
929 |
+
}
|
930 |
+
|
931 |
+
return $ancestors_to_limit;
|
932 |
+
}
|
933 |
+
|
934 |
+
|
935 |
+
/**
|
936 |
+
* Remove paragraphs that has ancestors that should not contain ads.
|
937 |
+
*
|
938 |
+
* @param array $paragraphs An array of `DOMNode` objects to insert ads before or after.
|
939 |
+
* @param array $ancestors_to_limit Paths of ancestor that should not contain ads.
|
940 |
+
*
|
941 |
+
* @return array $new_paragraphs An array of `DOMNode` objects to insert ads before or after.
|
942 |
+
*/
|
943 |
+
private static function filter_by_ancestors_to_limit( $paragraphs, $ancestors_to_limit ) {
|
944 |
+
$new_paragraphs = array();
|
945 |
+
|
946 |
+
foreach ( $paragraphs as $k => $paragraph ) {
|
947 |
+
foreach ( $ancestors_to_limit as $a ) {
|
948 |
+
if ( 0 === stripos( $paragraph->getNodePath(), $a ) ) {
|
949 |
+
continue 2;
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
$new_paragraphs[] = $paragraph;
|
954 |
+
}
|
955 |
+
|
956 |
+
return $new_paragraphs;
|
957 |
+
}
|
958 |
+
|
959 |
+
/**
|
960 |
+
* Get query to select ancestors that should not contain ads.
|
961 |
+
*
|
962 |
+
* @return string/false DOMXPath query or false.
|
963 |
+
*/
|
964 |
+
private static function get_ancestors_to_limit_query() {
|
965 |
+
/**
|
966 |
+
* TODO:
|
967 |
+
* - support `%` (rand) at the start
|
968 |
+
* - support plain text that node should contain instead of CSS selectors
|
969 |
+
* - support `prev` and `next` as `type`
|
970 |
+
*/
|
971 |
+
|
972 |
+
/**
|
973 |
+
* Filter the nodes that limit injection.
|
974 |
+
*
|
975 |
+
* @param array An array of arrays, each of which contains:
|
976 |
+
*
|
977 |
+
* @type string $type Accept: `ancestor` - limit injection inside the ancestor.
|
978 |
+
* @type string $node A "class selector" which targets one class (.) or "id selector" which targets one id (#),
|
979 |
+
* optionally with `%` at the end.
|
980 |
+
*/
|
981 |
+
$items = apply_filters(
|
982 |
+
'advanced-ads-content-injection-nodes-without-ads',
|
983 |
+
array(
|
984 |
+
array(
|
985 |
+
// a class anyone can use to prevent automatic ad injection into a specific element.
|
986 |
+
'node' => '.advads-stop-injection',
|
987 |
+
'type' => 'ancestor',
|
988 |
+
),
|
989 |
+
array(
|
990 |
+
// Product Slider for Beaver Builder by WooPack.
|
991 |
+
'node' => '.woopack-product-carousel',
|
992 |
+
'type' => 'ancestor',
|
993 |
+
),
|
994 |
+
array(
|
995 |
+
// WP Author Box Lite.
|
996 |
+
'node' => '#wpautbox-%',
|
997 |
+
'type' => 'ancestor',
|
998 |
+
),
|
999 |
+
array(
|
1000 |
+
// GeoDirectory Post Slider.
|
1001 |
+
'node' => '.geodir-post-slider',
|
1002 |
+
'type' => 'ancestor',
|
1003 |
+
),
|
1004 |
+
)
|
1005 |
+
);
|
1006 |
+
|
1007 |
+
$query = array();
|
1008 |
+
foreach ( $items as $p ) {
|
1009 |
+
$sel = $p['node'];
|
1010 |
+
|
1011 |
+
$sel_type = substr( $sel, 0, 1 );
|
1012 |
+
$sel = substr( $sel, 1 );
|
1013 |
+
|
1014 |
+
$rand_pos = strpos( $sel, '%' );
|
1015 |
+
$sel = str_replace( '%', '', $sel );
|
1016 |
+
$sel = sanitize_html_class( $sel );
|
1017 |
+
|
1018 |
+
if ( '.' === $sel_type ) {
|
1019 |
+
if ( false !== $rand_pos ) {
|
1020 |
+
$query[] = "@class and contains(concat(' ', normalize-space(@class), ' '), ' $sel')";
|
1021 |
+
} else {
|
1022 |
+
$query[] = "@class and contains(concat(' ', normalize-space(@class), ' '), ' $sel ')";
|
1023 |
+
}
|
1024 |
+
}
|
1025 |
+
if ( '#' === $sel_type ) {
|
1026 |
+
if ( false !== $rand_pos ) {
|
1027 |
+
$query[] = "@id and starts-with(@id, '$sel')";
|
1028 |
+
} else {
|
1029 |
+
$query[] = "@id and @id = '$sel'";
|
1030 |
+
}
|
1031 |
+
}
|
1032 |
+
}
|
1033 |
+
|
1034 |
+
if ( ! $query ) {
|
1035 |
+
return false;
|
1036 |
+
}
|
1037 |
+
|
1038 |
+
return '//*[' . implode( ' or ', $query ) . ']';
|
1039 |
+
}
|
1040 |
+
|
1041 |
+
|
1042 |
}
|
1043 |
|
modules/ads-txt/includes/class-advanced-ads-ads-txt-utils.php
CHANGED
@@ -8,13 +8,26 @@ class Advanced_Ads_Ads_Txt_Utils {
|
|
8 |
/**
|
9 |
* Get file info.
|
10 |
*
|
|
|
11 |
* @return array/WP_Error An array containing 'exists', 'is_third_party'.
|
12 |
* A WP_Error upon error.
|
13 |
*/
|
14 |
public static function get_file_info( $url = null ) {
|
15 |
$url = $url ? $url : home_url( '/' );
|
16 |
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
$code = wp_remote_retrieve_response_code( $response );
|
19 |
$content = wp_remote_retrieve_body( $response );
|
20 |
$content_type = wp_remote_retrieve_header( $response, 'content-type' );
|
8 |
/**
|
9 |
* Get file info.
|
10 |
*
|
11 |
+
* @param string $url Url to retrieve the file.
|
12 |
* @return array/WP_Error An array containing 'exists', 'is_third_party'.
|
13 |
* A WP_Error upon error.
|
14 |
*/
|
15 |
public static function get_file_info( $url = null ) {
|
16 |
$url = $url ? $url : home_url( '/' );
|
17 |
|
18 |
+
// Disable ssl verification to prevent errors on servers that are not properly configured with its https certificates.
|
19 |
+
/** This filter is documented in wp-includes/class-wp-http-streams.php */
|
20 |
+
$sslverify = apply_filters( 'https_local_ssl_verify', false );
|
21 |
+
$response = wp_remote_get(
|
22 |
+
trailingslashit( $url ) . 'ads.txt',
|
23 |
+
array(
|
24 |
+
'timeout' => 3,
|
25 |
+
'sslverify' => $sslverify,
|
26 |
+
'headers' => array(
|
27 |
+
'Cache-Control' => 'no-cache',
|
28 |
+
),
|
29 |
+
)
|
30 |
+
);
|
31 |
$code = wp_remote_retrieve_response_code( $response );
|
32 |
$content = wp_remote_retrieve_body( $response );
|
33 |
$content_type = wp_remote_retrieve_header( $response, 'content-type' );
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: ads, ad manager, ad rotation, adsense, banner
|
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 5.3
|
6 |
Requires PHP: 5.6
|
7 |
-
Stable tag: 1.17.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -304,6 +304,12 @@ Yes. Advanced Ads is based on WordPress standards and therefore easily customiza
|
|
304 |
|
305 |
== Changelog ==
|
306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
= 1.17.2 =
|
308 |
|
309 |
* replaced autoloader
|
4 |
Requires at least: 4.6
|
5 |
Tested up to: 5.3
|
6 |
Requires PHP: 5.6
|
7 |
+
Stable tag: 1.17.3
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
304 |
|
305 |
== Changelog ==
|
306 |
|
307 |
+
= 1.17.3 =
|
308 |
+
|
309 |
+
* prevented content injection into specific elements where ads cause issues
|
310 |
+
* assign `advads-stop-injection` class to any element into which you don’t want to automatically inject ads
|
311 |
+
* fixed possible cURL error when checking existing ads.txt file locally
|
312 |
+
|
313 |
= 1.17.2 =
|
314 |
|
315 |
* replaced autoloader
|