Completed
Push — update/admin-page-readme-more-... ( 8f2301...4565b6 )
by
unknown
11:51
created

Jetpack_RelatedPosts::_get_related_post_ids()   D

Complexity

Conditions 19
Paths 66

Size

Total Lines 94
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 19
eloc 54
nc 66
nop 3
dl 0
loc 94
rs 4.764
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
class Jetpack_RelatedPosts {
3
	const VERSION = '20150408';
4
	const SHORTCODE = 'jetpack-related-posts';
5
6
	/**
7
	 * Creates and returns a static instance of Jetpack_RelatedPosts.
8
	 *
9
	 * @return Jetpack_RelatedPosts
10
	 */
11 View Code Duplication
	public static function init() {
12
		static $instance = NULL;
13
14
		if ( ! $instance ) {
15
			if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init' ) ) {
16
				$instance = WPCOM_RelatedPosts::init();
17
			} else {
18
				$instance = new Jetpack_RelatedPosts(
19
					get_current_blog_id(),
20
					Jetpack_Options::get_option( 'id' )
21
				);
22
			}
23
		}
24
25
		return $instance;
26
	}
27
28
	/**
29
	 * Creates and returns a static instance of Jetpack_RelatedPosts_Raw.
30
	 *
31
	 * @return Jetpack_RelatedPosts
32
	 */
33 View Code Duplication
	public static function init_raw() {
34
		static $instance = NULL;
35
36
		if ( ! $instance ) {
37
			if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init_raw' ) ) {
38
				$instance = WPCOM_RelatedPosts::init_raw();
39
			} else {
40
				$instance = new Jetpack_RelatedPosts_Raw(
41
					get_current_blog_id(),
42
					Jetpack_Options::get_option( 'id' )
43
				);
44
			}
45
		}
46
47
		return $instance;
48
	}
49
50
	protected $_blog_id_local;
51
	protected $_blog_id_wpcom;
52
	protected $_options;
53
	protected $_allow_feature_toggle;
54
	protected $_blog_charset;
55
	protected $_convert_charset;
56
	protected $_previous_post_id;
57
	protected $_found_shortcode = false;
58
59
	/**
60
	 * Constructor for Jetpack_RelatedPosts.
61
	 *
62
	 * @param int $blog_id_local
63
	 * @param int $blog_id_wpcom
64
	 * @uses get_option, add_action, apply_filters
65
	 * @return null
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
66
	 */
67
	public function __construct( $blog_id_local, $blog_id_wpcom ) {
68
		$this->_blog_id_local = $blog_id_local;
69
		$this->_blog_id_wpcom = $blog_id_wpcom;
70
		$this->_blog_charset = get_option( 'blog_charset' );
71
		$this->_convert_charset = ( function_exists( 'iconv' ) && ! preg_match( '/^utf\-?8$/i', $this->_blog_charset ) );
72
73
		add_action( 'admin_init', array( $this, 'action_admin_init' ) );
74
		add_action( 'wp', array( $this, 'action_frontend_init' ) );
75
76
		if ( ! class_exists( 'Jetpack_Media_Summary' ) ) {
77
			jetpack_require_lib( 'class.media-summary' );
78
		}
79
	}
80
81
	/**
82
	 * =================
83
	 * ACTIONS & FILTERS
84
	 * =================
85
	 */
86
87
	/**
88
	 * Add a checkbox field to Settings > Reading for enabling related posts.
89
	 *
90
	 * @action admin_init
91
	 * @uses add_settings_field, __, register_setting, add_action
92
	 * @return null
93
	 */
94
	public function action_admin_init() {
95
96
		// Add the setting field [jetpack_relatedposts] and place it in Settings > Reading
97
		add_settings_field( 'jetpack_relatedposts', '<span id="jetpack_relatedposts">' . __( 'Related posts', 'jetpack' ) . '</span>', array( $this, 'print_setting_html' ), 'reading' );
98
		register_setting( 'reading', 'jetpack_relatedposts', array( $this, 'parse_options' ) );
99
		add_action('admin_head', array( $this, 'print_setting_head' ) );
100
101
		if( 'options-reading.php' == $GLOBALS['pagenow'] ) {
102
			// Enqueue style for live preview on the reading settings page
103
			$this->_enqueue_assets( false, true );
104
		}
105
	}
106
107
	/**
108
	 * Load related posts assets if it's a elegiable front end page or execute search and return JSON if it's an endpoint request.
109
	 *
110
	 * @global $_GET
111
	 * @action wp
112
	 * @uses add_shortcode, get_the_ID
113
	 * @returns null
114
	 */
115
	public function action_frontend_init() {
116
		// Add a shortcode handler that outputs nothing, this gets overridden later if we can display related content
117
		add_shortcode( self::SHORTCODE, array( $this, 'get_target_html_unsupported' ) );
118
119
		if ( ! $this->_enabled_for_request() )
120
			return;
121
122
		if ( isset( $_GET['relatedposts'] ) ) {
123
			$excludes = array();
124
			if ( isset( $_GET['relatedposts_exclude'] ) ) {
125
				$excludes = explode( ',', $_GET['relatedposts_exclude'] );
126
			}
127
128
			$this->_action_frontend_init_ajax( $excludes );
129
		} else {
130
			if ( isset( $_GET['relatedposts_hit'], $_GET['relatedposts_origin'], $_GET['relatedposts_position'] ) ) {
131
				$this->_log_click( $_GET['relatedposts_origin'], get_the_ID(), $_GET['relatedposts_position'] );
132
				$this->_previous_post_id = (int) $_GET['relatedposts_origin'];
133
			}
134
135
			$this->_action_frontend_init_page();
136
		}
137
138
	}
139
140
	/**
141
	 * Adds a target to the post content to load related posts into if a shortcode for it did not already exist.
142
	 *
143
	 * @filter the_content
144
	 * @param string $content
145
	 * @returns string
146
	 */
147
	public function filter_add_target_to_dom( $content ) {
148
		if ( !$this->_found_shortcode ) {
149
			$content .= "\n" . $this->get_target_html();
150
		}
151
152
		return $content;
153
	}
154
155
	/**
156
	 * Looks for our shortcode on the unfiltered content, this has to execute early.
157
	 *
158
	 * @filter the_content
159
	 * @param string $content
160
	 * @uses has_shortcode
161
	 * @returns string
162
	 */
163
	public function test_for_shortcode( $content ) {
164
		$this->_found_shortcode = has_shortcode( $content, self::SHORTCODE );
165
166
		return $content;
167
	}
