PluginProbe
Advanced Ads – Ad Manager & AdSense / 2.0.22
Advanced Ads – Ad Manager & AdSense v2.0.22
2.0.26 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 All 348 releases
advanced-ads / includes / compatibility / class-compatibility.php
class-compatibility.php
307 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Compatibility Compatibility.
4 *
5 * @package AdvancedAds
6 * @author Advanced Ads <info@wpadvancedads.com>
7 * @since 1.48.2
8 */
9
10 namespace AdvancedAds\Compatibility;
11
12 use Exception;
13 use ReflectionClass;
14 use AdvancedAds\Utilities\Data;
15 use AdvancedAds\Framework\Utilities\Str;
16 use AdvancedAds\Framework\Interfaces\Integration_Interface;
17
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * Compatibility Compatibility.
22 */
23 class Compatibility implements Integration_Interface {
24
25 /**
26 * Hook into WordPress.
27 *
28 * @return void
29 */
30 public function hooks(): void {
31 if ( is_admin() ) {
32 ( new Admin_Compatibility() )->hooks();
33 }
34
35 add_filter( 'wpseo_sitemap_entry', [ $this, 'wpseo_noindex_ad_attachments' ], 10, 3 );
36 add_filter( 'mailpoet_newsletter_shortcode', [ $this, 'mailpoet_ad_shortcode' ] );
37 if ( defined( 'ELEMENTOR_VERSION' ) ) {
38 add_filter( 'advanced-ads-placement-content-injection-xpath', [ $this, 'elementor_content_injection' ] );
39 }
40 if ( defined( 'BORLABS_COOKIE_VERSION' ) ) {
41 add_filter( 'advanced-ads-can-display-ads-in-header', [ $this, 'borlabs_cookie_can_add_auto_ads' ], 10 );
42 }
43 if ( defined( 'AIOVG_PLUGIN_VERSION' ) ) {
44 add_filter( 'advanced-ads-ad-select-args', [ $this, 'aiovg_modify_ad_select_args' ], 10 );
45 }
46 }
47
48 /**
49 * WordPress SEO: remove attachments attached to ads from `/attachment-sitemap.xml`.
50 *
51 * @param array $url Array of URL parts.
52 * @param string $type URL type.
53 * @param object $post WP_Post object of attachment.
54 *
55 * @return array|bool Unmodified array of URL parts or false to remove URL.
56 */
57 public function wpseo_noindex_ad_attachments( $url, $type, $post ) {
58 if ( 'post' !== $type ) {
59 return $url;
60 }
61
62 $ad_ids = Data::get_ads_ids();
63
64 if ( isset( $post->post_parent ) && in_array( $post->post_parent, $ad_ids, true ) ) {
65 return false;
66 }
67
68 return $url;
69 }
70
71 /**
72 * Display an ad or ad group in a newsletter created by MailPoet.
73 *
74 * Usage:
75 * [custom:ad:123] to display ad with the ID 123
76 * [custom:ad_group:345] to display ad group with the ID 345
77 *
78 * @param string $shortcode Shortcode that placed the ad.
79 *
80 * @return string
81 */
82 public function mailpoet_ad_shortcode( $shortcode ): string {
83 // Display an ad group.
84 if ( sscanf( $shortcode, '[custom:ad_group:%d]', $id ) === 1 ) {
85 $ad_group = wp_advads_get_group( $id );
86
87 return ( $ad_group && $ad_group->is_type( [ 'default', 'ordered' ] ) )
88 ? get_the_group( $ad_group )
89 : '';
90 }
91
92 // Display individual ad.
93 if ( sscanf( $shortcode, '[custom:ad:%d]', $id ) === 1 ) {
94 $ad = wp_advads_get_ad( $id );
95
96 if ( $ad && $ad->is_type( [ 'plain', 'image' ] ) ) {
97 $ad_content = get_the_ad( $ad );
98 // Add responsive styles for email compatibility.
99 if ( $ad->is_type( 'image' ) ) {
100 return str_replace(
101 '<img',
102 '<img style="max-width: 100%; height: auto; display: block;"',
103 $ad_content
104 );
105 }
106 return $ad_content;
107 }
108
109 return '';
110 }
111
112 return $shortcode;
113 }
114
115 /**
116 * Modify xPath expression for Elementor plugin.
117 * The plugin does not wrap newly created text in 'p' tags.
118 *
119 * @param string $tag Xpath tag.
120 *
121 * @return string
122 */
123 public function elementor_content_injection( $tag ): string {
124 // 'p' or 'div.elementor-widget-text-editor' without nested 'p'
125 if ( 'p' === $tag ) {
126 $tag = "*[self::p or self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' elementor-widget-text-editor ') and not(descendant::p)]]";
127 }
128
129 return $tag;
130 }
131
132 /**
133 * Check if Adsense Auto ads code can be added to the header.
134 *
135 * @param bool $can_display If the ad can be displayed.
136 *
137 * @return bool
138 */
139 public function borlabs_cookie_can_add_auto_ads( $can_display ): bool {
140 if ( ! $can_display ) {
141 return false;
142 }
143
144 return ! self::borlabs_cookie_adsense_auto_ads_code_exists();
145 }
146
147 /**
148 * Thrive Theme Builder Check if placements of type other than `header` can be injected during `wp_head` action.
149 */
150 public static function can_inject_during_wp_head() {
151 if ( did_action( 'before_theme_builder_template_render' ) && ! did_action( 'after_theme_builder_template_render' ) ) {
152 return true;
153 }
154
155 return false;
156 }
157
158 /**
159 * Check if Adsense Auto ads code is added by the Borlabs Cookie plugin.
160 *
161 * This allows to prevent the "Only one 'enable_page_level_ads' allowed per page" error
162 * that makes impossible to close the "Privacy Preference" window created by the "Borlabs Cookie" plugin.
163 *
164 * @return bool
165 */
166 public static function borlabs_cookie_adsense_auto_ads_code_exists(): bool {
167 static $result = null;
168
169 if ( null !== $result ) {
170 return $result;
171 }
172
173 $all_cookies = self::borlabs_get_cookies();
174 if ( empty( $all_cookies ) ) {
175 $result = false;
176 return $result;
177 }
178
179 foreach ( $all_cookies as $cookie_group_data ) {
180 if ( self::is_marketing_cookie( $cookie_group_data ) ) {
181 foreach ( $cookie_group_data->cookies as $cookie_data ) {
182 if ( self::is_adsense_cookie( $cookie_data ) ) {
183 $opt_in_js = $cookie_data->opt_in_js;
184 }
185 }
186 }
187 }
188
189 if ( empty( $opt_in_js ) ) {
190 $result = false;
191 return $result;
192 }
193
194 $result = preg_match( '/<script[^>]+data-ad-client/', $opt_in_js ) || false !== strpos( $opt_in_js, 'enable_page_level_ads:' );
195 return $result;
196 }
197
198 /**
199 * Get cookies from borlabs plugin
200 *
201 * @return bool|array
202 */
203 private static function borlabs_get_cookies() {
204 // Early bail!!
205 if ( ! class_exists( '\BorlabsCookie\Cookie\Frontend\Cookies' ) ) {
206 return false;
207 }
208
209 $all_cookies = [];
210
211 try {
212 $refl_cookies = new ReflectionClass( '\BorlabsCookie\Cookie\Frontend\Cookies' );
213
214 if ( $refl_cookies->hasMethod( 'getInstance' ) && $refl_cookies->hasMethod( 'getAllCookieGroups' ) ) {
215 $instance = $refl_cookies->getMethod( 'getInstance' );
216 $cookie_groups = $refl_cookies->getMethod( 'getAllCookieGroups' );
217
218 if ( $instance->isPublic() && $instance->isStatic() && $cookie_groups->isPublic() ) {
219 $all_cookies = \BorlabsCookie\Cookie\Frontend\Cookies::getInstance()->getAllCookieGroups();
220 }
221 }
222 } catch ( Exception $e ) {
223 return false;
224 }
225
226 return $all_cookies;
227 }
228
229 /**
230 * Is cookie is of marketing and has data
231 *
232 * @param mixed $cookie Cookie to check.
233 *
234 * @return bool
235 */
236 private static function is_marketing_cookie( $cookie ): bool {
237 if (
238 ! empty( $cookie->group_id ) &&
239 'marketing' === $cookie->group_id &&
240 ! empty( $cookie->cookies )
241 ) {
242 return true;
243 }
244
245 return false;
246 }
247
248 /**
249 * Is cookie is of marketing and has data
250 *
251 * @param mixed $cookie Cookie to check.
252 *
253 * @return bool
254 */
255 private static function is_adsense_cookie( $cookie ): bool {
256 if (
257 ! empty( $cookie->cookie_id ) &&
258 'google-adsense' === $cookie->cookie_id &&
259 ! empty( $cookie->opt_in_js )
260 ) {
261 return true;
262 }
263
264 return false;
265 }
266
267 /**
268 * Modify ad select arguments to treat AIOVG shortcode pages as native taxonomy archives.
269 *
270 * @param array<string, mixed> $args Current ad selection arguments.
271 *
272 * @return array<string, mixed> Modified ad selection arguments.
273 */
274 public function aiovg_modify_ad_select_args( array $args ): array {
275 $aiovg_taxs = [
276 'aiovg_categories' => 'aiovg_category',
277 'aiovg_tags' => 'aiovg_tag',
278 ];
279
280 foreach ( $aiovg_taxs as $aiovg_tax => $aiovg_query_var ) {
281 if ( taxonomy_exists( $aiovg_tax ) ) {
282 $aiovg_slug = get_query_var( $aiovg_query_var );
283
284 if ( ! empty( $aiovg_slug ) && is_scalar( $aiovg_slug ) ) {
285 $aiovg_term = get_term_by( 'slug', (string) $aiovg_slug, $aiovg_tax );
286
287 if ( $aiovg_term instanceof \WP_Term ) {
288 if ( ! isset( $args['wp_the_query'] ) || ! is_array( $args['wp_the_query'] ) ) {
289 $args['wp_the_query'] = [];
290 }
291
292 // Override the standard page parameters so Advanced Ads treats it as an archive.
293 $args['wp_the_query']['term_id'] = $aiovg_term->term_id;
294 $args['wp_the_query']['taxonomy'] = $aiovg_tax;
295 $args['wp_the_query']['is_archive'] = true;
296 $args['wp_the_query']['is_singular'] = false;
297
298 break;
299 }
300 }
301 }
302 }
303
304 return $args;
305 }
306 }
307