PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.20.1
Advanced Ads – Ad Manager & AdSense v1.20.1
2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / classes / ad.php
advanced-ads / classes Last commit date
EDD_SL_Plugin_Updater.php 6 years ago ad-ajax.php 5 years ago ad-debug.php 6 years ago ad-health-notices.php 6 years ago ad-model.php 5 years ago ad-select.php 9 years ago ad.php 5 years ago ad_ajax_callbacks.php 5 years ago ad_group.php 5 years ago ad_placements.php 5 years ago ad_type_abstract.php 5 years ago ad_type_content.php 5 years ago ad_type_dummy.php 5 years ago ad_type_group.php 6 years ago ad_type_image.php 5 years ago ad_type_plain.php 5 years ago checks.php 6 years ago compatibility.php 5 years ago display-conditions.php 5 years ago filesystem.php 8 years ago frontend-notices.php 6 years ago frontend_checks.php 5 years ago plugin.php 5 years ago upgrades.php 6 years ago utils.php 5 years ago visitor-conditions.php 6 years ago widget.php 6 years ago
ad.php
1004 lines
1 <?php
2 /**
3 * Advanced Ads Ad.
4 *
5 * @package Advanced_Ads_Ad
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>
31 */
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 }
193 }
194
195 /**
196 * Load an ad object by id based on its ad type
197 *
198 * @param int $id ad id.
199 *
200 * @return bool false if ad could not be loaded.
201 */
202 private function load( $id = 0 ) {
203
204 $_data = get_post( $id );
205 if ( null === $_data ) {
206 return false;
207 }
208
209 // return, if not an ad.
210 if ( Advanced_Ads::POST_TYPE_SLUG !== $_data->post_type ) {
211 return false;
212 } else {
213 $this->is_ad = true;
214 }
215
216 $this->type = $this->options( 'type' );
217 $this->title = $_data->post_title;
218 /* load ad type object */
219 $types = Advanced_Ads::get_instance()->ad_types;
220 if ( isset( $types[ $this->type ] ) ) {
221 $this->type_obj = $types[ $this->type ];
222 } else {
223 $this->type_obj = new Advanced_Ads_Ad_Type_Abstract();
224 }
225 $this->url = $this->get_url();
226 $this->width = absint( $this->options( 'width' ) );
227 $this->height = absint( $this->options( 'height' ) );
228 $this->conditions = $this->options( 'conditions' );
229 $this->description = $this->options( 'description' );
230 $this->output = $this->options( 'output' );
231 $this->status = $_data->post_status;
232 $this->expiry_date = $this->options( 'expiry_date' );
233 $this->is_head_placement = isset( $this->args['placement_type'] ) && 'header' === $this->args['placement_type'];
234 $this->args['is_top_level'] = ! isset( $this->args['is_top_level'] );
235
236 // load content based on ad type.
237 $this->content = $this->type_obj->load_content( $_data );
238
239 if ( ! $this->is_head_placement ) {
240 $this->maybe_create_label();
241 $this->wrapper = $this->load_wrapper_options();
242
243 // set wrapper conditions.
244 $this->wrapper = apply_filters( 'advanced-ads-set-wrapper', $this->wrapper, $this );
245 // add unique wrapper id.
246 if ( is_array( $this->wrapper )
247 && array() !== $this->wrapper
248 && ! isset( $this->wrapper['id'] ) ) {
249 // create unique id if not yet given.
250 $this->wrapper['id'] = $this->create_wrapper_id();
251 }
252 }
253 }
254
255 /**
256 * Get options from meta field and return specific field
257 *
258 * @param string $field post meta key to be returned.
259 * @param array $default default options.
260 *
261 * @return mixed meta field content
262 * @todo check against default values
263 */
264 public function options( $field = '', $default = null ) {
265 // retrieve options, if not given yet
266 // -TODO may execute multiple times (if empty); bad design and risk to access unintialised data with direct access to $this->options property.
267 if ( array() === $this->options ) {
268 // may return false.
269 $meta = get_post_meta( $this->id, self::$options_meta_field, true );
270 if ( $meta ) {
271 // merge meta with arguments given on ad load.
272 $this->options = Advanced_Ads_Utils::merge_deep_array( array( $meta, $this->args ) );
273 } else {
274 // load arguments given on ad load.
275 $this->options = $this->args;
276 }
277
278 if ( isset( $this->options['change-ad'] ) ) {
279 // some options was provided by the user.
280 $this->options = Advanced_Ads_Utils::merge_deep_array(
281 array(
282 $this->options,
283 $this->options['change-ad'],
284 )
285 );
286 }
287 }
288
289 // return specific option.
290 if ( '' !== $field ) {
291 if ( isset( $this->options[ $field ] ) ) {
292 return $this->options[ $field ];
293 }
294 } else { // return all options.
295 if ( ! empty( $this->options ) ) {
296 return $this->options;
297 }
298 }
299
300 return $default;
301 }
302
303 /**
304 * Set an option of the ad
305 *
306 * @param string $option name of the option.
307 * @param mixed $value value of the option.
308 *
309 * @since 1.1.0
310 */
311 public function set_option( $option = '', $value = '' ) {
312 if ( '' === $option ) {
313 return;
314 }
315
316 // get current options.
317 $options = $this->options();
318
319 // set options.
320 $options[ $option ] = $value;
321
322 // save options.
323 $this->options = $options;
324
325 }
326
327
328 /**
329 * Return ad content for frontend output
330 *
331 * @param array $output_options output options.
332 *
333 * @return string $output ad output
334 * @since 1.0.0
335 */
336 public function output( $output_options = array() ) {
337 if ( ! $this->is_ad ) {
338 return '';
339 }
340
341 $this->global_output = isset( $output_options['global_output'] ) ? $output_options['global_output'] : $this->global_output;
342 $output_options['global_output'] = $this->global_output;
343
344 // switch between normal and debug mode.
345 // check if debug output should only be displayed to admins.
346 $user_can_manage_ads = current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_manage_options' ) );
347 if ( isset( $this->output['debugmode'] )
348 && ( $user_can_manage_ads || ( ! $user_can_manage_ads && ! defined( 'ADVANCED_ADS_AD_DEBUG_FOR_ADMIN_ONLY' ) ) ) ) {
349 $debug = new Advanced_Ads_Ad_Debug();
350
351 return $debug->prepare_debug_output( $this );
352 } else {
353 $output = $this->prepare_frontend_output();
354 }
355
356 // add the ad to the global output array.
357 $advads = Advanced_Ads::get_instance();
358 if ( $output_options['global_output'] ) {
359 $new_ad = array(
360 'type' => 'ad',
361 'id' => $this->id,
362 'title' => $this->title,
363 'output' => $output,
364 );
365 // if ( method_exists( 'Advanced_Ads_Tracking_Plugin' , 'check_ad_tracking_enabled' ) ) {
366 // if ( class_exists( 'Advanced_Ads_Tracking_Plugin', false ) ) {
367 if ( defined( 'AAT_VERSION' ) && - 1 < version_compare( AAT_VERSION, '1.4.2' ) ) {
368
369 $new_ad['tracking_enabled'] = Advanced_Ads_Tracking_Plugin::get_instance()->check_ad_tracking_enabled( $this );
370
371 $tracking_options = Advanced_Ads_Tracking_Plugin::get_instance()->options();
372 if ( isset( $tracking_options['method'] ) && 'frontend' === $tracking_options['method'] && isset( $this->output['placement_id'] ) ) {
373 $new_ad['placement_id'] = $this->output['placement_id'];
374 }
375 }
376
377 $advads->current_ads[] = $new_ad;
378 }
379
380 // action when output is created.
381 do_action( 'advanced-ads-output', $this, $output, $output_options );
382
383 return apply_filters( 'advanced-ads-output-final', $output, $this, $output_options );
384 }
385
386 /**
387 * Check if the ad can be displayed in frontend due to its own conditions
388 *
389 * @param array $check_options check options.
390 *
391 * @return bool $can_display true if can be displayed in frontend
392 * @since 1.0.0
393 */
394 public function can_display( $check_options = array() ) {
395 $check_options = wp_parse_args(
396 $check_options,
397 array(
398 'passive_cache_busting' => false,
399 'ignore_debugmode' => false,
400 )
401 );
402
403 // prevent ad to show up through wp_head, if this is not a header placement.
404 if ( doing_action( 'wp_head' ) && isset( $this->options['placement_type'] ) && 'header' !== $this->options['placement_type']
405 && ! Advanced_Ads_Compatibility::can_inject_during_wp_head() ) {
406 return false;
407 }
408
409 // Check If the current ad is requested using a shortcode placed in the content of the current ad.
410 if ( isset( $this->options['shortcode_ad_id'] ) && (int) $this->options['shortcode_ad_id'] === $this->id ) {
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
425 if ( ! $this->can_display_by_visitor() || ! $this->can_display_by_expiry_date() ) {
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 /**
489 * "old" visitor conditions
490 *
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 }
515
516 return true;
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 */
548 do_action( 'advanced-ads-ad-expired', $this->id, $this );
549 }
550
551 return false;
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'] = isset( $options['output']['wrapper-id'] ) ? sanitize_key( $options['output']['wrapper-id'] ) : '';
589
590 // sanitize options before saving
591 $options = $this->prepare_options_to_save( $options );
592
593 // filter to manipulate options or add more to be saved.
594 $options = apply_filters( 'advanced-ads-save-options', $options, $this );
595
596 update_post_meta( $this->id, self::$options_meta_field, $options );
597 }
598
599 /**
600 * Save ad options.
601 * Meant to be used from the outside of an ad.
602 *
603 * @param int $ad_id post ID of the ad.
604 * @param array $options ad options.
605 */
606 public static function save_ad_options( $ad_id, array $options ) {
607
608 // don’t allow to clear options by accident.
609 if ( array() === $options ) {
610 return;
611 }
612
613 update_post_meta( $ad_id, self::$options_meta_field, $options );
614 }
615
616 /**
617 * Native filter for content field before being saved
618 *
619 * @return string $content ad content
620 */
621 public function prepare_content_to_save() {
622
623 $content = $this->content;
624
625 // load ad type specific parameter filter
626 // @todo this is just a hotfix for type_obj not set, yet the cause is still unknown. Likely when the ad is first saved
627 if ( is_object( $this->type_obj ) ) {
628 $content = $this->type_obj->sanitize_content( $content );
629 }
630 // apply a custom filter by ad type.
631 $content = apply_filters( 'advanced-ads-pre-ad-save-' . $this->type, $content );
632
633 return $content;
634 }
635
636 /**
637 * Sanitize ad options before being saved
638 * allows some ad types to sanitize certain values
639 *
640 * @param array $options ad options.
641 * @return array sanitized options.
642 */
643 public function prepare_options_to_save( $options ) {
644
645 // load ad type specific sanitize function.
646 // we need to load the ad type object if not set (e.g., when the ad is saved for the first time)
647 if ( ! is_object( $this->type_obj ) || ! $this->type_obj->ID ) {
648 $types = Advanced_Ads::get_instance()->ad_types;
649 if ( isset( $types[ $this->type ] ) ) {
650 $this->type_obj = $types[ $this->type ];
651 }
652 }
653
654 $options = $this->type_obj->sanitize_options( $options );
655
656 return $options;
657 }
658
659 /**
660 * Prepare ads output
661 *
662 * @return string.
663 */
664 public function prepare_frontend_output() {
665 $options = $this->options();
666
667 if ( isset( $options['change-ad']['content'] ) ) {
668 // output was provided by the user.
669 $output = $options['change-ad']['content'];
670 } else {
671 // load ad type specific content filter.
672 $output = $this->type_obj->prepare_output( $this );
673 }
674
675 // don’t deliver anything, if main ad content is empty.
676 if ( empty( $output ) ) {
677 return;
678 }
679
680 if ( ! $this->is_head_placement ) {
681 // filter to manipulate the output before the wrapper is added
682 $output = apply_filters( 'advanced-ads-output-inside-wrapper', $output, $this );
683
684 // build wrapper around the ad.
685 $output = $this->add_wrapper( $output );
686
687 // add a clearfix, if set.
688 if ( ( isset( $this->output['clearfix'] ) && $this->output['clearfix'] )
689 || ( ! empty( $this->args['is_top_level'] ) && ! empty( $this->args['placement_clearfix'] ) ) ) {
690 $output .= '<br style="clear: both; display: block; float: none;"/>';
691 }
692 }
693
694 // apply a custom filter by ad type.
695 $output = apply_filters( 'advanced-ads-ad-output', $output, $this );
696
697 return $output;
698 }
699
700 /**
701 * Sanitize ad display conditions when saving the ad
702 *
703 * @param array $conditions conditions array send via the dashboard form for an ad.
704 *
705 * @return array with sanitized conditions
706 * @since 1.0.0
707 */
708 public function sanitize_conditions_on_save( $conditions = array() ) {
709
710 global $advanced_ads_ad_conditions;
711
712 if ( ! is_array( $conditions ) || array() === $conditions ) {
713 return array();
714 }
715
716 foreach ( $conditions as $_key => $_condition ) {
717 if ( 'postids' === $_key ) {
718 // sanitize single post conditions
719 if ( empty( $_condition['ids'] ) ) { // remove, if empty.
720 $_condition['include'] = array();
721 $_condition['exclude'] = array();
722 } elseif ( isset( $_condition['method'] ) ) {
723 switch ( $_condition['method'] ) {
724 case 'include':
725 $_condition['include'] = $_condition['ids'];
726 $_condition['exclude'] = array();
727 break;
728 case 'exclude':
729 $_condition['include'] = array();
730 $_condition['exclude'] = $_condition['ids'];
731 break;
732 }
733 }
734 } else {
735 if ( ! is_array( $_condition ) ) {
736 $_condition = trim( $_condition );
737 }
738 if ( $_condition == '' ) {
739 $conditions[ $_key ] = $_condition;
740 continue;
741 }
742 }
743 $type = ! empty( $advanced_ads_ad_conditions[ $_key ]['type'] ) ? $advanced_ads_ad_conditions[ $_key ]['type'] : 0;
744 if ( empty( $type ) ) {
745 continue;
746 }
747
748 // dynamically apply filters for each condition used.
749 $conditions[ $_key ] = apply_filters( 'advanced-ads-sanitize-condition-' . $type, $_condition );
750 }
751
752 return $conditions;
753 }
754
755 /**
756 * Sanitize id input field(s) for pattern /1,2,3,4/
757 *
758 * @param mixed $cond input string/array.
759 *
760 * @return array/string $cond sanitized string/array
761 */
762 public static function sanitize_condition_idfield( $cond = '' ) {
763 // strip anything that is not comma or number.
764
765 if ( is_array( $cond ) ) {
766 foreach ( $cond as $_key => $_cond ) {
767 $cond[ $_key ] = preg_replace( '#[^0-9,]#', '', $_cond );
768 }
769 } else {
770 $cond = preg_replace( '#[^0-9,]#', '', $cond );
771 }
772
773 return $cond;
774 }
775
776 /**
777 * Sanitize radio input field
778 *
779 * @param string $string input string.
780 *
781 * @return string $string sanitized string.
782 */
783 public static function sanitize_condition_radio( $string = '' ) {
784 // only allow 0, 1 and empty.
785 return preg_replace( '#[^01]#', '', $string );
786 }
787
788 /**
789 * Sanitize comma seperated text input field
790 *
791 * @param mixed $cond input string/array.
792 *
793 * @return array/string $cond sanitized string/array.
794 */
795 public static function sanitize_condition_textvalues( $cond = '' ) {
796 // strip anything that is not comma, alphanumeric, minus and underscore.
797 if ( is_array( $cond ) ) {
798 foreach ( $cond as $_key => $_cond ) {
799 $cond[ $_key ] = preg_replace( '#[^0-9,A-Za-z-_]#', '', $_cond );
800 }
801 } else {
802 $cond = preg_replace( '#[^0-9,A-Za-z-_]#', '', $cond );
803 }
804
805 return $cond;
806 }
807
808 /**
809 * Load wrapper options set with the ad
810 *
811 * @return array $wrapper options array ready to be use in add_wrapper() function.
812 * @since 1.3
813 */
814 protected function load_wrapper_options() {
815 $wrapper = array();
816
817 $position = ! empty( $this->output['position'] ) ? $this->output['position'] : '';
818 $use_placement_pos = false;
819
820 if ( $this->args['is_top_level'] ) {
821 if ( isset( $this->output['class'] ) && is_array( $this->output['class'] ) ) {
822 $wrapper['class'] = $this->output['class'];
823 }
824 if ( ! empty( $this->args['placement_position'] ) ) {
825 // If not group, Set placement position instead of ad position.
826 $use_placement_pos = true;
827 $position = $this->args['placement_position'];
828 }
829 }
830
831 switch ( $position ) {
832 case 'left':
833 $wrapper['style']['float'] = 'left';
834 break;
835 case 'right':
836 $wrapper['style']['float'] = 'right';
837 break;
838 case 'center':
839 $wrapper['style']['margin-left'] = 'auto';
840 $wrapper['style']['margin-right'] = 'auto';
841
842 if ( empty( $this->output['add_wrapper_sizes'] ) || $use_placement_pos ) {
843 $wrapper['style']['text-align'] = 'center';
844 }
845
846 // add css rule after wrapper to center the ad.
847 break;
848 case 'clearfix':
849 $wrapper['style']['clear'] = 'both';
850 break;
851 }
852
853 // add manual classes.
854 if ( isset( $this->output['wrapper-class'] ) && '' !== $this->output['wrapper-class'] ) {
855 $classes = explode( ' ', $this->output['wrapper-class'] );
856
857 foreach ( $classes as $_class ) {
858 $wrapper['class'][] = sanitize_text_field( $_class );
859 }
860 }
861
862 if ( ! empty( $this->output['margin']['top'] ) ) {
863 $wrapper['style']['margin-top'] = intval( $this->output['margin']['top'] ) . 'px';
864 }
865 if ( empty( $wrapper['style']['margin-right'] ) && ! empty( $this->output['margin']['right'] ) ) {
866 $wrapper['style']['margin-right'] = intval( $this->output['margin']['right'] ) . 'px';
867 }
868 if ( ! empty( $this->output['margin']['bottom'] ) ) {
869 $wrapper['style']['margin-bottom'] = intval( $this->output['margin']['bottom'] ) . 'px';
870 }
871 if ( empty( $wrapper['style']['margin-left'] ) && ! empty( $this->output['margin']['left'] ) ) {
872 $wrapper['style']['margin-left'] = intval( $this->output['margin']['left'] ) . 'px';
873 }
874
875 if ( ! empty( $this->output['add_wrapper_sizes'] ) ) {
876 $wrapper['style']['width'] = intval( $this->width ) . 'px';
877 $wrapper['style']['height'] = intval( $this->height ) . 'px';
878 }
879
880 if ( ! empty( $this->output['clearfix_before'] ) ) {
881 $wrapper['style']['clear'] = 'both';
882 }
883
884 return $wrapper;
885 }
886
887 /**
888 * Add a wrapper arount the ad content if wrapper information are given
889 *
890 * @param string $ad_content content of the ad.
891 *
892 * @return string $wrapper ad within the wrapper
893 * @since 1.1.4
894 */
895 protected function add_wrapper( $ad_content = '' ) {
896 $wrapper_options = apply_filters( 'advanced-ads-output-wrapper-options', $this->wrapper, $this );
897
898 if ( ( ! isset( $this->output['wrapper-id'] ) || '' === $this->output['wrapper-id'] )
899 && array() === $wrapper_options || ! is_array( $wrapper_options ) ) {
900 return $ad_content;
901 }
902
903 // create unique id if not yet given.
904 if ( empty( $wrapper_options['id'] ) ) {
905 $wrapper_options['id'] = $this->create_wrapper_id();
906 $this->wrapper['id'] = $wrapper_options['id'];
907 }
908
909 if ( $this->label && ! empty( $wrapper_options['style']['height'] ) ) {
910 // Create another wrapper so that the label does not reduce the height of the ad wrapper.
911 $height = array( 'style' => array( 'height' => $wrapper_options['style']['height'] ) );
912 unset( $wrapper_options['style']['height'] );
913 $ad_content = $this->label
914 . '<div' . Advanced_Ads_Utils::build_html_attributes( $height ) . '>'
915 . $ad_content
916 . '</div>';
917 } else {
918 $ad_content = $this->label . $ad_content;
919 }
920
921 // add edit button for users with the appropriate rights.
922 if ( ! defined( 'ADVANCED_ADS_DISABLE_EDIT_BAR' ) && current_user_can( Advanced_Ads_Plugin::user_cap( 'advanced_ads_edit_ads' ) ) ) {
923 ob_start();
924 include ADVADS_BASE_PATH . 'public/views/ad-edit-bar.php';
925 $ad_content = ob_get_clean() . $ad_content;
926 }
927
928
929
930 // build the box
931 $wrapper = '<div' . Advanced_Ads_Utils::build_html_attributes( $wrapper_options ) . '>';
932 $wrapper .= apply_filters( 'advanced-ads-output-wrapper-before-content', '', $this );
933 $wrapper .= $ad_content;
934 $wrapper .= apply_filters( 'advanced-ads-output-wrapper-after-content', '', $this );
935 $wrapper .= '</div>';
936
937 return $wrapper;
938 }
939
940 /**
941 * Create a random wrapper id
942 *
943 * @return string $id random id string
944 * @since 1.1.4
945 */
946 private function create_wrapper_id() {
947
948 if ( isset( $this->output['wrapper-id'] ) ) {
949 $id = sanitize_key( $this->output['wrapper-id'] );
950 if ( '' !== $id ) {
951 return $id;
952 }
953 }
954
955 $prefix = Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();
956
957 return $prefix . mt_rand();
958 }
959
960 /**
961 * Create an "Advertisement" label if conditions are met.
962 */
963 public function maybe_create_label() {
964 $placement_state = isset( $this->args['ad_label'] ) ? $this->args['ad_label'] : 'default';
965
966 $label = Advanced_Ads::get_instance()->get_label( $placement_state );
967
968 if ( $this->args['is_top_level'] && $label ) {
969 $this->label = $label;
970 }
971 }
972
973 /**
974 * Get the ad url.
975 *
976 * @return string
977 */
978 private function get_url() {
979 $this->url = $this->options( 'url' );
980
981 // If the tracking add-on is not active.
982 if ( ! defined( 'AAT_VERSION' ) ) {
983 global $pagenow;
984 // If this is not the ad edit page.
985 if ( 'post.php' !== $pagenow && 'post-new.php' !== $pagenow ) {
986 // Remove placeholders.
987 $this->url = str_replace(
988 array(
989 '[POST_ID]',
990 '[POST_SLUG]',
991 '[CAT_SLUG]',
992 '[AD_ID]',
993 ),
994 '',
995 $this->url
996 );
997 }
998 }
999
1000 return $this->url;
1001 }
1002
1003 }
1004