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 / ad-health-notices.php
advanced-ads / classes Last commit date
ad-health-notices.php 1 month ago checks.php 3 months ago display-conditions.php 3 days 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 3 days ago
ad-health-notices.php
862 lines
1 <?php // phpcs:ignoreFile
2
3 use AdvancedAds\Framework\Utilities\Arr;
4 use AdvancedAds\Framework\Utilities\Params;
5 use AdvancedAds\Utilities\Conditional;
6 use AdvancedAds\Utilities\WordPress;
7
8 /**
9 * Container class for Ad Health notice handling
10 *
11 * @package WordPress
12 * @subpackage Advanced Ads Plugin
13 * @since 1.12
14 *
15 * related scripts / functions
16 *
17 * advads_push_notice() function to push notifications using AJAX in admin/assets/js/admin-global.js
18 * push_ad_health_notice() in AdvancedAds\Admin\Ajax to push notifications sent via AJAX
19 * Advanced_Ads_Checks – for the various checks
20 * list of notification texts in admin/includes/ad-health-notices.php
21 */
22 class Advanced_Ads_Ad_Health_Notices {
23
24 /**
25 * Options
26 *
27 * @var array
28 */
29 protected $options;
30
31 /**
32 * All detected notices
33 *
34 * Structure is
35 * [notice_key] => array(
36 * 'text' - if not given, it uses the default text for output )
37 * 'orig_key' - original notice key
38 * )
39 *
40 * @var array
41 */
42 public $notices = [];
43
44 /**
45 * All ignored notices
46 *
47 * @var array
48 */
49 public $ignore = [];
50
51 /**
52 * All displayed notices ($notices minus $hidden)
53 *
54 * @var array
55 */
56 public $displayed_notices = [];
57
58 /**
59 * Load default notices
60 *
61 * @var array
62 */
63 public $default_notices = [];
64
65 /**
66 * The last notice key saved
67 *
68 * @var string
69 */
70 public $last_saved_notice_key = false;
71
72 /**
73 * Name of the transient saved for daily checks in the backend
74 *
75 * @const string
76 */
77 const DAILY_CHECK_TRANSIENT_NAME = 'advanced-ads-daily-ad-health-check-ran';
78
79 /**
80 * Return an instance of this class.
81 *
82 * @return object A single instance of this class.
83 */
84 public static function get_instance() {
85 static $instance;
86
87 // If the single instance hasn't been set, set it now.
88 if ( null === $instance ) {
89 $instance = new self();
90 }
91
92 return $instance;
93 }
94
95 /**
96 * Advanced_Ads_Ad_Health_Notices constructor.
97 */
98 public function __construct() {
99 // failsafe for there were some reports of 502 errors.
100 if ( 1 < did_action( 'plugins_loaded' ) ) {
101 return;
102 }
103
104 // stop here if notices are disabled.
105 if ( ! self::notices_enabled() ) {
106 return;
107 }
108
109 add_action( 'init', [ $this, 'load_default_notices' ] );
110 add_action( 'init', [ $this, 'load_notices' ] );
111
112 /**
113 * Run checks
114 * needs to run after plugins_loaded with priority 10
115 * current_screen seems like the perfect hook
116 */
117 add_action( 'current_screen', [ $this, 'run_checks' ], 20 );
118
119 // add notification when an ad expires.
120 add_action( 'advanced-ads-ad-expired', [ $this, 'ad_expired' ] );
121 }
122
123 /**
124 * Check if notices are enabled using "disable-notices" option in plugin settings
125 *
126 * @return bool
127 */
128 public static function notices_enabled() {
129 $options = Advanced_Ads::get_instance()->options();
130
131 return empty( $options['disable-notices'] );
132 }
133
134 public function load_default_notices() {
135 // load default notices.
136 if ( [] === $this->default_notices ) {
137 include ADVADS_ABSPATH . '/admin/includes/ad-health-notices.php';
138 $options = $this->options();
139 $hide_notices = $options['hide_notices'] ?? [];
140 if ( ! empty( $hide_notices ) ) {
141 $advanced_ads_ad_health_notices = array_diff_key($advanced_ads_ad_health_notices, $hide_notices);
142 }
143 $this->default_notices = $advanced_ads_ad_health_notices;
144 }
145 }
146
147 /**
148 * Load notice arrays
149 */
150 public function load_notices() {
151
152 $options = $this->options();
153
154 // load notices from "notices".
155 $this->notices = $options['notices'] ?? [];
156
157 /**
158 * Cleanup notices
159 */
160 foreach ( $this->notices as $_key => $_notice ) {
161 // without valid key caused by an issue prior to 1.13.3.
162 if ( empty( $_key ) ) {
163 unset( $this->notices[ $_key ] );
164 }
165
166 $time = current_time( 'timestamp', 0 );
167 $notice_array = $this->get_notice_array_for_key( $_key );
168
169 // handle notices with a timeout.
170 if ( isset( $_notice['closed'] ) ) {
171 // remove notice when timeout expired – was closed longer ago than timeout set in the notice options.
172 if ( empty( $notice_array['timeout'] )
173 || ( ( $time - $_notice['closed'] ) > $notice_array['timeout'] ) ) {
174 $this->remove( $_key );
175 } else {
176 // just ignore notice if timeout is still valid.
177 unset( $this->notices[ $_key ] );
178 }
179 }
180
181 // check if notice still exists.
182 if ( [] === $this->get_notice_array_for_key( $_key ) ) {
183 unset( $this->notices[ $_key ] );
184 }
185 }
186
187 // unignore notices if `show-hidden=true` is set in the URL.
188 $nonce = Params::get( 'advads_nonce' );
189 if (
190 $nonce && wp_verify_nonce( wp_unslash( $nonce ), 'advanced-ads-show-hidden-notices' )
191 && true === Params::get( 'advads-show-hidden-notices', false, FILTER_VALIDATE_BOOLEAN )
192 ) {
193 $this->unignore();
194 // remove the argument from the URL.
195 add_filter( 'removable_query_args', [ $this, 'remove_query_vars_after_notice_update' ] );
196 }
197
198 // load hidden notices.
199 $this->ignore = $this->get_valid_ignored();
200
201 // get displayed notices
202 // get keys of notices.
203 $notice_keys = array_keys( $this->notices );
204 $this->displayed_notices = array_diff( $notice_keys, $this->ignore );
205 }
206
207 /**
208 * Remove query var from URL after notice was updated
209 *
210 * @param array $removable_query_args array with removable query vars.
211 * @return array updated query vars.
212 */
213 public function remove_query_vars_after_notice_update( $removable_query_args ) {
214 $removable_query_args[] = 'advads-show-hidden-notices';
215 $removable_query_args[] = 'advads_nonce';
216
217 return $removable_query_args;
218 }
219
220 /**
221 * Manage when to run checks
222 * - only when users have ads
223 * - once per day on any backend page
224 * - on each Advanced Ads related page
225 */
226 public function run_checks() {
227
228 // run in WP Admin only and if there are any ads.
229 if ( ! is_admin() || ! WordPress::get_count_ads() ) {
230 return;
231 }
232
233 // don’t run on AJAX calls.
234 if ( wp_doing_ajax() ) {
235 return;
236 }
237
238 // run only daily unless we are on an Advanced Ads related page.
239 if ( ! Conditional::is_screen_advanced_ads()
240 && get_transient( self::DAILY_CHECK_TRANSIENT_NAME ) ) {
241 return;
242 }
243
244 $this->checks();
245 }
246
247 /**
248 * General checks done on each Advanced Ads-related page or once per day
249 */
250 public function checks() {
251 $checks = [
252 'old_php' => ! Advanced_Ads_Checks::php_version_minimum(),
253 'conflicting_plugins' => count( Advanced_Ads_Checks::conflicting_plugins() ),
254 'php_extensions_missing' => count( Advanced_Ads_Checks::php_extensions() ),
255 'ads_disabled' => Advanced_Ads_Checks::ads_disabled(),
256 'constants_enabled' => Advanced_Ads_Checks::get_defined_constants(),
257 'assets_expired' => Advanced_Ads_Checks::assets_expired(),
258 'license_invalid' => Advanced_Ads_Checks::licenses_invalid(),
259 'buddypress_no_pro' => class_exists( 'BuddyPress', false ) && ! defined( 'BP_PLATFORM_VERSION' ) && ! defined( 'AAP_VERSION' ),
260 'buddyboss_no_pro' => defined( 'BP_PLATFORM_VERSION' ) && ! defined( 'AAP_VERSION' ),
261 'gamipress_no_pro' => class_exists( 'GamiPress', false ) && ! defined( 'AAP_VERSION' ),
262 'pmp_no_pro' => defined( 'PMPRO_VERSION' ) && ! defined( 'AAP_VERSION' ),
263 'members_no_pro' => function_exists( 'members_plugin' ) && ! defined( 'AAP_VERSION' ),
264 'translatepress_no_pro' => function_exists( 'trp_enable_translatepress' ) && ! defined( 'AAP_VERSION' ),
265 'weglot_no_pro' => defined( 'WEGLOT_VERSION' ) && ! defined( 'AAP_VERSION' ),
266 'learndash' => defined( 'LEARNDASH_VERSION' ),
267 'aawp' => defined( 'AAWP_PLUGIN_FILE' ),
268 'polylang' => defined( 'POLYLANG_VERSION' ),
269 'mailpoet' => function_exists( 'mailpoet_check_requirements' ),
270 'wp_rocket' => Advanced_Ads_Checks::active_wp_rocket(),
271 'quiz_plugins_no_pro' => Advanced_Ads_Checks::active_quiz_plugins(),
272 'elementor' => defined( 'ELEMENTOR_VERSION' ),
273 'siteorigin' => defined( 'SITEORIGIN_PANELS_VERSION' ),
274 'divi_no_pro' => function_exists( 'et_setup_theme' ) || defined( 'ET_BUILDER_PLUGIN_VERSION' ),
275 'beaver_builder' => class_exists( 'FLBuilderLoader' ),
276 'pagelayer' => defined( 'PAGELAYER_FILE' ),
277 'wpb' => defined( 'WPB_VC_VERSION' ),
278 'newspaper' => defined( 'TAGDIV_ROOT' ),
279 'bbpress_no_pro' => class_exists( 'bbPress', false ) && ! defined( 'AAP_VERSION' ),
280 'WPML_active' => defined( 'ICL_SITEPRESS_VERSION' ),
281 'AMP_active' => Advanced_Ads_Checks::active_amp_plugin(),
282 'wpengine' => Advanced_Ads_Checks::wp_engine_hosting(),// do not remove
283 'ads_txt_plugins_enabled' => count( Advanced_Ads_Checks::ads_txt_plugins() ),
284 'header_footer_plugins_enabled' => count( Advanced_Ads_Checks::header_footer_plugins() ),
285 ];
286
287 foreach ( $checks as $key => $check ) {
288 if ( $check ) {
289 $this->add( $key );
290 } elseif ( 'wpengine' !== $key ) {
291 $this->remove( $key );
292 }
293 }
294
295
296 set_transient( self::DAILY_CHECK_TRANSIENT_NAME, true, DAY_IN_SECONDS );
297 }
298
299 /**
300 * Add a notice to the queue
301 *
302 * @param string $notice_key notice key to be added to the notice array.
303 * @param array $atts additional attributes.
304 *
305 * attributes
306 * - append_key string attached to the key; enables to create multiple messages for one original key
307 * - append_text text added to the default message
308 * - ad_id ID of an ad, attaches the link to the ad edit page to the message
309 */
310 public function add( $notice_key, $atts = [] ) {
311 // Early bail!!
312 if ( empty( $notice_key ) || ! self::notices_enabled() ) {
313 return;
314 }
315
316 // add string to key.
317 if ( ! empty( $atts['append_key'] ) ) {
318 $orig_notice_key = $notice_key;
319 $notice_key .= $atts['append_key'];
320 }
321
322 $options = $this->options();
323 $notice_key = sanitize_key( $notice_key );
324
325 // load notices from "queue".
326 $notices = $options['notices'] ?? [];
327
328 // check if notice_key was already saved, this prevents the same notice from showing up in different forms.
329 if ( isset( $notices[ $notice_key ] ) ) {
330 return;
331 }
332
333 // save the new notice key.
334 $notices[ $notice_key ] = [];
335
336 // save text, if given.
337 if ( ! empty( $atts['text'] ) ) {
338 $notices[ $notice_key ]['text'] = $atts['text'];
339 }
340
341 // attach link to ad, if given.
342 if ( ! empty( $atts['ad_id'] ) ) {
343 $id = absint( $atts['ad_id'] );
344 $ad = wp_advads_get_ad( $id );
345 if ( $id && '' !== $ad->get_title() ) {
346 $edit_link = ' <a href="' . admin_url( 'post.php?post=' . $id . '&action=edit' ) . '">' . $ad->get_title() . '</a>';
347 $notices[ $notice_key ]['append_text'] = isset( $notices[ $notice_key ]['append_text'] ) ? $notices[ $notice_key ]['append_text'] . $edit_link : $edit_link;
348 }
349 }
350
351 // save the original key, if we manipulated it.
352 if ( ! empty( $atts['append_key'] ) ) {
353 $notices[ $notice_key ]['orig_key'] = $orig_notice_key;
354 }
355
356 // add more text.
357 if ( ! empty( $atts['append_text'] ) ) {
358 $notices[ $notice_key ]['append_text'] = esc_attr( $atts['append_text'] );
359 }
360
361 // add current time – we store localized time including the offset set in WP.
362 $notices[ $notice_key ]['time'] = current_time( 'timestamp', 0 );
363
364 $this->last_saved_notice_key = $notice_key;
365
366 $this->update_notices( $notices );
367 }
368
369 /**
370 * Updating an existing notice or add it, if it doesn’t exist, yet
371 *
372 * @param string $notice_key notice key to be added to the notice array.
373 * @param array $atts additional attributes.
374 *
375 * attributes:
376 * - append_text – text added to the default message
377 */
378 public function update( $notice_key, $atts = [] ) {
379 // Early bail!!
380 if ( empty( $notice_key ) || ! self::notices_enabled() ) {
381 return;
382 }
383
384 // check if the notice already exists.
385 $notice_key = esc_attr( $notice_key );
386 $options = $this->options();
387
388 // load notices from "queue".
389 $notices = isset( $options['notices'] ) ? $options['notices'] : [];
390
391 // check if notice_key was already saved, this prevents the same notice from showing up in different forms.
392 if ( ! isset( $notices[ $notice_key ] ) ) {
393 $this->add( $notice_key, $atts );
394
395 $notice_key = $this->last_saved_notice_key;
396
397 // just in case, get notices again.
398 $notices = $this->notices;
399 } else {
400 // add more text if this is an update.
401 if ( ! empty( $atts['append_text'] ) ) {
402 $notices[ $notice_key ]['append_text'] = isset( $notices[ $notice_key ]['append_text'] ) ? $notices[ $notice_key ]['append_text'] . $atts['append_text'] : $atts['append_text'];
403 }
404 // add `closed` marker, if given.
405 if ( ! empty( $atts['closed'] ) ) {
406 $notices[ $notice_key ]['closed'] = absint( $atts['closed'] );
407 }
408 }
409
410 // update db.
411 $this->update_notices( $notices );
412 }
413
414 /**
415 * Decide based on the notice, whether to remove or ignore it
416 *
417 * @param string $notice_key key of the notice.
418 */
419 public function hide( $notice_key ) {
420 if ( empty( $notice_key ) ) {
421 return;
422 }
423
424 // get original notice array for the "hide" attribute.
425 $notice_array = $this->get_notice_array_for_key( $notice_key );
426
427 // handle notices with a timeout.
428 // set `closed` timestamp if the notice definition has a timeout information.
429 if ( isset( $notice_array['timeout'] ) ) {
430 $this->update( $notice_key, [ 'closed' => current_time( 'timestamp', 0 ) ] );
431
432 return;
433 }
434
435 if ( isset( $notice_array['hide'] ) && false === $notice_array['hide'] ) {
436 // remove item.
437 $this->remove( $notice_key );
438 } else {
439 // hide item.
440 $this->ignore( $notice_key );
441 }
442
443 }
444
445 /**
446 * Remove notice
447 * Would remove it from "notice" array. The notice can be added anytime again
448 * practically, this allows users to "skip" an notice if they are sure that it was only temporary
449 *
450 * @param string $notice_key notice key to be removed.
451 */
452 public function remove( $notice_key ) {
453 // Early bail!!
454 if ( empty( $notice_key ) || ! self::notices_enabled() ) {
455 return;
456 }
457
458 $options = $this->options();
459 if (
460 ! isset( $options['notices'] )
461 || ! is_array( $options['notices'] )
462 || ! isset( $options['notices'][ $notice_key ] )
463 ) {
464 return;
465 }
466
467 unset( $options['notices'][ $notice_key ] );
468 $options['hide_notices'][ $notice_key] = true;
469 $this->hide_notices( $options[ 'hide_notices' ] ); // for non wp notices
470 $this->update_notices( $options['notices'] );
471 }
472
473 /**
474 * Ignore any notice
475 * adds notice key into "ignore" array
476 * does not remove it from "notices" array
477 *
478 * @param string $notice_key key of the notice to be ignored.
479 */
480 public function ignore( $notice_key ) {
481 // Early bail!!
482 if ( empty( $notice_key ) || ! self::notices_enabled() ) {
483 return;
484 }
485
486 $options = $this->options();
487 $ignored = isset( $options['ignore'] ) && is_array( $options['ignore'] ) ? $options['ignore'] : [];
488
489 // adds notice key to ignore array if it doesn’t exist already.
490 if ( false === array_search( $notice_key, $ignored, true ) ) {
491 $ignored[] = $notice_key;
492 }
493
494 // update db.
495 $this->update_ignore( $ignored );
496 }
497
498 /**
499 * Clear all "ignore" messages
500 */
501 public function unignore() {
502 $this->update_ignore();
503 }
504
505 /**
506 * Update ignored notices if there is any change
507 *
508 * @param string[] $ignore_list list of ignored keys.
509 *
510 * @return void
511 */
512 public function update_ignore( $ignore_list = [] ) {
513 $options = $this->options();
514 $before = Arr::get( $options, 'ignore', [] );
515
516 if ( $ignore_list === $before ) {
517 return;
518 }
519
520 $options['ignore'] = $ignore_list;
521 $this->update_options( $options );
522 }
523
524 /**
525 * Update notices list if there is any change
526 *
527 * @param array $notices New options.
528 *
529 * @return void
530 */
531 public function update_notices( $notices ): void {
532 $options = $this->options();
533
534 if ( Arr::get( $options, 'notices', [] ) === $notices ) {
535 return;
536 }
537
538 $options['notices'] = $notices;
539 $this->update_options( $options );
540 $this->load_notices();
541 }
542
543 /**
544 * Hide notices list if there is any change
545 *
546 * @param array $notices New options.
547 *
548 * @return void
549 */
550 public function hide_notices( $notices ): void {
551 $options = $this->options();
552
553 if ( Arr::get( $options, 'notices', [] ) === $notices ) {
554 return;
555 }
556
557 $options['hide_notices'] = $notices;
558 $this->update_options( $options );
559 $this->load_notices();
560 }
561
562 /**
563 * Render notice widget on overview page
564 */
565 public function render_widget() {
566 $ignored_count = count( $this->ignore );
567
568 include ADVADS_ABSPATH . 'views/admin/widgets/aa-dashboard/overview-notices.php';
569 }
570
571 /**
572 * Display notices in a list
573 *
574 * @param string $type which type of notice to show; default: 'problem'.
575 *
576 * @return void
577 */
578 public function display( $type = 'problem' ) {
579 // Early baill!!
580 if ( ! is_array( $this->notices ) ) {
581 return;
582 }
583 foreach ( $this->notices as $_notice_key => $_notice ) {
584 $notice_array = $this->get_notice_array_for_key( $_notice_key );
585
586 // remove the notice if key doesn’t exist anymore.
587 if ( [] === $notice_array ) {
588 $this->remove( $_notice_key );
589 }
590
591 $notice_type = isset( $notice_array['type'] ) ? $notice_array['type'] : 'problem';
592
593 // skip if type is not correct.
594 if ( $notice_type !== $type ) {
595 continue;
596 }
597
598 if ( ! empty( $_notice['text'] ) ) {
599 $text = $_notice['text'];
600 } elseif ( isset( $notice_array['text'] ) ) {
601 $text = $notice_array['text'];
602 } else {
603 continue;
604 }
605
606 // attach "append_text".
607 if ( ! empty( $_notice['append_text'] ) ) {
608 $text .= $_notice['append_text'];
609 }
610
611 // attach "get help" link.
612 if ( ! empty( $_notice['get_help_link'] ) ) {
613 $text .= $this->get_help_link( $_notice['get_help_link'] );
614 } elseif ( isset( $notice_array['get_help_link'] ) ) {
615 $text .= $this->get_help_link( $notice_array['get_help_link'] );
616 }
617
618 $can_hide = ( ! isset( $notice_array['can_hide'] ) || true === $notice_array['can_hide'] ) ? true : false;
619 $hide = ( ! isset( $notice_array['hide'] ) || true === $notice_array['hide'] ) ? true : false;
620 $is_hidden = in_array( $_notice_key, $this->ignore, true ) ? true : false;
621 $date = isset( $_notice['time'] ) ? date_i18n( get_option( 'date_format' ), $_notice['time'] ) : false;
622 $dashicon = 'dashicons-warning';
623
624 if ( 'notice' === $type ) {
625 $dashicon = 'dashicons-info';
626 } elseif ( 'pitch' === $type ) {
627 $dashicon = 'dashicons-lightbulb';
628 }
629
630 include ADVADS_ABSPATH . '/admin/views/overview-notice-row.php';
631 }
632 }
633
634 /**
635 * Display plugins and themes pitches
636 *
637 * @return void
638 */
639 public function display_pitches() {
640 $this->display( 'pitch' );
641 }
642
643 /**
644 * Display problems.
645 */
646 public function display_problems() {
647 $this->display( 'problem' );
648 }
649
650 /**
651 * Display notices.
652 */
653 public function display_notices() {
654 $this->display( 'notice' );
655 }
656
657 /**
658 * Return notices option from DB
659 *
660 * @return array $options
661 */
662 public function options() {
663 if ( ! isset( $this->options ) ) {
664 $this->options = get_option( ADVADS_SLUG . '-ad-health-notices', [] );
665 }
666
667 if ( ! is_array( $this->options ) ) {
668 $this->options = [];
669 }
670
671 return $this->options;
672 }
673
674 /**
675 * Update notice options
676 *
677 * @param array $options new options.
678 */
679 public function update_options( array $options ) {
680 // do not allow to clear options.
681 if ( [] === $options ) {
682 return;
683 }
684
685 $this->options = $options;
686 update_option( ADVADS_SLUG . '-ad-health-notices', $options );
687 }
688
689 /**
690 * Get the number of overall visible notices
691 */
692 public static function get_number_of_notices() {
693 $displayed_notices = self::get_instance()->displayed_notices;
694 if ( ! is_array( $displayed_notices ) ) {
695 return 0;
696 }
697
698 return count( $displayed_notices );
699 }
700
701 /**
702 * Get ignored messages that are also in the notices
703 * also updates ignored array, if needed
704 */
705 public function get_valid_ignored() {
706 $options = $this->options();
707 $ignore_before = $options['ignore'] ?? [];
708
709 // get keys from notices.
710 $notice_keys = array_keys( $this->notices );
711
712 // get the errors that are in ignore AND notices and reset the keys.
713 $ignore = array_values( array_intersect( $ignore_before, $notice_keys ) );
714
715 // only update if changed.
716 if ( $ignore !== $ignore_before ) {
717 $this->update_ignore( $ignore );
718 }
719
720 return $ignore;
721 }
722
723 /**
724 * Check if there are visible problems (notices of type "problem")
725 *
726 * @return bool true if there are visible notices (notices that are not hidden)
727 */
728 public static function has_visible_problems() {
729 $displayed_notices = self::get_instance()->displayed_notices;
730 if ( ! is_array( $displayed_notices ) ) {
731 return false;
732 }
733
734 return 0 < count( $displayed_notices );
735 }
736
737 /**
738 * Get visible notices by type – hidden and displayed
739 *
740 * @param string $type type of the notice.
741 *
742 * @return array
743 */
744 public function get_visible_notices_by_type( $type = 'problem' ) {
745 $notices_by_type = [];
746
747 foreach ( $this->notices as $_key => $_notice ) {
748 $notice_array = $this->get_notice_array_for_key( $_key );
749
750 if ( isset( $notice_array['type'] ) && $type === $notice_array['type']
751 && ( ! isset( $this->ignore ) || false === array_search( $_key, $this->ignore, true ) ) ) {
752 $notices_by_type[ $_key ] = $_notice;
753 }
754 }
755
756 return $notices_by_type;
757 }
758
759 /**
760 * Check if there are notices
761 *
762 * @return bool true if there are notices, false if not
763 */
764 public function has_notices() {
765 return isset( $this->notices ) && is_array( $this->notices ) && count( $this->notices );
766 }
767
768 /**
769 * Check if there are visible notices for a given type
770 *
771 * @param string $type type of the notice.
772 *
773 * @return integer
774 */
775 public function has_notices_by_type( $type = 'problem' ) {
776 $notices = $this->get_visible_notices_by_type( $type );
777
778 if ( ! is_array( $notices ) ) {
779 return 0;
780 }
781
782 return count( $notices );
783 }
784
785 /**
786 * Get the notice array for a notice key
787 * useful, if a notice key was manipulated
788 *
789 * @param string $notice_key key of the notice.
790 *
791 * @return array type
792 */
793 public function get_notice_array_for_key( $notice_key ) {
794 // check if there is an original key.
795 $orig_key = isset( $this->notices[ $notice_key ]['orig_key'] ) ? $this->notices[ $notice_key ]['orig_key'] : $notice_key;
796
797 return isset( $this->default_notices[ $orig_key ] ) ? $this->default_notices[ $orig_key ] : [];
798 }
799
800 /**
801 * Add notification when an ad expires based on the expiry date
802 *
803 * @param integer $ad_id ID of the ad.
804 *
805 * @return void
806 */
807 public function ad_expired( $ad_id ): void {
808 $id = ! empty( $ad_id ) ? absint( $ad_id ) : 0;
809 $this->update(
810 'ad_expired',
811 [
812 'append_key' => $id,
813 'ad_id' => $id,
814 ]
815 );
816 }
817
818 /**
819 * Get AdSense error link
820 * this is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link() which might not be available all the time
821 *
822 * @param string $code error code.
823 *
824 * @return string link
825 */
826 public static function get_adsense_error_link( $code ) {
827 if ( ! empty( $code ) ) {
828 $code = '-' . $code;
829 }
830
831 if ( class_exists( 'Advanced_Ads_AdSense_MAPI', false ) ) {
832 return Advanced_Ads_AdSense_MAPI::get_adsense_error_link( 'disapprovedAccount' );
833 }
834
835 // is a copy of Advanced_Ads_AdSense_MAPI::get_adsense_error_link().
836 return sprintf(
837 /* translators: %1$s is an anchor (link) opening tag, %2$s is the closing tag. */
838 esc_attr__( 'Learn more about AdSense account issues %1$shere%2$s.', 'advanced-ads' ),
839 '<a href="https://wpadvancedads.com/adsense-errors/?utm_source=advanced-ads&utm_medium=link&utm_campaign=adsense-error' . $code . '" target="_blank">',
840 '</a>'
841 );
842 }
843
844 /**
845 * Return a "Get Help" link
846 *
847 * @param string $link target URL.
848 *
849 * @return string HTML of the target link
850 */
851 public function get_help_link( $link ) {
852
853 $link = esc_url( $link );
854
855 if ( ! $link ) {
856 return '';
857 }
858
859 return '&nbsp;<a href="' . $link . '" target="_blank">' . __( 'Get help', 'advanced.ads' ) . '</a>';
860 }
861 }
862