Completed
Push — update/activity-log-links ( 92fe50...3b9362 )
by
unknown
12:21
created

WordAds::insert_ad()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 4
nop 1
dl 0
loc 22
rs 8.6346
c 0
b 0
f 0
1
<?php
2
3
define( 'WORDADS_ROOT', dirname( __FILE__ ) );
4
define( 'WORDADS_BASENAME', plugin_basename( __FILE__ ) );
5
define( 'WORDADS_FILE_PATH', WORDADS_ROOT . '/' . basename( __FILE__ ) );
6
define( 'WORDADS_URL', plugins_url( '/', __FILE__ ) );
7
define( 'WORDADS_API_TEST_ID', '26942' );
8
define( 'WORDADS_API_TEST_ID2', '114160' );
9
10
require_once( WORDADS_ROOT . '/php/widgets.php' );
11
require_once( WORDADS_ROOT . '/php/api.php' );
12
require_once( WORDADS_ROOT . '/php/cron.php' );
13
14
class WordAds {
15
16
	public $params = null;
17
18
	public $ads = array();
19
20
	/**
21
	 * Array of supported ad types.
22
	 *
23
	 * @var array
24
	 */
25
	public static $ad_tag_ids = array(
26
		'mrec' => array(
27
			'tag'       => '300x250_mediumrectangle',
28
			'height'    => '250',
29
			'width'     => '300',
30
		),
31
		'lrec' => array(
32
			'tag'       => '336x280_largerectangle',
33
			'height'    => '280',
34
			'width'     => '336',
35
		),
36
		'leaderboard' => array(
37
			'tag'       => '728x90_leaderboard',
38
			'height'    => '90',
39
			'width'     => '728',
40
		),
41
		'wideskyscraper' => array(
42
			'tag'       => '160x600_wideskyscraper',
43
			'height'    => '600',
44
			'width'     => '160',
45
		),
46
	);
47
48
	/**
49
	 * Convenience function for grabbing options from params->options
50
	 *
51
	 * @param  string $option the option to grab
52
	 * @param  mixed  $default (optional)
53
	 * @return option or $default if not set
54
	 *
55
	 * @since 4.5.0
56
	 */
57
	function option( $option, $default = false ) {
58
		if ( ! isset( $this->params->options[ $option ] ) ) {
59
			return $default;
60
		}
61
62
		return $this->params->options[ $option ];
63
	}
64
65
	/**
66
	 * Instantiate the plugin
67
	 *
68
	 * @since 4.5.0
69
	 */
70
	function __construct() {
71
		add_action( 'init', array( $this, 'init' ) );
72
	}
73
74
	/**
75
	 * Code to run on WordPress 'init' hook
76
	 *
77
	 * @since 4.5.0
78
	 */
79
	function init() {
80
		// bail on infinite scroll
81
		if ( self::is_infinite_scroll() ) {
82
			return;
83
		}
84
85
		require_once( WORDADS_ROOT . '/php/params.php' );
86
		$this->params = new WordAds_Params();
87
88
		if ( is_admin() ) {
89
			require_once( WORDADS_ROOT . '/php/admin.php' );
90
			return;
91
		}
92
93
		if ( $this->should_bail() ) {
94
			return;
95
		}
96
97
		$this->insert_adcode();
98
99
		if ( '/ads.txt' === $_SERVER['REQUEST_URI'] ) {
100
101
			if ( false === ( $ads_txt_transient = get_transient( 'jetpack_ads_txt' ) ) ) {
102
				$ads_txt_transient = ! is_wp_error( WordAds_API::get_wordads_ads_txt() ) ? WordAds_API::get_wordads_ads_txt() : '';
103
				set_transient( 'jetpack_ads_txt', $ads_txt_transient, DAY_IN_SECONDS );
104
			}
105
106
			/**
107
			 * Provide plugins a way of modifying the contents of the automatically-generated ads.txt file.
108
			 *
109
			 * @module wordads
110
			 *
111
			 * @since 6.1.0
112
			 *
113
			 * @param string WordAds_API::get_wordads_ads_txt() The contents of the ads.txt file.
114
			 */
115
			$ads_txt_content = apply_filters( 'wordads_ads_txt', $ads_txt_transient );
116
117
			header( 'Content-Type: text/plain; charset=utf-8' );
118
			echo esc_html( $ads_txt_content );
119
			die();
120
		}
121
	}
122
123
	/**
124
	 * Check for Jetpack's The_Neverending_Home_Page and use got_infinity
125
	 *
126
	 * @return boolean true if load came from infinite scroll
127
	 *
128
	 * @since 4.5.0
129
	 */
130
	public static function is_infinite_scroll() {
131
		return class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::got_infinity();
132
	}
133
134
	/**
135
	 * Add the actions/filters to insert the ads. Checks for mobile or desktop.
136
	 *
137
	 * @since 4.5.0
138
	 */
139
	private function insert_adcode() {
140
		add_action( 'wp_head',              array( $this, 'insert_head_meta' ), 20 );
141
		add_action( 'wp_head',              array( $this, 'insert_head_iponweb' ), 30 );
142
		add_action( 'wp_enqueue_scripts',   array( $this, 'enqueue_scripts' ) );
143
		add_filter( 'wordads_ads_txt',      array( $this, 'insert_custom_adstxt' ) );
144
145
		/**
146
		 * Filters enabling ads in `the_content` filter
147
		 *
148
		 * @see https://jetpack.com/support/ads/
149
		 *
150
		 * @module wordads
151
		 *
152
		 * @since 5.8.0
153
		 *
154
		 * @param bool True to disable ads in `the_content`
155
		 */
156
		if ( ! apply_filters( 'wordads_content_disable', false ) ) {
157
			add_filter( 'the_content', array( $this, 'insert_ad' ) );
158
		}
159
160
		/**
161
		 * Filters enabling ads in `the_excerpt` filter
162
		 *
163
		 * @see https://jetpack.com/support/ads/
164
		 *
165
		 * @module wordads
166
		 *
167
		 * @since 5.8.0
168
		 *
169
		 * @param bool True to disable ads in `the_excerpt`
170
		 */
171
		if ( ! apply_filters( 'wordads_excerpt_disable', false ) ) {
172
			add_filter( 'the_excerpt', array( $this, 'insert_ad' ) );
173
		}
174
175
		if ( $this->option( 'enable_header_ad', true ) ) {
176
			switch ( get_stylesheet() ) {
177
				case 'twentyseventeen':
178
				case 'twentyfifteen':
179
				case 'twentyfourteen':
180
					add_action( 'wp_footer', array( $this, 'insert_header_ad_special' ) );
181
					break;
182
				default:
183
					add_action( 'wp_head', array( $this, 'insert_header_ad' ), 100 );
184
					break;
185
			}
186
		}
187
	}
188
189
	/**
190
	 * Register desktop scripts and styles
191
	 *
192
	 * @since 4.5.0
193
	 */
194
	function enqueue_scripts() {
195
		wp_enqueue_style(
196
			'wordads',
197
			WORDADS_URL . 'css/style.css',
198
			array(),
199
			'2015-12-18'
200
		);
201
	}
202
203
	/**
204
	 * IPONWEB metadata used by the various scripts
205
	 * @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...
206
	 */
207
	function insert_head_meta() {
208
		$themename = esc_js( get_stylesheet() );
209
		$pagetype = intval( $this->params->get_page_type_ipw() );
210
		$data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
211
		$site_id = $this->params->blog_id;
212
		$consent = intval( isset( $_COOKIE['personalized-ads-consent'] ) );
213
		echo <<<HTML
214
		<script$data_tags type="text/javascript">
215
			var __ATA_PP = { pt: $pagetype, ht: 2, tn: '$themename', amp: false, siteid: $site_id, consent: $consent };
216
			var __ATA = __ATA || {};
217
			__ATA.cmd = __ATA.cmd || [];
218
			__ATA.criteo = __ATA.criteo || {};
219
			__ATA.criteo.cmd = __ATA.criteo.cmd || [];
220
		</script>
221
HTML;
222
	}
223
224
	/**
225
	 * IPONWEB scripts in <head>
226
	 *
227
	 * @since 4.5.0
228
	 */
229
	function insert_head_iponweb() {
230
		$data_tags = ( $this->params->cloudflare ) ? ' data-cfasync="false"' : '';
231
		echo <<<HTML
232
		<link rel='dns-prefetch' href='//s.pubmine.com' />
233
		<link rel='dns-prefetch' href='//x.bidswitch.net' />
234
		<link rel='dns-prefetch' href='//static.criteo.net' />
235
		<link rel='dns-prefetch' href='//ib.adnxs.com' />
236
		<link rel='dns-prefetch' href='//aax.amazon-adsystem.com' />
237
		<link rel='dns-prefetch' href='//bidder.criteo.com' />
238
		<link rel='dns-prefetch' href='//cas.criteo.com' />
239
		<link rel='dns-prefetch' href='//gum.criteo.com' />
240
		<link rel='dns-prefetch' href='//ads.pubmatic.com' />
241
		<link rel='dns-prefetch' href='//gads.pubmatic.com' />
242
		<link rel='dns-prefetch' href='//tpc.googlesyndication.com' />
243
		<link rel='dns-prefetch' href='//ad.doubleclick.net' />
244
		<link rel='dns-prefetch' href='//googleads.g.doubleclick.net' />
245
		<link rel='dns-prefetch' href='//www.googletagservices.com' />
246
		<script$data_tags async type="text/javascript" src="//s.pubmine.com/head.js"></script>
247
HTML;
248
	}
249
250
	/**
251
	 * Insert the ad onto the page
252
	 *
253
	 * @since 4.5.0
254
	 */
255
	function insert_ad( $content ) {
256
		// Don't insert ads in feeds, or for anything but the main display. (This is required for compatibility with the Publicize module).
257
		if ( is_feed() || ! is_main_query() || ! in_the_loop() ) {
258
			return $content;
259
		}
260
		/**
261
		 * Allow third-party tools to disable the display of in post ads.
262
		 *
263
		 * @module wordads
264
		 *
265
		 * @since 4.5.0
266
		 *
267
		 * @param bool true Should the in post unit be disabled. Default to false.
268
		 */
269
		$disable = apply_filters( 'wordads_inpost_disable', false );
270
		if ( ! $this->params->should_show() || $disable ) {
271
			return $content;
272
		}
273
274
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
275
		return $content . $this->get_ad( 'belowpost', $ad_type );
276
	}
277
278
	/**
279
	 * Insert an inline ad into a post content
280
	 * Used for rendering the `wordads` shortcode.
281
	 *
282
	 * @since 6.1.0
283
	 */
284
	function insert_inline_ad( $content ) {
285
		// Ad JS won't work in XML feeds.
286
		if ( is_feed() ) {
287
			return $content;
288
		}
289
		/**
290
		 * Allow third-party tools to disable the display of in post ads.
291
		 *
292
		 * @module wordads
293
		 *
294
		 * @since 4.5.0
295
		 *
296
		 * @param bool true Should the in post unit be disabled. Default to false.
297
		 */
298
		$disable = apply_filters( 'wordads_inpost_disable', false );
299
		if ( $disable ) {
300
			return $content;
301
		}
302
303
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
304
		$content .= $this->get_ad( 'inline', $ad_type );
305
		return $content;
306
	}
307
308
	/**
309
	 * Inserts ad into header
310
	 *
311
	 * @since 4.5.0
312
	 */
313
	function insert_header_ad() {
314
		/**
315
		 * Allow third-party tools to disable the display of header ads.
316
		 *
317
		 * @module wordads
318
		 *
319
		 * @since 4.5.0
320
		 *
321
		 * @param bool true Should the header unit be disabled. Default to false.
322
		 */
323
		if ( apply_filters( 'wordads_header_disable', false ) ) {
324
			return;
325
		}
326
327
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
328
		echo $this->get_ad( 'top', $ad_type );
329
	}
330
331
	/**
332
	 * Special cases for inserting header unit via jQuery
333
	 *
334
	 * @since 4.5.0
335
	 */
336
	function insert_header_ad_special() {
337
		/**
338
		 * Allow third-party tools to disable the display of header ads.
339
		 *
340
		 * @module wordads
341
		 *
342
		 * @since 4.5.0
343
		 *
344
		 * @param bool true Should the header unit be disabled. Default to false.
345
		 */
346
		if ( apply_filters( 'wordads_header_disable', false ) ) {
347
			return;
348
		}
349
350
		$selector = '#content';
351
		switch ( get_stylesheet() ) {
352
			case 'twentyseventeen':
353
				$selector = '#content';
354
				break;
355
			case 'twentyfifteen':
356
				$selector = '#main';
357
				break;
358
			case 'twentyfourteen':
359
				$selector = 'article:first';
360
				break;
361
		}
362
363
		$ad_type = $this->option( 'wordads_house' ) ? 'house' : 'iponweb';
364
		echo $this->get_ad( 'top', $ad_type );
365
		echo <<<HTML
366
		<script type="text/javascript">
367
			jQuery('.wpcnt-header').insertBefore('$selector');
368
		</script>
369
HTML;
370
	}
371
372
	/**
373
	 * Filter the latest ads.txt to include custom user entries. Strips any tags or whitespace.
374
	 * @param  string $adstxt The ads.txt being filtered
375
	 * @return string         Filtered ads.txt with custom entries, if applicable
376
	 *
377
	 * @since 6.5.0
378
	 */
379
	function insert_custom_adstxt( $adstxt ) {
380
		$custom_adstxt = trim( wp_strip_all_tags( $this->option( 'wordads_custom_adstxt' ) ) );
381
		if ( $custom_adstxt ) {
382
			$adstxt .= "\n\n#Jetpack - User Custom Entries\n";
383
			$adstxt .= $custom_adstxt . "\n";
384
		}
385
386
		return $adstxt;
387
	}
388
389
	/**
390
	 * Get the ad for the spot and type.
391
	 * @param  string $spot top, side, inline, or belowpost
392
	 * @param  string $type iponweb or adsense
393
	 */
394
	function get_ad( $spot, $type = 'iponweb' ) {
395
		$snippet = '';
396
		if ( 'iponweb' == $type ) {
397
			// Default to mrec
398
			$width = 300;
399
			$height = 250;
400
401
			$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...
402
			$second_belowpost = '';
0 ignored issues
show
Unused Code introduced by
$second_belowpost 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...
403
			$snippet = '';
404
			if ( 'top' == $spot ) {
405
				// mrec for mobile, leaderboard for desktop
406
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '2';
407
				$width = $this->params->mobile_device ? 300 : 728;
408
				$height = $this->params->mobile_device ? 250 : 90;
409
				$snippet = $this->get_ad_snippet( $section_id, $height, $width, $spot );
410
			} else if ( 'belowpost' == $spot ) {
411
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '1';
412
				$width = 300;
413
				$height = 250;
414
415
				$snippet = $this->get_ad_snippet( $section_id, $height, $width, $spot, 'float:left;margin-right:5px;margin-top:0px;' );
416
				if ( $this->option( 'wordads_second_belowpost', true ) ) {
417
					$section_id2 = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID2 : $this->params->blog_id . '4';
418
					$snippet .= $this->get_ad_snippet( $section_id2, $height, $width, $spot, 'float:left;margin-top:0px;' );
419
				}
420
			} else if ( 'inline' === $spot ) {
421
				$section_id = 0 === $this->params->blog_id ? WORDADS_API_TEST_ID : $this->params->blog_id . '5';
422
				$snippet = $this->get_ad_snippet( $section_id, $height, $width, $spot, 'mrec', 'float:left;margin-right:5px;margin-top:0px;' );
0 ignored issues
show
Unused Code introduced by
The call to WordAds::get_ad_snippet() has too many arguments starting with 'float:left;margin-right:5px;margin-top:0px;'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
423
			}
424
		} else if ( 'house' == $type ) {
425
			$leaderboard = 'top' == $spot && ! $this->params->mobile_device;
426
			$snippet = $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
427
			if ( 'belowpost' == $spot && $this->option( 'wordads_second_belowpost', true ) ) {
428
				$snippet .= $this->get_house_ad( $leaderboard ? 'leaderboard' : 'mrec' );
429
			}
430
		}
431
432
		$header = 'top' == $spot ? 'wpcnt-header' : '';
433
		$about = __( 'Advertisements', 'jetpack' );
434
		return <<<HTML
435
		<div class="wpcnt $header">
436
			<div class="wpa">
437
				<span class="wpa-about">$about</span>
438
				<div class="u $spot">
439
					$snippet
440
				</div>
441
			</div>
442
		</div>
443
HTML;
444
	}
445
446
447
	/**
448
	 * Returns the snippet to be inserted into the ad unit
449
	 * @param  int $section_id
450
	 * @param  int $height
451
	 * @param  int $width
452
	 * @param  int $location
0 ignored issues
show
Documentation introduced by
Should the type for parameter $location not be string|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
453
	 * @param  string $css
454
	 * @return string
455
	 *
456
	 * @since 5.7
457
	 */
458
	function get_ad_snippet( $section_id, $height, $width, $location = '', $css = '' ) {
459
		$this->ads[] = array( 'location' => $location, 'width' => $width, 'height' => $height );
460
		$ad_number = count( $this->ads );
461
		// Max 6 ads per page.
462
		if ( $ad_number > 5 && 'top' !== $location ) {
463
			return;
464
		}
465
		$data_tags = $this->params->cloudflare ? ' data-cfasync="false"' : '';
466
467
		return <<<HTML
468
		<div style="padding-bottom:15px;width:{$width}px;height:{$height}px;$css">
469
			<div id="atatags-{$ad_number}">
470
				<script$data_tags type="text/javascript">
471
				__ATA.cmd.push(function() {
472
					__ATA.initSlot('atatags-{$ad_number}',  {
473
						collapseEmpty: 'before',
474
						sectionId: '{$section_id}',
475
						location: '{$location}',
476
						width: {$width},
477
						height: {$height}
478
					});
479
				});
480
				</script>
481
			</div>
482
		</div>
483
HTML;
484
	}
485
486
	/**
487
	 * Check the reasons to bail before we attempt to insert ads.
488
	 * @return true if we should bail (don't insert ads)
489
	 *
490
	 * @since 4.5.0
491
	 */
492
	public function should_bail() {
493
		return ! $this->option( 'wordads_approved' ) || !! $this->option( 'wordads_unsafe' );
494
	}
495
496
	/**
497
	 * Returns markup for HTML5 house ad base on unit
498
	 * @param  string $unit mrec, widesky, or leaderboard
499
	 * @return string       markup for HTML5 house ad
500
	 *
501
	 * @since 4.7.0
502
	 */
503
	public function get_house_ad( $unit = 'mrec' ) {
504
505
		switch ( $unit ) {
506
			case 'widesky':
507
				$width  = 160;
508
				$height = 600;
509
				break;
510
			case 'leaderboard':
511
				$width  = 728;
512
				$height = 90;
513
				break;
514
			case 'mrec':
515
			default:
516
				$width  = 300;
517
				$height = 250;
518
				break;
519
		}
520
521
		return <<<HTML
522
		<iframe
523
			src="https://s0.wp.com/wp-content/blog-plugins/wordads/house/html5/$unit/index.html"
524
			width="$width"
525
			height="$height"
526
			frameborder="0"
527
			scrolling="no"
528
			marginheight="0"
529
			marginwidth="0">
530
		</iframe>
531
HTML;
532
	}
533
534
	/**
535
	 * Activation hook actions
536
	 *
537
	 * @since 4.5.0
538
	 */
539
	public static function activate() {
540
		WordAds_API::update_wordads_status_from_api();
541
	}
542
}
543
544
add_action( 'jetpack_activate_module_wordads', array( 'WordAds', 'activate' ) );
545
add_action( 'jetpack_activate_module_wordads', array( 'WordAds_Cron', 'activate' ) );
546
add_action( 'jetpack_deactivate_module_wordads', array( 'WordAds_Cron', 'deactivate' ) );
547
548
global $wordads;
549
$wordads = new WordAds();
550