Completed
Push — master-stable ( e58779...194e10 )
by Jeremy
114:51 queued 105:08
created

Jetpack_RelatedPosts::print_setting_head()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 138
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 138
rs 8.1935
cc 4
eloc 38
nc 4
nop 0

How to fix   Long Method   

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 frontend 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' );
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' ).size() ) {
472
				html += '$related_headline';
473
			}
474
			if ( $( 'input[name="jetpack_relatedposts[show_thumbnails]"]:checked' ).size() ) {
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
		// Load all cached values
1018
		$cache = get_post_meta( $post_id, $cache_meta_key, true );
1019
		if ( empty( $cache ) )
1020
			$cache = array();
1021
1022
		// Build cache key
1023
		$cache_key = md5( serialize( $body ) );
1024
1025
		// Cache is valid! Return cached value.
1026
		if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) && $cache[ $cache_key ][ 'expires' ] > $now_ts ) {
1027
			return $cache[ $cache_key ][ 'payload' ];
1028
		}
1029
1030
		$response = wp_remote_post(
1031
			"https://public-api.wordpress.com/rest/v1/sites/{$this->_blog_id_wpcom}/posts/$post_id/related/",
1032
			array(
1033
				'timeout' => 10,
1034
				'user-agent' => 'jetpack_related_posts',
1035
				'sslverify' => true,
1036
				'body' => $body,
1037
			)
1038
		);
1039
1040
		// Oh no... return nothing don't cache errors.
1041
		if ( is_wp_error( $response ) ) {
1042
			if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) )
1043
				return $cache[ $cache_key ][ 'payload' ]; // return stale
1044
			else
1045
				return array();
1046
		}
1047
1048
		$results = json_decode( wp_remote_retrieve_body( $response ), true );
1049
		$related_posts = array();
1050
		if ( is_array( $results ) && !empty( $results['hits'] ) ) {
1051
			foreach( $results['hits'] as $hit ) {
1052
				$related_posts[] = array(
1053
					'id' => $hit['fields']['post_id'],
1054
				);
1055
			}
1056
		}
1057
1058
		// Copy all valid cache values
1059
		$new_cache = array();
1060
		foreach ( $cache as $k => $v ) {
1061
			if ( is_array( $v ) && $v[ 'expires' ] > $now_ts ) {
1062
				$new_cache[ $k ] = $v;
1063
			}
1064
		}
1065
1066
		// Set new cache value if valid
1067
		if ( ! empty( $related_posts ) ) {
1068
			$new_cache[ $cache_key ] = array(
1069
				'expires' => 12 * HOUR_IN_SECONDS + $now_ts,
1070
				'payload' => $related_posts,
1071
			);
1072
		}
1073
1074
		// Update cache
1075
		update_post_meta( $post_id, $cache_meta_key, $new_cache );
1076
1077
		return $related_posts;
1078
	}
1079
1080
	/**
1081
	 * Filter out any hits that are not public anymore.
1082
	 *
1083
	 * @param array $related_posts
1084
	 * @uses get_post_stati, get_post_status
1085
	 * @return array
1086
	 */
1087
	protected function _filter_non_public_posts( array $related_posts ) {
1088
		$public_stati = get_post_stati( array( 'public' => true ) );
1089
1090
		$filtered = array();
1091
		foreach ( $related_posts as $hit ) {
1092
			if ( in_array( get_post_status( $hit['id'] ), $public_stati ) ) {
1093
				$filtered[] = $hit;
1094
			}
1095
		}
1096
		return $filtered;
1097
	}
1098
1099
	/**
1100
	 * Generates a context for the related content (second line in related post output).
1101
	 * Order of importance:
1102
	 *   - First category (Not 'Uncategorized')
1103
	 *   - First post tag
1104
	 *   - Number of comments
1105
	 *
1106
	 * @param int $post_id
1107
	 * @uses get_the_category, get_the_terms, get_comments_number, number_format_i18n, __, _n
1108
	 * @return string
1109
	 */