168
169
	/**
170
	 * Returns the HTML for the related posts section.
171
	 *
172
	 * @uses esc_html__, apply_filters
173
	 * @returns string
174
	 */
175
	public function get_target_html() {
176
		$options = $this->get_options();
177
178
		if ( $options['show_headline'] ) {
179
			$headline = sprintf(
180
				'<h3 class="jp-relatedposts-headline"><em>%s</em></h3>',
181
				esc_html__( 'Related', 'jetpack' )
182
			);
183
		} else {
184
			$headline = '';
185
		}
186
187
		/**
188
		 * Filter the Related Posts headline.
189
		 *
190
		 * @module related-posts
191
		 *
192
		 * @since 3.0.0
193
		 *
194
		 * @param string $headline Related Posts heading.
195
		 */
196
		$headline = apply_filters( 'jetpack_relatedposts_filter_headline', $headline );
197
198
		if ( $this->_previous_post_id ) {
199
			$exclude = "data-exclude='{$this->_previous_post_id}'";
200
		} else {
201
			$exclude = "";
202
		}
203
204
		return <<<EOT
205
<div id='jp-relatedposts' class='jp-relatedposts' $exclude>
206
	$headline
207
</div>
208
EOT;
209
	}
210
211
	/**
212
	 * Returns the HTML for the related posts section if it's running in the loop or other instances where we don't support related posts.
213
	 *
214
	 * @returns string
215
	 */
216
	public function get_target_html_unsupported() {
217
		return "\n\n<!-- Jetpack Related Posts is not supported in this context. -->\n\n";
218
	}
219
220
	/**
221
	 * ========================
222
	 * PUBLIC UTILITY FUNCTIONS
223
	 * ========================
224
	 */
225
226
	/**
227
	 * Gets options set for Jetpack_RelatedPosts and merge with defaults.
228
	 *
229
	 * @uses Jetpack_Options::get_option, apply_filters
230
	 * @return array
231
	 */
232
	public function get_options() {
233
		if ( null === $this->_options ) {
234
			$this->_options = Jetpack_Options::get_option( 'relatedposts', array() );
235
			if ( ! is_array( $this->_options ) )
236
				$this->_options = array();
237
			if ( ! isset( $this->_options['enabled'] ) )
238
				$this->_options['enabled'] = true;
239
			if ( ! isset( $this->_options['show_headline'] ) )
240
				$this->_options['show_headline'] = true;
241
			if ( ! isset( $this->_options['show_thumbnails'] ) )
242
				$this->_options['show_thumbnails'] = false;
243
			if ( empty( $this->_options['size'] ) || (int)$this->_options['size'] < 1 )
244
				$this->_options['size'] = 3;
245
246
			/**
247
			 * Filter Related Posts basic options.
248
			 *
249
			 * @module related-posts
250
			 *
251
			 * @since 2.8.0
252
			 *
253
			 * @param array $this->_options Array of basic Related Posts options.
254
			 */
255
			$this->_options = apply_filters( 'jetpack_relatedposts_filter_options', $this->_options );
256
		}
257
258
		return $this->_options;
259
	}
260
261
	/**
262
	 * Parses input and returnes normalized options array.
263
	 *
264
	 * @param array $input
265
	 * @uses self::get_options
266
	 * @return array
267
	 */
268
	public function parse_options( $input ) {
269
		$current = $this->get_options();
270
271
		if ( !is_array( $input ) )
272
			$input = array();
273
274
		if ( isset( $input['enabled'] ) && '1' == $input['enabled'] ) {
275
			$current['enabled'] = true;
276
			$current['show_headline'] = ( isset( $input['show_headline'] ) && '1' == $input['show_headline'] );
277
			$current['show_thumbnails'] = ( isset( $input['show_thumbnails'] ) && '1' == $input['show_thumbnails'] );
278
		} else {
279
			$current['enabled'] = false;
280
		}
281
282
		if ( isset( $input['size'] ) && (int)$input['size'] > 0 )
283
			$current['size'] = (int)$input['size'];
284
		else
285
			$current['size'] = null;
286
287
		return $current;
288
	}
289
290
	/**
291
	 * HTML for admin settings page.
292
	 *
293
	 * @uses self::get_options, checked, esc_html__
294
	 * @returns null
295
	 */
296
	public function print_setting_html() {
297
		$options = $this->get_options();
298
299
		$ui_settings_template = <<<EOT
300
<ul id="settings-reading-relatedposts-customize">
301
	<li>
302
		<label><input name="jetpack_relatedposts[show_headline]" type="checkbox" value="1" %s /> %s</label>
303
	</li>
304
	<li>
305
		<label><input name="jetpack_relatedposts[show_thumbnails]" type="checkbox" value="1" %s /> %s</label>
306
	</li>
307
</ul>
308
<div id='settings-reading-relatedposts-preview'>
309
	%s
310
	<div id="jp-relatedposts" class="jp-relatedposts"></div>
311
</div>
312
EOT;
313
		$ui_settings = sprintf(
314
			$ui_settings_template,
315
			checked( $options['show_headline'], true, false ),
316
			esc_html__( 'Show a "Related" header to more clearly separate the related section from posts', 'jetpack' ),
317
			checked( $options['show_thumbnails'], true, false ),
318
			esc_html__( 'Use a large and visually striking layout', 'jetpack' ),
319
			esc_html__( 'Preview:', 'jetpack' )
320
		);
321
322
		if ( !$this->_allow_feature_toggle() ) {
323
			$template = <<<EOT
324
<input type="hidden" name="jetpack_relatedposts[enabled]" value="1" />
325
%s
326
EOT;
327
			printf(
328
				$template,
329
				$ui_settings
330
			);
331
		} else {
332
			$template = <<<EOT
333
<ul id="settings-reading-relatedposts">
334
	<li>
335
		<label><input type="radio" name="jetpack_relatedposts[enabled]" value="0" class="tog" %s /> %s</label>
336
	</li>
337
	<li>
338
		<label><input type="radio" name="jetpack_relatedposts[enabled]" value="1" class="tog" %s /> %s</label>
339
		%s
340
	</li>
341
</ul>
342
EOT;
343
			printf(
344
				$template,
345
				checked( $options['enabled'], false, false ),
346
				esc_html__( 'Hide related content after posts', 'jetpack' ),
347
				checked( $options['enabled'], true, false ),
348
				esc_html__( 'Show related content after posts', 'jetpack' ),
349
				$ui_settings
350
			);
351
		}
352
	}
353
354
	/**
355
	 * Head JS/CSS for admin settings page.
356
	 *
357
	 * @uses esc_html__
358
	 * @returns null
359
	 */
