PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.45.1
Advanced Ads – Ad Manager & AdSense v1.45.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 / plugin.php
advanced-ads / classes Last commit date
Advanced_Ads_Modal.php 2 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_checks.php 3 years ago in-content-injector.php 3 years ago inline-css.php 3 years ago plugin.php 2 years ago upgrades.php 6 years ago utils.php 3 years ago visitor-conditions.php 3 years ago widget.php 3 years ago
plugin.php
956 lines
1 <?php
2
3 /**
4 * WordPress integration and definitions:
5 *
6 * - posttypes
7 * - taxonomy
8 * - textdomain
9 */
10 class Advanced_Ads_Plugin {
11 /**
12 * Instance of Advanced_Ads_Plugin
13 *
14 * @var object Advanced_Ads_Plugin
15 */
16 protected static $instance;
17
18 /**
19 * Instance of Advanced_Ads_Model
20 *
21 * @var object Advanced_Ads_Model
22 */
23 protected $model;
24
25 /**
26 * Plugin options
27 *
28 * @var array $options
29 */
30 protected $options;
31
32 /**
33 * Interal plugin options – set by the plugin
34 *
35 * @var array $internal_options
36 */
37 protected $internal_options;
38
39 /**
40 * Default prefix of selectors (id, class) in the frontend
41 * can be changed by options
42 *
43 * @var Advanced_Ads_Plugin
44 */
45 const DEFAULT_FRONTEND_PREFIX = 'advads-';
46
47 /**
48 * Frontend prefix for classes and IDs
49 *
50 * @var string $frontend_prefix
51 */
52 private $frontend_prefix;
53
54 /**
55 * Advanced_Ads_Plugin constructor.
56 */
57 private function __construct() {
58 register_activation_hook( ADVADS_BASE, [ $this, 'activate' ] );
59 register_deactivation_hook( ADVADS_BASE, [ $this, 'deactivate' ] );
60 register_uninstall_hook( ADVADS_BASE, [ 'Advanced_Ads_Plugin', 'uninstall' ] );
61
62 add_action( 'plugins_loaded', [ $this, 'wp_plugins_loaded' ], 20 );
63 add_action( 'init', [ $this, 'run_upgrades' ], 9 );
64 }
65
66 /**
67 * Get instance of Advanced_Ads_Plugin
68 *
69 * @return Advanced_Ads_Plugin
70 */
71 public static function get_instance() {
72 // If the single instance hasn't been set, set it now.
73 if ( null === self::$instance ) {
74 self::$instance = new self();
75 }
76
77 return self::$instance;
78 }
79
80 /**
81 * Get instance of Advanced_Ads_Model
82 *
83 * @param Advanced_Ads_Model $model model to access data.
84 */
85 public function set_model( Advanced_Ads_Model $model ) {
86 $this->model = $model;
87 }
88
89 /**
90 * Execute various hooks after WordPress and all plugins are available
91 */
92 public function wp_plugins_loaded() {
93 // Load plugin text domain.
94 $this->load_plugin_textdomain();
95
96 // activate plugin when new blog is added on multisites // -TODO this is admin-only.
97 add_action( 'wpmu_new_blog', [ $this, 'activate_new_site' ] );
98
99 // Load public-facing style sheet and JavaScript.
100 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_styles' ] );
101 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
102 add_action( 'wp_head', [ $this, 'print_head_scripts' ], 7 );
103 // higher priority to make sure other scripts are printed before.
104 add_action( 'wp_footer', [ $this, 'print_footer_scripts' ], 100 );
105
106 // add short codes.
107 add_shortcode( 'the_ad', [ $this, 'shortcode_display_ad' ] );
108 add_shortcode( 'the_ad_group', [ $this, 'shortcode_display_ad_group' ] );
109 add_shortcode( 'the_ad_placement', [ $this, 'shortcode_display_ad_placement' ] );
110
111 // load widgets.
112 add_action( 'widgets_init', [ $this, 'widget_init' ] );
113
114 // Call action hooks for ad status changes.
115 add_action( 'transition_post_status', [ $this, 'transition_ad_status' ], 10, 3 );
116
117 // register expired post status.
118 Advanced_Ads_Ad_Expiration::register_post_status();
119
120 // if expired ad gets untrashed, revert it to expired status (instead of draft).
121 add_filter( 'wp_untrash_post_status', [ Advanced_Ads_Ad_Expiration::class, 'wp_untrash_post_status' ], 10, 3 );
122
123 // load display conditions.
124 Advanced_Ads_Display_Conditions::get_instance();
125 new Advanced_Ads_Frontend_Checks();
126 new Advanced_Ads_Compatibility();
127 Advanced_Ads_Ad_Health_Notices::get_instance(); // load to fetch notices.
128 }
129
130 /**
131 * Run upgrades.
132 *
133 * Compatibility with the Piklist plugin that has a function hooked to `posts_where` that access $GLOBALS['wp_query'].
134 * Since `Advanced_Ads_Upgrades` applies `posts_where`: (`Advanced_Ads_Admin_Notices::get_instance()` >
135 * `Advanced_Ads::get_number_of_ads()` > new WP_Query > ... 'posts_where') this function is hooked to `init` so that `$GLOBALS['wp_query']` is instantiated.
136 */
137 public function run_upgrades() {
138 /**
139 * Run upgrades, if this is a new version or version does not exist.
140 */
141 $internal_options = $this->internal_options();
142
143 if ( ! defined( 'DOING_AJAX' ) && ( ! isset( $internal_options['version'] ) || version_compare( $internal_options['version'], ADVADS_VERSION, '<' ) ) ) {
144 new Advanced_Ads_Upgrades();
145 }
146 }
147
148 /**
149 * Register and enqueue public-facing style sheet.
150 */
151 public function enqueue_styles() {
152 // wp_enqueue_style( $this->get_plugin_slug() . '-plugin-styles', plugins_url('assets/css/public.css', __FILE__), array(), ADVADS_VERSION);
153 }
154
155 /**
156 * Return the plugin slug.
157 *
158 * @return string plugin slug variable.
159 */
160 public function get_plugin_slug() {
161 return ADVADS_SLUG;
162 }
163
164 /**
165 * Register and enqueues public-facing JavaScript files.
166 */
167 public function enqueue_scripts() {
168 if ( advads_is_amp() ) {
169 return;
170 }
171 // wp_enqueue_script( $this->get_plugin_slug() . '-plugin-script', plugins_url('assets/js/public.js', __FILE__), array('jquery'), ADVADS_VERSION);
172
173 wp_register_script(
174 $this->get_plugin_slug() . '-advanced-js',
175 sprintf( '%spublic/assets/js/advanced%s.js', ADVADS_BASE_URL, defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min' ),
176 [ 'jquery' ],
177 ADVADS_VERSION,
178 false
179 );
180
181 $privacy = Advanced_Ads_Privacy::get_instance();
182 $privacy_options = $privacy->options();
183 $privacy_options['enabled'] = ! empty( $privacy_options['enabled'] );
184 $privacy_options['state'] = $privacy->get_state();
185
186 wp_localize_script(
187 $this->get_plugin_slug() . '-advanced-js',
188 'advads_options',
189 [
190 'blog_id' => get_current_blog_id(),
191 'privacy' => $privacy_options,
192 ]
193 );
194
195 $activated_js = apply_filters( 'advanced-ads-activate-advanced-js', isset( $this->options()['advanced-js'] ) );
196
197 if ( $activated_js || ! empty( $_COOKIE['advads_frontend_picker'] ) ) {
198 wp_enqueue_script( $this->get_plugin_slug() . '-advanced-js' );
199 }
200
201 wp_register_script(
202 $this->get_plugin_slug() . '-frontend-picker',
203 sprintf( '%spublic/assets/js/frontend-picker%s.js', ADVADS_BASE_URL, defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min' ),
204 [ 'jquery', $this->get_plugin_slug() . '-advanced-js' ],
205 ADVADS_VERSION,
206 false
207 );
208
209 if ( ! empty( $_COOKIE['advads_frontend_picker'] ) ) {
210 wp_enqueue_script( $this->get_plugin_slug() . '-frontend-picker' );
211 }
212 }
213
214 /**
215 * Print public-facing JavaScript in the HTML head.
216 */
217 public function print_head_scripts() {
218 $short_url = self::get_short_url();
219 $attribution = '<!-- ' . $short_url . ' is managing ads with Advanced Ads%1$s%2$s -->';
220 $version = self::is_new_user( 1585224000 ) ? ' ' . ADVADS_VERSION : '';
221 $plugin_url = self::get_group_by_url( $short_url, 'a' ) ? '' . ADVADS_URL : '';
222 // escaping would break HTML comment tags so we disable checks here.
223 // phpcs:ignore
224 echo apply_filters( 'advanced-ads-attribution', sprintf( $attribution, $version, $plugin_url ) );
225
226 if ( advads_is_amp() ) {
227 return;
228 }
229
230 ob_start();
231 ?>
232 <script id="<?php echo esc_attr( $this->get_frontend_prefix() ); ?>ready">
233 <?php
234 readfile( sprintf(
235 '%spublic/assets/js/ready%s.js',
236 ADVADS_BASE_PATH,
237 defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'
238 ) );
239 ?>
240 </script>
241 <?php
242 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaping would break the HTML
243 echo Advanced_Ads_Utils::get_inline_asset( ob_get_clean() );
244 }
245
246 /**
247 * Print inline scripts in wp_footer.
248 */
249 public function print_footer_scripts() {
250 if ( advads_is_amp() ) {
251 return;
252 }
253
254 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaping would break the HTML
255 echo Advanced_Ads_Utils::get_inline_asset(
256 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- we're getting the contents of a local file
257 sprintf( '<script>%s</script>', file_get_contents( sprintf(
258 '%spublic/assets/js/ready-queue%s.js',
259 ADVADS_BASE_PATH,
260 defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'
261 ) ) )
262 );
263 }
264
265 /**
266 * Register the Advanced Ads widget
267 */
268 public function widget_init() {
269 register_widget( 'Advanced_Ads_Widget' );
270 }
271
272 /**
273 * Fired when a new site is activated with a WPMU environment.
274 *
275 * @param int $blog_id ID of the new blog.
276 */
277 public function activate_new_site( $blog_id ) {
278
279 if ( 1 !== did_action( 'wpmu_new_blog' ) ) {
280 return;
281 }
282
283 switch_to_blog( $blog_id );
284 $this->single_activate();
285 restore_current_blog();
286 }
287
288 /**
289 * Fired for each blog when the plugin is activated.
290 */
291 protected function single_activate() {
292 // $this->post_types_rewrite_flush();
293 // -TODO inform modules
294 $this->create_capabilities();
295 }
296
297 /**
298 * Fired for each blog when the plugin is deactivated.
299 */
300 protected function single_deactivate() {
301 // -TODO inform modules
302 $this->remove_capabilities();
303 }
304
305 /**
306 * Load the plugin text domain for translation.
307 */
308 public function load_plugin_textdomain() {
309 load_plugin_textdomain( 'advanced-ads', false, ADVADS_BASE_DIR . '/languages' );
310 }
311
312 /**
313 * Fired when the plugin is activated.
314 *
315 * @param boolean $network_wide True if WPMU superadmin uses
316 * "Network Activate" action, false if
317 * WPMU is disabled or plugin is
318 * activated on an individual blog.
319 */
320 public function activate( $network_wide ) {
321 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
322
323 if ( $network_wide ) {
324 // get all blog ids.
325 global $wpdb;
326 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" );
327 $original_blog_id = $wpdb->blogid;
328
329 foreach ( $blog_ids as $blog_id ) {
330 switch_to_blog( $blog_id );
331 $this->single_activate();
332 }
333
334 switch_to_blog( $original_blog_id );
335 } else {
336 $this->single_activate();
337 }
338 } else {
339 $this->single_activate();
340 }
341 }
342
343 /**
344 * Fired when the plugin is deactivated.
345 *
346 * @param boolean $network_wide true if Advanced Ads should be disabled network-wide.
347 *
348 * True if WPMU superadmin uses
349 * "Network Deactivate" action, false if
350 * WPMU is disabled or plugin is
351 * deactivated on an individual blog.
352 */
353 public function deactivate( $network_wide ) {
354 if ( function_exists( 'is_multisite' ) && is_multisite() ) {
355
356 if ( $network_wide ) {
357 // get all blog ids.
358 global $wpdb;
359 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" );
360 $original_blog_id = $wpdb->blogid;
361
362 foreach ( $blog_ids as $blog_id ) {
363 switch_to_blog( $blog_id );
364 $this->single_deactivate();
365 }
366
367 switch_to_blog( $original_blog_id );
368 } else {
369 $this->single_deactivate();
370 }
371 } else {
372 $this->single_deactivate();
373 }
374 }
375
376
377 /**
378 * Shortcode to include ad in frontend
379 *
380 * @param array $atts shortcode attributes.
381 *
382 * @return string ad content.
383 */
384 public function shortcode_display_ad( $atts ) {
385 $atts = is_array( $atts ) ? $atts : [];
386 $id = isset( $atts['id'] ) ? (int) $atts['id'] : 0;
387 // check if there is an inline attribute with or without value.
388 if ( isset( $atts['inline'] ) || in_array( 'inline', $atts, true ) ) {
389 $atts['inline_wrapper_element'] = true;
390 }
391 $atts = $this->prepare_shortcode_atts( $atts );
392
393 // use the public available function here.
394 return get_ad( $id, $atts );
395 }
396
397 /**
398 * Shortcode to include ad from an ad group in frontend
399 *
400 * @param array $atts shortcode attributes.
401 *
402 * @return string ad group content.
403 */
404 public function shortcode_display_ad_group( $atts ) {
405 $atts = is_array( $atts ) ? $atts : [];
406 $id = isset( $atts['id'] ) ? (int) $atts['id'] : 0;
407 $atts = $this->prepare_shortcode_atts( $atts );
408
409 // use the public available function here.
410 return get_ad_group( $id, $atts );
411 }
412
413 /**
414 * Shortcode to display content of an ad placement in frontend
415 *
416 * @param array $atts shortcode attributes.
417 *
418 * @return string ad placement content.
419 */
420 public function shortcode_display_ad_placement( $atts ) {
421 $atts = is_array( $atts ) ? $atts : [];
422 $id = isset( $atts['id'] ) ? (string) $atts['id'] : '';
423 $atts = $this->prepare_shortcode_atts( $atts );
424
425 // use the public available function here.
426 return get_ad_placement( $id, $atts );
427 }
428
429 /**
430 * Prepare shortcode attributes.
431 *
432 * @param array $atts array with strings.
433 *
434 * @return array
435 */
436 private function prepare_shortcode_atts( $atts ) {
437 $result = [];
438
439 /**
440 * Prepare attributes by converting strings to multi-dimensional array
441 * Example: [ 'output__margin__top' => 1 ] => ['output']['margin']['top'] = 1
442 */
443 if ( ! defined( 'ADVANCED_ADS_DISABLE_CHANGE' ) || ! ADVANCED_ADS_DISABLE_CHANGE ) {
444 foreach ( $atts as $attr => $data ) {
445 $levels = explode( '__', $attr );
446 $last = array_pop( $levels );
447
448 $cur_lvl = &$result;
449
450 foreach ( $levels as $lvl ) {
451 if ( ! isset( $cur_lvl[ $lvl ] ) ) {
452 $cur_lvl[ $lvl ] = [];
453 }
454
455 $cur_lvl = &$cur_lvl[ $lvl ];
456 }
457
458 $cur_lvl[ $last ] = $data;
459 }
460
461 $result = array_diff_key(
462 $result,
463 [
464 'id' => false,
465 'blog_id' => false,
466 'ad_args' => false,
467 ]
468 );
469 }
470
471 // Ad type: 'content' and a shortcode inside.
472 if ( isset( $atts['ad_args'] ) ) {
473 $result = array_merge( $result, json_decode( urldecode( $atts['ad_args'] ), true ) );
474
475 }
476
477 return $result;
478 }
479
480 /**
481 * Return plugin options
482 * these are the options updated by the user
483 *
484 * @return array $options
485 */
486 public function options() {
487 // we can’t store options if WPML String Translations is enabled, or it would not translate the "Ad Label" option.
488 if ( ! isset( $this->options ) || class_exists( 'WPML_ST_String' ) ) {
489 $this->options = get_option( ADVADS_SLUG, [] );
490 }
491
492 // allow to change options dynamically
493 $this->options = apply_filters( 'advanced-ads-options', $this->options );
494
495 return $this->options;
496 }
497
498 /**
499 * Update plugin options (not for settings page, but if automatic options are needed)
500 *
501 * @param array $options new options.
502 */
503 public function update_options( array $options ) {
504 // do not allow to clear options.
505 if ( [] === $options ) {
506 return;
507 }
508
509 $this->options = $options;
510 update_option( ADVADS_SLUG, $options );
511 }
512
513 /**
514 * Return internal plugin options
515 * these are options set by the plugin
516 *
517 * @return array $options
518 */
519 public function internal_options() {
520 if ( ! isset( $this->internal_options ) ) {
521 $defaults = [
522 'version' => ADVADS_VERSION,
523 'installed' => time(), // when was this installed.
524 ];
525 $this->internal_options = get_option( ADVADS_SLUG . '-internal', [] );
526
527 // save defaults.
528 if ( [] === $this->internal_options ) {
529 $this->internal_options = $defaults;
530 $this->update_internal_options( $this->internal_options );
531
532 self::get_instance()->create_capabilities();
533 }
534
535 // for versions installed prior to 1.5.3 set installed date for now.
536 if ( ! isset( $this->internal_options['installed'] ) ) {
537 $this->internal_options['installed'] = time();
538 $this->update_internal_options( $this->internal_options );
539 }
540 }
541
542 return $this->internal_options;
543 }
544
545 /**
546 * Update internal plugin options
547 *
548 * @param array $options new internal options.
549 */
550 public function update_internal_options( array $options ) {
551 // do not allow to clear options.
552 if ( [] === $options ) {
553 return;
554 }
555
556 $this->internal_options = $options;
557 update_option( ADVADS_SLUG . '-internal', $options );
558 }
559
560 /**
561 * Get prefix used for frontend elements
562 *
563 * @return string
564 */
565 public function get_frontend_prefix() {
566 if ( isset( $this->frontend_prefix ) ) {
567 return $this->frontend_prefix;
568 }
569
570 $options = $this->options();
571
572 if ( ! isset( $options['front-prefix'] ) ) {
573 if ( isset( $options['id-prefix'] ) ) {
574 // deprecated: keeps widgets working that previously received an id based on the front-prefix.
575 $frontend_prefix = $options['id-prefix'];
576 } else {
577 $frontend_prefix = preg_match( '/[A-Za-z][A-Za-z0-9_]{4}/', parse_url( get_home_url(), PHP_URL_HOST ), $result )
578 ? $result[0] . '-'
579 : self::DEFAULT_FRONTEND_PREFIX;
580 }
581 } else {
582 $frontend_prefix = $options['front-prefix'];
583 }
584 /**
585 * Applying the filter here makes sure that it is the same frontend prefix for all
586 * calls on this page impression
587 *
588 * @param string $frontend_prefix
589 */
590 $this->frontend_prefix = (string) apply_filters( 'advanced-ads-frontend-prefix', $frontend_prefix );
591 $this->frontend_prefix = $this->sanitize_frontend_prefix( $frontend_prefix );
592
593 return $this->frontend_prefix;
594 }
595
596 /**
597 * Sanitize the frontend prefix to result in valid HTML classes.
598 * See https://www.w3.org/TR/selectors-3/#grammar for valid tokens.
599 *
600 * @param string $prefix The HTML class to sanitize.
601 * @param string $fallback The fallback if the class is invalid.
602 *
603 * @return string
604 */
605 public function sanitize_frontend_prefix( $prefix, $fallback = '' ) {
606 $prefix = sanitize_html_class( $prefix );
607 $nonascii = '[^\0-\177]';
608 $unicode = '\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?';
609 $escape = sprintf( '%s|\\[^\n\r\f0-9a-f]', $unicode );
610 $nmstart = sprintf( '[_a-z]|%s|%s', $nonascii, $escape );
611 $nmchar = sprintf( '[_a-z0-9-]|%s|%s', $nonascii, $escape );
612
613 if ( ! preg_match( sprintf( '/-?(?:%s)(?:%s)*/i', $nmstart, $nmchar ), $prefix, $matches ) ) {
614 return $fallback;
615 }
616
617 return $matches[0];
618 }
619
620 /**
621 * Get priority used for injection inside content
622 */
623 public function get_content_injection_priority() {
624 $options = $this->options();
625
626 return isset( $options['content-injection-priority'] ) ? (int) $options['content-injection-priority'] : 100;
627 }
628
629 /**
630 * Returns the capability needed to perform an action
631 *
632 * @param string $capability a capability to check, can be internal to Advanced Ads.
633 *
634 * @return string $capability a valid WordPress capability.
635 */
636 public static function user_cap( $capability = 'manage_options' ) {
637
638 global $advanced_ads_capabilities;
639
640 // admins can do everything.
641 // is also a fallback if no option or more specific capability is given.
642 if ( current_user_can( 'manage_options' ) ) {
643 return 'manage_options';
644 }
645
646 return apply_filters( 'advanced-ads-capability', $capability );
647 }
648
649 /**
650 * Create roles and capabilities
651 */
652 public function create_capabilities() {
653 if ( $role = get_role( 'administrator' ) ) {
654 $role->add_cap( 'advanced_ads_manage_options' );
655 $role->add_cap( 'advanced_ads_see_interface' );
656 $role->add_cap( 'advanced_ads_edit_ads' );
657 $role->add_cap( 'advanced_ads_manage_placements' );
658 $role->add_cap( 'advanced_ads_place_ads' );
659 }
660 }
661
662 /**
663 * Remove roles and capabilities
664 */
665 public function remove_capabilities() {
666 if ( $role = get_role( 'administrator' ) ) {
667 $role->remove_cap( 'advanced_ads_manage_options' );
668 $role->remove_cap( 'advanced_ads_see_interface' );
669 $role->remove_cap( 'advanced_ads_edit_ads' );
670 $role->remove_cap( 'advanced_ads_manage_placements' );
671 $role->remove_cap( 'advanced_ads_place_ads' );
672 }
673 }
674
675 /**
676 * Fired when the plugin is uninstalled.
677 */
678 public static function uninstall() {
679 $advads_options = Advanced_Ads::get_instance()->options();
680
681 if ( ! empty( $advads_options['uninstall-delete-data'] ) ) {
682 global $wpdb;
683 $main_blog_id = $wpdb->blogid;
684
685 // Delete assets (main blog).
686 Advanced_Ads_Ad_Blocker_Admin::get_instance()->clear_assets();
687 Advanced_Ads::get_instance()->create_post_types();
688
689 if ( ! is_multisite() ) {
690 self::get_instance()->uninstall_single();
691 } else {
692 $blog_ids = $wpdb->get_col( "SELECT blog_id FROM {$wpdb->blogs}" );
693
694 foreach ( $blog_ids as $blog_id ) {
695 switch_to_blog( $blog_id );
696 self::get_instance()->uninstall_single();
697 }
698 switch_to_blog( $main_blog_id );
699 }
700
701
702 }
703
704 }
705
706 /**
707 * Fired for each blog when the plugin is uninstalled.
708 */
709 protected function uninstall_single() {
710 global $wpdb;
711
712 // Ads.
713 $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s", Advanced_Ads::POST_TYPE_SLUG ) );
714
715 if ( $post_ids ) {
716 $wpdb->delete(
717 $wpdb->posts,
718 [ 'post_type' => Advanced_Ads::POST_TYPE_SLUG ],
719 [ '%s' ]
720 );
721
722 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE post_id IN( %s )", implode( ',', $post_ids ) ) );
723 }
724
725 // Groups.
726 $term_ids = $wpdb->get_col( $wpdb->prepare( "SELECT t.term_id FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s", Advanced_Ads::AD_GROUP_TAXONOMY ) );
727
728 foreach ( $term_ids as $term_id ) {
729 wp_delete_term( $term_id, Advanced_Ads::AD_GROUP_TAXONOMY );
730 }
731
732 delete_option( 'advanced-ads' );
733 delete_option( 'advanced-ads-internal' );
734 delete_option( 'advanced-ads-notices' );
735 delete_option( 'advads-ad-groups' );
736 delete_option( 'advanced_ads_groups_children' );
737 delete_option( 'advads-ad-weights' );
738 delete_option( 'advanced_ads_ads_txt' );
739 delete_option( 'advanced-ads-ad-health-notices' );
740 delete_option( 'advanced-ads-adsense' );
741 delete_option( 'advanced_ads_adsense_report_domain' );
742 delete_option( 'advanced_ads_adsense_report_unit' );
743 delete_option( 'advanced-ads-adsense-dashboard-filter' );
744 delete_option( 'advanced-ads-adsense-mapi' );
745 delete_option( 'advanced-ads-licenses' );
746 delete_option( 'advanced-ads-ab-module' );
747 delete_option( 'widget_' . Advanced_Ads_Widget::get_base_id() );
748 delete_option( 'advads-ads-placements' );
749
750 // User metadata.
751 delete_metadata( 'user', null, 'advanced-ads-hide-wizard', '', true );
752 delete_metadata( 'user', null, 'advanced-ads-subscribed', '', true );
753 delete_metadata( 'user', null, 'advanced-ads-ad-list-screen-options', '', true );
754 delete_metadata( 'user', null, 'advanced-ads-admin-settings', '', true );
755 delete_metadata( 'user', null, 'advanced-ads-role', '', true );
756 delete_metadata( 'user', null, 'edit_advanced_ads_per_page', '', true );
757 delete_metadata( 'user', null, 'meta-box-order_advanced_ads', '', true );
758 delete_metadata( 'user', null, 'screen_layout_advanced_ads', '', true );
759 delete_metadata( 'user', null, 'closedpostboxes_advanced_ads', '', true );
760 delete_metadata( 'user', null, 'metaboxhidden_advanced_ads', '', true );
761
762 // Post metadata.
763 delete_metadata( 'post', null, '_advads_ad_settings', '', true );
764
765 // Transients.
766 delete_transient( 'advanced-ads_add-on-updates-checked' );
767
768 do_action( 'advanced-ads-uninstall' );
769
770 wp_cache_flush();
771 }
772
773 /**
774 * Check if any add-on is activated
775 *
776 * @return bool true if there is any add-on activated
777 */
778 public static function any_activated_add_on() {
779 return ( defined( 'AAP_VERSION' ) // Advanced Ads Pro.
780 || defined( 'AAGAM_VERSION' ) // Google Ad Manager.
781 || defined( 'AASA_VERSION' ) // Selling Ads.
782 || defined( 'AAT_VERSION' ) // Tracking.
783 || defined( 'AASADS_VERSION' ) // Sticky Ads.
784 || defined( 'AAR_VERSION' ) // Responsive Ads.
785 || defined( 'AAPLDS_VERSION' ) // PopUp and Layer Ads.
786 );
787 }
788
789 /**
790 * Get the correct support URL: wp.org for free users and website for those with any add-on installed
791 *
792 * @param string $utm add UTM parameter to the link leading to https://wpadvancedads.com, if given.
793 *
794 * @return string URL.
795 */
796 public static function support_url( $utm = '' ) {
797
798 $utm = empty( $utm ) ? '?utm_source=advanced-ads&utm_medium=link&utm_campaign=support' : $utm;
799 if ( self::any_activated_add_on() ) {
800 $url = ADVADS_URL . 'support/' . $utm . '-with-addons';
801 } else {
802 $url = ADVADS_URL . 'support/' . $utm . '-free-user';
803 }
804
805 return $url;
806 }
807
808 /**
809 * Create a random group
810 *
811 * @param string $url optional parameter.
812 * @param string $ex group.
813 *
814 * @return bool
815 */
816 public static function get_group_by_url( $url = '', $ex = 'a' ) {
817
818 $url = self::get_short_url( $url );
819
820 $code = (int)substr( md5( $url ), - 1 );
821
822 switch ( $ex ) {
823 case 'b':
824 return ( $code & 2 ) >> 1; // returns 1 or 0.
825 case 'c':
826 return ( $code & 4 ) >> 2; // returns 1 or 0.
827 case 'd':
828 return ( $code & 8 ) >> 3; // returns 1 or 0.
829 default:
830 return $code & 1; // returns 1 or 0.
831 }
832 }
833
834 /**
835 * Check if user started after a given date
836 *
837 * @param integer $timestamp time stamp.
838 *
839 * @return bool true if user is added after timestamp.
840 */
841 public static function is_new_user( $timestamp = 0 ) {
842
843 // allow admins to see version for new users in any case.
844 if ( current_user_can( self::user_cap( 'advanced_ads_manage_options' ) )
845 && isset( $_REQUEST['advads-ignore-timestamp'] ) ) {
846 return true;
847 }
848
849 $timestamp = absint( $timestamp );
850
851 $options = self::get_instance()->internal_options();
852 $installed = isset( $options['installed'] ) ? $options['installed'] : 0;
853
854 return ( $installed >= $timestamp );
855 }
856
857 /**
858 * Show stuff to new users only.
859 *
860 * @param integer $timestamp time after which to show whatever.
861 * @param string $group optional group.
862 *
863 * @return bool true if user enabled after given timestamp.
864 */
865 public static function show_to_new_users( $timestamp, $group = 'a' ) {
866
867 return ( self::get_group_by_url( null, $group ) && self::is_new_user( $timestamp ) );
868 }
869
870 /**
871 * Get short version of home_url()
872 * remove protocol and www
873 * remove slash
874 *
875 * @param string $url URL to be shortened.
876 *
877 * @return string
878 */
879 public static function get_short_url( $url = '' ) {
880
881 $url = empty( $url ) ? home_url() : $url;
882
883 // strip protocols.
884 if ( preg_match( '/^(\w[\w\d]*:\/\/)?(www\.)?(.*)$/', trim( $url ), $matches ) ) {
885 $url = $matches[3];
886 }
887
888 // strip slashes.
889 $url = trim( $url, '/' );
890
891 return $url;
892 }
893
894 /**
895 * Return Advanced Ads logo in base64 format for use in WP Admin menu.
896 *
897 * @return string
898 */
899 public static function get_icon_svg() {
900 return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE4LjEuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJFYmVuZV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgdmlld0JveD0iMCAwIDY0Ljk5MyA2NS4wMjQiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDY0Ljk5MyA2NS4wMjQ7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIHN0eWxlPSJmaWxsOiNFNEU0RTQ7IiBkPSJNNDYuNTcxLDI3LjY0MXYyMy4xMzNIMTQuMjVWMTguNDUzaDIzLjExOGMtMC45NTYtMi4xODMtMS40OTQtNC41OS0xLjQ5NC03LjEyNg0KCWMwLTIuNTM1LDAuNTM4LTQuOTQyLDEuNDk0LTcuMTI0aC02Ljk1N0gwdjQ5LjQ5M2wxLjYxOCwxLjYxOEwwLDUzLjY5NmMwLDYuMjU2LDUuMDY4LDExLjMyNiwxMS4zMjQsMTEuMzI4djBoMTkuMDg3aDMwLjQxMlYyNy42MTENCgljLTIuMTkxLDAuOTY0LTQuNjA5LDEuNTA5LTcuMTU3LDEuNTA5QzUxLjE0MiwyOS4xMiw0OC43NDYsMjguNTg4LDQ2LjU3MSwyNy42NDF6Ii8+DQo8Y2lyY2xlIHN0eWxlPSJmaWxsOiM5ODk4OTg7IiBjeD0iNTMuNjY2IiBjeT0iMTEuMzI4IiByPSIxMS4zMjgiLz4NCjwvc3ZnPg0K';
901 }
902
903 /**
904 * Fires when a post is transitioned from one status to another.
905 *
906 * @param string $new_status New post status.
907 * @param string $old_status Old post status.
908 * @param WP_Post $post Post object.
909 */
910 public function transition_ad_status( $new_status, $old_status, $post ) {
911 if ( ! isset( $post->post_type ) || Advanced_Ads::POST_TYPE_SLUG !== $post->post_type || ! isset( $post->ID ) ) {
912 return;
913 }
914
915 $ad = \Advanced_Ads\Ad_Repository::get( $post->ID );
916
917 if ( $old_status !== $new_status ) {
918 /**
919 * Fires when an ad has transitioned from one status to another.
920 *
921 * @param Advanced_Ads_Ad $ad Ad object.
922 */
923 do_action( "advanced-ads-ad-status-{$old_status}-to-{$new_status}", $ad );
924 }
925
926 if ( 'publish' === $new_status && 'publish' !== $old_status ) {
927 /**
928 * Fires when an ad has transitioned from any other status to `publish`.
929 *
930 * @param Advanced_Ads_Ad $ad Ad object.
931 */
932 do_action( 'advanced-ads-ad-status-published', $ad );
933 }
934
935 if ( 'publish' === $old_status && 'publish' !== $new_status ) {
936 /**
937 * Fires when an ad has transitioned from `publish` to any other status.
938 *
939 * @param Advanced_Ads_Ad $ad Ad object.
940 */
941 do_action( 'advanced-ads-ad-status-unpublished', $ad );
942 }
943
944 if ( $old_status === 'publish' && $new_status === Advanced_Ads_Ad_Expiration::POST_STATUS ) {
945 /**
946 * Fires when an ad is expired.
947 *
948 * @param int $id
949 * @param Advanced_Ads_Ad $ad
950 */
951 do_action( 'advanced-ads-ad-expired', $ad->id, $ad );
952 }
953 }
954
955 }
956