PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.40.0
Advanced Ads – Ad Manager & AdSense v1.40.0
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
Advanced_Ads_Modal.php 3 years ago EDD_SL_Plugin_Updater.php 4 years ago ad-ajax.php 3 years ago ad-debug.php 3 years ago ad-expiration.php 3 years ago ad-health-notices.php 3 years ago ad-model.php 3 years ago ad-select.php 3 years ago ad.php 3 years ago ad_ajax_callbacks.php 3 years ago ad_group.php 3 years ago ad_placements.php 3 years ago ad_type_abstract.php 3 years ago ad_type_content.php 3 years ago ad_type_dummy.php 3 years ago ad_type_group.php 3 years ago ad_type_image.php 3 years ago ad_type_plain.php 3 years ago checks.php 3 years ago compatibility.php 3 years ago display-conditions.php 3 years ago filesystem.php 3 years ago frontend-notices.php 3 years ago frontend_checks.php 3 years ago in-content-injector.php 3 years ago inline-css.php 3 years ago plugin.php 3 years ago upgrades.php 6 years ago utils.php 3 years ago visitor-conditions.php 3 years ago widget.php 3 years ago
visitor-conditions.php
526 lines
1 <?php
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' => ADVADS_URL . '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' => ADVADS_URL . '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( $this->conditions, 'Advanced_Ads_Admin::sort_condition_array_by_label' );
97
98 return $this->conditions;
99 }
100
101 /**
102 * Callback to render the mobile condition using the "is not" condition
103 *
104 * @param array $options options of the condition.
105 * @param int $index index of the condition.
106 * @param string $form_name name of the form, falls back to class constant.
107 */
108 public static function mobile_is_or_not( $options, $index = 0, $form_name = '' ) {
109
110 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
111 return;
112 }
113
114 $type_options = self::get_instance()->conditions;
115
116 if ( ! isset( $type_options[ $options['type'] ] ) ) {
117 return;
118 }
119
120 // options.
121 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is';
122
123 // convert previous binary option to device selector.
124 if ( ! array_key_exists( 'value', $options ) ) {
125 $options['value'] = $operator === 'is' ? [ 'tablet', 'mobile' ] : [ 'desktop' ];
126 $operator = 'is';
127 }
128
129 $type_options[ $options['type'] ]['device_types'] = array_map( function( $device_type ) use ( $options ) {
130 $device_type['checked'] = in_array( $device_type['id'], $options['value'], true );
131
132 return $device_type;
133 }, $type_options[ $options['type'] ]['device_types'] );
134
135 // form name basis.
136 $name = self::get_form_name_with_index( $form_name, $index );
137
138 include ADVADS_BASE_PATH . 'admin/views/conditions/condition-device.php';
139
140 if ( ! defined( 'AAR_SLUG' ) ) {
141 ?><p><?php
142 sprintf(
143 wp_kses(
144 // translators: %s is a URL. Please don’t change it.
145 __( 'Display ads by the available space on the device or target tablets with the <a href="%s" target="_blank">Responsive add-on</a>', 'advanced-ads' ),
146 [
147 'a' => [
148 'href' => [],
149 'target' => [],
150 ],
151 ]
152 ),
153 ADVADS_URL . 'add-ons/responsive-ads/?utm_source=advanced-ads&utm_medium=link&utm_campaign=edit-visitor-responsive'
154 );
155 ?></p><?php
156 }
157 }
158
159 /**
160 * Callback to display the "is not" condition
161 *
162 * @param array $options options of the condition.
163 * @param int $index index of the condition.
164 * @param string $form_name name of the form, falls back to class constant.
165 */
166 public static function metabox_is_or_not( $options, $index = 0, $form_name = '' ) {
167
168 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
169 return;
170 }
171
172 $type_options = self::get_instance()->conditions;
173
174 if ( ! isset( $type_options[ $options['type'] ] ) ) {
175 return;
176 }
177
178 // form name basis.
179 $name = self::get_form_name_with_index( $form_name, $index );
180
181 // options.
182 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is';
183
184 include ADVADS_BASE_PATH . 'admin/views/conditions/condition-is-or-not.php';
185 }
186
187 /**
188 * Callback to display the any condition based on a number
189 *
190 * @param array $options options of the condition.
191 * @param int $index index of the condition.
192 * @param string $form_name name of the form, falls back to class constant.
193 */
194 public static function metabox_number( $options, $index = 0, $form_name = '' ) {
195
196 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
197 return;
198 }
199
200 $type_options = self::get_instance()->conditions;
201
202 if ( ! isset( $type_options[ $options['type'] ] ) ) {
203 return;
204 }
205
206 // form name basis.
207 $name = self::get_form_name_with_index( $form_name, $index );
208
209 // options.
210 $value = isset( $options['value'] ) ? $options['value'] : 0;
211 $operator = isset( $options['operator'] ) ? $options['operator'] : 'is_equal';
212
213 include ADVADS_BASE_PATH . 'admin/views/conditions/condition-number.php';
214 }
215
216 /**
217 * Callback to display the any condition based on a number
218 *
219 * @param array $options options of the condition.
220 * @param int $index index of the condition.
221 * @param string $form_name name of the form, falls back to class constant.
222 */
223 public static function metabox_string( $options, $index = 0, $form_name = '' ) {
224
225 if ( ! isset( $options['type'] ) || '' === $options['type'] ) {
226 return;
227 }
228
229 $type_options = self::get_instance()->conditions;
230
231 if ( ! isset( $type_options[ $options['type'] ] ) ) {
232 return;
233 }
234
235 // form name basis.
236 $name = self::get_form_name_with_index( $form_name, $index );
237
238 // options.
239 $value = isset( $options['value'] ) ? $options['value'] : '';
240 $operator = isset( $options['operator'] ) ? $options['operator'] : 'contains';
241
242 include ADVADS_BASE_PATH . 'admin/views/conditions/condition-string.php';
243 }
244
245 /**
246 * Controls frontend checks for conditions
247 *
248 * @param array $options options of the condition.
249 * @param bool|object $ad false or Advanced_Ads_Ad.
250 *
251 * @return bool false, if ad can’t be delivered
252 */
253 public static function frontend_check( $options = [], $ad = false ) {
254 $visitor_conditions = self::get_instance()->conditions;
255
256 if ( is_array( $options ) && isset( $visitor_conditions[ $options['type'] ]['check'] ) ) {
257 $check = $visitor_conditions[ $options['type'] ]['check'];
258 } else {
259 return true;
260 }
261
262 // call frontend check callback.
263 if ( method_exists( $check[0], $check[1] ) ) {
264 return call_user_func( [ $check[0], $check[1] ], $options, $ad );
265 }
266
267 return true;
268 }
269
270 /**
271 * Render the list of set visisor conditions
272 *
273 * @param array $set_conditions array of existing conditions.
274 * @param string $list_target ID of the list with the conditions.
275 * @param string $form_name prefix of the form.
276 */
277 public static function render_condition_list( array $set_conditions, $list_target = '', $form_name = '' ) {
278
279 $conditions = self::get_instance()->get_conditions();
280
281 // use default form name if not given explicitly.
282 // @todo create a random form name, in case we have more than one form per page and the parameter is not given.
283 $form_name = ! $form_name ? self::FORM_NAME : $form_name;
284
285 include ADVADS_BASE_PATH . 'admin/views/conditions/visitor-conditions-list.php';
286
287 /**
288 * Prepare condition form
289 *
290 * @todo if needed, allow to disable the form to add new conditions
291 */
292
293 // add mockup conditions if add-ons are missing.
294 $pro_conditions = [];
295 if ( ! defined( 'AAP_VERSION' ) ) {
296 $pro_conditions[] = __( 'browser language', 'advanced-ads' );
297 $pro_conditions[] = __( 'cookie', 'advanced-ads' );
298 $pro_conditions[] = __( 'max. ad clicks', 'advanced-ads' );
299 $pro_conditions[] = __( 'max. ad impressions', 'advanced-ads' );
300 $pro_conditions[] = __( 'new visitor', 'advanced-ads' );
301 $pro_conditions[] = __( 'page impressions', 'advanced-ads' );
302 $pro_conditions[] = __( 'geo location', 'advanced-ads' );
303 $pro_conditions[] = __( 'referrer url', 'advanced-ads' );
304 $pro_conditions[] = __( 'user agent', 'advanced-ads' );
305 $pro_conditions[] = __( 'user can (capabilities)', 'advanced-ads' );
306 $pro_conditions[] = __( 'user role', 'advanced-ads' );
307 }
308 if ( ! defined( 'AAR_VERSION' ) ) {
309 $pro_conditions[] = __( 'browser width', 'advanced-ads' );
310 }
311 asort( $pro_conditions );
312
313 // the action to call using AJAX.
314 $action = 'load_visitor_conditions_metabox';
315 $connector_default = 'and';
316
317 include ADVADS_BASE_PATH . 'admin/views/conditions/visitor-conditions-form-top.php';
318 include ADVADS_BASE_PATH . 'admin/views/conditions/conditions-form.php';
319 }
320
321 /**
322 * Render connector option
323 *
324 * @param int $index incremental index of the options.
325 * @param string $value connector value.
326 * @param string $form_name name of the form, falls back to class constant.
327 *
328 * @return string HTML of the connector option
329 * @todo combine this with the same function used for Display Conditions
330 *
331 * @since 1.7.0.4
332 */
333 public static function render_connector_option( $index, $value, $form_name ) {
334
335 $label = ( 'or' === $value ) ? __( 'or', 'advanced-ads' ) : __( 'and', 'advanced-ads' );
336
337 $name = self::get_form_name_with_index( $form_name, $index );
338
339 // create random value to identify the form field.
340 $rand = md5( $form_name );
341
342 return '<input type="checkbox" name="' . $name . '[connector]' . '" value="or" id="advads-conditions-' .
343 $index . '-connector-' . $rand . '"' .
344 checked( 'or', $value, false )
345 . '><label for="advads-conditions-' . $index . '-connector-' . $rand . '">' . $label . '</label>';
346 }
347
348 /**
349 * Helper function to the name of a form field.
350 * falls back to default
351 *
352 * @param string $form_name form name if submitted.
353 * @param int $index index of the condition.
354 *
355 * @return string
356 */
357 public static function get_form_name_with_index( $form_name = '', $index = 0 ) {
358 return ! empty( $form_name ) ? $form_name . '[' . $index . ']' : self::FORM_NAME . '[' . $index . ']';
359 }
360
361 /**
362 * Check whether device visitor condition in frontend is true.
363 *
364 * @param array $options options of the condition.
365 *
366 * @return bool
367 */
368 public static function check_device( $options = [] ) {
369 if ( ! array_key_exists( 'value', $options ) ) {
370 return self::check_mobile( $options );
371 }
372
373 $mobile_detect = new Mobile_Detect();
374 // register callbacks to decide whether device "is".
375 $callbacks = array_intersect_key( [
376 'mobile' => function() use ( $mobile_detect ) {
377 return $mobile_detect->isMobile() && ! $mobile_detect->isTablet();
378 },
379 'tablet' => function() use ( $mobile_detect ) {
380 return $mobile_detect->isTablet();
381 },
382 'desktop' => function() use ( $mobile_detect ) {
383 return ! $mobile_detect->isTablet() && ! $mobile_detect->isMobile();
384 },
385 ], array_flip( $options['value'] ) );
386 // only call devices that are part of the condition.
387 array_walk( $callbacks, static function( callable &$value ) {
388 $value = $value();
389 } );
390
391 return array_filter( $callbacks ) !== [];
392 }
393
394 /**
395 * Check mobile visitor condition in frontend
396 *
397 * @param array $options options of the condition.
398 * @deprecated -- Only used if new options hasn't been saved
399 *
400 * @return bool
401 */
402 private static function check_mobile( $options ) {
403 if ( ! isset( $options['operator'] ) ) {
404 return true;
405 }
406
407 switch ( $options['operator'] ) {
408 case 'is':
409 if ( ! wp_is_mobile() ) {
410 return false;
411 }
412 break;
413 case 'is_not':
414 if ( wp_is_mobile() ) {
415 return false;
416 }
417 break;
418 }
419
420 return true;
421 }
422
423 /**
424 * Check mobile visitor condition in frontend
425 *
426 * @param array $options options of the condition.
427 *
428 * @return bool true if can be displayed
429 * @since 1.6.3
430 */
431 public static function check_logged_in( $options = [] ) {
432
433 if ( ! isset( $options['operator'] ) ) {
434 return true;
435 }
436
437 switch ( $options['operator'] ) {
438 case 'is':
439 if ( ! is_user_logged_in() ) {
440 return false;
441 }
442 break;
443 case 'is_not':
444 if ( is_user_logged_in() ) {
445 return false;
446 }
447 break;
448 }
449
450 return true;
451 }
452
453 /**
454 * Helper for check with strings
455 *
456 * @param string $string string that is going to be checked.
457 * @param array $options options of this condition.
458 *
459 * @return bool true if ad can be displayed
460 * @since 1.6.3
461 */
462 public static function helper_check_string( $string = '', $options = [] ) {
463 if ( ! isset( $options['operator'] ) || empty( $options['value'] ) ) {
464 return true;
465 }
466
467 $operator = $options['operator'];
468 $string = (string) maybe_serialize( $string );
469 $value = (string) maybe_serialize( $options['value'] );
470
471 // check the condition by mode and bool.
472 $condition = true;
473 switch ( $operator ) {
474 // referrer contains string on any position.
475 case 'contain':
476 $condition = stripos( $string, $value ) !== false;
477 break;
478 // referrer does not contain string on any position.
479 case 'contain_not':
480 $condition = stripos( $string, $value ) === false;
481 break;
482 // referrer starts with the string.
483 case 'start':
484 $condition = stripos( $string, $value ) === 0;
485 break;
486 // referrer does not start with the string.
487 case 'start_not':
488 $condition = stripos( $string, $value ) !== 0;
489 break;
490 // referrer ends with the string.
491 case 'end':
492 $condition = substr( $string, - strlen( $value ) ) === $value;
493 break;
494 // referrer does not end with the string.
495 case 'end_not':
496 $condition = substr( $string, - strlen( $value ) ) !== $value;
497 break;
498 // referrer is equal to the string.
499 case 'match':
500 // strings do match, but should not or not match but should.
501 $condition = strcasecmp( $value, $string ) === 0;
502 break;
503 // referrer is not equal to the string.
504 case 'match_not':
505 // strings do match, but should not or not match but should.
506 $condition = strcasecmp( $value, $string ) !== 0;
507 break;
508 case 'regex':
509 case 'regex_not':
510 $condition = @preg_match( sprintf( '/%s/', $value ), $string );
511 // if the return value is `false`, the regex is incorrect.
512 if ( $condition === false ) {
513 Advanced_Ads::log( "Advanced Ads: regular expression '$value' in visitor condition is broken." );
514 break;
515 }
516
517 if ( $operator === 'regex_not' ) {
518 $condition = ! $condition;
519 }
520 break;
521 }
522
523 return $condition;
524 }
525 }
526