360
	public function print_setting_head() {
361
362
		// only dislay the Related Posts JavaScript on the Reading Settings Admin Page
363
		$current_screen =  get_current_screen();
364
365
		if ( is_null( $current_screen ) ) {
366
			return;
367
		}
368
369
		if( 'options-reading' != $current_screen->id )
370
			return;
371
372
		$related_headline = sprintf(
373
			'<h3 class="jp-relatedposts-headline"><em>%s</em></h3>',
374
			esc_html__( 'Related', 'jetpack' )
375
		);
376
377
		$href_params = 'class="jp-relatedposts-post-a" href="#jetpack_relatedposts" rel="nofollow" data-origin="0" data-position="0"';
378
		$related_with_images = <<<EOT
379
<div class="jp-relatedposts-items jp-relatedposts-items-visual">
380
	<div class="jp-relatedposts-post jp-relatedposts-post0 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
381
		<a $href_params>
382
			<img class="jp-relatedposts-post-img" src="http://jetpackme.files.wordpress.com/2014/08/1-wpios-ipad-3-1-viewsite.png?w=350&amp;h=200&amp;crop=1" width="350" alt="Big iPhone/iPad Update Now Available" scale="0">
383
		</a>
384
		<h4 class="jp-relatedposts-post-title">
385
			<a $href_params>Big iPhone/iPad Update Now Available</a>
386
		</h4>
387
		<p class="jp-relatedposts-post-excerpt">Big iPhone/iPad Update Now Available</p>
388
		<p class="jp-relatedposts-post-context">In "Mobile"</p>
389
	</div>
390
	<div class="jp-relatedposts-post jp-relatedposts-post1 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
391
		<a $href_params>
392
			<img class="jp-relatedposts-post-img" src="http://jetpackme.files.wordpress.com/2014/08/wordpress-com-news-wordpress-for-android-ui-update2.jpg?w=350&amp;h=200&amp;crop=1" width="350" alt="The WordPress for Android App Gets a Big Facelift" scale="0">
393
		</a>
394
		<h4 class="jp-relatedposts-post-title">
395
			<a $href_params>The WordPress for Android App Gets a Big Facelift</a>
396
		</h4>
397
		<p class="jp-relatedposts-post-excerpt">The WordPress for Android App Gets a Big Facelift</p>
398
		<p class="jp-relatedposts-post-context">In "Mobile"</p>
399
	</div>
400
	<div class="jp-relatedposts-post jp-relatedposts-post2 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
401
		<a $href_params>
402
			<img class="jp-relatedposts-post-img" src="http://jetpackme.files.wordpress.com/2014/08/videopresswedding.jpg?w=350&amp;h=200&amp;crop=1" width="350" alt="Upgrade Focus: VideoPress For Weddings" scale="0">
403
		</a>
404
		<h4 class="jp-relatedposts-post-title">
405
			<a $href_params>Upgrade Focus: VideoPress For Weddings</a>
406
		</h4>
407
		<p class="jp-relatedposts-post-excerpt">Upgrade Focus: VideoPress For Weddings</p>
408
		<p class="jp-relatedposts-post-context">In "Upgrade"</p>
409
	</div>
410
</div>
411
EOT;
412
		$related_with_images = str_replace( "\n", '', $related_with_images );
413
		$related_without_images = <<<EOT
414
<div class="jp-relatedposts-items jp-relatedposts-items-minimal">
415
	<p class="jp-relatedposts-post jp-relatedposts-post0" data-post-id="0" data-post-format="image">
416
		<span class="jp-relatedposts-post-title"><a $href_params>Big iPhone/iPad Update Now Available</a></span>
417
		<span class="jp-relatedposts-post-context">In "Mobile"</span>
418
	</p>
419
	<p class="jp-relatedposts-post jp-relatedposts-post1" data-post-id="0" data-post-format="image">
420
		<span class="jp-relatedposts-post-title"><a $href_params>The WordPress for Android App Gets a Big Facelift</a></span>
421
		<span class="jp-relatedposts-post-context">In "Mobile"</span>
422
	</p>
423
	<p class="jp-relatedposts-post jp-relatedposts-post2" data-post-id="0" data-post-format="image">
424
		<span class="jp-relatedposts-post-title"><a $href_params>Upgrade Focus: VideoPress For Weddings</a></span>
425
		<span class="jp-relatedposts-post-context">In "Upgrade"</span>
426
	</p>
427
</div>
428
EOT;
429
		$related_without_images = str_replace( "\n", '', $related_without_images );
430
431
		if ( $this->_allow_feature_toggle() ) {
432
			$extra_css = '#settings-reading-relatedposts-customize { padding-left:2em; margin-top:.5em; }';
433
		} else {
434
			$extra_css = '';
435
		}
436
437
		echo <<<EOT
438
<style type="text/css">
439
	#settings-reading-relatedposts .disabled { opacity:.5; filter:Alpha(opacity=50); }
440
	#settings-reading-relatedposts-preview .jp-relatedposts { background:#fff; padding:.5em; width:75%; }
441
	$extra_css
442
</style>
443
<script type="text/javascript">
444
	jQuery( document ).ready( function($) {
445
		var update_ui = function() {
446
			var is_enabled = true;
447
			if ( 'radio' == $( 'input[name="jetpack_relatedposts[enabled]"]' ).attr('type') ) {
448
				if ( '0' == $( 'input[name="jetpack_relatedposts[enabled]"]:checked' ).val() ) {
449
					is_enabled = false;
450
				}
451
			}
452
			if ( is_enabled ) {
453
				$( '#settings-reading-relatedposts-customize' )
454
					.removeClass( 'disabled' )
455
					.find( 'input' )
456
					.attr( 'disabled', false );
457
				$( '#settings-reading-relatedposts-preview' )
458
					.removeClass( 'disabled' );
459
			} else {
460
				$( '#settings-reading-relatedposts-customize' )
461
					.addClass( 'disabled' )
462
					.find( 'input' )
463
					.attr( 'disabled', true );
464
				$( '#settings-reading-relatedposts-preview' )
465
					.addClass( 'disabled' );
466
			}
467
		};
468
469
		var update_preview = function() {
470
			var html = '';
471
			if ( $( 'input[name="jetpack_relatedposts[show_headline]"]:checked' ).length ) {
472
				html += '$related_headline';
473
			}
474
			if ( $( 'input[name="jetpack_relatedposts[show_thumbnails]"]:checked' ).length ) {
475
				html += '$related_with_images';
476
			} else {
477
				html += '$related_without_images';
478
			}
479
			$( '#settings-reading-relatedposts-preview .jp-relatedposts' )
480
				.html( html )
481
				.show();
482
		};
483
484
		// Update on load
485
		update_preview();
486
		update_ui();
487
488
		// Update on change
489
		$( '#settings-reading-relatedposts-customize input' )
490
			.change( update_preview );
491
		$( '#settings-reading-relatedposts' )
492
			.find( 'input.tog' )
493
			.change( update_ui );
494
	});
495
</script>
496
EOT;
497
	}