1110
	protected function _generate_related_post_context( $post_id ) {
1111
		$categories = get_the_category( $post_id );
1112 View Code Duplication
		if ( is_array( $categories ) ) {
1113
			foreach ( $categories as $category ) {
1114
				if ( 'uncategorized' != $category->slug && '' != trim( $category->name ) ) {
1115
					$post_cat_context = sprintf(
1116
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1117
						$category->name
1118
					);
1119
					/**
1120
					 * Filter the "In Category" line displayed in the post context below each Related Post.
1121
					 *
1122
					 * @module related-posts
1123
					 *
1124
					 * @since 3.2.0
1125
					 *
1126
					 * @param string $post_cat_context "In Category" line displayed in the post context below each Related Post.
1127
					 * @param array $category Array containing information about the category.
1128
					 */
1129
					return apply_filters( 'jetpack_relatedposts_post_category_context', $post_cat_context, $category );
1130
				}
1131
			}
1132
		}
1133
1134
		$tags = get_the_terms( $post_id, 'post_tag' );
1135 View Code Duplication
		if ( is_array( $tags ) ) {
1136
			foreach ( $tags as $tag ) {
1137
				if ( '' != trim( $tag->name ) ) {
1138
					$post_tag_context = sprintf(
1139
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1140
						$tag->name
1141
					);
1142
					/**
1143
					 * Filter the "In Tag" line displayed in the post context below each Related Post.
1144
					 *
1145
					 * @module related-posts
1146
					 *
1147
					 * @since 3.2.0
1148
					 *
1149
					 * @param string $post_tag_context "In Tag" line displayed in the post context below each Related Post.
1150
					 * @param array $tag Array containing information about the tag.
1151
					 */
1152
					return apply_filters( 'jetpack_relatedposts_post_tag_context', $post_tag_context, $tag );
1153
				}
1154
			}
1155
		}
1156
1157
		$comment_count = get_comments_number( $post_id );
1158
		if ( $comment_count > 0 ) {
1159
			return sprintf(
1160
				_n( 'With 1 comment', 'With %s comments', $comment_count, 'jetpack' ),
1161
				number_format_i18n( $comment_count )
1162
			);
1163
		}
1164
1165
		return __( 'Similar post', 'jetpack' );
1166
	}
1167
1168
	/**
1169
	 * Logs clicks for clickthrough analysis and related result tuning.
1170
	 *
1171
	 * @return null
1172
	 */
1173
	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...
1174
1175
	}
1176
1177
	/**
1178
	 * Determines if the current post is able to use related posts.
1179
	 *
1180
	 * @uses self::get_options, is_admin, is_single, apply_filters
1181
	 * @return bool
1182
	 */
1183
	protected function _enabled_for_request() {
1184
		// Default to enabled
1185
		$enabled = true;
1186
1187
		// Must have feature enabled
1188
		$options = $this->get_options();
1189
		if ( ! $options['enabled'] ) {
1190
			$enabled = false;
1191
		}
1192
1193
		// Only run for frontend pages
1194
		if ( is_admin() ) {
1195
			$enabled = false;
1196
		}
1197
1198
		// Only run for standalone posts
1199
		if ( ! is_single() ) {
1200
			$enabled = false;
1201
		}
1202
1203
		/**
1204
		 * Filter the Enabled value to allow related posts to be shown on pages as well.
1205
		 *
1206
		 * @module related-posts
1207
		 *
1208
		 * @since 3.3.0
1209
		 *
1210
		 * @param bool $enabled Should Related Posts be enabled on the current page.
1211
		 */
1212
		return apply_filters( 'jetpack_relatedposts_filter_enabled_for_request', $enabled );
1213
	}
1214
1215
	/**
1216
	 * Adds filters and enqueues assets.
1217
	 *
1218
	 * @uses self::_enqueue_assets, self::_setup_shortcode, add_filter
1219
	 * @return null
1220
	 */
1221
	protected function _action_frontend_init_page() {
1222
		$this->_enqueue_assets( true, true );
1223
		$this->_setup_shortcode();
1224
1225
		add_filter( 'the_content', array( $this, 'filter_add_target_to_dom' ), 40 );
1226
	}
1227
1228
	/**
1229
	 * Enqueues assets needed to do async loading of related posts.
1230
	 *
1231
	 * @uses wp_enqueue_script, wp_enqueue_style, plugins_url
1232
	 * @return null
1233
	 */
