PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.25
Advanced Ads – Ad Manager & AdSense v2.0.25
2.0.25 2.0.24 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 / visitor-conditions.php
advanced-ads / classes Last commit date
ad-health-notices.php 1 month ago checks.php 3 months ago display-conditions.php 1 day ago filesystem.php 1 month ago frontend_checks.php 1 week ago inline-css.php 1 year ago utils.php 1 week ago visitor-conditions.php 1 day ago
visitor-conditions.php
523 lines
1 <?php // phpcs:ignore WordPress.Files.FileName
2
3 /**
4 * Visitor conditions under which to (not) show an ad
5 *
6 * @since 1.5.4
7 */
8 class Advanced_Ads_Visitor_Conditions {
9
10 /**
11 * Instance of Advanced_Ads_Visitor_Conditions
12 *
13 * @var Advanced_Ads_Visitor_Conditions
14 */
15 protected static $instance;
16
17 /**
18 * Registered visitor conditions
19 *
20 * @var array $conditions
21 */
22 public $conditions;
23
24 /**
25 * Start of name in form elements
26 */
27 const FORM_NAME = 'advanced_ad[visitors]';
28
29 /**
30 * Advanced_Ads_Visitor_Conditions constructor
31 */
32 public function __construct() {
33
34 // register conditions.
35 $this->conditions = apply_filters(
36 'advanced-ads-visitor-conditions',
37 [
38 'mobile' => [
39 // type of the condition.
40 'label' => __( 'Device', 'advanced-ads' ),
41 'metabox' => [ 'Advanced_Ads_Visitor_Conditions', 'mobile_is_or_not' ], // callback to generate the metabox.
42 'check' => [ 'Advanced_Ads_Visitor_Conditions', 'check_device' ], // callback for frontend check.
43 'helplink' => 'https://wpadvancedads.com/manual/display-ads-either-on-mobile-or-desktop/?utm_source=advanced-ads&utm_medium=link&utm_campaign=condition-device',
44 'device_types' => [
45 'mobile' => [
46 'id' => 'mobile',
47 'label' => _x( 'Mobile', 'Device condition', 'advanced-ads' ),
48 ],
49 'tablet' => [
50 'id' => 'tablet',
51 'label' => _x( 'Tablet', 'Device condition', 'advanced-ads' ),
52 ],
53 'desktop' => [
54 'id' => 'desktop',
55 'label' => _x( 'Desktop', 'Device condition', 'advanced-ads' ),
56 ],
57 ],
58 ],
59 'loggedin' => [
60 'label' => __( 'logged-in visitor', 'advanced-ads' ),
61 'description' => __( 'Whether the visitor has to be logged in or not in order to see the ad.', 'advanced-ads' ),
62 'metabox' => [ 'Advanced_Ads_Visitor_Conditions', 'metabox_is_or_not' ], // callback to generate the metabox.
63 'check' => [ 'Advanced_Ads_Visitor_Conditions', 'check_logged_in' ], // callback for frontend check.
64 'helplink' => 'https://wpadvancedads.com/manual/logged-in-visitors/?utm_source=advanced-ads&utm_medium=link&utm_campaign=condition-logged-in-visitors',
65 'passive_info' => [
66 'hash_fields' => null,
67 'remove' => 'login',
68 'function' => 'is_user_logged_in',
69 ],
70 ],
71 ]
72 );
73 }
74
75 /**
76 * Load instance of Advanced_Ads_Visitor_Conditions
77 *
78 * @return Advanced_Ads_Visitor_Conditions
79 */
80 public static function get_instance() {
81 // If the single instance hasn't been set, set it now.
82 if ( null === self::$instance ) {
83 self::$instance = new self();
84 }
85
86 return self::$instance;
87 }
88
89
90 /**
91 * Get the conditions array alphabetically by label
92 *
93 * @since 1.8.12
94 */
95 public function get_conditions() {
96 uasort(
97 $this->conditions,
98 static function ( $a, $b ) {
99 if ( ! isset( $a['label'], $b['label'] ) ) {
100 return 0;
101 }
102
103 return strcmp( strtolower( $a['label'] ), strtolower( $b['label'] ) );
104 }
105 );
106
107 return $this->conditions;
108 }
109
110 /**
111 * Callback to render the mobile condition using the "is not" condition
112 *
113 * @param array $options options of the condition.
114 * @param int $index index of the condition.
115 * @param string $form_name name of the form, falls back to class constant.
116 */
117 public static function mobile_is_or_not( $options, $index = 0, $form_name = '' ) {
118
119 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
120 return;
121 }
122
123 $type_options = self::get_instance()->conditions;
124
125 if ( ! isset( $type_options[ $options['type'] ] ) ) {
126 return;
127 }
128
129 // options.
130 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is';
131
132 // convert previous binary option to device selector.
133 if ( ! array_key_exists( 'value', $options ) ) {
134 $options['value'] = 'is' === $operator ? [ 'tablet', 'mobile' ] : [ 'desktop' ];
135 $operator = 'is';
136 }
137
138 $type_options[ $options['type'] ]['device_types'] = array_map(
139 function ( $device_type ) use ( $options ) {
140 $device_type['checked'] = in_array( $device_type['id'], $options['value'], true );
141
142 return $device_type;
143 },
144 $type_options[ $options['type'] ]['device_types']
145 );
146
147 // form name basis.
148 $name = self::get_form_name_with_index( $form_name, $index );
149
150 include ADVADS_ABSPATH . 'admin/views/conditions/condition-device.php';
151 }
152
153 /**
154 * Callback to display the "is not" condition
155 *
156 * @param array $options options of the condition.
157 * @param int $index index of the condition.
158 * @param string $form_name name of the form, falls back to class constant.
159 */
160 public static function metabox_is_or_not( $options, $index = 0, $form_name = '' ) {
161 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
162 return;
163 }
164
165 $type_options = self::get_instance()->conditions;
166 if ( ! isset( $type_options[ $options['type'] ] ) ) {
167 return;
168 }
169
170 // form name basis.
171 $name = self::get_form_name_with_index( $form_name, $index );
172 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is';
173
174 include ADVADS_ABSPATH . 'admin/views/conditions/condition-is-or-not.php';
175 }
176
177 /**
178 * Callback to display the any condition based on a number
179 *
180 * @param array $options options of the condition.
181 * @param int $index index of the condition.
182 * @param string $form_name name of the form, falls back to class constant.
183 */
184 public static function metabox_number( $options, $index = 0, $form_name = '' ) {
185
186 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
187 return;
188 }
189
190 $type_options = self::get_instance()->conditions;
191
192 if ( ! isset( $type_options[ $options['type'] ] ) ) {
193 return;
194 }
195
196 // form name basis.
197 $name = self::get_form_name_with_index( $form_name, $index );
198
199 // options.
200 $value = isset( $options['value'] ) ? $options['value'] : 0;
201 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is_equal';
202
203 include ADVADS_ABSPATH . 'admin/views/conditions/condition-number.php';
204 }
205
206 /**
207 * Callback to display the any condition based on a number
208 *
209 * @param array $options options of the condition.
210 * @param int $index index of the condition.
211 * @param string $form_name name of the form, falls back to class constant.
212 */
213 public static function metabox_string( $options, $index = 0, $form_name = '' ) {
214
215 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
216 return;
217 }
218
219 $type_options = self::get_instance()->conditions;
220
221 if ( ! isset( $type_options[ $options['type'] ] ) ) {
222 return;
223 }
224
225 // form name basis.
226 $name = self::get_form_name_with_index( $form_name, $index );
227
228 // options.
229 $value = isset( $options['value'] ) ? $options['value'] : '';
230 $operator = isset( $options['operator'] ) ? $options['operator'] : 'contains';
231
232 include ADVADS_ABSPATH . 'admin/views/conditions/condition-string.php';
233 }
234
235 /**
236 * Controls frontend checks for conditions
237 *
238 * @param array $options Options of the condition.
239 * @param bool|Ad $ad Ad instance.
240 *
241 * @return bool false, if ad can’t be delivered
242 */
243 public static function frontend_check( $options = [], $ad = false ) {
244 $visitor_conditions = self::get_instance()->conditions;
245
246 if ( is_array( $options ) && isset( $visitor_conditions[ $options['type'] ]['check'] ) ) {
247 $check = $visitor_conditions[ $options['type'] ]['check'];
248 } else {
249 return true;
250 }
251
252 // call frontend check callback.
253 if ( method_exists( $check[0], $check[1] ) ) {
254 return call_user_func( [ $check[0], $check[1] ], $options, $ad );
255 }
256
257 return true;
258 }
259
260 /**
261 * Render the list of set visisor conditions
262 *
263 * @param array $set_conditions array of existing conditions.
264 * @param string $list_target ID of the list with the conditions.
265 * @param string $form_name prefix of the form.
266 */
267 public static function render_condition_list( array $set_conditions, $list_target = '', $form_name = '' ) {
268
269 $conditions = self::get_instance()->get_conditions();
270
271 // use default form name if not given explicitly.
272 // TODO: create a random form name, in case we have more than one form per page and the parameter is not given.
273 $form_name = ! $form_name ? self::FORM_NAME : $form_name;
274
275 include ADVADS_ABSPATH . 'admin/views/conditions/visitor-conditions-list.php';
276
277 /**
278 * Prepare condition form
279 *
280 * @todo if needed, allow to disable the form to add new conditions
281 */
282
283 // add mockup conditions if add-ons are missing.
284 $pro_conditions = [];
285 if ( ! defined( 'AAP_VERSION' ) ) {
286 $pro_conditions[] = __( 'browser language', 'advanced-ads' );
287 $pro_conditions[] = __( 'cookie', 'advanced-ads' );
288 $pro_conditions[] = __( 'max. ad clicks', 'advanced-ads' );
289 $pro_conditions[] = __( 'max. ad impressions', 'advanced-ads' );
290 $pro_conditions[] = __( 'new visitor', 'advanced-ads' );
291 $pro_conditions[] = __( 'page impressions', 'advanced-ads' );
292 $pro_conditions[] = __( 'geo location', 'advanced-ads' );
293 $pro_conditions[] = __( 'referrer url', 'advanced-ads' );
294 $pro_conditions[] = __( 'user agent', 'advanced-ads' );
295 $pro_conditions[] = __( 'user can (capabilities)', 'advanced-ads' );
296 $pro_conditions[] = __( 'user role', 'advanced-ads' );
297 $pro_conditions[] = __( 'browser width', 'advanced-ads' );
298 }
299
300 asort( $pro_conditions );
301
302 // the action to call using AJAX.
303 $action = 'load_visitor_conditions_metabox';
304 $connector_default = 'and';
305
306 $empty_options = ! is_array( $set_conditions ) || ! count( $set_conditions );
307
308 include ADVADS_ABSPATH . 'admin/views/conditions/conditions-form.php';
309 }
310
311 /**
312 * Render connector option
313 *
314 * @param int $index incremental index of the options.
315 * @param string $value connector value.
316 * @param string $form_name name of the form, falls back to class constant.
317 *
318 * @return string HTML of the connector option
319 * @todo combine this with the same function used for Display Conditions
320 *
321 * @since 1.7.0.4
322 */
323 public static function render_connector_option( $index, $value, $form_name ) {
324
325 $label = ( 'or' === $value ) ? __( 'or', 'advanced-ads' ) : __( 'and', 'advanced-ads' );
326
327 $name = self::get_form_name_with_index( $form_name, $index );
328
329 // create random value to identify the form field.
330 $rand = uniqid();
331
332 return '<input type="checkbox" name="' . $name . '[connector]' . '" value="or" id="advads-conditions-' . // phpcs:ignore
333 $index . '-connector-' . $rand . '"' .
334 checked( 'or', $value, false )
335 . '><label for="advads-conditions-' . $index . '-connector-' . $rand . '">' . $label . '</label>';
336 }
337
338 /**
339 * Helper function to the name of a form field.
340 * falls back to default
341 *
342 * @param string $form_name form name if submitted.
343 * @param int $index index of the condition.
344 *
345 * @return string
346 */
347 public static function get_form_name_with_index( $form_name = '', $index = 0 ) {
348 return ! empty( $form_name ) ? $form_name . '[' . $index . ']' : self::FORM_NAME . '[' . $index . ']';
349 }
350
351 /**
352 * Check whether device visitor condition in frontend is true.
353 *
354 * @param array $options options of the condition.
355 *
356 * @return bool
357 */
358 public static function check_device( $options = [] ) {
359 if ( ! array_key_exists( 'value', $options ) ) {
360 return self::check_mobile( $options );
361 }
362
363 $mobile_detect = new \Detection\MobileDetect();
364 // register callbacks to decide whether device "is".
365 $callbacks = array_intersect_key(
366 [
367 'mobile' => function () use ( $mobile_detect ) {
368 return $mobile_detect->isMobile() && ! $mobile_detect->isTablet();
369 },
370 'tablet' => function () use ( $mobile_detect ) {
371 return $mobile_detect->isTablet();
372 },
373 'desktop' => function () use ( $mobile_detect ) {
374 return ! $mobile_detect->isTablet() && ! $mobile_detect->isMobile();
375 },
376 ],
377 array_flip( $options['value'] )
378 );
379
380 // Only call devices that are part of the condition.
381 array_walk(
382 $callbacks,
383 function ( callable &$value ) {
384 $value = $value();
385 }
386 );
387
388 return array_filter( $callbacks ) !== [];
389 }
390
391 /**
392 * Check mobile visitor condition in frontend
393 *
394 * @param array $options options of the condition.
395 * @deprecated -- Only used if new options hasn't been saved
396 *
397 * @return bool
398 */
399 private static function check_mobile( $options ) {
400 if ( ! isset( $options['operator'] ) ) {
401 return true;
402 }
403
404 switch ( $options['operator'] ) {
405 case 'is':
406 if ( ! wp_is_mobile() ) {
407 return false;
408 }
409 break;
410 case 'is_not':
411 if ( wp_is_mobile() ) {
412 return false;
413 }
414 break;
415 }
416
417 return true;
418 }
419
420 /**
421 * Check mobile visitor condition in frontend
422 *
423 * @param array $options options of the condition.
424 *
425 * @return bool true if can be displayed
426 * @since 1.6.3
427 */
428 public static function check_logged_in( $options = [] ) {
429
430 if ( ! isset( $options['operator'] ) ) {
431 return true;
432 }
433
434 switch ( $options['operator'] ) {
435 case 'is':
436 if ( ! is_user_logged_in() ) {
437 return false;
438 }
439 break;
440 case 'is_not':
441 if ( is_user_logged_in() ) {
442 return false;
443 }
444 break;
445 }
446
447 return true;
448 }
449
450 /**
451 * Helper for check with strings
452 *
453 * @param string $string string that is going to be checked.
454 * @param array $options options of this condition.
455 *
456 * @return bool true if ad can be displayed
457 * @since 1.6.3
458 */
459 public static function helper_check_string( $string = '', $options = [] ) { // phpcs:ignore
460 if ( ! isset( $options['operator'] ) || empty( $options['value'] ) ) {
461 return true;
462 }
463
464 $operator = $options['operator'];
465 $string = (string) maybe_serialize( $string );
466 $value = (string) maybe_serialize( $options['value'] );
467
468 // check the condition by mode and bool.
469 $condition = true;
470 switch ( $operator ) {
471 // referrer contains string on any position.
472 case 'contain':
473 $condition = stripos( $string, $value ) !== false;
474 break;
475 // referrer does not contain string on any position.
476 case 'contain_not':
477 $condition = stripos( $string, $value ) === false;
478 break;
479 // referrer starts with the string.
480 case 'start':
481 $condition = stripos( $string, $value ) === 0;
482 break;
483 // referrer does not start with the string.
484 case 'start_not':
485 $condition = stripos( $string, $value ) !== 0;
486 break;
487 // referrer ends with the string.
488 case 'end':
489 $condition = substr( $string, - strlen( $value ) ) === $value;
490 break;
491 // referrer does not end with the string.
492 case 'end_not':
493 $condition = substr( $string, - strlen( $value ) ) !== $value;
494 break;
495 // referrer is equal to the string.
496 case 'match':
497 // strings do match, but should not or not match but should.
498 $condition = strcasecmp( $value, $string ) === 0;
499 break;
500 // referrer is not equal to the string.
501 case 'match_not':
502 // strings do match, but should not or not match but should.
503 $condition = strcasecmp( $value, $string ) !== 0;
504 break;
505 case 'regex':
506 case 'regex_not':
507 $condition = @preg_match( sprintf( '/%s/', $value ), $string ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
508 // If the return value is `false`, the regex is incorrect.
509 if ( false === $condition ) {
510 Advanced_Ads::log( "Advanced Ads: regular expression '$value' in visitor condition is broken." );
511 break;
512 }
513
514 if ( 'regex_not' === $operator ) {
515 $condition = ! $condition;
516 }
517 break;
518 }
519
520 return $condition;
521 }
522 }
523