498
499
	/**
500
	 * Gets an array of related posts that match the given post_id.
501
	 *
502
	 * @param int $post_id
503
	 * @param array $args - params to use when building ElasticSearch filters to narrow down the search domain.
504
	 * @uses self::get_options, get_post_type, wp_parse_args, apply_filters
505
	 * @return array
506
	 */
507
	public function get_for_post_id( $post_id, array $args ) {
508
		$options = $this->get_options();
509
510
		if ( ! empty( $args['size'] ) )
511
			$options['size'] = $args['size'];
512
513
		if ( ! $options['enabled'] || 0 == (int)$post_id || empty( $options['size'] ) )
514
			return array();
515
516
		$defaults = array(
517
			'size' => (int)$options['size'],
518
			'post_type' => get_post_type( $post_id ),
519
			'post_formats' => array(),
520
			'has_terms' => array(),
521
			'date_range' => array(),
522
			'exclude_post_ids' => array(),
523
		);
524
		$args = wp_parse_args( $args, $defaults );
525
		/**
526
		 * Filter the arguments used to retrieve a list of Related Posts.
527
		 *
528
		 * @module related-posts
529
		 *
530
		 * @since 2.8.0
531
		 *
532
		 * @param array $args Array of options to retrieve Related Posts.
533
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
534
		 */
535
		$args = apply_filters( 'jetpack_relatedposts_filter_args', $args, $post_id );
536
537
		$filters = $this->_get_es_filters_from_args( $post_id, $args );
538
		/**
539
		 * Filter ElasticSearch options used to calculate Related Posts.
540
		 *
541
		 * @module related-posts
542
		 *
543
		 * @since 2.8.0
544
		 *
545
		 * @param array $filters Array of ElasticSearch filters based on the post_id and args.
546
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
547
		 */
548
		$filters = apply_filters( 'jetpack_relatedposts_filter_filters', $filters, $post_id );
549
550
		$results = $this->_get_related_posts( $post_id, $args['size'], $filters );
551
		/**
552
		 * Filter the array of related posts matched by ElasticSearch.
553
		 *
554
		 * @module related-posts
555
		 *
556
		 * @since 2.8.0
557
		 *
558
		 * @param array $results Array of related posts matched by ElasticSearch.
559
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
560
		 */
561
		return apply_filters( 'jetpack_relatedposts_returned_results', $results, $post_id );
562
	}
563
564
	/**
565
	 * =========================
566
	 * PRIVATE UTILITY FUNCTIONS
567
	 * =========================
568
	 */
569
570
	/**
571
	 * Creates an array of ElasticSearch filters based on the post_id and args.
572
	 *
573
	 * @param int $post_id
574
	 * @param array $args
575
	 * @uses apply_filters, get_post_types, get_post_format_strings
576
	 * @return array
577
	 */
578
	protected function _get_es_filters_from_args( $post_id, array $args ) {
579
		$filters = array();
580
581
		/**
582
		 * Filter the terms used to search for Related Posts.
583
		 *
584
		 * @module related-posts
585
		 *
586
		 * @since 2.8.0
587
		 *
588
		 * @param array $args['has_terms'] Array of terms associated to the Related Posts.
589
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
590
		 */
591
		$args['has_terms'] = apply_filters( 'jetpack_relatedposts_filter_has_terms', $args['has_terms'], $post_id );
592
		if ( ! empty( $args['has_terms'] ) ) {
593
			foreach( (array)$args['has_terms'] as $term ) {
594
				if ( mb_strlen( $term->taxonomy ) ) {
595
					switch ( $term->taxonomy ) {
596
						case 'post_tag':
597
							$tax_fld = 'tag.slug';
598
							break;
599
						case 'category':
600
							$tax_fld = 'category.slug';
601
							break;
602
						default:
603
							$tax_fld = 'taxonomy.' . $term->taxonomy . '.slug';
604
							break;
605
					}
606
					$filters[] = array( 'term' => array( $tax_fld => $term->slug ) );
607
				}
608
			}
609
		}
610
611
		/**
612
		 * Filter the Post Types where we search Related Posts.
613
		 *
614
		 * @module related-posts
615
		 *
616
		 * @since 2.8.0
617
		 *
618
		 * @param array $args['post_type'] Array of Post Types.
619
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
620
		 */
621
		$args['post_type'] = apply_filters( 'jetpack_relatedposts_filter_post_type', $args['post_type'], $post_id );
622
		$valid_post_types = get_post_types();
623
		if ( is_array( $args['post_type'] ) ) {
624
			$sanitized_post_types = array();
625
			foreach ( $args['post_type'] as $pt ) {
626
				if ( in_array( $pt, $valid_post_types ) )
627
					$sanitized_post_types[] = $pt;
628
			}
629
			if ( ! empty( $sanitized_post_types ) )
630
				$filters[] = array( 'terms' => array( 'post_type' => $sanitized_post_types ) );
631
		} else if ( in_array( $args['post_type'], $valid_post_types ) && 'all' != $args['post_type'] ) {
632
			$filters[] = array( 'term' => array( 'post_type' => $args['post_type'] ) );
633
		}
634
635
		/**
636
		 * Filter the Post Formats where we search Related Posts.
637
		 *
638
		 * @module related-posts
639
		 *
640
		 * @since 3.3.0
641
		 *
642
		 * @param array $args['post_formats'] Array of Post Formats.
643
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
644
		 */
645
		$args['post_formats'] = apply_filters( 'jetpack_relatedposts_filter_post_formats', $args['post_formats'], $post_id );
646
		$valid_post_formats = get_post_format_strings();
647
		$sanitized_post_formats = array();
648
		foreach ( $args['post_formats'] as $pf ) {
649
			if ( array_key_exists( $pf, $valid_post_formats ) ) {
650
				$sanitized_post_formats[] = $pf;
651
			}
652
		}
653
		if ( ! empty( $sanitized_post_formats ) ) {
654
			$filters[] = array( 'terms' => array( 'post_format' => $sanitized_post_formats ) );
655
		}
656
657
		/**
658
		 * Filter the date range used to search Related Posts.
659
		 *
660
		 * @module related-posts
661
		 *
662
		 * @since 2.8.0
663
		 *
664
		 * @param array $args['date_range'] Array of a month interval where we search Related Posts.
665
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
666
		 */
667
		$args['date_range'] = apply_filters( 'jetpack_relatedposts_filter_date_range', $args['date_range'], $post_id );
668
		if ( is_array( $args['date_range'] ) && ! empty( $args['date_range'] ) ) {
669
			$args['date_range'] = array_map( 'intval', $args['date_range'] );
670
			if ( !empty( $args['date_range']['from'] ) && !empty( $args['date_range']['to'] ) ) {
671
				$filters[] = array(
672
					'range' => array(
673
						'date_gmt' => $this->_get_coalesced_range( $args['date_range'] ),
674
					)
675
				);
676
			}
677
		}
678
679
		/**
680
		 * Filter the Post IDs excluded from appearing in Related Posts.
681
		 *
682
		 * @module related-posts
683
		 *
684
		 * @since 2.9.0
685
		 *
686
		 * @param array $args['exclude_post_ids'] Array of Post IDs.
687
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
688
		 */
689
		$args['exclude_post_ids'] = apply_filters( 'jetpack_relatedposts_filter_exclude_post_ids', $args['exclude_post_ids'], $post_id );
690
		if ( !empty( $args['exclude_post_ids'] ) && is_array( $args['exclude_post_ids'] ) ) {
691
			foreach ( $args['exclude_post_ids'] as $exclude_post_id) {
692
				$exclude_post_id = (int)$exclude_post_id;
693
694
				if ( $exclude_post_id > 0 )
695
					$filters[] = array( 'not' => array( 'term' => array( 'post_id' => $exclude_post_id ) ) );
696
			}
697
		}
698
699
		return $filters;
700
	}