1234
	protected function _enqueue_assets( $script, $style ) {
1235
		if ( $script ) {
1236
			wp_enqueue_script( 'jetpack_related-posts', plugins_url( 'related-posts.js', __FILE__ ), array( 'jquery' ), self::VERSION );
1237
			$related_posts_js_options = array(
1238
				/**
1239
				 * Filter each Related Post Heading structure.
1240
				 *
1241
				 * @since 4.0.0
1242
				 *
1243
				 * @param string $str Related Post Heading structure. Default to h4.
1244
				 */
1245
				'post_heading' => apply_filters( 'jetpack_relatedposts_filter_post_heading', esc_attr( 'h4' ) ),
1246
			);
1247
			wp_localize_script( 'jetpack_related-posts', 'related_posts_js_options', $related_posts_js_options );
1248
		}
1249
		if ( $style ){
1250
			if( is_rtl() ) {
1251
				wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'rtl/related-posts-rtl.css', __FILE__ ), array(), self::VERSION );
1252
			} else {
1253
				wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'related-posts.css', __FILE__ ), array(), self::VERSION );
1254
			}
1255
		}
1256
	}
1257
1258
	/**
1259
	 * Sets up the shortcode processing.
1260
	 *
1261
	 * @uses add_filter, add_shortcode
1262
	 * @return null
1263
	 */
1264
	protected function _setup_shortcode() {
1265
		add_filter( 'the_content', array( $this, 'test_for_shortcode' ), 0 );
1266
1267
		add_shortcode( self::SHORTCODE, array( $this, 'get_target_html' ) );
1268
	}
1269
1270
	protected function _allow_feature_toggle() {
1271
		if ( null === $this->_allow_feature_toggle ) {
1272
			/**
1273
			 * Filter the display of the Related Posts toggle in Settings > Reading.
1274
			 *
1275
			 * @module related-posts
1276
			 *
1277
			 * @since 2.8.0
1278
			 *
1279
			 * @param bool false Display a feature toggle. Default to false.
1280
			 */
1281
			$this->_allow_feature_toggle = apply_filters( 'jetpack_relatedposts_filter_allow_feature_toggle', false );
1282
		}
1283
		return $this->_allow_feature_toggle;
1284
	}
1285
}
1286
1287
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...
1288
	protected $_query_name;
1289
1290
	/**
1291
	 * Allows callers of this class to tag each query with a unique name for tracking purposes.
1292
	 *
1293
	 * @param string $name
1294
	 * @return Jetpack_RelatedPosts_Raw
1295
	 */
1296
	public function set_query_name( $name ) {
1297
		$this->_query_name = (string) $name;
1298
		return $this;
1299
	}
1300
1301
	/**
1302
	 * The raw related posts class can be used by other plugins or themes
1303
	 * to get related content. This class wraps the existing RelatedPosts
1304
	 * logic thus we never want to add anything to the DOM or do anything
1305
	 * for event hooks. We will also not present any settings for this
1306
	 * class and keep it enabled as calls to this class is done
1307
	 * programmatically.
1308
	 */
1309
	public function action_admin_init() {}
1310
	public function action_frontend_init() {}
1311
	public function get_options() {
1312
		return array(
1313
			'enabled' => true,
1314
		);
1315
	}
1316
1317
	/**
1318
	 * Workhorse method to return array of related posts ids matched by ElasticSearch.
1319
	 *
1320
	 * @param int $post_id
1321
	 * @param int $size
1322
	 * @param array $filters
1323
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body
1324
	 * @return array
1325
	 */
1326
	protected function _get_related_posts( $post_id, $size, array $filters ) {
1327
		$hits = $this->_filter_non_public_posts(
1328
			$this->_get_related_post_ids(
1329
				$post_id,
1330
				$size,
1331
				$filters
1332
			)
1333
		);
1334
1335
		/** This filter is already documented in modules/related-posts/related-posts.php */
1336
		$hits = apply_filters( 'jetpack_relatedposts_filter_hits', $hits, $post_id );
1337
1338
		return $hits;
1339
	}
1340
}
1341