Completed
Push — update/wpcs-require-list-4 ( 8f4a75 )
by
unknown
40:33 queued 32:32
created

WordAds::insert_head_iponweb()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
/**
3
 * Main WordAds file.
4
 *
5
 * @package Jetpack
6
 */
7
8
define( 'WORDADS_ROOT', dirname( __FILE__ ) );
9
define( 'WORDADS_BASENAME', plugin_basename( __FILE__ ) );
10
define( 'WORDADS_FILE_PATH', WORDADS_ROOT . '/' . basename( __FILE__ ) );
11
define( 'WORDADS_URL', plugins_url( '/', __FILE__ ) );
12
define( 'WORDADS_API_TEST_ID', '26942' );
13
define( 'WORDADS_API_TEST_ID2', '114160' );
14
15
require_once WORDADS_ROOT . '/php/class-wordads-sidebar-widget.php';
16
require_once WORDADS_ROOT . '/php/class-wordads-api.php';
17
require_once WORDADS_ROOT . '/php/class-wordads-cron.php';
18
require_once WORDADS_ROOT . '/php/class-wordads-california-privacy.php';
19
20
/**
21
 * Primary WordAds class.
22
 */
23
class WordAds {
24
25
	/**
26
	 * Ads parameters.
27
	 *
28
	 * @var null
29
	 */
30
	public $params = null;
31
32
	/**
33
	 * Ads.
34
	 *
35
	 * @var array
36
	 */
37
	public $ads = array();
38
39
	/**
40
	 * Array of supported ad types.
41
	 *
42
	 * @var array
43
	 */
44
	public static $ad_tag_ids = array(
45
		'mrec'               => array(
46
			'tag'    => '300x250_mediumrectangle',
47
			'height' => '250',
48
			'width'  => '300',
49
		),
50
		'leaderboard'        => array(
51
			'tag'    => '728x90_leaderboard',
52
			'height' => '90',
53
			'width'  => '728',
54
		),
55
		'mobile_leaderboard' => array(
56
			'tag'    => '320x50_mobileleaderboard',
57
			'height' => '50',
58
			'width'  => '320',
59
		),
60
		'wideskyscraper'     => array(
61
			'tag'    => '160x600_wideskyscraper',
62
			'height' => '600',
63
			'width'  => '160',
64
		),
65
	);
66
67
	/**
68
	 * Mapping array of location slugs to placement ids
69
	 *
70
	 * @var array
71
	 */
72
	public static $ad_location_ids = array(
73
		'top'           => 110,
74
		'belowpost'     => 120,
75
		'belowpost2'    => 130,
76
		'sidebar'       => 140,
77
		'widget'        => 150,
78
		'gutenberg'     => 200,
79
		'inline'        => 310,
80
		'inline-plugin' => 320,
81
	);
82
83
	/**
84
	 * Counter to enable unique, sequential section IDs for all amp-ad units
85
	 *
86
	 * @var int
87
	 */
88
	public static $amp_section_id = 1;
89
90
	/**
91
	 * Solo unit CSS string.
92
	 *
93
	 * @var string
94
	 */
95
	public static $solo_unit_css = 'float:left;margin-right:5px;margin-top:0px;';
96
97
	/**
98
	 * Checks for AMP support and returns true iff active & AMP request
99
	 *
100
	 * @return boolean True if supported AMP request
101
	 *
102
	 * @since 7.5.0
103
	 */
104
	public static function is_amp() {
105
		return class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request();
106
	}
107
108
	/**
109
	 * Increment the AMP section ID and return the value
110
	 *
111
	 * @return int
112
	 */
113
	public static function get_amp_section_id() {
114
		return self::$amp_section_id++;
115
	}
116
117
	/**
118
	 * Convenience function for grabbing options from params->options
119
	 *
120
	 * @param  string $option the option to grab.
121
	 * @param  mixed  $default (optional).
122
	 * @return option or $default if not set
123
	 *
124
	 * @since 4.5.0
125
	 */
126
	public function option( $option, $default = false ) {
127
		if ( ! isset( $this->params->options[ $option ] ) ) {
128
			return $default;
129
		}
130
131
		return $this->params->options[ $option ];
132
	}
133
134
	/**
135
	 * Returns the ad tag property array for supported ad types.
136
	 *
137
	 * @return array      array with ad tags
138
	 *
139
	 * @since 7.1.0
140
	 */
141
	public function get_ad_tags() {
142
		return self::$ad_tag_ids;
143
	}
144
145
	/**
146
	 * Returns the solo css for unit
147
	 *
148
	 * @return string the special css for solo units
149
	 *
150
	 * @since 7.1.0
151
	 */
152
	public function get_solo_unit_css() {
153
		return self::$solo_unit_css;
154
	}
155
156
	/**
157
	 * Instantiate the plugin
158
	 *
159
	 * @since 4.5.0
160
	 */
161
	public function __construct() {
162
		add_action( 'wp', array( $this, 'init' ) );
163
		add_action( 'rest_api_init', array( $this, 'init' ) );
164
		add_action( 'widgets_init', array( $this, 'widget_callback' ) );
165
166
		if ( is_admin() ) {
167
			WordAds_California_Privacy::init_ajax_actions();
168
		}
169
	}
170
171
	/**
172
	 * Code to run on WordPress 'init' hook
173
	 *
174
	 * @since 4.5.0
175
	 */
176
	public function init() {
177
		require_once WORDADS_ROOT . '/php/class-wordads-params.php';
178
		$this->params = new WordAds_Params();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \WordAds_Params() of type object<WordAds_Params> is incompatible with the declared type null of property $params.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
179
180
		if ( $this->should_bail() || self::is_infinite_scroll() ) {
181
			return;
182
		}
183
184
		if ( is_admin() ) {
185
			require_once WORDADS_ROOT . '/php/class-wordads-admin.php';
186
			return;
187
		}
188
189
		$this->insert_adcode();
190
191
		// Include California Privacy Act related features if enabled.
192
		if ( $this->params->options['wordads_ccpa_enabled'] ) {
0 ignored issues
show
Bug introduced by
The property options does not seem to exist in WordAds_Params.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
193
			WordAds_California_Privacy::init();
194
		}
195
196
		if ( '/ads.txt' === $_SERVER['REQUEST_URI'] ) {
197
198
			$ads_txt_transient = get_transient( 'jetpack_ads_txt' );
199
200
			if ( false === ( $ads_txt_transient ) ) {
201
				$ads_txt_transient = ! is_wp_error( WordAds_API::get_wordads_ads_txt() ) ? WordAds_API::get_wordads_ads_txt() : '';
202
				set_transient( 'jetpack_ads_txt', $ads_txt_transient, DAY_IN_SECONDS );
203
			}
204
205
			/**
206
			 * Provide plugins a way of modifying the contents of the automatically-generated ads.txt file.
207
			 *
208
			 * @module wordads
209
			 *
210
			 * @since 6.1.0
211
			 *
212
			 * @param string WordAds_API::get_wordads_ads_txt() The contents of the ads.txt file.
213
			 */
214
			$ads_txt_content = apply_filters( 'wordads_ads_txt', $ads_txt_transient );
215
216
			http_response_code( 200 );
217
			header( 'Content-Type: text/plain; charset=utf-8' );
218
			echo esc_html( $ads_txt_content );
219
			die();
220
		}
221
	}
222
223
	/**
224
	 * Check for Jetpack's The_Neverending_Home_Page and use got_infinity
225
	 *
226
	 * @return boolean true if load came from infinite scroll
227
	 *
228
	 * @since 4.5.0
229
	 */
230
	public static function is_infinite_scroll() {
231
		return class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::got_infinity();
232
	}
233
234
	/**
235
	 * Add the actions/filters to insert the ads. Checks for mobile or desktop.
236
	 *
237
	 * @since 4.5.0
238
	 */
239
	private function insert_adcode() {
240
		add_filter( 'wp_resource_hints', array( $this, 'resource_hints' ), 10, 2 );
241
		add_action( 'wp_head', array( $this, 'insert_head_meta' ), 20 );
242
		add_action( 'wp_head', array( $this, 'insert_head_iponweb' ), 30 );
243
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
244
		add_filter( 'wordads_ads_txt', array( $this, 'insert_custom_adstxt' ) );
245
246
		/**
247
		 * Filters enabling ads in `the_content` filter
248
		 *
249
		 * @see https://jetpack.com/support/ads/
250
		 *
251
		 * @module wordads
252
		 *
253
		 * @since 5.8.0
254
		 *
255
		 * @param bool True to disable ads in `the_content`
256
		 */
257
		if ( ! apply_filters( 'wordads_content_disable', false ) ) {
258
			add_filter( 'the_content', array( $this, 'insert_ad' ) );
259
		}
260
261
		/**
262
		 * Filters enabling ads in `the_excerpt` 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_excerpt`
271
		 */
272
		if ( ! apply_filters( 'wordads_excerpt_disable', false ) ) {
273
			add_filter( 'the_excerpt', array( $this, 'insert_ad' ) );
274
		}
275
276
		if ( $this->option( 'enable_header_ad', true ) ) {
277
			if ( self::is_amp() ) {
278
				add_filter( 'the_content', array( $this, 'insert_header_ad_amp' ) );
279
			} else {
280
				switch ( get_stylesheet() ) {
281
					case 'twentyseventeen':
282
					case 'twentyfifteen':
283
					case 'twentyfourteen':
284
						add_action( 'wp_footer', array( $this, 'insert_header_ad_special' ) );
285
						break;
286
					default:
287
						add_action( 'wp_head', array( $this, 'insert_header_ad' ), 100 );
288
						break;
289
				}
290
			}
291
		}
292
	}
293
294
	/**
295
	 * Register desktop scripts and styles
296
	 *
297
	 * @since 4.5.0
298
	 */
299
	public function enqueue_scripts() {
300
		wp_enqueue_style(
301
			'wordads',
302
			WORDADS_URL . 'css/style.css',
303
			array(),
304
			'2015-12-18'
305
		);
306
	}
307
308
	/**
309
	 * Add the IPW resource hints
310
	 *
311
	 * @since 7.9
312
	 *
313
	 * @param array  $hints Domains for hinting.
314
	 * @param string $relation_type Resource type.
315
	 *
316
	 * @return array Domains for hinting.
317
	 */
318
	public function resource_hints( $hints, $relation_type ) {
319
		if ( 'dns-prefetch' === $relation_type ) {
320
			$hints[] = '//s.pubmine.com';
321
			$hints[] = '//x.bidswitch.net';
322
			$hints[] = '//static.criteo.net';
323
			$hints[] = '//ib.adnxs.com';
324
			$hints[] = '//aax.amazon-adsystem.com';
325
			$hints[] = '//bidder.criteo.com';
326
			$hints[] = '//cas.criteo.com';
327
			$hints[] = '//gum.criteo.com';
328
			$hints[] = '//ads.pubmatic.com';
329
			$hints[] = '//gads.pubmatic.com';
330
			$hints[] = '//tpc.googlesyndication.com';
331
			$hints[] = '//ad.doubleclick.net';
332
			$hints[] = '//googleads.g.doubleclick.net';
333
			$hints[] = '//www.googletagservices.com';
334
			$hints[] = '//cdn.switchadhub.com';
335
			$hints[] = '//delivery.g.switchadhub.com';
336
			$hints[] = '//delivery.swid.switchadhub.com';
337
		}
338
339
		return $hints;
340
	}
341
342
	/**
343
	 * IPONWEB metadata used by the various scripts
344
	 *
345
	 * @return [type] [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
346
	 */
347
	public function insert_head_meta() {
348
		if ( self::is_amp() ) {
349
			return;
350
		}
351
		$pagetype  = intval( $this->params->get_page_type_ipw() );
0 ignored issues
show
Bug introduced by
The method get_page_type_ipw cannot be called on $this->params (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
352
		$data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
353
		$site_id   = $this->params->blog_id;
354
		$consent   = intval( isset( $_COOKIE['personalized-ads-consent'] ) );
355
		?>
356
		<script<?php esc_attr( $data_tags ); ?> type="text/javascript">
357
			var __ATA_PP = { pt: <?php esc_js( $pagetype ); ?>, ht: 2, tn: '<?php esc_js( get_stylesheet() ); ?>', amp: false, siteid: <?php esc_js( $site_id ); ?>, consent: <?php esc_js( $consent ); ?> };
358
			var __ATA = __ATA || {};
359
			__ATA.cmd = __ATA.cmd || [];
360
			__ATA.criteo = __ATA.criteo || {};
361
			__ATA.criteo.cmd = __ATA.criteo.cmd || [];
362
		</script>
363
		<?php
364
	}
365
366
	/**
367
	 * IPONWEB scripts in <head>
368
	 *
369
	 * @since 4.5.0
370
	 */
371
	public function insert_head_iponweb() {
372
		if ( self::is_amp() ) {
373
			return;
374
		}
375
		$data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
376
		?>
377
		<script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
378
		(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("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}
379
		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;v.rid=u;v.createdAt=g();var w=window.__ATA||{},x="s.pubmine.com";
380
		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},"",".");
381
		(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);
382
		</script>
383
		<?php
384
	}
385
386
	/**
387
	 * Insert the ad onto the page
388
	 *
389
	 * @since 4.5.0
390
	 *
391
	 * @param string $content HTML content.
392
	 */
393
	public function insert_ad( $content ) {
394
		// Don't insert ads in feeds, or for anything but the main display. (This is required for compatibility with the Publicize module).
395
		if ( is_feed() || ! is_main_query() || ! in_the_loop() ) {
396
			return $content;
397
		}
398
		/**
399
		 * Allow third-party tools to disable the display of in post ads.
400
		 *
401
		 * @module wordads
402
		 *
403
		 * @since 4.5.0
404
		 *
405
		 * @param bool true Should the in post unit be disabled. Default to false.
406
		 */
407
		$disable = apply_filters( 'wordads_inpost_disable', false );
408
		if ( ! $this->params->should_show() || $disable ) {
0 ignored issues
show
Bug introduced by
The method should_show cannot be called on $this->params (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
409
			return $content;
410
		}
411
412
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
413
		return $content . $this->get_ad( 'belowpost', $ad_type );
414
	}
415
416
	/**
417
	 * Insert an inline ad into a post content
418
	 * Used for rendering the `wordads` shortcode.
419
	 *
420
	 * @since 6.1.0
421
	 *
422
	 * @param string $content HTML content.
423
	 */
424
	public function insert_inline_ad( $content ) {
425
		// Ad JS won't work in XML feeds.
426
		if ( is_feed() ) {
427
			return $content;
428
		}
429
		/**
430
		 * Allow third-party tools to disable the display of in post ads.
431
		 *
432
		 * @module wordads
433
		 *
434
		 * @since 4.5.0
435
		 *
436
		 * @param bool true Should the in post unit be disabled. Default to false.
437
		 */
438
		$disable = apply_filters( 'wordads_inpost_disable', false );
439
		if ( $disable ) {
440
			return $content;
441
		}
442
443
		$ad_type  = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
444
		$content .= $this->get_ad( 'inline', $ad_type );
445
		return $content;
446
	}
447
448
	/**
449
	 * Inserts ad into header
450
	 *
451
	 * @since 4.5.0
452
	 */
453
	public function insert_header_ad() {
454
		/**
455
		 * Allow third-party tools to disable the display of header ads.
456
		 *
457
		 * @module wordads
458
		 *
459
		 * @since 4.5.0
460
		 *
461
		 * @param bool true Should the header unit be disabled. Default to false.
462
		 */
463
		if ( apply_filters( 'wordads_header_disable', false ) ) {
464
			return;
465
		}
466
467
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
468
		echo $this->get_ad( 'top', $ad_type ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
469
	}
470
471
	/**
472
	 * Special cases for inserting header unit via JS
473
	 *
474
	 * @since 4.5.0
475
	 */
476
	public function insert_header_ad_special() {
477
		/**
478
		 * Allow third-party tools to disable the display of header ads.
479
		 *
480
		 * @module wordads
481
		 *
482
		 * @since 4.5.0
483
		 *
484
		 * @param bool true Should the header unit be disabled. Default to false.
485
		 */
486
		if ( apply_filters( 'wordads_header_disable', false ) ) {
487
			return;
488
		}
489
490
		$selector = '#content';
491
		switch ( get_stylesheet() ) {
492
			case 'twentyseventeen':
493
				$selector = '#content';
494
				break;
495
			case 'twentyfifteen':
496
				$selector = '#main';
497
				break;
498
			case 'twentyfourteen':
499
				$selector = 'article';
500
				break;
501
		}
502
503
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
504
		echo $this->get_ad( 'top', $ad_type ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
505
		if ( ! self::is_amp() ) {
506
			?>
507
		<script type="text/javascript">
508
			(function ( selector ) {
509
				var main = document.querySelector( selector );
510
				var headerAd = document.querySelector('.wpcnt-header');
511
512
				if ( main ) {
513
					main.parentNode.insertBefore( headerAd, main );
514
				}
515
			})( '<?php echo esc_js( $selector ); ?>' );
516
517
		</script>
518
			<?php
519
		}
520
	}
521
522
	/**
523
	 * Header unit for AMP
524
	 *
525
	 * @param string $content Content of the page.
526
	 *
527
	 * @since 7.5.0
528
	 */
529
	public function insert_header_ad_amp( $content ) {
530
531
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
532
		if ( 'house' === $ad_type ) {
533
			return $content;
534
		}
535
		return $this->get_ad( 'top_amp', $ad_type ) . $content;
536
537
	}
538
539
	/**
540
	 * Filter the latest ads.txt to include custom user entries. Strips any tags or whitespace.
541
	 *
542
	 * @param  string $adstxt The ads.txt being filtered.
543
	 * @return string         Filtered ads.txt with custom entries, if applicable.
544
	 *
545
	 * @since 6.5.0
546
	 */
547
	public function insert_custom_adstxt( $adstxt ) {
548
		if ( ! $this->option( 'wordads_custom_adstxt_enabled' ) ) {
549
			return $adstxt;
550
		}
551
552
		$custom_adstxt = trim( wp_strip_all_tags( $this->option( 'wordads_custom_adstxt' ) ) );
553
		if ( $custom_adstxt ) {
554
			$adstxt .= "\n\n#Jetpack - User Custom Entries\n";
555
			$adstxt .= $custom_adstxt . "\n";
556
		}
557
558
		return $adstxt;
559
	}
560
561
	/**
562
	 * Get the ad for the spot and type.
563
	 *
564
	 * @param  string $spot top, side, inline, or belowpost.
565
	 * @param  string $type iponweb or adsense.
566
	 */
567
	public function get_ad( $spot, $type = 'iponweb' ) {
568
		$snippet = '';
569
		if ( 'iponweb' === $type ) {
570
			// Default to mrec.
571
			$width  = 300;
572
			$height = 250;
573
574
			$section_id = WORDADS_API_TEST_ID;
0 ignored issues
show
Unused Code introduced by
$section_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
575
			$snippet    = '';
576
			if ( 'top' === $spot ) {
577
				// mrec for mobile, leaderboard for desktop.
578
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
579
				$width      = $this->params->mobile_device ? 300 : 728;
580
				$height     = $this->params->mobile_device ? 250 : 90;
581
				$snippet    = $this->get_ad_snippet( $section_id, $height, $width, $spot );
582
			} elseif ( 'belowpost' === $spot ) {
583
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '1';
584
				$width      = 300;
585
				$height     = 250;
586
587
				$snippet = $this->get_ad_snippet( $section_id, $height, $width, $spot, self::$solo_unit_css );
588
				if ( $this->option( 'wordads_second_belowpost', true ) ) {
589
					$section_id2 = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID2 : $this->params->blog_id . '4';
590
					$snippet    .= $this->get_ad_snippet( $section_id2, $height, $width, $spot . '2', 'float:left;margin-top:0px;' );
591
				}
592
			} elseif ( 'inline' === $spot ) {
593
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '5';
594
				$snippet    = $this->get_ad_snippet( $section_id, $height, $width, $spot, self::$solo_unit_css );
595
			} elseif ( 'top_amp' === $spot ) {
596
				// Ad unit which can safely be inserted below title, above content in a variety of themes.
597
				$width   = $this->params->mobile_device ? 320 : 300;
598
				$height  = $this->params->mobile_device ? 50 : 250;
599
				$snippet = $this->get_ad_snippet( null, $height, $width );
600
			}
601
		} elseif ( 'house' === $type ) {
602
			$leaderboard = 'top' === $spot && ! $this->params->mobile_device;
603
			$snippet     = $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
604
			if ( 'belowpost' === $spot && $this->option( 'wordads_second_belowpost', true ) ) {
605
				$snippet .= $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
606
			}
607
		}
608
609
		return $this->get_ad_div( $spot, $snippet );
610
	}
611
612
613
	/**
614
	 * Returns the snippet to be inserted into the ad unit
615
	 *
616
	 * @param  int    $section_id Ad section.
617
	 * @param  int    $height Ad height.
618
	 * @param  int    $width Ad width.
619
	 * @param  string $location Location.
620
	 * @param  string $css CSS.
621
	 *
622
	 * @return string
623
	 *
624
	 * @since 5.7
625
	 */
626
	public function get_ad_snippet( $section_id, $height, $width, $location = '', $css = '' ) {
627
		$this->ads[] = array(
628
			'location' => $location,
629
			'width'    => $width,
630
			'height'   => $height,
631
		);
632
633
		if ( self::is_amp() ) {
634
			$height         = esc_attr( $height + 15 ); // this will ensure enough padding for "Report this ad".
635
			$width          = esc_attr( $width );
636
			$amp_section_id = esc_attr( self::get_amp_section_id() );
637
			$site_id        = esc_attr( $this->params->blog_id );
638
			return <<<HTML
639
			<amp-ad width="$width" height="$height"
640
			    type="pubmine"
641
			    data-siteid="$site_id"
642
			    data-section="$amp_section_id">
643
			</amp-ad>
644
HTML;
645
		}
646
647
		$ad_number = count( $this->ads ) . '-' . uniqid();
648
		$data_tags = $this->params->cloudflare ? ' data-cfasync="false"' : '';
649
		$css       = esc_attr( $css );
650
651
		$loc_id = 100;
652
		if ( ! empty( self::$ad_location_ids[ $location ] ) ) {
653
			$loc_id = self::$ad_location_ids[ $location ];
654
		}
655
656
		return <<<HTML
657
		<div style="padding-bottom:15px;width:{$width}px;height:{$height}px;$css">
658
			<div id="atatags-{$ad_number}">
659
				<script$data_tags type="text/javascript">
660
				__ATA.cmd.push(function() {
661
					__ATA.initSlot('atatags-{$ad_number}',  {
662
						collapseEmpty: 'before',
663
						sectionId: '{$section_id}',
664
						location: {$loc_id},
665
						width: {$width},
666
						height: {$height}
667
					});
668
				});
669
				</script>
670
			</div>
671
		</div>
672
HTML;
673
	}
674
675
	/**
676
	 * Returns the complete ad div with snippet to be inserted into the page
677
	 *
678
	 * @param  string $spot top, side, inline, or belowpost.
679
	 * @param  string $snippet The snippet to insert into the div.
680
	 * @param  array  $css_classes CSS classes.
681
	 * @return string The supporting ad unit div.
682
	 *
683
	 * @since 7.1
684
	 */
685
	public function get_ad_div( $spot, $snippet, array $css_classes = array() ) {
686
		if ( empty( $css_classes ) ) {
687
			$css_classes = array();
688
		}
689
690
		$css_classes[] = 'wpcnt';
691
		if ( 'top' === $spot ) {
692
			$css_classes[] = 'wpcnt-header';
693
		}
694
695
		$spot    = esc_attr( $spot );
696
		$classes = esc_attr( implode( ' ', $css_classes ) );
697
		$about   = esc_html__( 'Advertisements', 'jetpack' );
698
		return <<<HTML
699
		<div class="$classes">
700
			<div class="wpa">
701
				<span class="wpa-about">$about</span>
702
				<div class="u $spot">
703
					$snippet
704
				</div>
705
			</div>
706
		</div>
707
HTML;
708
	}
709
710
	/**
711
	 * Check the reasons to bail before we attempt to insert ads.
712
	 *
713
	 * @return true if we should bail (don't insert ads)
714
	 *
715
	 * @since 4.5.0
716
	 */
717
	public function should_bail() {
718
		return ! $this->option( 'wordads_approved' ) || (bool) $this->option( 'wordads_unsafe' );
719
	}
720
721
	/**
722
	 * Returns markup for HTML5 house ad base on unit
723
	 *
724
	 * @param  string $unit mrec, widesky, or leaderboard.
725
	 * @return string       markup for HTML5 house ad
726
	 *
727
	 * @since 4.7.0
728
	 */
729
	public function get_house_ad( $unit = 'mrec' ) {
730
731
		switch ( $unit ) {
732
			case 'widesky':
733
				$width  = 160;
734
				$height = 600;
735
				break;
736
			case 'leaderboard':
737
				$width  = 728;
738
				$height = 90;
739
				break;
740
			case 'mrec':
741
			default:
742
				$width  = 300;
743
				$height = 250;
744
				break;
745
		}
746
747
		return <<<HTML
748
		<iframe
749
			src="https://s0.wp.com/wp-content/blog-plugins/wordads/house/html5/$unit/index.html"
750
			width="$width"
751
			height="$height"
752
			frameborder="0"
753
			scrolling="no"
754
			marginheight="0"
755
			marginwidth="0">
756
		</iframe>
757
HTML;
758
	}
759
760
	/**
761
	 * Activation hook actions
762
	 *
763
	 * @since 4.5.0
764
	 */
765
	public static function activate() {
766
		WordAds_API::update_wordads_status_from_api();
767
	}
768
769
	/**
770
	 * Registers the widgets.
771
	 */
772
	public function widget_callback() {
773
			register_widget( 'WordAds_Sidebar_Widget' );
774
775
			$ccpa_enabled = get_option( 'wordads_ccpa_enabled' );
776
777
		if ( $ccpa_enabled ) {
778
			register_widget( 'WordAds_Ccpa_Do_Not_Sell_Link_Widget' );
779
		}
780
	}
781
}
782
783
add_action( 'jetpack_activate_module_wordads', array( 'WordAds', 'activate' ) );
784
add_action( 'jetpack_activate_module_wordads', array( 'WordAds_Cron', 'activate' ) );
785
add_action( 'jetpack_deactivate_module_wordads', array( 'WordAds_Cron', 'deactivate' ) );
786
787
global $wordads;
788
$wordads = new WordAds();
789