701
702
	/**
703
	 * Takes a range and coalesces it into a month interval bracketed by a time as determined by the blog_id to enhance caching.
704
	 *
705
	 * @param array $date_range
706
	 * @return array
707
	 */
708
	protected function _get_coalesced_range( array $date_range ) {
709
		$now = time();
710
		$coalesce_time = $this->_blog_id_wpcom % 86400;
711
		$current_time = $now - strtotime( 'today', $now );
712
713
		if ( $current_time < $coalesce_time && '01' == date( 'd', $now ) ) {
714
			// Move back 1 period
715
			return array(
716
				'from' => date( 'Y-m-01', strtotime( '-1 month', $date_range['from'] ) ) . ' ' . date( 'H:i:s', $coalesce_time ),
717
				'to'   => date( 'Y-m-01', $date_range['to'] ) . ' ' . date( 'H:i:s', $coalesce_time ),
718
			);
719
		} else {
720
			// Use current period
721
			return array(
722
				'from' => date( 'Y-m-01', $date_range['from'] ) . ' ' . date( 'H:i:s', $coalesce_time ),
723
				'to'   => date( 'Y-m-01', strtotime( '+1 month', $date_range['to'] ) ) . ' ' . date( 'H:i:s', $coalesce_time ),
724
			);
725
		}
726
	}
727
728
	/**
729
	 * Generate and output ajax response for related posts API call.
730
	 * NOTE: Calls exit() to end all further processing after payload has been outputed.
731
	 *
732
	 * @param array $excludes array of post_ids to exclude
733
	 * @uses send_nosniff_header, self::get_for_post_id, get_the_ID
734
	 * @return null
735
	 */
736
	protected function _action_frontend_init_ajax( array $excludes ) {
737
		define( 'DOING_AJAX', true );
738
739
		header( 'Content-type: application/json; charset=utf-8' ); // JSON can only be UTF-8
740
		send_nosniff_header();
741
742
		$related_posts = $this->get_for_post_id(
743
			get_the_ID(),
744
			array(
745
				'exclude_post_ids' => $excludes,
746
			)
747
		);
748
749
		$options = $this->get_options();
750
751
		$response = array(
752
			'version' => self::VERSION,
753
			'show_thumbnails' => (bool) $options['show_thumbnails'],
754
			'items' => array(),
755
		);
756
757
		if ( count( $related_posts ) == $options['size'] )
758
			$response['items'] = $related_posts;
759
760
		echo json_encode( $response );
761
762
		exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method _action_frontend_init_ajax() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
763
	}
764
765
	/**
766
	 * Returns a UTF-8 encoded array of post information for the given post_id
767
	 *
768
	 * @param int $post_id
769
	 * @param int $position
770
	 * @param int $origin The post id that this is related to
771
	 * @uses get_post, get_permalink, remove_query_arg, get_post_format, apply_filters
772
	 * @return array
773
	 */
774
	protected function _get_related_post_data_for_post( $post_id, $position, $origin ) {
775
		$post = get_post( $post_id );
776
777
		return array(
778
			'id' => $post->ID,
779
			'url' => get_permalink( $post->ID ),
780
			'url_meta' => array( 'origin' => $origin, 'position' => $position ),
781
			'title' => $this->_to_utf8( $this->_get_title( $post->post_title, $post->post_content ) ),
782
			'date' => get_the_date( '', $post->ID ),
783
			'format' => get_post_format( $post->ID ),
784
			'excerpt' => html_entity_decode( $this->_to_utf8( $this->_get_excerpt( $post->post_excerpt, $post->post_content ) ), ENT_QUOTES, 'UTF-8' ),
785
			/**
786
			 * Filters the rel attribute for the Related Posts' links.
787
			 *
788
			 * @module related-posts
789
			 *
790
			 * @since 3.7.0
791
			 *
792
			 * @param string nofollow Link rel attribute for Related Posts' link. Default is nofollow.
793
			 * @param int $post->ID Post ID.
794
			 */
795
			'rel' => apply_filters( 'jetpack_relatedposts_filter_post_link_rel', 'nofollow', $post->ID ),
796
			/**
797
			 * Filter the context displayed below each Related Post.
798
			 *
799
			 * @module related-posts
800
			 *
801
			 * @since 3.0.0
802
			 *
803
			 * @param string $this->_to_utf8( $this->_generate_related_post_context( $post->ID ) ) Context displayed below each related post.
804
			 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
805
			 */
806
			'context' => apply_filters(
807
				'jetpack_relatedposts_filter_post_context',
808
				$this->_to_utf8( $this->_generate_related_post_context( $post->ID ) ),
809
				$post->ID
810
			),
811
			'img' => $this->_generate_related_post_image_params( $post->ID ),
812
			/**
813
			 * Filter the post css classes added on HTML markup.
814
			 *
815
			 * @module related-posts
816
			 *
817
			 * @since 3.8.0
818
			 *
819
			 * @param array array() CSS classes added on post HTML markup.
820
			 * @param string $post_id Post ID.
821
			 */
822
			'classes' => apply_filters(
823
				'jetpack_relatedposts_filter_post_css_classes',
824
				array(),
825
				$post->ID
826
			),
827
		);
828
	}
