PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 12.3.2
Jetpack – WP Security, Backup, Speed, & Growth v12.3.2
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / wordads / class-wordads.php
jetpack / modules / wordads Last commit date
css 5 years ago js 3 years ago php 3 years ago class-wordads.php 3 years ago
class-wordads.php
871 lines
1 <?php
2 /**
3 * Main WordAds file.
4 *
5 * @package automattic/jetpack
6 */
7
8 use Automattic\Jetpack\Status\Host;
9
10 define( 'WORDADS_ROOT', __DIR__ );
11 define( 'WORDADS_BASENAME', plugin_basename( __FILE__ ) );
12 define( 'WORDADS_FILE_PATH', WORDADS_ROOT . '/' . basename( __FILE__ ) );
13 define( 'WORDADS_URL', plugins_url( '/', __FILE__ ) );
14 define( 'WORDADS_API_TEST_ID', '26942' );
15 define( 'WORDADS_API_TEST_ID2', '114160' );
16
17 require_once WORDADS_ROOT . '/php/class-wordads-sidebar-widget.php';
18 require_once WORDADS_ROOT . '/php/class-wordads-api.php';
19 require_once WORDADS_ROOT . '/php/class-wordads-cron.php';
20 require_once WORDADS_ROOT . '/php/class-wordads-california-privacy.php';
21 require_once WORDADS_ROOT . '/php/class-wordads-ccpa-do-not-sell-link-widget.php';
22
23 /**
24 * Primary WordAds class.
25 */
26 class WordAds {
27
28 /**
29 * Ads parameters.
30 *
31 * @var null
32 */
33 public $params = null;
34
35 /**
36 * Ads.
37 *
38 * @var array
39 */
40 public $ads = array();
41
42 /**
43 * Array of supported ad types.
44 *
45 * @var array
46 */
47 public static $ad_tag_ids = array(
48 'mrec' => array(
49 'tag' => '300x250_mediumrectangle',
50 'height' => '250',
51 'width' => '300',
52 ),
53 'leaderboard' => array(
54 'tag' => '728x90_leaderboard',
55 'height' => '90',
56 'width' => '728',
57 ),
58 'mobile_leaderboard' => array(
59 'tag' => '320x50_mobileleaderboard',
60 'height' => '50',
61 'width' => '320',
62 ),
63 'wideskyscraper' => array(
64 'tag' => '160x600_wideskyscraper',
65 'height' => '600',
66 'width' => '160',
67 ),
68 );
69
70 /**
71 * Mapping array of location slugs to placement ids
72 *
73 * @var array
74 */
75 public static $ad_location_ids = array(
76 'top' => 110,
77 'belowpost' => 120,
78 'belowpost2' => 130,
79 'sidebar' => 140,
80 'widget' => 150,
81 'gutenberg' => 200,
82 'inline' => 310,
83 'inline-plugin' => 320,
84 );
85
86 /**
87 * Mapping array of form factor slugs to form factor ids
88 *
89 * @var array
90 */
91 public static $form_factor_ids = array(
92 'square' => '001', // 250x250
93 'leaderboard' => '002', // 728x90
94 'skyscraper' => '003', // 120x600
95 );
96
97 /**
98 * Counter to enable unique, sequential section IDs for all amp-ad units
99 *
100 * @var int
101 */
102 public static $amp_section_id = 1;
103
104 /**
105 * Solo unit CSS string.
106 *
107 * @var string
108 */
109 public static $solo_unit_css = 'float:left;margin-right:5px;margin-top:0px;';
110
111 /**
112 * Checks for AMP support and returns true iff active & AMP request
113 *
114 * @return boolean True if supported AMP request
115 *
116 * @since 7.5.0
117 */
118 public static function is_amp() {
119 return class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request();
120 }
121
122 /**
123 * Increment the AMP section ID and return the value
124 *
125 * @return int
126 */
127 public static function get_amp_section_id() {
128 return self::$amp_section_id++;
129 }
130
131 /**
132 * Convenience function for grabbing options from params->options
133 *
134 * @param string $option the option to grab.
135 * @param mixed $default (optional).
136 * @return option or $default if not set
137 *
138 * @since 4.5.0
139 */
140 public function option( $option, $default = false ) {
141 if ( ! isset( $this->params->options[ $option ] ) ) {
142 return $default;
143 }
144
145 return $this->params->options[ $option ];
146 }
147
148 /**
149 * Returns the ad tag property array for supported ad types.
150 *
151 * @return array array with ad tags
152 *
153 * @since 7.1.0
154 */
155 public function get_ad_tags() {
156 return self::$ad_tag_ids;
157 }
158
159 /**
160 * Returns the solo css for unit
161 *
162 * @return string the special css for solo units
163 *
164 * @since 7.1.0
165 */
166 public function get_solo_unit_css() {
167 return self::$solo_unit_css;
168 }
169
170 /**
171 * Instantiate the plugin
172 *
173 * @since 4.5.0
174 */
175 public function __construct() {
176 add_action( 'wp', array( $this, 'init' ) );
177 add_action( 'rest_api_init', array( $this, 'init' ) );
178 add_action( 'widgets_init', array( $this, 'widget_callback' ) );
179
180 if ( is_admin() ) {
181 WordAds_California_Privacy::init_ajax_actions();
182 }
183 }
184
185 /**
186 * Code to run on WordPress 'init' hook
187 *
188 * @since 4.5.0
189 */
190 public function init() {
191 require_once WORDADS_ROOT . '/php/class-wordads-params.php';
192 $this->params = new WordAds_Params();
193
194 if ( $this->should_bail() || self::is_infinite_scroll() ) {
195 return;
196 }
197
198 if ( is_admin() ) {
199 require_once WORDADS_ROOT . '/php/class-wordads-admin.php';
200 return;
201 }
202
203 $this->insert_adcode();
204
205 // Include California Privacy Act related features if enabled.
206 if ( $this->params->options['wordads_ccpa_enabled'] ) {
207 WordAds_California_Privacy::init();
208 }
209
210 if ( isset( $_SERVER['REQUEST_URI'] ) && '/ads.txt' === $_SERVER['REQUEST_URI'] ) {
211
212 $ads_txt_transient = get_transient( 'wordads_ads_txt' );
213
214 if ( false === ( $ads_txt_transient ) ) {
215 $wordads_ads_txt = WordAds_API::get_wordads_ads_txt();
216 $ads_txt_transient = is_wp_error( $wordads_ads_txt ) ? '' : $wordads_ads_txt;
217 set_transient( 'wordads_ads_txt', $ads_txt_transient, DAY_IN_SECONDS );
218 }
219
220 /**
221 * Provide plugins a way of modifying the contents of the automatically-generated ads.txt file.
222 *
223 * @module wordads
224 *
225 * @since 6.1.0
226 *
227 * @param string WordAds_API::get_wordads_ads_txt() The contents of the ads.txt file.
228 */
229 $ads_txt_content = apply_filters( 'wordads_ads_txt', $ads_txt_transient );
230
231 http_response_code( 200 );
232 header( 'Content-Type: text/plain; charset=utf-8' );
233 echo esc_html( $ads_txt_content );
234 die();
235 }
236 }
237
238 /**
239 * Check for Jetpack's The_Neverending_Home_Page and use got_infinity
240 *
241 * @return boolean true if load came from infinite scroll
242 *
243 * @since 4.5.0
244 */
245 public static function is_infinite_scroll() {
246 return class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::got_infinity();
247 }
248
249 /**
250 * Add the actions/filters to insert the ads. Checks for mobile or desktop.
251 *
252 * @since 4.5.0
253 */
254 private function insert_adcode() {
255 add_filter( 'wp_resource_hints', array( $this, 'resource_hints' ), 10, 2 );
256 add_action( 'wp_head', array( $this, 'insert_head_meta' ), 20 );
257 add_action( 'wp_head', array( $this, 'insert_head_iponweb' ), 30 );
258 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
259 add_filter( 'wordads_ads_txt', array( $this, 'insert_custom_adstxt' ) );
260
261 /**
262 * Filters enabling ads in `the_content` filter
263 *
264 * @see https://jetpack.com/support/ads/
265 *
266 * @module wordads
267 *
268 * @since 5.8.0
269 *
270 * @param bool True to disable ads in `the_content`
271 */
272 if ( ! apply_filters( 'wordads_content_disable', false ) ) {
273 add_filter( 'the_content', array( $this, 'insert_ad' ) );
274 }
275
276 /**
277 * Filters enabling ads in `the_excerpt` filter
278 *
279 * @see https://jetpack.com/support/ads/
280 *
281 * @module wordads
282 *
283 * @since 5.8.0
284 *
285 * @param bool True to disable ads in `the_excerpt`
286 */
287 if ( ! apply_filters( 'wordads_excerpt_disable', false ) ) {
288 add_filter( 'the_excerpt', array( $this, 'insert_ad' ) );
289 }
290
291 if ( $this->option( 'enable_header_ad', true ) ) {
292 if ( self::is_amp() ) {
293 add_filter( 'the_content', array( $this, 'insert_header_ad_amp' ) );
294 } else {
295 add_action( 'wordads_header_ad', array( $this, 'insert_header_ad' ), 100 );
296 add_action( 'wp_footer', array( $this, 'insert_header_ad' ), 100 );
297 }
298 }
299 }
300
301 /**
302 * Register desktop scripts and styles
303 *
304 * @since 4.5.0
305 */
306 public function enqueue_scripts() {
307 wp_enqueue_style(
308 'wordads',
309 WORDADS_URL . 'css/style.css',
310 array(),
311 '2015-12-18'
312 );
313 }
314
315 /**
316 * Add the IPW resource hints
317 *
318 * @since 7.9
319 *
320 * @param array $hints Domains for hinting.
321 * @param string $relation_type Resource type.
322 *
323 * @return array Domains for hinting.
324 */
325 public function resource_hints( $hints, $relation_type ) {
326 if ( 'dns-prefetch' === $relation_type ) {
327 $hints[] = '//s.pubmine.com';
328 $hints[] = '//x.bidswitch.net';
329 $hints[] = '//static.criteo.net';
330 $hints[] = '//ib.adnxs.com';
331 $hints[] = '//aax.amazon-adsystem.com';
332 $hints[] = '//bidder.criteo.com';
333 $hints[] = '//cas.criteo.com';
334 $hints[] = '//gum.criteo.com';
335 $hints[] = '//ads.pubmatic.com';
336 $hints[] = '//gads.pubmatic.com';
337 $hints[] = '//tpc.googlesyndication.com';
338 $hints[] = '//ad.doubleclick.net';
339 $hints[] = '//googleads.g.doubleclick.net';
340 $hints[] = '//www.googletagservices.com';
341 $hints[] = '//cdn.switchadhub.com';
342 $hints[] = '//delivery.g.switchadhub.com';
343 $hints[] = '//delivery.swid.switchadhub.com';
344 }
345
346 return $hints;
347 }
348
349 /**
350 * IPONWEB metadata used by the various scripts
351 *
352 * @return [type] [description]
353 */
354 public function insert_head_meta() {
355 if ( self::is_amp() ) {
356 return;
357 }
358 $hosting_type = ( new Host() )->is_woa_site() ? 1 : 2; // 1 = WPCOM, 2 = Jetpack.
359 $pagetype = (int) $this->params->get_page_type_ipw();
360 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
361 $site_id = $this->params->blog_id;
362 $consent = (int) isset( $_COOKIE['personalized-ads-consent'] );
363 $is_logged_in = is_user_logged_in() ? '1' : '0';
364 ?>
365 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
366 var __ATA_PP = { pt: <?php echo esc_js( $pagetype ); ?>, ht: <?php echo esc_js( $hosting_type ); ?>, tn: '<?php echo esc_js( get_stylesheet() ); ?>', uloggedin: <?php echo esc_js( $is_logged_in ); ?>, amp: false, siteid: <?php echo esc_js( $site_id ); ?>, consent: <?php echo esc_js( $consent ); ?>, ad: { label: { text: '<?php echo esc_js( __( 'Advertisements', 'jetpack' ) ); ?>' }, reportAd: { text: '<?php echo esc_js( __( 'Report this ad', 'jetpack' ) ); ?>' } } };
367 var __ATA = __ATA || {};
368 __ATA.cmd = __ATA.cmd || [];
369 __ATA.criteo = __ATA.criteo || {};
370 __ATA.criteo.cmd = __ATA.criteo.cmd || [];
371 </script>
372 <?php
373 }
374
375 /**
376 * IPONWEB scripts in <head>
377 *
378 * @since 4.5.0
379 */
380 public function insert_head_iponweb() {
381 if ( self::is_amp() ) {
382 return;
383 }
384
385 $data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
386 ?>
387 <script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
388 (function(){var g=Date.now||function(){return+new Date};function h(a,b){a:{for(var c=a.length,d="string"==typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"==typeof a?a.charAt(b):a[b]};function k(a,b,c){c=null!=c?"="+encodeURIComponent(String(c)):"";if(b+=c){c=a.indexOf("#");0>c&&(c=a.length);var d=a.indexOf("?");if(0>d||d>c){d=c;var e=""}else e=a.substring(d+1,c);a=[a.substr(0,d),e,a.substr(c)];c=a[1];a[1]=b?c?c+"&"+b:b:c;a=a[0]+(a[1]?"?"+a[1]:"")+a[2]}return a};var l=0;function m(a,b){var c=document.createElement("script");c.src=a;c.onload=function(){b&&b(void 0)};c.onerror=function(){b&&b("error")};a=document.getElementsByTagName("head");var d;a&&0!==a.length?d=a[0]:d=document.documentElement;d.appendChild(c)}function n(a){var b=void 0===b?document.cookie:b;return(b=h(b.split("; "),function(c){return-1!=c.indexOf(a+"=")}))?b.split("=")[1]:""}function p(a){return"string"==typeof a&&0<a.length}
389 function r(a,b,c){b=void 0===b?"":b;c=void 0===c?".":c;var d=[];Object.keys(a).forEach(function(e){var f=a[e],q=typeof f;"object"==q&&null!=f||"function"==q?d.push(r(f,b+e+c)):null!==f&&void 0!==f&&(e=encodeURIComponent(b+e),d.push(e+"="+encodeURIComponent(f)))});return d.filter(p).join("&")}function t(a,b){a||((window.__ATA||{}).config=b.c,m(b.url))}var u=Math.floor(1E13*Math.random()),v=window.__ATA||{};window.__ATA=v;window.__ATA.cmd=v.cmd||[];v.rid=u;v.createdAt=g();var w=window.__ATA||{},x="s.pubmine.com";
390 w&&w.serverDomain&&(x=w.serverDomain);var y="//"+x+"/conf",z=window.top===window,A=window.__ATA_PP&&window.__ATA_PP.gdpr_applies,B="boolean"===typeof A?Number(A):null,C=window.__ATA_PP||null,D=z?document.referrer?document.referrer:null:null,E=z?window.location.href:document.referrer?document.referrer:null,F,G=n("__ATA_tuuid");F=G?G:null;var H=window.innerWidth+"x"+window.innerHeight,I=n("usprivacy"),J=r({gdpr:B,pp:C,rid:u,src:D,ref:E,tuuid:F,vp:H,us_privacy:I?I:null},"",".");
391 (function(a){var b=void 0===b?"cb":b;l++;var c="callback__"+g().toString(36)+"_"+l.toString(36);a=k(a,b,c);window[c]=function(d){t(void 0,d)};m(a,function(d){d&&t(d)})})(y+"?"+J);}).call(this);
392 </script>
393 <?php
394 }
395
396 /**
397 * Insert the ad onto the page
398 *
399 * @since 4.5.0
400 *
401 * @param string $content HTML content.
402 */
403 public function insert_ad( $content ) {
404 // Don't insert ads in feeds, or for anything but the main display. (This is required for compatibility with the Publicize module).
405 if ( is_feed() || ! is_main_query() || ! in_the_loop() ) {
406 return $content;
407 }
408 /**
409 * Allow third-party tools to disable the display of in post ads.
410 *
411 * @module wordads
412 *
413 * @since 4.5.0
414 *
415 * @param bool true Should the in post unit be disabled. Default to false.
416 */
417 $disable = apply_filters( 'wordads_inpost_disable', false );
418 if ( ! $this->params->should_show() || $disable ) {
419 return $content;
420 }
421
422 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
423 return $content . $this->get_ad( 'belowpost', $ad_type );
424 }
425
426 /**
427 * Insert an inline ad into a post content
428 * Used for rendering the `wordads` shortcode.
429 *
430 * @since 6.1.0
431 *
432 * @param string $content HTML content.
433 */
434 public function insert_inline_ad( $content ) {
435 // Ad JS won't work in XML feeds.
436 if ( is_feed() ) {
437 return $content;
438 }
439 /**
440 * Allow third-party tools to disable the display of in post ads.
441 *
442 * @module wordads
443 *
444 * @since 4.5.0
445 *
446 * @param bool true Should the in post unit be disabled. Default to false.
447 */
448 $disable = apply_filters( 'wordads_inpost_disable', false );
449 if ( $disable ) {
450 return $content;
451 }
452
453 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
454 $content .= $this->get_ad( 'inline', $ad_type );
455 return $content;
456 }
457
458 /**
459 * Inserts ad into header
460 *
461 * @since 4.5.0
462 */
463 public function insert_header_ad() {
464 /**
465 * Allow third-party tools to disable the display of header ads.
466 *
467 * @module wordads
468 *
469 * @since 4.5.0
470 *
471 * @param bool true Should the header unit be disabled. Default to false.
472 */
473 if ( apply_filters( 'wordads_header_disable', false ) ) {
474 return;
475 }
476
477 // Prevent multiple manual ads.
478 if ( 2 <= did_action( 'wordads_header_ad' ) ) {
479 return;
480 }
481
482 // Prevent placing an automatic ad if a manual ad has already been placed.
483 if ( doing_action( 'wp_footer' ) && did_action( 'wordads_header_ad' ) ) {
484 return;
485 }
486
487 // Prevent placing a manual ad if an automatic ad has already been placed.
488 if ( doing_action( 'wordads_header_ad' ) && did_action( 'wp_footer' ) ) {
489 return;
490 }
491
492 // Default ad placement to just after the <body> tag.
493 $selector = 'body > :first-child';
494
495 // Special theme cases.
496 switch ( get_stylesheet() ) {
497 case 'twentyseventeen':
498 $selector = '#content';
499 break;
500 case 'twentyfifteen':
501 $selector = '#main';
502 break;
503 case 'twentyfourteen':
504 $selector = 'article';
505 break;
506 }
507
508 // Don't relocate if the ad is being placed manually.
509 if ( doing_action( 'wordads_header_ad' ) ) {
510 $selector = '';
511 }
512
513 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
514 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
515 echo $this->get_dynamic_ad_snippet( $section_id, $form_factor, 'top', $selector ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
516 }
517
518 /**
519 * Header unit for AMP
520 *
521 * @param string $content Content of the page.
522 *
523 * @since 7.5.0
524 */
525 public function insert_header_ad_amp( $content ) {
526
527 $ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
528 if ( 'house' === $ad_type ) {
529 return $content;
530 }
531 return $this->get_ad( 'top_amp', $ad_type ) . $content;
532 }
533
534 /**
535 * Filter the latest ads.txt to include custom user entries. Strips any tags or whitespace.
536 *
537 * @param string $adstxt The ads.txt being filtered.
538 * @return string Filtered ads.txt with custom entries, if applicable.
539 *
540 * @since 6.5.0
541 */
542 public function insert_custom_adstxt( $adstxt ) {
543 if ( ! $this->option( 'wordads_custom_adstxt_enabled' ) ) {
544 return $adstxt;
545 }
546
547 $custom_adstxt = trim( wp_strip_all_tags( $this->option( 'wordads_custom_adstxt' ) ) );
548 if ( $custom_adstxt ) {
549 $adstxt .= "\n\n#Jetpack - User Custom Entries\n";
550 $adstxt .= $custom_adstxt . "\n";
551 }
552
553 return $adstxt;
554 }
555
556 /**
557 * Get the ad for the spot and type.
558 *
559 * @param string $spot top, side, inline, or belowpost.
560 * @param string $type iponweb or adsense.
561 */
562 public function get_ad( $spot, $type = 'iponweb' ) {
563 $snippet = '';
564 if ( 'iponweb' === $type ) {
565 $section_id = WORDADS_API_TEST_ID;
566 $snippet = '';
567
568 if ( 'top' === $spot ) {
569 // mrec for mobile, leaderboard for desktop.
570 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
571 $form_factor = $this->params->mobile_device ? 'square' : 'leaderboard';
572 $snippet = $this->get_dynamic_ad_snippet( $section_id, $form_factor, $spot );
573 } elseif ( 'belowpost' === $spot ) {
574 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '1';
575 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
576 } elseif ( 'inline' === $spot ) {
577 $section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '5';
578 $snippet = $this->get_dynamic_ad_snippet( $section_id, 'square', $spot );
579 } elseif ( 'top_amp' === $spot ) {
580 // Ad unit which can safely be inserted below title, above content in a variety of themes.
581 $width = 300;
582 $height = 250;
583 $snippet = $this->get_ad_div( $spot, $this->get_amp_snippet( $height, $width ) );
584 }
585 } elseif ( 'house' === $type ) {
586 $leaderboard = 'top' === $spot && ! $this->params->mobile_device;
587 $snippet = $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
588 if ( 'belowpost' === $spot && $this->option( 'wordads_second_belowpost', true ) ) {
589 $snippet .= $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
590 }
591 }
592
593 return $snippet;
594 }
595
596 /**
597 * Returns the AMP snippet to be inserted
598 *
599 * @param int $height Height.
600 * @param int $width Width.
601 * @return string
602 *
603 * @since 8.7
604 */
605 public function get_amp_snippet( $height, $width ) {
606 $height = esc_attr( $height + 15 ); // this will ensure enough padding for "Report this ad".
607 $width = esc_attr( $width );
608 $amp_section_id = esc_attr( self::get_amp_section_id() );
609 $site_id = esc_attr( $this->params->blog_id );
610 return <<<HTML
611 <amp-ad width="$width" height="$height"
612 type="pubmine"
613 data-siteid="$site_id"
614 data-section="$amp_section_id">
615 </amp-ad>
616 HTML;
617 }
618
619 /**
620 * Compatibility function -- main functionality replaced with get_dynamic_ad_snippet
621 *
622 * @param int $section_id Ad section.
623 * @param int $height Ad height.
624 * @param int $width Ad width.
625 * @param string $location Location.
626 * @param string $css CSS.
627 *
628 * @return string
629 *
630 * @since 5.7
631 */
632 public function get_ad_snippet( $section_id, $height, $width, $location = '', $css = '' ) {
633 if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
634 return $this->get_amp_snippet( $height, $width );
635 }
636
637 $this->ads[] = array(
638 'location' => $location,
639 'width' => $width,
640 'height' => $height,
641 );
642
643 if ( 'gutenberg' === $location ) {
644 $ad_number = count( $this->ads ) . '-' . uniqid();
645 $data_tags = $this->params->cloudflare ? ' data-cfasync="false"' : '';
646 $css = esc_attr( $css );
647
648 $loc_id = 100;
649 if ( ! empty( self::$ad_location_ids[ $location ] ) ) {
650 $loc_id = self::$ad_location_ids[ $location ];
651 }
652
653 $loc_id = esc_js( $loc_id );
654 return <<<HTML
655 <div style="padding-bottom:15px;width:{$width}px;height:{$height}px;$css">
656 <div id="atatags-{$ad_number}">
657 <script$data_tags type="text/javascript">
658 __ATA.cmd.push(function() {
659 __ATA.initSlot('atatags-{$ad_number}', {
660 collapseEmpty: 'before',
661 sectionId: '{$section_id}',
662 location: {$loc_id},
663 width: {$width},
664 height: {$height}
665 });
666 });
667 </script>
668 </div>
669 </div>
670 HTML;
671 }
672
673 $form_factor = 'square';
674 if ( 250 > $width ) {
675 $form_factor = 'skyscraper';
676 } elseif ( 300 < $width ) {
677 $form_factor = 'leaderboard';
678 }
679
680 return $this->get_dynamic_ad_snippet( $section_id, $form_factor, $location );
681 }
682
683 /**
684 * Returns the dynamic snippet to be inserted into the ad unit
685 *
686 * @param int $section_id section_id.
687 * @param string $form_factor form_factor.
688 * @param string $location location.
689 * @param string $relocate location to be moved after the fact for themes without required hook.
690 * @return string
691 *
692 * @since 8.7
693 */
694 public function get_dynamic_ad_snippet( $section_id, $form_factor = 'square', $location = '', $relocate = '' ) {
695 $div_id = 'atatags-' . $section_id . '-' . uniqid();
696 $div_id = esc_attr( $div_id );
697
698 // Default form factor.
699 $form_factor_id = self::$form_factor_ids['square'];
700 if ( isset( self::$form_factor_ids[ $form_factor ] ) ) {
701 $form_factor_id = self::$form_factor_ids[ $form_factor ];
702 }
703
704 $loc_id = 100;
705 if ( isset( self::$ad_location_ids[ $location ] ) ) {
706 $loc_id = self::$ad_location_ids[ $location ];
707 }
708
709 $form_factor_id = esc_js( $form_factor_id );
710 $advertisements_text = esc_js( __( 'Advertisements', 'jetpack' ) );
711 $report_ad_text = esc_js( __( 'Report this ad', 'jetpack' ) );
712 $privacy_settings_text = esc_js( __( 'Privacy settings', 'jetpack' ) );
713
714 $relocate_script = '';
715 if ( ! empty( $relocate ) ) {
716 $selector = wp_json_encode( $relocate );
717 $relocate_script = <<<JS
718 <script type="text/javascript">
719 var adNode = document.getElementById( '{$div_id}' );
720 var selector = {$selector};
721 var relocateNode = document.querySelector( selector );
722 relocateNode.parentNode.insertBefore( adNode, relocateNode );
723 </script>
724 JS;
725 }
726
727 return <<<HTML
728 <div id="{$div_id}"></div>
729 {$relocate_script}
730 <script>
731 __ATA.cmd.push(function() {
732 __ATA.initDynamicSlot({
733 id: '{$div_id}',
734 location: {$loc_id},
735 formFactor: '{$form_factor_id}',
736 label: {
737 text: '{$advertisements_text}',
738 },
739 creative: {
740 reportAd: {
741 text: '{$report_ad_text}',
742 },
743 privacySettings: {
744 text: '{$privacy_settings_text}',
745 }
746 }
747 });
748 });
749 </script>
750 HTML;
751 }
752
753 /**
754 * Returns the complete ad div with snippet to be inserted into the page
755 *
756 * @param string $spot top, side, inline, or belowpost.
757 * @param string $snippet The snippet to insert into the div.
758 * @param array $css_classes CSS classes.
759 * @return string The supporting ad unit div.
760 *
761 * @since 7.1
762 */
763 public function get_ad_div( $spot, $snippet, array $css_classes = array() ) {
764 if ( strpos( strtolower( $spot ), 'amp' ) === false && ! 'inline' === $spot ) {
765 return $snippet; // we don't want dynamic ads to be inserted for AMP & Gutenberg.
766 }
767
768 if ( empty( $css_classes ) ) {
769 $css_classes = array();
770 }
771
772 $css_classes[] = 'wpcnt';
773 if ( 'top' === $spot ) {
774 $css_classes[] = 'wpcnt-header';
775 }
776
777 $spot = esc_attr( $spot );
778 $classes = esc_attr( implode( ' ', $css_classes ) );
779 $about = esc_html__( 'Advertisements', 'jetpack' );
780 return <<<HTML
781 <div class="$classes">
782 <div class="wpa">
783 <span class="wpa-about">$about</span>
784 <div class="u $spot">
785 $snippet
786 </div>
787 </div>
788 </div>
789 HTML;
790 }
791
792 /**
793 * Check the reasons to bail before we attempt to insert ads.
794 *
795 * @return true if we should bail (don't insert ads)
796 *
797 * @since 4.5.0
798 */
799 public function should_bail() {
800 return ! $this->option( 'wordads_approved' ) || (bool) $this->option( 'wordads_unsafe' );
801 }
802
803 /**
804 * Returns markup for HTML5 house ad base on unit
805 *
806 * @param string $unit mrec, widesky, or leaderboard.
807 * @return string markup for HTML5 house ad
808 *
809 * @since 4.7.0
810 */
811 public function get_house_ad( $unit = 'mrec' ) {
812
813 switch ( $unit ) {
814 case 'widesky':
815 $width = 160;
816 $height = 600;
817 break;
818 case 'leaderboard':
819 $width = 728;
820 $height = 90;
821 break;
822 case 'mrec':
823 default:
824 $width = 300;
825 $height = 250;
826 break;
827 }
828
829 return <<<HTML
830 <iframe
831 src="https://s0.wp.com/wp-content/blog-plugins/wordads/house/html5/$unit/index.html"
832 width="$width"
833 height="$height"
834 frameborder="0"
835 scrolling="no"
836 marginheight="0"
837 marginwidth="0">
838 </iframe>
839 HTML;
840 }
841
842 /**
843 * Activation hook actions
844 *
845 * @since 4.5.0
846 */
847 public static function activate() {
848 WordAds_API::update_wordads_status_from_api();
849 }
850
851 /**
852 * Registers the widgets.
853 */
854 public function widget_callback() {
855 register_widget( 'WordAds_Sidebar_Widget' );
856
857 $ccpa_enabled = get_option( 'wordads_ccpa_enabled' );
858
859 if ( $ccpa_enabled ) {
860 register_widget( 'WordAds_Ccpa_Do_Not_Sell_Link_Widget' );
861 }
862 }
863 }
864
865 add_action( 'jetpack_activate_module_wordads', array( 'WordAds', 'activate' ) );
866 add_action( 'jetpack_activate_module_wordads', array( 'WordAds_Cron', 'activate' ) );
867 add_action( 'jetpack_deactivate_module_wordads', array( 'WordAds_Cron', 'deactivate' ) );
868
869 global $wordads;
870 $wordads = new WordAds();
871