PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.47.1
Advanced Ads – Ad Manager & AdSense v1.47.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 / compatibility.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 2 years ago ad-debug.php 2 years ago ad-expiration.php 3 years ago ad-health-notices.php 2 years ago ad-model.php 2 years ago ad-select.php 3 years ago ad.php 2 years ago ad_ajax_callbacks.php 2 years ago ad_group.php 2 years ago ad_placements.php 2 years ago ad_type_abstract.php 2 years ago ad_type_content.php 2 years ago ad_type_dummy.php 2 years ago ad_type_group.php 2 years ago ad_type_image.php 2 years ago ad_type_plain.php 2 years ago checks.php 2 years ago class-translation-promo.php 2 years ago compatibility.php 2 years ago display-conditions.php 2 years ago filesystem.php 3 years ago frontend_checks.php 2 years ago in-content-injector.php 2 years ago inline-css.php 2 years ago plugin.php 2 years ago upgrades.php 2 years ago utils.php 3 years ago visitor-conditions.php 2 years ago widget.php 2 years ago
compatibility.php
394 lines
1 <?php
2 // phpcs:ignoreFile
3
4 use AdvancedAds\Entities;
5 use AdvancedAds\Utilities\Conditional;
6
7 /**
8 * Compatibility fixes with other plugins.
9 */
10 class Advanced_Ads_Compatibility {
11 /**
12 * Array that holds strings that should not be optimized by other plugins.
13 *
14 * @var array
15 */
16 private $critical_inline_js;
17
18 /**
19 * Advanced_Ads_Compatibility constructor.
20 */
21 public function __construct() {
22 // Elementor plugin.
23 if ( defined( 'ELEMENTOR_VERSION' ) ) {
24 add_filter(
25 'advanced-ads-placement-content-injection-xpath',
26 [
27 $this,
28 'content_injection_elementor',
29 ],
30 10,
31 1
32 );
33 }
34 // WP Rocket
35 add_filter( 'rocket_excluded_inline_js_content', [ $this, 'rocket_exclude_inline_js' ] );
36 add_filter( 'rocket_delay_js_exclusions', [ $this, 'rocket_exclude_inline_js' ] );
37 // WPML.
38 add_filter( 'wpml_admin_language_switcher_active_languages', [ $this, 'wpml_language_switcher' ] );
39 // WordPress SEO by Yoast.
40 add_filter( 'wpseo_sitemap_entry', [ $this, 'wordpress_seo_noindex_ad_attachments' ], 10, 3 );
41 // Add shortcode for MailPoet.
42 add_filter( 'mailpoet_newsletter_shortcode', [ 'Advanced_Ads_Compatibility', 'mailpoet_ad_shortcode' ], 10, 5 );
43
44 // Enable Advanced Custom Fields on ad edit pages.
45 if ( class_exists( 'ACF', false ) ) {
46 add_filter( 'advanced-ads-ad-edit-allowed-metaboxes', [ $this, 'advanced_custom_fields_box' ] );
47 }
48
49 add_action( 'admin_enqueue_scripts', [ $this, 'admin_dequeue_scripts_and_styles' ], 100 );
50
51 if ( defined( 'BORLABS_COOKIE_VERSION' ) ) {
52 // Check if Verification code & Auto ads ads can be displayed.
53 add_filter( 'advanced-ads-can-display-ads-in-header', [ $this, 'borlabs_cookie_can_add_auto_ads_code' ], 10 );
54 }
55
56 // Make sure inline JS in head is executed when Complianz is set to block JS.
57 $complianz_version = get_option( 'cmplz-current-version', false );
58 // if complianz version equal or greater then 6.0.0 use cmplz_service_category
59 if ( $complianz_version && version_compare( $complianz_version, '6.0.0', '>=' ) ) {
60 add_filter( 'cmplz_service_category', [ $this, 'complianz_exclude_inline_js' ], 10, 2 );
61 } else {
62 // if complianz version less then 6.0.0 use cmplz_script_class
63 add_filter( 'cmplz_script_class', [ $this, 'complianz_exclude_inline_js' ], 10, 2 );
64 }
65
66 $this->critical_inline_js = $this->critical_inline_js();
67 }
68
69 /**
70 * Modify xPath expression for Elementor plugin.
71 * The plugin does not wrap newly created text in 'p' tags.
72 *
73 * @param string $tag xpath tag.
74 * @return string xPath expression
75 */
76 public function content_injection_elementor( $tag ) {
77 if ( 'p' === $tag ) {
78 // 'p' or 'div.elementor-widget-text-editor' without nested 'p'
79 $tag = "*[self::p or self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' elementor-widget-text-editor ') and not(descendant::p)]]";
80 }
81
82 return $tag;
83 }
84
85 /**
86 * Prevent the 'advanced_ads_ready' function declaration from being merged with other JS
87 * and outputted into the footer. This is needed because WP Rocket does not output all
88 * the code that depends on this function into the footer.
89 *
90 * @param array $exclusions Patterns to match in inline JS content.
91 *
92 * @return array
93 */
94 public function rocket_exclude_inline_js( $exclusions ) {
95 return array_merge( $exclusions, $this->critical_inline_js );
96 }
97
98 /**
99 * Prevent Complianz from suppressing our head inline script.
100 *
101 * @param string $class the class Complianz adds to the script, `cmplz-script` for prevented scripts, `cmplz-native` for allowed.
102 * @param string $total_match the script string.
103 *
104 * @return string
105 */
106 public function complianz_exclude_inline_js( $class, $total_match ) {
107 if ( $class === 'cmplz-native' ) {
108 return $class;
109 }
110 foreach ( $this->critical_inline_js as $critical_inline_js ) {
111 if ( strpos( $total_match, $critical_inline_js ) !== false ) {
112 return 'cmplz-native';
113 }
114 }
115
116 return $class;
117 }
118
119 /**
120 * Compatibility with WPML
121 * show only all languages in language switcher on Advanced Ads pages if ads and groups are translated
122 *
123 * @param array $active_languages languages that can be used in language switcher.
124 * @return array
125 */
126 public function wpml_language_switcher( $active_languages ) {
127 global $sitepress;
128 $screen = get_current_screen();
129 if ( ! isset( $screen->id ) ) {
130 return $active_languages;
131 }
132
133 switch ( $screen->id ) {
134 // check if we are on a group edit page and ad group translations are disabled.
135 case 'advanced-ads_page_advanced-ads-groups':
136 $translatable_taxonomies = $sitepress->get_translatable_taxonomies();
137 if ( ! is_array( $translatable_taxonomies ) || ! in_array( 'advanced_ads_groups', $translatable_taxonomies, true ) ) {
138 return [];
139 }
140 break;
141 // check if Advanced Ads ad post type is translatable.
142 case 'edit-advanced_ads': // overview page.
143 case 'advanced_ads': // edit page.
144 $translatable_documents = $sitepress->get_translatable_documents();
145 if ( empty( $translatable_documents['advanced_ads'] ) ) {
146 return [];
147 }
148 break;
149 }
150
151 return $active_languages;
152 }
153
154 /**
155 * WordPress SEO: remove attachments attached to ads from `/attachment-sitemap.xml`.
156 *
157 * @param array $url Array of URL parts.
158 * @param string $type URL type.
159 * @param object $post WP_Post object of attachment.
160 * @return array|bool Unmodified array of URL parts or false to remove URL.
161 */
162 public function wordpress_seo_noindex_ad_attachments( $url, $type, $post ) {
163 if ( 'post' !== $type ) {
164 return $url;
165 }
166
167 static $ad_ids = null;
168 if ( null === $ad_ids ) {
169 $ad_ids = Advanced_Ads::get_instance()->get_model()->get_ads(
170 [
171 'post_status' => 'any',
172 'fields' => 'ids',
173 ]
174 );
175 }
176
177 if ( isset( $post->post_parent ) && in_array( $post->post_parent, $ad_ids, true ) ) {
178 return false;
179 }
180
181 return $url;
182 }
183
184 /**
185 * Display an ad or ad group in a newsletter created by MailPoet.
186 * e.g., [custom:ad:123] to display ad with the ID 123
187 * [custom:ad_group:345] to display ad group with the ID 345
188 *
189 * @param string $shortcode shortcode that placed the ad.
190 * @param mixed $newsletter unused.
191 * @param mixed $subscriber unused.
192 * @param mixed $queue unused.
193 * @param string $newsletter_body unused.
194 *
195 * @return string
196 */
197 public static function mailpoet_ad_shortcode( $shortcode, $newsletter, $subscriber, $queue, $newsletter_body ) {
198
199 // display an ad group.
200 if ( 0 === strpos( $shortcode, '[custom:ad_group:' ) ) {
201 // get ad group ID.
202 preg_match( '/\d+/', $shortcode, $matches );
203 $group_id = $matches[0];
204
205 // is returning an empty string when the ad group is not found good UI?
206 if ( empty( $group_id ) ) {
207 return '';
208 }
209
210 // only display if the ad group type could work, i.e. default (random) and ordered.
211 $ad_group = new Advanced_Ads_Group( $group_id );
212 if ( isset( $ad_group->type ) && in_array( $ad_group->type, [ 'default', 'ordered' ], true ) ) {
213 return get_ad_group( $group_id );
214 }
215
216 return '';
217
218 // display individual ad.
219 } elseif ( 0 === strpos( $shortcode, '[custom:ad:' ) ) {
220 // get ad ID.
221 preg_match( '/\d+/', $shortcode, $matches );
222 $ad_id = $matches[0];
223
224 // is returning an empty string when the ad is not found good UI?
225 if ( empty( $ad_id ) ) {
226 return '';
227 }
228
229 $ad = \Advanced_Ads\Ad_Repository::get( $ad_id );
230 // only display if the ad type could work, i.e. plain text and image ads.
231 if ( isset( $ad->type ) && in_array( $ad->type, [ 'plain', 'image' ], true ) ) {
232 return get_ad( $ad_id );
233 }
234
235 return '';
236 } else {
237 // always return the shortcode if it doesn't match your own!
238 return $shortcode;
239 }
240 }
241
242 /**
243 * Check if placements of type other than `header` can be injected during `wp_head` action.
244 */
245 public static function can_inject_during_wp_head() {
246 // the "Thrive Theme Builder" theme.
247 if ( did_action( 'before_theme_builder_template_render' ) && ! did_action( 'after_theme_builder_template_render' ) ) {
248 return true;
249 }
250 return false;
251 }
252
253 /**
254 * Dequeue scripts and styles to prevent layout issues.
255 */
256 public function admin_dequeue_scripts_and_styles() {
257 if ( ! Conditional::is_screen_advanced_ads() ) {
258 return;
259 }
260
261 // Dequeue the css file enqueued by the JNews theme.
262 if ( defined( 'JNEWS_THEME_URL' ) ) {
263 wp_dequeue_style( 'jnews-admin' );
264 }
265 }
266
267 /**
268 * Check if Adsense Auto ads code can be added to the header.
269 *
270 * @param bool $can_display if the ad can already be displayed.
271 * @return bool
272 */
273 public function borlabs_cookie_can_add_auto_ads_code( $can_display ) {
274 if ( ! $can_display ) {
275 return false;
276 }
277
278 return ! self::borlabs_cookie_adsense_auto_ads_code_exists();
279 }
280
281 /**
282 * Check if Adsense Auto ads code is added by the Borlabs Cookie plugin.
283 *
284 * This allows to prevent the "Only one 'enable_page_level_ads' allowed per page" error
285 * that makes impossible to close the "Privacy Preference" window created by the "Borlabs Cookie" plugin.
286 *
287 * @return bool
288 */
289 public static function borlabs_cookie_adsense_auto_ads_code_exists() {
290 // Cache the result in order to perform the check only once.
291 static $result = null;
292
293 if ( null !== $result ) {
294 return $result;
295 }
296
297 // Set the `autoload` param to `true` so that the class loads both in frontend and backend.
298 if ( class_exists( '\BorlabsCookie\Cookie\Frontend\Cookies', true ) ) {
299 try {
300 $refl_cookies = new ReflectionClass( '\BorlabsCookie\Cookie\Frontend\Cookies' );
301
302 if ( $refl_cookies->hasMethod( 'getInstance' ) && $refl_cookies->hasMethod( 'getAllCookieGroups' ) ) {
303 $instance = $refl_cookies->getMethod( 'getInstance' );
304 $cookie_groups = $refl_cookies->getMethod( 'getAllCookieGroups' );
305
306 if ( $instance->isPublic() && $instance->isStatic() && $cookie_groups->isPublic() ) {
307 $all_cookies = BorlabsCookie\Cookie\Frontend\Cookies::getInstance()->getAllCookieGroups();
308 }
309 }
310 } catch ( Exception $e ) {
311 $result = false;
312 return $result;
313 }
314 }
315
316 if ( empty( $all_cookies ) ) {
317 $result = false;
318 return $result;
319 }
320
321 foreach ( $all_cookies as $cookie_group_data ) {
322 if ( ! empty( $cookie_group_data->group_id ) && 'marketing' === $cookie_group_data->group_id
323 && ! empty( $cookie_group_data->cookies ) ) {
324 foreach ( $cookie_group_data->cookies as $cookie_data ) {
325 if ( ! empty( $cookie_data->cookie_id ) && 'google-adsense' === $cookie_data->cookie_id
326 && ! empty( $cookie_data->opt_in_js ) ) {
327 $opt_in_js = $cookie_data->opt_in_js;
328 }
329 }
330 }
331 }
332
333 if ( empty( $opt_in_js ) ) {
334 $result = false;
335 return $result;
336 }
337
338 $result = preg_match( '/<script[^>]+data-ad-client/', $opt_in_js ) || false !== strpos( $opt_in_js, 'enable_page_level_ads:' );
339 return $result;
340 }
341
342 /**
343 * Whitelist meta boxes created by the Advanced Custom Fields plugin on the ad edit pages
344 * when they are dedicated for the "Ad" post type.
345 *
346 * @param array $meta_boxes already whitelisted meta boxes.
347 * @return array
348 */
349 public function advanced_custom_fields_box( $meta_boxes ) {
350
351 // fixes an issue reported when ACF class exists, but this function does not
352 if ( ! function_exists( 'acf_get_field_groups' ) ) {
353 return $meta_boxes;
354 }
355
356 // load ACF field groups dedicated to the Advanced Ads post type
357 $groups = acf_get_field_groups( [ 'post_type' => Entities::POST_TYPE_AD ] );
358
359 if ( is_array( $groups ) && $groups ) {
360 foreach ( $groups as $_group ) {
361 if ( isset( $_group['key'] ) ) {
362 $meta_boxes[] = 'acf-' . $_group['key'];
363 }
364 }
365 }
366
367 return $meta_boxes;
368 }
369
370 /**
371 * Get an array of strings to exclude when plugins "optimize" JS.
372 *
373 * @return array
374 */
375 private function critical_inline_js() {
376 $frontend_prefix = Advanced_Ads_Plugin::get_instance()->get_frontend_prefix();
377 $default = [
378 sprintf( 'id="%sready"', $frontend_prefix ),
379 ];
380 /**
381 * Filters an array of strings of (inline) JavaScript "identifiers" that should not be "optimized"/delayed etc.
382 *
383 * @param array $default Array of excluded patterns.
384 */
385 $exclusions = apply_filters( 'advanced-ads-compatibility-critical-inline-js', $default, $frontend_prefix );
386
387 if ( ! is_array( $exclusions ) ) {
388 $exclusions = $default;
389 }
390
391 return $exclusions;
392 }
393 }
394