829
830
	/**
831
	 * Returns either the title or a small excerpt to use as title for post.
832
	 *
833
	 * @param string $post_title
834
	 * @param string $post_content
835
	 * @uses strip_shortcodes, wp_trim_words, __
836
	 * @return string
837
	 */
838
	protected function _get_title( $post_title, $post_content ) {
839
		if ( ! empty( $post_title ) ) {
840
			return wp_strip_all_tags( $post_title );
841
		}
842
843
		$post_title = wp_trim_words( wp_strip_all_tags( strip_shortcodes( $post_content ) ), 5, '…' );
844
		if ( ! empty( $post_title ) ) {
845
			return $post_title;
846
		}
847
848
		return __( 'Untitled Post', 'jetpack' );
849
	}
850
851
	/**
852
	 * Returns a plain text post excerpt for title attribute of links.
853
	 *
854
	 * @param string $post_excerpt
855
	 * @param string $post_content
856
	 * @uses strip_shortcodes, wp_strip_all_tags, wp_trim_words
857
	 * @return string
858
	 */
859
	protected function _get_excerpt( $post_excerpt, $post_content ) {
860
		if ( empty( $post_excerpt ) )
861
			$excerpt = $post_content;
862
		else
863
			$excerpt = $post_excerpt;
864
865
		return wp_trim_words( wp_strip_all_tags( strip_shortcodes( $excerpt ) ), 50, '…' );
866
	}
867
868
	/**
869
	 * Generates the thumbnail image to be used for the post. Uses the
870
	 * image as returned by Jetpack_PostImages::get_image()
871
	 *
872
	 * @param int $post_id
873
	 * @uses self::get_options, apply_filters, Jetpack_PostImages::get_image, Jetpack_PostImages::fit_image_url
874
	 * @return string
875
	 */
876
	protected function _generate_related_post_image_params( $post_id ) {
877
		$options = $this->get_options();
878
		$image_params = array(
879
			'src' => '',
880
			'width' => 0,
881
			'height' => 0,
882
		);
883
884
		if ( ! $options['show_thumbnails'] ) {
885
			return $image_params;
886
		}
887
888
		/**
889
		 * Filter the size of the Related Posts images.
890
		 *
891
		 * @module related-posts
892
		 *
893
		 * @since 2.8.0
894
		 *
895
		 * @param array array( 'width' => 350, 'height' => 200 ) Size of the images displayed below each Related Post.
896
		 */
897
		$thumbnail_size = apply_filters(
898
			'jetpack_relatedposts_filter_thumbnail_size',
899
			array( 'width' => 350, 'height' => 200 )
900
		);
901
		if ( !is_array( $thumbnail_size ) ) {
902
			$thumbnail_size = array(
903
				'width' => (int)$thumbnail_size,
904
				'height' => (int)$thumbnail_size
905
			);
906
		}
907
908
		// Try to get post image
909
		if ( class_exists( 'Jetpack_PostImages' ) ) {
910
			$img_url = '';
911
			$post_image = Jetpack_PostImages::get_image(
912
				$post_id,
913
				$thumbnail_size
914
			);
915
916
			if ( is_array($post_image) ) {
917
				$img_url = $post_image['src'];
918
			} elseif ( class_exists( 'Jetpack_Media_Summary' ) ) {
919
				$media = Jetpack_Media_Summary::get( $post_id );
920
921
				if ( is_array($media) && !empty( $media['image'] ) ) {
922
					$img_url = $media['image'];
923
				}
924
			}
925
926
			if ( !empty( $img_url ) ) {
927
				$image_params['width'] = $thumbnail_size['width'];
928
				$image_params['height'] = $thumbnail_size['height'];
929
				$image_params['src'] = Jetpack_PostImages::fit_image_url(
930
					$img_url,
931
					$thumbnail_size['width'],
932
					$thumbnail_size['height']
933
				);
934
			}
935
		}
936
937
		return $image_params;
938
	}
939
940
	/**
941
	 * Returns the string UTF-8 encoded
942
	 *
943
	 * @param string $text
944
	 * @return string
945
	 */
946
	protected function _to_utf8( $text ) {
947
		if ( $this->_convert_charset ) {
948
			return iconv( $this->_blog_charset, 'UTF-8', $text );
949
		} else {
950
			return $text;
951
		}
952
	}
953
954
	/**
955
	 * =============================================
956
	 * PROTECTED UTILITY FUNCTIONS EXTENDED BY WPCOM
957
	 * =============================================
958
	 */
959
960
	/**
961
	 * Workhorse method to return array of related posts matched by ElasticSearch.
962
	 *
963
	 * @param int $post_id
964
	 * @param int $size
965
	 * @param array $filters
966
	 * @uses wp_remote_post, is_wp_error, get_option, wp_remote_retrieve_body, get_post, add_query_arg, remove_query_arg, get_permalink, get_post_format, apply_filters
967
	 * @return array
968
	 */
969
	protected function _get_related_posts( $post_id, $size, array $filters ) {
970
		$hits = $this->_filter_non_public_posts(
971
			$this->_get_related_post_ids(
972
				$post_id,
973
				$size,
974
				$filters
975
			)
976
		);
977
978
		/**
979
		 * Filter the Related Posts matched by ElasticSearch.
980
		 *
981
		 * @module related-posts
982
		 *
983
		 * @since 2.9.0
984
		 *
985
		 * @param array $hits Array of Post IDs matched by ElasticSearch.
986
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
987
		 */
988
		$hits = apply_filters( 'jetpack_relatedposts_filter_hits', $hits, $post_id );
989
990
		$related_posts = array();
991
		foreach ( $hits as $i => $hit ) {
992
			$related_posts[] = $this->_get_related_post_data_for_post( $hit['id'], $i, $post_id );
993
		}
994
		return $related_posts;
995
	}
996
997
	/**
998
	 * Get array of related posts matched by ElasticSearch.
999
	 *
1000
	 * @param int $post_id
1001
	 * @param int $size
1002
	 * @param array $filters
1003
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body, get_post_meta, update_post_meta
1004
	 * @return array
1005
	 */
1006
	protected function _get_related_post_ids( $post_id, $size, array $filters ) {
1007
		$now_ts = time();
1008
		$cache_meta_key = '_jetpack_related_posts_cache';
1009
1010
		$body = array(
1011
			'size' => (int) $size,
1012
		);
1013
1014
		if ( !empty( $filters ) )
1015
			$body['filter'] = array( 'and' => $filters );
1016
1017
		// Build cache key
1018
		$cache_key = md5( serialize( $body ) );
1019
1020
		// Load all cached values
1021
		if ( wp_using_ext_object_cache() ) {
1022
			$transient_name = "{$cache_meta_key}_{$cache_key}_{$post_id}";
1023
			$cache = get_transient( $transient_name );
1024
			if ( false !== $cache ) {
1025
				return $cache;
1026
			}
1027
		} else {
1028
			$cache = get_post_meta( $post_id, $cache_meta_key, true );
1029
1030
			if ( empty( $cache ) )
1031
				$cache = array();
1032
1033
1034
			// Cache is valid! Return cached value.
1035
			if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) && $cache[ $cache_key ][ 'expires' ] > $now_ts ) {
1036
				return $cache[ $cache_key ][ 'payload' ];
1037
			}
1038
		}
1039
1040
		$response = wp_remote_post(
1041
			"https://public-api.wordpress.com/rest/v1/sites/{$this->_blog_id_wpcom}/posts/$post_id/related/",
1042
			array(
1043
				'timeout' => 10,
1044
				'user-agent' => 'jetpack_related_posts',
1045
				'sslverify' => true,
1046
				'body' => $body,
1047
			)
1048
		);
1049
1050
		// Oh no... return nothing don't cache errors.
1051
		if ( is_wp_error( $response ) ) {
1052
			if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) )
1053
				return $cache[ $cache_key ][ 'payload' ]; // return stale
1054
			else
1055
				return array();
1056
		}
1057
1058
		$results = json_decode( wp_remote_retrieve_body( $response ), true );
1059
		$related_posts = array();
1060
		if ( is_array( $results ) && !empty( $results['hits'] ) ) {
1061
			foreach( $results['hits'] as $hit ) {
1062
				$related_posts[] = array(
1063
					'id' => $hit['fields']['post_id'],
1064
				);
1065
			}
1066
		}
1067
1068
		// An empty array might indicate no related posts or that posts
1069
		// are not yet synced to WordPress.com, so we cache for only 1
1070
		// minute in this case
1071
		if ( empty( $related_posts ) ) {
1072
			$cache_ttl = 60;
1073
		} else {
1074
			$cache_ttl = 12 * HOUR_IN_SECONDS;
1075
		}
1076
1077
		// Update cache
1078
		if ( wp_using_ext_object_cache() ) {
1079
			set_transient( $transient_name, $related_posts, $cache_ttl );
0 ignored issues
show
Bug introduced by
The variable $transient_name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1080
		} else {
1081
			// Copy all valid cache values
1082
			$new_cache = array();
1083
			foreach ( $cache as $k => $v ) {
1084
				if ( is_array( $v ) && $v[ 'expires' ] > $now_ts ) {
1085
					$new_cache[ $k ] = $v;
1086
				}
1087
			}
1088
1089
			// Set new cache value
1090
			$cache_expires = $cache_ttl + $now_ts;
1091
			$new_cache[ $cache_key ] = array(
1092
				'expires' => $cache_expires,
1093
				'payload' => $related_posts,
1094
			);
1095
			update_post_meta( $post_id, $cache_meta_key, $new_cache );
1096
		}
1097
1098
		return $related_posts;
1099
	}
1100
1101
	/**
1102
	 * Filter out any hits that are not public anymore.
1103
	 *
1104
	 * @param array $related_posts
1105
	 * @uses get_post_stati, get_post_status
1106
	 * @return array
1107
	 */
1108
	protected function _filter_non_public_posts( array $related_posts ) {
1109
		$public_stati = get_post_stati( array( 'public' => true ) );
1110
1111
		$filtered = array();
1112
		foreach ( $related_posts as $hit ) {
1113
			if ( in_array( get_post_status( $hit['id'] ), $public_stati ) ) {
1114
				$filtered[] = $hit;
1115
			}
1116
		}
1117
		return $filtered;
1118
	}
1119
1120
	/**
1121
	 * Generates a context for the related content (second line in related post output).
1122
	 * Order of importance:
1123
	 *   - First category (Not 'Uncategorized')
1124
	 *   - First post tag
1125
	 *   - Number of comments
1126
	 *
1127
	 * @param int $post_id
1128
	 * @uses get_the_category, get_the_terms, get_comments_number, number_format_i18n, __, _n
1129
	 * @return string
1130
	 */
1131
	protected function _generate_related_post_context( $post_id ) {
1132
		$categories = get_the_category( $post_id );
1133 View Code Duplication
		if ( is_array( $categories ) ) {
1134
			foreach ( $categories as $category ) {
1135
				if ( 'uncategorized' != $category->slug && '' != trim( $category->name ) ) {
1136
					$post_cat_context = sprintf(
1137
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1138
						$category->name
1139
					);
1140
					/**
1141
					 * Filter the "In Category" line displayed in the post context below each Related Post.
1142
					 *
1143
					 * @module related-posts
1144
					 *
1145
					 * @since 3.2.0
1146
					 *
1147
					 * @param string $post_cat_context "In Category" line displayed in the post context below each Related Post.
1148
					 * @param array $category Array containing information about the category.
1149
					 */
1150
					return apply_filters( 'jetpack_relatedposts_post_category_context', $post_cat_context, $category );
1151
				}
1152
			}
1153
		}
1154
1155
		$tags = get_the_terms( $post_id, 'post_tag' );
1156 View Code Duplication
		if ( is_array( $tags ) ) {
1157
			foreach ( $tags as $tag ) {
1158
				if ( '' != trim( $tag->name ) ) {
1159
					$post_tag_context = sprintf(
1160
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1161
						$tag->name
1162
					);
1163
					/**
1164
					 * Filter the "In Tag" line displayed in the post context below each Related Post.
1165
					 *
1166
					 * @module related-posts
1167
					 *
1168
					 * @since 3.2.0
1169
					 *
1170
					 * @param string $post_tag_context "In Tag" line displayed in the post context below each Related Post.
1171
					 * @param array $tag Array containing information about the tag.
1172
					 */
1173
					return apply_filters( 'jetpack_relatedposts_post_tag_context', $post_tag_context, $tag );
1174
				}
1175
			}
1176
		}
1177
1178
		$comment_count = get_comments_number( $post_id );
1179
		if ( $comment_count > 0 ) {
1180
			return sprintf(
1181
				_n( 'With 1 comment', 'With %s comments', $comment_count, 'jetpack' ),
1182
				number_format_i18n( $comment_count )
1183
			);
1184
		}
1185
1186
		return __( 'Similar post', 'jetpack' );
1187
	}
1188
1189
	/**
1190
	 * Logs clicks for clickthrough analysis and related result tuning.
1191
	 *
1192
	 * @return null
1193
	 */
1194
	protected function _log_click( $post_id, $to_post_id, $link_position ) {
0 ignored issues
show
Unused Code introduced by
The parameter $post_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $to_post_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $link_position is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1195
1196
	}
1197
1198
	/**
1199
	 * Determines if the current post is able to use related posts.
1200
	 *
1201
	 * @uses self::get_options, is_admin, is_single, apply_filters
1202
	 * @return bool
1203
	 */
1204
	protected function _enabled_for_request() {
1205
		// Default to enabled
1206
		$enabled = true;
1207
1208
		// Must have feature enabled
1209
		$options = $this->get_options();
1210
		if ( ! $options['enabled'] ) {
1211
			$enabled = false;
1212
		}
1213
1214
		// Only run for frontend pages
1215
		if ( is_admin() ) {
1216
			$enabled = false;
1217
		}
1218
1219
		// Only run for standalone posts
1220
		if ( ! is_single() ) {
1221
			$enabled = false;
1222
		}
1223
1224
		/**
1225
		 * Filter the Enabled value to allow related posts to be shown on pages as well.
1226
		 *
1227
		 * @module related-posts
1228
		 *
1229
		 * @since 3.3.0
1230
		 *
1231
		 * @param bool $enabled Should Related Posts be enabled on the current page.
1232
		 */
1233
		return apply_filters( 'jetpack_relatedposts_filter_enabled_for_request', $enabled );
1234
	}
1235
1236
	/**
1237
	 * Adds filters and enqueues assets.
1238
	 *
1239
	 * @uses self::_enqueue_assets, self::_setup_shortcode, add_filter
1240
	 * @return null
1241
	 */
1242
	protected function _action_frontend_init_page() {
1243
		$this->_enqueue_assets( true, true );
1244
		$this->_setup_shortcode();
1245
1246
		add_filter( 'the_content', array( $this, 'filter_add_target_to_dom' ), 40 );
1247
	}
1248
1249
	/**
1250
	 * Enqueues assets needed to do async loading of related posts.
1251
	 *
1252
	 * @uses wp_enqueue_script, wp_enqueue_style, plugins_url
1253
	 * @return null
1254
	 */
1255
	protected function _enqueue_assets( $script, $style ) {
1256
		if ( $script ) {
1257
			wp_enqueue_script( 'jetpack_related-posts', plugins_url( 'related-posts.js', __FILE__ ), array( 'jquery' ), self::VERSION );
1258
			$related_posts_js_options = array(
1259
				/**
1260
				 * Filter each Related Post Heading structure.
1261
				 *
1262
				 * @since 4.0.0
1263
				 *
1264
				 * @param string $str Related Post Heading structure. Default to h4.
1265
				 */
1266
				'post_heading' => apply_filters( 'jetpack_relatedposts_filter_post_heading', esc_attr( 'h4' ) ),
1267
			);
1268
			wp_localize_script( 'jetpack_related-posts', 'related_posts_js_options', $related_posts_js_options );
1269
		}
1270
		if ( $style ){
1271
			if( is_rtl() ) {
1272
				wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'rtl/related-posts-rtl.css', __FILE__ ), array(), self::VERSION );
1273
			} else {
1274
				wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'related-posts.css', __FILE__ ), array(), self::VERSION );
1275
			}
1276
		}
1277
	}
1278
1279
	/**
1280
	 * Sets up the shortcode processing.
1281
	 *
1282
	 * @uses add_filter, add_shortcode
1283
	 * @return null
1284
	 */
1285
	protected function _setup_shortcode() {
1286
		add_filter( 'the_content', array( $this, 'test_for_shortcode' ), 0 );
1287
1288
		add_shortcode( self::SHORTCODE, array( $this, 'get_target_html' ) );
1289
	}
1290
1291
	protected function _allow_feature_toggle() {
1292
		if ( null === $this->_allow_feature_toggle ) {
1293
			/**
1294
			 * Filter the display of the Related Posts toggle in Settings > Reading.
1295
			 *
1296
			 * @module related-posts
1297
			 *
1298
			 * @since 2.8.0
1299
			 *
1300
			 * @param bool false Display a feature toggle. Default to false.
1301
			 */
1302
			$this->_allow_feature_toggle = apply_filters( 'jetpack_relatedposts_filter_allow_feature_toggle', false );
1303
		}
1304
		return $this->_allow_feature_toggle;
1305
	}
1306
}
1307
1308
class Jetpack_RelatedPosts_Raw extends Jetpack_RelatedPosts {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
1309
	protected $_query_name;
1310
1311
	/**
1312
	 * Allows callers of this class to tag each query with a unique name for tracking purposes.
1313
	 *
1314
	 * @param string $name
1315
	 * @return Jetpack_RelatedPosts_Raw
1316
	 */
1317
	public function set_query_name( $name ) {
1318
		$this->_query_name = (string) $name;
1319
		return $this;
1320
	}
1321
1322
	/**
1323
	 * The raw related posts class can be used by other plugins or themes
1324
	 * to get related content. This class wraps the existing RelatedPosts
1325
	 * logic thus we never want to add anything to the DOM or do anything
1326
	 * for event hooks. We will also not present any settings for this
1327
	 * class and keep it enabled as calls to this class is done
1328
	 * programmatically.
1329
	 */
1330
	public function action_admin_init() {}
1331
	public function action_frontend_init() {}
1332
	public function get_options() {
1333
		return array(
1334
			'enabled' => true,
1335
		);
1336
	}
1337
1338
	/**
1339
	 * Workhorse method to return array of related posts ids matched by ElasticSearch.
1340
	 *
1341
	 * @param int $post_id
1342
	 * @param int $size
1343
	 * @param array $filters
1344
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body
1345
	 * @return array
1346
	 */
1347
	protected function _get_related_posts( $post_id, $size, array $filters ) {
1348
		$hits = $this->_filter_non_public_posts(
1349
			$this->_get_related_post_ids(
1350
				$post_id,
1351
				$size,
1352
				$filters
1353
			)
1354
		);
1355
1356
		/** This filter is already documented in modules/related-posts/related-posts.php */
1357
		$hits = apply_filters( 'jetpack_relatedposts_filter_hits', $hits, $post_id );
1358
1359
		return $hits;
1360
	}
1361
}
1362