Completed
Push — sync/2may2017-related-posts ( 11e680...9efa2d )
by George
23:43 queued 15:35
created

Jetpack_RelatedPosts::get_option()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
class Jetpack_RelatedPosts {
3
	const VERSION = '20170109';
4
	const SHORTCODE = 'jetpack-related-posts';
5
	private static $instance = null;
6
	private static $instance_raw = null;
7
8
	/**
9
	 * Creates and returns a static instance of Jetpack_RelatedPosts.
10
	 *
11
	 * @return Jetpack_RelatedPosts
12
	 */
13 View Code Duplication
	public static function init() {
14
		if ( ! self::$instance ) {
15
			if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init' ) ) {
16
				self::$instance = WPCOM_RelatedPosts::init();
17
			} else {
18
				self::$instance = new Jetpack_RelatedPosts(
19
					get_current_blog_id(),
20
					Jetpack_Options::get_option( 'id' )
21
				);
22
			}
23
		}
24
25
		return self::$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
		if ( ! self::$instance_raw ) {
35
			if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init_raw' ) ) {
36
				self::$instance_raw = WPCOM_RelatedPosts::init_raw();
37
			} else {
38
				self::$instance_raw = new Jetpack_RelatedPosts_Raw(
39
					get_current_blog_id(),
40
					Jetpack_Options::get_option( 'id' )
41
				);
42
			}
43
		}
44
45
		return self::$instance_raw;
46
	}
47
48
	protected $_blog_id_local;
49
	protected $_blog_id_wpcom;
50
	protected $_options;
51
	protected $_allow_feature_toggle;
52
	protected $_blog_charset;
53
	protected $_convert_charset;
54
	protected $_previous_post_id;
55
	protected $_found_shortcode = false;
56
	protected $_citations_enabled = false;
57
58
	/**
59
	 * Constructor for Jetpack_RelatedPosts.
60
	 *
61
	 * @param int $blog_id_local
62
	 * @param int $blog_id_wpcom
63
	 * @uses get_option, add_action, apply_filters
64
	 * @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...
65
	 */
66
	public function __construct( $blog_id_local, $blog_id_wpcom ) {
67
		$this->_blog_id_local = $blog_id_local;
68
		$this->_blog_id_wpcom = $blog_id_wpcom;
69
		$this->_blog_charset = get_option( 'blog_charset' );
70
		$this->_convert_charset = ( function_exists( 'iconv' ) && ! preg_match( '/^utf\-?8$/i', $this->_blog_charset ) );
71
72
		add_action( 'admin_init', array( $this, 'action_admin_init' ) );
73
		add_action( 'wp', array( $this, 'action_frontend_init' ) );
74
75
		if ( ! class_exists( 'Jetpack_Media_Summary' ) ) {
76
			$lib = 'class.media-summary';
77
			if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
78
				$lib = 'class.wpcom-media-summary';
79
			}
80
			jetpack_require_lib( $lib );
81
		}
82
83
		// Add Related Posts to the REST API Post response.
84
		if ( function_exists( 'register_rest_field' ) ) {
85
			add_action( 'rest_api_init',  array( $this, 'rest_register_related_posts' ) );
86
		}
87
	}
88
89
	protected function set_citations_enabled() {
90
		//disable, some bugs causing query parsing errors
91
		return;
92
		if ( ! is_automattician() )
0 ignored issues
show
Unused Code introduced by
if (!is_automattician()) { return; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
93
			return;
94
		$whitelist = array(
95
			56857843, //elasticsearchp2
96
			14838835, //datap2
97
			86187505, //readersquadp2
98
		);
99
100
		$_blog_id = get_current_blog_id();
101
		if ( in_array( $_blog_id, $whitelist ) )
102
			$this->_citations_enabled = true;
103
		else
104
			$this->_citations_enabled = false;
105
	}
106
107
	/**
108
	 * =================
109
	 * ACTIONS & FILTERS
110
	 * =================
111
	 */
112
113
	/**
114
	 * Add a checkbox field to Settings > Reading for enabling related posts.
115
	 *
116
	 * @action admin_init
117
	 * @uses add_settings_field, __, register_setting, add_action
118
	 * @return null
119
	 */
120
	public function action_admin_init() {
121
122
		// Add the setting field [jetpack_relatedposts] and place it in Settings > Reading
123
		add_settings_field( 'jetpack_relatedposts', '<span id="jetpack_relatedposts">' . __( 'Related posts', 'jetpack' ) . '</span>', array( $this, 'print_setting_html' ), 'reading' );
124
		register_setting( 'reading', 'jetpack_relatedposts', array( $this, 'parse_options' ) );
125
		add_action('admin_head', array( $this, 'print_setting_head' ) );
126
127
		if( 'options-reading.php' == $GLOBALS['pagenow'] ) {
128
			// Enqueue style for live preview on the reading settings page
129
			$this->_enqueue_assets( false, true );
130
		}
131
	}
132
133
	/**
134
	 * Load related posts assets if it's a elegiable front end page or execute search and return JSON if it's an endpoint request.
135
	 *
136
	 * @global $_GET
137
	 * @action wp
138
	 * @uses add_shortcode, get_the_ID
139
	 * @returns null
140
	 */
141
	public function action_frontend_init() {
142
		$this->set_citations_enabled();
143
		// Add a shortcode handler that outputs nothing, this gets overridden later if we can display related content
144
		add_shortcode( self::SHORTCODE, array( $this, 'get_target_html_unsupported' ) );
145
146
		if ( ! $this->_enabled_for_request() )
147
			return;
148
149
		if ( isset( $_GET['relatedposts'] ) ) {
150
			$excludes = array();
151
			if ( isset( $_GET['relatedposts_exclude'] ) ) {
152
				if ( is_string( $_GET['relatedposts_exclude'] ) ) {
153
					$excludes = explode( ',', $_GET['relatedposts_exclude'] );
154
				} elseif ( is_array( $_GET['relatedposts_exclude'] ) ) {
155
					$excludes = array_values( $_GET['relatedposts_exclude'] );
156
				}
157
158
				$excludes = array_unique( array_filter( array_map( 'absint', $excludes ) ) );
159
			}
160
161
			$this->_action_frontend_init_ajax( $excludes );
162
		} else {
163
			if ( isset( $_GET['relatedposts_hit'], $_GET['relatedposts_origin'], $_GET['relatedposts_position'] ) ) {
164
				$this->_log_click( $_GET['relatedposts_origin'], get_the_ID(), $_GET['relatedposts_position'] );
165
				$this->_previous_post_id = (int) $_GET['relatedposts_origin'];
166
			}
167
168
			$this->_action_frontend_init_page();
169
		}
170
171
	}
172
173
	/**
174
	 * Render insertion point.
175
	 *
176
	 * @since 4.2.0
177
	 *
178
	 * @return string
179
	 */
180
	public function get_headline() {
181
		$options = $this->get_options();
182
183
		if ( $options['show_headline'] ) {
184
			if ( $this->_citations_enabled ) {
185
				$options['headline'] = __( 'Potential Citations', 'jetpack' );
186
			}
187
			$headline = sprintf(
188
				/** This filter is already documented in modules/sharedaddy/sharing-service.php */
189
				apply_filters( 'jetpack_sharing_headline_html', '<h3 class="jp-relatedposts-headline"><em>%s</em></h3>', esc_html( $options['headline'] ), 'related-posts' ),
190
				esc_html( $options['headline'] )
191
			);
192
		} else {
193
			$headline = '';
194
		}
195
		return $headline;
196
	}
197
198
	/**
199
	 * Adds a target to the post content to load related posts into if a shortcode for it did not already exist.
200
	 *
201
	 * @filter the_content
202
	 * @param string $content
203
	 * @returns string
204
	 */
205
	public function filter_add_target_to_dom( $content ) {
206
		if ( !$this->_found_shortcode ) {
207
			$content .= "\n" . $this->get_target_html();
208
		}
209
210
		return $content;
211
	}
212
213
	/**
214
	 * Looks for our shortcode on the unfiltered content, this has to execute early.
215
	 *
216
	 * @filter the_content
217
	 * @param string $content
218
	 * @uses has_shortcode
219
	 * @returns string
220
	 */
221
	public function test_for_shortcode( $content ) {
222
		$this->_found_shortcode = has_shortcode( $content, self::SHORTCODE );
223
224
		return $content;
225
	}
226
227
	/**
228
	 * Returns the HTML for the related posts section.
229
	 *
230
	 * @uses esc_html__, apply_filters
231
	 * @returns string
232
	 */
233
	public function get_target_html() {
234
		require_once JETPACK__PLUGIN_DIR . '/sync/class.jetpack-sync-settings.php';
235
		if ( Jetpack_Sync_Settings::is_syncing() ) {
236
			return '';
237
		}
238
239
		/**
240
		 * Filter the Related Posts headline.
241
		 *
242
		 * @module related-posts
243
		 *
244
		 * @since 3.0.0
245
		 *
246
		 * @param string $headline Related Posts heading.
247
		 */
248
		$headline = apply_filters( 'jetpack_relatedposts_filter_headline', $this->get_headline() );
249
250
		if ( $this->_previous_post_id ) {
251
			$exclude = "data-exclude='{$this->_previous_post_id}'";
252
		} else {
253
			$exclude = "";
254
		}
255
256
		return <<<EOT
257
<div id='jp-relatedposts' class='jp-relatedposts' $exclude>
258
	$headline
259
</div>
260
EOT;
261
	}
262
263
	/**
264
	 * 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.
265
	 *
266
	 * @returns string
267
	 */
268
	public function get_target_html_unsupported() {
269
		require_once JETPACK__PLUGIN_DIR . '/sync/class.jetpack-sync-settings.php';
270
		if ( Jetpack_Sync_Settings::is_syncing() ) {
271
			return '';
272
		}
273
		return "\n\n<!-- Jetpack Related Posts is not supported in this context. -->\n\n";
274
	}
275
276
	/**
277
	 * ========================
278
	 * PUBLIC UTILITY FUNCTIONS
279
	 * ========================
280
	 */
281
282
	/**
283
	 * Gets options set for Jetpack_RelatedPosts and merge with defaults.
284
	 *
285
	 * @uses Jetpack_Options::get_option, apply_filters
286
	 * @return array
287
	 */
288
	public function get_options() {
289
		if ( null === $this->_options ) {
290
			$this->_options = Jetpack_Options::get_option( 'relatedposts', array() );
291
			if ( ! is_array( $this->_options ) )
292
				$this->_options = array();
293
			if ( ! isset( $this->_options['enabled'] ) )
294
				$this->_options['enabled'] = true;
295
			if ( ! isset( $this->_options['show_headline'] ) )
296
				$this->_options['show_headline'] = true;
297
			if ( ! isset( $this->_options['show_thumbnails'] ) )
298
				$this->_options['show_thumbnails'] = false;
299
			if ( ! isset( $this->_options['show_date'] ) ) {
300
				$this->_options['show_date'] = true;
301
			}
302
			if ( ! isset( $this->_options['show_context'] ) ) {
303
				$this->_options['show_context'] = true;
304
			}
305
			if ( ! isset( $this->_options['layout'] ) ) {
306
				$this->_options['layout'] = 'grid';
307
			}
308
			if ( ! isset( $this->_options['headline'] ) ) {
309
				$this->_options['headline'] = esc_html__( 'Related', 'jetpack' );
310
			}
311
			if ( empty( $this->_options['size'] ) || (int)$this->_options['size'] < 1 ) {
312
				if ( $this->_citations_enabled )
313
					$this->_options['size'] = 12;
314
				else
315
					$this->_options['size'] = 3;
316
			}
317
318
			/**
319
			 * Filter Related Posts basic options.
320
			 *
321
			 * @module related-posts
322
			 *
323
			 * @since 2.8.0
324
			 *
325
			 * @param array $this->_options Array of basic Related Posts options.
326
			 */
327
			$this->_options = apply_filters( 'jetpack_relatedposts_filter_options', $this->_options );
328
		}
329
330
		return $this->_options;
331
	}
332
333
	public function get_option( $option_name ) {
334
		$options = $this->get_options();
335
336
		if ( isset( $options[ $option_name ] ) ) {
337
			return $options[ $option_name ];
338
		}
339
340
		return false;
341
	}
342
343
	/**
344
	 * Parses input and returns normalized options array.
345
	 *
346
	 * @param array $input
347
	 * @uses self::get_options
348
	 * @return array
349
	 */
350
	public function parse_options( $input ) {
351
		$current = $this->get_options();
352
353
		if ( !is_array( $input ) )
354
			$input = array();
355
356
		if (
357
			! isset( $input['enabled'] )
358
			|| isset( $input['show_date'] )
359
			|| isset( $input['show_context'] )
360
			|| isset( $input['layout'] )
361
			|| isset( $input['headline'] )
362
			) {
363
			$input['enabled'] = '1';
364
		}
365
366
		if ( '1' == $input['enabled'] ) {
367
			$current['enabled'] = true;
368
			$current['show_headline'] = ( isset( $input['show_headline'] ) && '1' == $input['show_headline'] );
369
			$current['show_thumbnails'] = ( isset( $input['show_thumbnails'] ) && '1' == $input['show_thumbnails'] );
370
			$current['show_date'] = ( isset( $input['show_date'] ) && '1' == $input['show_date'] );
371
			$current['show_context'] = ( isset( $input['show_context'] ) && '1' == $input['show_context'] );
372
			$current['layout'] = isset( $input['layout'] ) && in_array( $input['layout'], array( 'grid', 'list' ), true ) ? $input['layout'] : 'grid';
373
			$current['headline'] = isset( $input['headline'] ) ? $input['headline'] : esc_html__( 'Related', 'jetpack' );
374
		} else {
375
			$current['enabled'] = false;
376
		}
377
378
		if ( isset( $input['size'] ) && (int)$input['size'] > 0 )
379
			$current['size'] = (int)$input['size'];
380
		else
381
			$current['size'] = null;
382
383
		return $current;
384
	}
385
386
	/**
387
	 * HTML for admin settings page.
388
	 *
389
	 * @uses self::get_options, checked, esc_html__
390
	 * @returns null
391
	 */
392
	public function print_setting_html() {
393
		$options = $this->get_options();
394
395
		$ui_settings_template = <<<EOT
396
<ul id="settings-reading-relatedposts-customize">
397
	<li>
398
		<label><input name="jetpack_relatedposts[show_headline]" type="checkbox" value="1" %s /> %s</label>
399
	</li>
400
	<li>
401
		<label><input name="jetpack_relatedposts[show_thumbnails]" type="checkbox" value="1" %s /> %s</label>
402
	</li>
403
	<li>
404
		<label><input name="jetpack_relatedposts[show_date]" type="checkbox" value="1" %s /> %s</label>
405
	</li>
406
	<li>
407
		<label><input name="jetpack_relatedposts[show_context]" type="checkbox" value="1" %s /> %s</label>
408
	</li>
409
</ul>
410
<div id='settings-reading-relatedposts-preview'>
411
	%s
412
	<div id="jp-relatedposts" class="jp-relatedposts"></div>
413
</div>
414
EOT;
415
		$ui_settings = sprintf(
416
			$ui_settings_template,
417
			checked( $options['show_headline'], true, false ),
418
			esc_html__( 'Show a "Related" header to more clearly separate the related section from posts', 'jetpack' ),
419
			checked( $options['show_thumbnails'], true, false ),
420
			esc_html__( 'Use a large and visually striking layout', 'jetpack' ),
421
			checked( $options['show_date'], true, false ),
422
			esc_html__( 'Show entry date', 'jetpack' ),
423
			checked( $options['show_context'], true, false ),
424
			esc_html__( 'Show context (category or tag)', 'jetpack' ),
425
			esc_html__( 'Preview:', 'jetpack' )
426
		);
427
428
		if ( !$this->_allow_feature_toggle() ) {
429
			$template = <<<EOT
430
<input type="hidden" name="jetpack_relatedposts[enabled]" value="1" />
431
%s
432
EOT;
433
			printf(
434
				$template,
435
				$ui_settings
436
			);
437
		} else {
438
			$template = <<<EOT
439
<ul id="settings-reading-relatedposts">
440
	<li>
441
		<label><input type="radio" name="jetpack_relatedposts[enabled]" value="0" class="tog" %s /> %s</label>
442
	</li>
443
	<li>
444
		<label><input type="radio" name="jetpack_relatedposts[enabled]" value="1" class="tog" %s /> %s</label>
445
		%s
446
	</li>
447
</ul>
448
EOT;
449
			printf(
450
				$template,
451
				checked( $options['enabled'], false, false ),
452
				esc_html__( 'Hide related content after posts', 'jetpack' ),
453
				checked( $options['enabled'], true, false ),
454
				esc_html__( 'Show related content after posts', 'jetpack' ),
455
				$ui_settings
456
			);
457
		}
458
	}
459
460
	/**
461
	 * Head JS/CSS for admin settings page.
462
	 *
463
	 * @uses esc_html__
464
	 * @returns null
465
	 */
466
	public function print_setting_head() {
467
468
		// only dislay the Related Posts JavaScript on the Reading Settings Admin Page
469
		$current_screen =  get_current_screen();
470
471
		if ( is_null( $current_screen ) ) {
472
			return;
473
		}
474
475
		if( 'options-reading' != $current_screen->id )
476
			return;
477
478
		$related_headline = sprintf(
479
			'<h3 class="jp-relatedposts-headline"><em>%s</em></h3>',
480
			esc_html__( 'Related', 'jetpack' )
481
		);
482
483
		$href_params = 'class="jp-relatedposts-post-a" href="#jetpack_relatedposts" rel="nofollow" data-origin="0" data-position="0"';
484
		$related_with_images = <<<EOT
485
<div class="jp-relatedposts-items jp-relatedposts-items-visual">
486
	<div class="jp-relatedposts-post jp-relatedposts-post0 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
487
		<a $href_params>
488
			<img class="jp-relatedposts-post-img" src="https://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">
489
		</a>
490
		<h4 class="jp-relatedposts-post-title">
491
			<a $href_params>Big iPhone/iPad Update Now Available</a>
492
		</h4>
493
		<p class="jp-relatedposts-post-excerpt">Big iPhone/iPad Update Now Available</p>
494
		<p class="jp-relatedposts-post-context">In "Mobile"</p>
495
	</div>
496
	<div class="jp-relatedposts-post jp-relatedposts-post1 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
497
		<a $href_params>
498
			<img class="jp-relatedposts-post-img" src="https://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">
499
		</a>
500
		<h4 class="jp-relatedposts-post-title">
501
			<a $href_params>The WordPress for Android App Gets a Big Facelift</a>
502
		</h4>
503
		<p class="jp-relatedposts-post-excerpt">The WordPress for Android App Gets a Big Facelift</p>
504
		<p class="jp-relatedposts-post-context">In "Mobile"</p>
505
	</div>
506
	<div class="jp-relatedposts-post jp-relatedposts-post2 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
507
		<a $href_params>
508
			<img class="jp-relatedposts-post-img" src="https://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">
509
		</a>
510
		<h4 class="jp-relatedposts-post-title">
511
			<a $href_params>Upgrade Focus: VideoPress For Weddings</a>
512
		</h4>
513
		<p class="jp-relatedposts-post-excerpt">Upgrade Focus: VideoPress For Weddings</p>
514
		<p class="jp-relatedposts-post-context">In "Upgrade"</p>
515
	</div>
516
</div>
517
EOT;
518
		$related_with_images = str_replace( "\n", '', $related_with_images );
519
		$related_without_images = <<<EOT
520
<div class="jp-relatedposts-items jp-relatedposts-items-minimal">
521
	<p class="jp-relatedposts-post jp-relatedposts-post0" data-post-id="0" data-post-format="image">
522
		<span class="jp-relatedposts-post-title"><a $href_params>Big iPhone/iPad Update Now Available</a></span>
523
		<span class="jp-relatedposts-post-context">In "Mobile"</span>
524
	</p>
525
	<p class="jp-relatedposts-post jp-relatedposts-post1" data-post-id="0" data-post-format="image">
526
		<span class="jp-relatedposts-post-title"><a $href_params>The WordPress for Android App Gets a Big Facelift</a></span>
527
		<span class="jp-relatedposts-post-context">In "Mobile"</span>
528
	</p>
529
	<p class="jp-relatedposts-post jp-relatedposts-post2" data-post-id="0" data-post-format="image">
530
		<span class="jp-relatedposts-post-title"><a $href_params>Upgrade Focus: VideoPress For Weddings</a></span>
531
		<span class="jp-relatedposts-post-context">In "Upgrade"</span>
532
	</p>
533
</div>
534
EOT;
535
		$related_without_images = str_replace( "\n", '', $related_without_images );
536
537
		if ( $this->_allow_feature_toggle() ) {
538
			$extra_css = '#settings-reading-relatedposts-customize { padding-left:2em; margin-top:.5em; }';
539
		} else {
540
			$extra_css = '';
541
		}
542
543
		echo <<<EOT
544
<style type="text/css">
545
	#settings-reading-relatedposts .disabled { opacity:.5; filter:Alpha(opacity=50); }
546
	#settings-reading-relatedposts-preview .jp-relatedposts { background:#fff; padding:.5em; width:75%; }
547
	$extra_css
548
</style>
549
<script type="text/javascript">
550
	jQuery( document ).ready( function($) {
551
		var update_ui = function() {
552
			var is_enabled = true;
553
			if ( 'radio' == $( 'input[name="jetpack_relatedposts[enabled]"]' ).attr('type') ) {
554
				if ( '0' == $( 'input[name="jetpack_relatedposts[enabled]"]:checked' ).val() ) {
555
					is_enabled = false;
556
				}
557
			}
558
			if ( is_enabled ) {
559
				$( '#settings-reading-relatedposts-customize' )
560
					.removeClass( 'disabled' )
561
					.find( 'input' )
562
					.attr( 'disabled', false );
563
				$( '#settings-reading-relatedposts-preview' )
564
					.removeClass( 'disabled' );
565
			} else {
566
				$( '#settings-reading-relatedposts-customize' )
567
					.addClass( 'disabled' )
568
					.find( 'input' )
569
					.attr( 'disabled', true );
570
				$( '#settings-reading-relatedposts-preview' )
571
					.addClass( 'disabled' );
572
			}
573
		};
574
575
		var update_preview = function() {
576
			var html = '';
577
			if ( $( 'input[name="jetpack_relatedposts[show_headline]"]:checked' ).length ) {
578
				html += '$related_headline';
579
			}
580
			if ( $( 'input[name="jetpack_relatedposts[show_thumbnails]"]:checked' ).length ) {
581
				html += '$related_with_images';
582
			} else {
583
				html += '$related_without_images';
584
			}
585
			$( '#settings-reading-relatedposts-preview .jp-relatedposts' ).html( html );
586
			if ( $( 'input[name="jetpack_relatedposts[show_date]"]:checked' ).length ) {
587
				$( '.jp-relatedposts-post-title' ).each( function() {
588
					$( this ).after( $( '<span>August 8, 2005</span>' ) );
589
				} );
590
			}
591
			if ( $( 'input[name="jetpack_relatedposts[show_context]"]:checked' ).length ) {
592
				$( '.jp-relatedposts-post-context' ).show();
593
			} else {
594
				$( '.jp-relatedposts-post-context' ).hide();
595
			}
596
			$( '#settings-reading-relatedposts-preview .jp-relatedposts' ).show();
597
		};
598
599
		// Update on load
600
		update_preview();
601
		update_ui();
602
603
		// Update on change
604
		$( '#settings-reading-relatedposts-customize input' )
605
			.change( update_preview );
606
		$( '#settings-reading-relatedposts' )
607
			.find( 'input.tog' )
608
			.change( update_ui );
609
	});
610
</script>
611
EOT;
612
	}
613
614
	/**
615
	 * Gets an array of related posts that match the given post_id.
616
	 *
617
	 * @param int $post_id
618
	 * @param array $args - params to use when building ElasticSearch filters to narrow down the search domain.
619
	 * @uses self::get_options, get_post_type, wp_parse_args, apply_filters
620
	 * @return array
621
	 */
622
	public function get_for_post_id( $post_id, array $args ) {
623
		$options = $this->get_options();
624
625
		if ( ! empty( $args['size'] ) )
626
			$options['size'] = $args['size'];
627
628
		if ( ! $options['enabled'] || 0 == (int)$post_id || empty( $options['size'] ) )
629
			return array();
630
631
		$defaults = array(
632
			'size' => (int)$options['size'],
633
			'post_type' => get_post_type( $post_id ),
634
			'post_formats' => array(),
635
			'has_terms' => array(),
636
			'date_range' => array(),
637
			'exclude_post_ids' => array(),
638
		);
639
		$args = wp_parse_args( $args, $defaults );
640
		/**
641
		 * Filter the arguments used to retrieve a list of Related Posts.
642
		 *
643
		 * @module related-posts
644
		 *
645
		 * @since 2.8.0
646
		 *
647
		 * @param array $args Array of options to retrieve Related Posts.
648
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
649
		 */
650
		$args = apply_filters( 'jetpack_relatedposts_filter_args', $args, $post_id );
651
652
		$filters = $this->_get_es_filters_from_args( $post_id, $args );
653
		/**
654
		 * Filter ElasticSearch options used to calculate Related Posts.
655
		 *
656
		 * @module related-posts
657
		 *
658
		 * @since 2.8.0
659
		 *
660
		 * @param array $filters Array of ElasticSearch filters based on the post_id and args.
661
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
662
		 */
663
		$filters = apply_filters( 'jetpack_relatedposts_filter_filters', $filters, $post_id );
664
665
		$results = $this->_get_related_posts( $post_id, $args['size'], $filters );
666
		/**
667
		 * Filter the array of related posts matched by ElasticSearch.
668
		 *
669
		 * @module related-posts
670
		 *
671
		 * @since 2.8.0
672
		 *
673
		 * @param array $results Array of related posts matched by ElasticSearch.
674
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
675
		 */
676
		return apply_filters( 'jetpack_relatedposts_returned_results', $results, $post_id );
677
	}
678
679
	/**
680
	 * Gets an array of auto citations for the given post_id.
681
	 *
682
	 * @param int $post_id
683
	 * @param array $args - params to use when building ElasticSearch filters to narrow down the search domain.
684
	 * @uses get_options, wp_parse_args, apply_filters
685
	 * @return array
686
	 */
687
	public function get_auto_citation_posts( $post_id, array $args ) {
688
		$options = $this->get_options();
689
		if ( ! $options['enabled'] || 0 == (int)$post_id )
690
			return array();
691
692
		$defaults = array(
693
			'size' => 12,
694
			'date_range' => array(),
695
			'seed' => mt_rand( 0, 10 ), //auto citations should change
696
		);
697
		$args = wp_parse_args( $args, $defaults );
698
699
		$filters = array();
700
701
		$results = $this->_get_auto_citation_posts( $post_id, $args['size'], $filters );
0 ignored issues
show
Bug introduced by
The method _get_auto_citation_posts() does not exist on Jetpack_RelatedPosts. Did you maybe mean get_auto_citation_posts()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
702
703
		$posts = array();
704
		foreach( $results as $i => $item )
705
			$posts[] = $this->_get_autocite_post_data_for_post( $item, $i, $post_id );
706
707
		return $posts;
708
	}
709
710
711
	/**
712
	 * Returns a UTF-8 encoded array of post information for the given post_id
713
	 *
714
	 * @param int $post_id
0 ignored issues
show
Bug introduced by
There is no parameter named $post_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
715
	 * @param int $position
716
	 * @param int $origin The post id that this is related to
717
	 * @uses get_post, get_permalink, remove_query_arg, get_post_format, apply_filters
718
	 * @return array
719
	 */
720
	protected function _get_autocite_post_data_for_post( $item, $position, $origin ) {
721
		switch_to_blog( $item['blog_id'] );
722
723
		$post = get_post( $item['post_id'] );
724
725
		$data = array(
726
			'id' => $post->ID,
727
			'url' => get_permalink( $post->ID ),
728
			'url_meta' => array( 'origin' => $origin, 'position' => $position ),
729
			'title' => $this->_to_utf8( $this->_get_title( $post->post_title, $post->post_content ) ),
730
			'date' => get_the_date( '', $post->ID ),
731
			'format' => get_post_format( $post->ID ),
732
			'excerpt' => $this->_to_utf8( $this->_get_excerpt( $post->post_excerpt, $post->post_content ) ),
733
			'rel' => 'nofollow',
734
			'context' => $item['context'],
735
			'img' => '',
736
		);
737
738
		restore_current_blog();
739
		return $data;
740
	}
741
742
743
	/**
744
	 * =========================
745
	 * PRIVATE UTILITY FUNCTIONS
746
	 * =========================
747
	 */
748
749
	/**
750
	 * Creates an array of ElasticSearch filters based on the post_id and args.
751
	 *
752
	 * @param int $post_id
753
	 * @param array $args
754
	 * @uses apply_filters, get_post_types, get_post_format_strings
755
	 * @return array
756
	 */
757
	protected function _get_es_filters_from_args( $post_id, array $args ) {
758
		$filters = array();
759
760
		/**
761
		 * Filter the terms used to search for Related Posts.
762
		 *
763
		 * @module related-posts
764
		 *
765
		 * @since 2.8.0
766
		 *
767
		 * @param array $args['has_terms'] Array of terms associated to the Related Posts.
768
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
769
		 */
770
		$args['has_terms'] = apply_filters( 'jetpack_relatedposts_filter_has_terms', $args['has_terms'], $post_id );
771
		if ( ! empty( $args['has_terms'] ) ) {
772
			foreach( (array)$args['has_terms'] as $term ) {
773
				if ( mb_strlen( $term->taxonomy ) ) {
774
					switch ( $term->taxonomy ) {
775
						case 'post_tag':
776
							$tax_fld = 'tag.slug';
777
							break;
778
						case 'category':
779
							$tax_fld = 'category.slug';
780
							break;
781
						default:
782
							$tax_fld = 'taxonomy.' . $term->taxonomy . '.slug';
783
							break;
784
					}
785
					$filters[] = array( 'term' => array( $tax_fld => $term->slug ) );
786
				}
787
			}
788
		}
789
790
		/**
791
		 * Filter the Post Types where we search Related Posts.
792
		 *
793
		 * @module related-posts
794
		 *
795
		 * @since 2.8.0
796
		 *
797
		 * @param array $args['post_type'] Array of Post Types.
798
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
799
		 */
800
		$args['post_type'] = apply_filters( 'jetpack_relatedposts_filter_post_type', $args['post_type'], $post_id );
801
		$valid_post_types = get_post_types();
802
		if ( is_array( $args['post_type'] ) ) {
803
			$sanitized_post_types = array();
804
			foreach ( $args['post_type'] as $pt ) {
805
				if ( in_array( $pt, $valid_post_types ) )
806
					$sanitized_post_types[] = $pt;
807
			}
808
			if ( ! empty( $sanitized_post_types ) )
809
				$filters[] = array( 'terms' => array( 'post_type' => $sanitized_post_types ) );
810
		} else if ( in_array( $args['post_type'], $valid_post_types ) && 'all' != $args['post_type'] ) {
811
			$filters[] = array( 'term' => array( 'post_type' => $args['post_type'] ) );
812
		}
813
814
		/**
815
		 * Filter the Post Formats where we search Related Posts.
816
		 *
817
		 * @module related-posts
818
		 *
819
		 * @since 3.3.0
820
		 *
821
		 * @param array $args['post_formats'] Array of Post Formats.
822
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
823
		 */
824
		$args['post_formats'] = apply_filters( 'jetpack_relatedposts_filter_post_formats', $args['post_formats'], $post_id );
825
		$valid_post_formats = get_post_format_strings();
826
		$sanitized_post_formats = array();
827
		foreach ( $args['post_formats'] as $pf ) {
828
			if ( array_key_exists( $pf, $valid_post_formats ) ) {
829
				$sanitized_post_formats[] = $pf;
830
			}
831
		}
832
		if ( ! empty( $sanitized_post_formats ) ) {
833
			$filters[] = array( 'terms' => array( 'post_format' => $sanitized_post_formats ) );
834
		}
835
836
		/**
837
		 * Filter the date range used to search Related Posts.
838
		 *
839
		 * @module related-posts
840
		 *
841
		 * @since 2.8.0
842
		 *
843
		 * @param array $args['date_range'] Array of a month interval where we search Related Posts.
844
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
845
		 */
846
		$args['date_range'] = apply_filters( 'jetpack_relatedposts_filter_date_range', $args['date_range'], $post_id );
847
		if ( is_array( $args['date_range'] ) && ! empty( $args['date_range'] ) ) {
848
			$args['date_range'] = array_map( 'intval', $args['date_range'] );
849
			if ( !empty( $args['date_range']['from'] ) && !empty( $args['date_range']['to'] ) ) {
850
				$filters[] = array(
851
					'range' => array(
852
						'date_gmt' => $this->_get_coalesced_range( $args['date_range'] ),
853
					)
854
				);
855
			}
856
		}
857
858
		/**
859
		 * Filter the Post IDs excluded from appearing in Related Posts.
860
		 *
861
		 * @module related-posts
862
		 *
863
		 * @since 2.9.0
864
		 *
865
		 * @param array $args['exclude_post_ids'] Array of Post IDs.
866
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
867
		 */
868
		$args['exclude_post_ids'] = apply_filters( 'jetpack_relatedposts_filter_exclude_post_ids', $args['exclude_post_ids'], $post_id );
869
		if ( !empty( $args['exclude_post_ids'] ) && is_array( $args['exclude_post_ids'] ) ) {
870
			foreach ( $args['exclude_post_ids'] as $exclude_post_id) {
871
				$exclude_post_id = (int)$exclude_post_id;
872
				$excluded_post_ids = array();
873
				if ( $exclude_post_id > 0 )
874
					$excluded_post_ids[] = $exclude_post_id;
875
			}
876
			$filters[] = array( 'not' => array( 'terms' => array( 'post_id' => $excluded_post_ids ) ) );
0 ignored issues
show
Bug introduced by
The variable $excluded_post_ids 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...
877
		}
878
879
		return $filters;
880
	}
881
882
	/**
883
	 * Takes a range and coalesces it into a month interval bracketed by a time as determined by the blog_id to enhance caching.
884
	 *
885
	 * @param array $date_range
886
	 * @return array
887
	 */
888
	protected function _get_coalesced_range( array $date_range ) {
889
		$now = time();
890
		$coalesce_time = $this->_blog_id_wpcom % 86400;
891
		$current_time = $now - strtotime( 'today', $now );
892
893
		if ( $current_time < $coalesce_time && '01' == date( 'd', $now ) ) {
894
			// Move back 1 period
895
			return array(
896
				'from' => date( 'Y-m-01', strtotime( '-1 month', $date_range['from'] ) ) . ' ' . date( 'H:i:s', $coalesce_time ),
897
				'to'   => date( 'Y-m-01', $date_range['to'] ) . ' ' . date( 'H:i:s', $coalesce_time ),
898
			);
899
		} else {
900
			// Use current period
901
			return array(
902
				'from' => date( 'Y-m-01', $date_range['from'] ) . ' ' . date( 'H:i:s', $coalesce_time ),
903
				'to'   => date( 'Y-m-01', strtotime( '+1 month', $date_range['to'] ) ) . ' ' . date( 'H:i:s', $coalesce_time ),
904
			);
905
		}
906
	}
907
908
	/**
909
	 * Generate and output ajax response for related posts API call.
910
	 * NOTE: Calls exit() to end all further processing after payload has been outputed.
911
	 *
912
	 * @param array $excludes array of post_ids to exclude
913
	 * @uses send_nosniff_header, self::get_for_post_id, get_the_ID
914
	 * @return null
915
	 */
916
	protected function _action_frontend_init_ajax( array $excludes ) {
917
		define( 'DOING_AJAX', true );
918
919
		header( 'Content-type: application/json; charset=utf-8' ); // JSON can only be UTF-8
920
		send_nosniff_header();
921
922
		if ( $this->_citations_enabled ) {
923
			$related_posts = $this->get_auto_citation_posts( get_the_ID(), array() );
0 ignored issues
show
Unused Code introduced by
$related_posts is not used, you could remove the assignment.

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

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

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

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

Loading history...
924
		} else {
925
			$related_posts = $this->get_for_post_id(
0 ignored issues
show
Unused Code introduced by
$related_posts is not used, you could remove the assignment.

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

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

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

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

Loading history...
926
				get_the_ID(),
927
				array(
928
					'exclude_post_ids' => $excludes,
929
				)
930
			);
931
		}
932
933
		$options = $this->get_options();
934
935
		if ( isset( $_GET['jetpackrpcustomize'] ) ) {
936
937
			// If we're in the customizer, add dummy content.
938
			$date_now = current_time( get_option( 'date_format' ) );
939
			$related_posts = array(
940
				array(
941
					'id'       => - 1,
942
					'url'      => 'https://jetpackme.files.wordpress.com/2014/08/1-wpios-ipad-3-1-viewsite.png?w=350&h=200&crop=1',
943
					'url_meta' => array(
944
						'origin'   => 0,
945
						'position' => 0
946
					),
947
					'title'    => esc_html__( 'Big iPhone/iPad Update Now Available', 'jetpack' ),
948
					'date'     => $date_now,
949
					'format'   => false,
950
					'excerpt'  => esc_html__( 'It is that time of the year when devices are shiny again.', 'jetpack' ),
951
					'rel'      => 'nofollow',
952
					'context'  => esc_html__( 'In "Mobile"', 'jetpack' ),
953
					'img'      => array(
954
						'src'    => 'https://jetpackme.files.wordpress.com/2014/08/1-wpios-ipad-3-1-viewsite.png?w=350&h=200&crop=1',
955
						'width'  => 350,
956
						'height' => 200
957
					),
958
					'classes'  => array()
959
				),
960
				array(
961
					'id'       => - 1,
962
					'url'      => 'https://jetpackme.files.wordpress.com/2014/08/wordpress-com-news-wordpress-for-android-ui-update2.jpg?w=350&h=200&crop=1',
963
					'url_meta' => array(
964
						'origin'   => 0,
965
						'position' => 0
966
					),
967
					'title'    => esc_html__( 'The WordPress for Android App Gets a Big Facelift', 'jetpack' ),
968
					'date'     => $date_now,
969
					'format'   => false,
970
					'excerpt'  => esc_html__( 'Writing is new again in Android with the new WordPress app.', 'jetpack' ),
971
					'rel'      => 'nofollow',
972
					'context'  => esc_html__( 'In "Mobile"', 'jetpack' ),
973
					'img'      => array(
974
						'src'    => 'https://jetpackme.files.wordpress.com/2014/08/wordpress-com-news-wordpress-for-android-ui-update2.jpg?w=350&h=200&crop=1',
975
						'width'  => 350,
976
						'height' => 200
977
					),
978
					'classes'  => array()
979
				),
980
				array(
981
					'id'       => - 1,
982
					'url'      => 'https://jetpackme.files.wordpress.com/2014/08/videopresswedding.jpg?w=350&h=200&crop=1',
983
					'url_meta' => array(
984
						'origin'   => 0,
985
						'position' => 0
986
					),
987
					'title'    => esc_html__( 'Upgrade Focus, VideoPress for weddings', 'jetpack' ),
988
					'date'     => $date_now,
989
					'format'   => false,
990
					'excerpt'  => esc_html__( 'Weddings are in the spotlight now with VideoPress for weddings.', 'jetpack' ),
991
					'rel'      => 'nofollow',
992
					'context'  => esc_html__( 'In "Mobile"', 'jetpack' ),
993
					'img'      => array(
994
						'src'    => 'https://jetpackme.files.wordpress.com/2014/08/videopresswedding.jpg?w=350&h=200&crop=1',
995
						'width'  => 350,
996
						'height' => 200
997
					),
998
					'classes'  => array()
999
				),
1000
			);
1001
1002
			for ( $total = 0; $total < $options['size'] - 3; $total++ ) {
1003
				$related_posts[] = $related_posts[ $total ];
1004
			}
1005
1006
			$current_post = get_post();
1007
1008
			// Exclude current post after filtering to make sure it's excluded and not lost during filtering.
1009
			$excluded_posts = array_merge(
1010
				/** This filter is already documented in modules/related-posts/jetpack-related-posts.php */
1011
				apply_filters( 'jetpack_relatedposts_filter_exclude_post_ids', array() ),
1012
				array( $current_post->ID )
1013
			);
1014
1015
			// Fetch posts with featured image.
1016
			$with_post_thumbnails = get_posts( array(
1017
				'posts_per_page'   => $options['size'],
1018
				'post__not_in'     => $excluded_posts,
1019
				'post_type'        => $current_post->post_type,
1020
				'meta_key'         => '_thumbnail_id',
1021
				'suppress_filters' => false,
1022
			) );
1023
1024
			// If we don't have enough, fetch posts without featured image.
1025
			if ( 0 < ( $more = $options['size'] - count( $with_post_thumbnails ) ) ) {
1026
				$no_post_thumbnails = get_posts( array(
1027
					'posts_per_page'  => $more,
1028
					'post__not_in'    => $excluded_posts,
1029
					'post_type'       => $current_post->post_type,
1030
					'meta_query' => array(
1031
						array(
1032
							'key'     => '_thumbnail_id',
1033
							'compare' => 'NOT EXISTS',
1034
						),
1035
					),
1036
					'suppress_filters' => false,
1037
				) );
1038
			} else {
1039
				$no_post_thumbnails = array();
1040
			}
1041
1042
			foreach ( array_merge( $with_post_thumbnails, $no_post_thumbnails ) as $index => $real_post ) {
1043
				$related_posts[ $index ]['id']      = $real_post->ID;
1044
				$related_posts[ $index ]['url']     = esc_url( get_permalink( $real_post ) );
1045
				$related_posts[ $index ]['title']   = $this->_to_utf8( $this->_get_title( $real_post->post_title, $real_post->post_content ) );
1046
				$related_posts[ $index ]['date']    = get_the_date( '', $real_post );
1047
				$related_posts[ $index ]['excerpt'] = html_entity_decode( $this->_to_utf8( $this->_get_excerpt( $real_post->post_excerpt, $real_post->post_content ) ), ENT_QUOTES, 'UTF-8' );
1048
				$related_posts[ $index ]['img']     = $this->_generate_related_post_image_params( $real_post->ID );
1049
				$related_posts[ $index ]['context'] = $this->_generate_related_post_context( $real_post->ID );
1050
			}
1051
		} else {
1052
			$related_posts = $this->get_for_post_id(
1053
				get_the_ID(),
1054
				array(
1055
					'exclude_post_ids' => $excludes,
1056
				)
1057
			);
1058
		}
1059
1060
		$response = array(
1061
			'version' => self::VERSION,
1062
			'show_thumbnails' => (bool) $options['show_thumbnails'],
1063
			'show_date' => (bool) $options['show_date'],
1064
			'show_context' => (bool) $options['show_context'],
1065
			'layout' => (string) $options['layout'],
1066
			'headline' => (string) $options['headline'],
1067
			'items' => array(),
1068
		);
1069
1070
		if ( $this->_citations_enabled ) {
1071
			if ( count( $related_posts ) > 3 ) {
1072
				$i = 0;
1073
				foreach( $related_posts as $p ) {
1074
					$response['items'][$i][] = $p;
1075
					$i++;
1076
					if ( 3 == $i )
1077
						$i = 0;
1078
				}
1079
			}
1080
		} else {
1081
			if ( count( $related_posts ) == $options['size'] )
1082
				$response['items'] = $related_posts;
1083
		}
1084
1085
		echo json_encode( $response );
1086
1087
		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...
1088
	}
1089
1090
	/**
1091
	 * Returns a UTF-8 encoded array of post information for the given post_id
1092
	 *
1093
	 * @param int $post_id
1094
	 * @param int $position
1095
	 * @param int $origin The post id that this is related to
1096
	 * @uses get_post, get_permalink, remove_query_arg, get_post_format, apply_filters
1097
	 * @return array
1098
	 */
1099
	protected function _get_related_post_data_for_post( $post_id, $position, $origin ) {
1100
		$post = get_post( $post_id );
1101
1102
		return array(
1103
			'id' => $post->ID,
1104
			'url' => get_permalink( $post->ID ),
1105
			'url_meta' => array( 'origin' => $origin, 'position' => $position ),
1106
			'title' => $this->_to_utf8( $this->_get_title( $post->post_title, $post->post_content ) ),
1107
			'date' => get_the_date( '', $post->ID ),
1108
			'format' => get_post_format( $post->ID ),
1109
			'excerpt' => html_entity_decode( $this->_to_utf8( $this->_get_excerpt( $post->post_excerpt, $post->post_content ) ), ENT_QUOTES, 'UTF-8' ),
1110
			/**
1111
			 * Filters the rel attribute for the Related Posts' links.
1112
			 *
1113
			 * @module related-posts
1114
			 *
1115
			 * @since 3.7.0
1116
			 *
1117
			 * @param string nofollow Link rel attribute for Related Posts' link. Default is nofollow.
1118
			 * @param int $post->ID Post ID.
1119
			 */
1120
			'rel' => apply_filters( 'jetpack_relatedposts_filter_post_link_rel', 'nofollow', $post->ID ),
1121
			/**
1122
			 * Filter the context displayed below each Related Post.
1123
			 *
1124
			 * @module related-posts
1125
			 *
1126
			 * @since 3.0.0
1127
			 *
1128
			 * @param string $this->_to_utf8( $this->_generate_related_post_context( $post->ID ) ) Context displayed below each related post.
1129
			 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
1130
			 */
1131
			'context' => apply_filters(
1132
				'jetpack_relatedposts_filter_post_context',
1133
				$this->_to_utf8( $this->_generate_related_post_context( $post->ID ) ),
1134
				$post->ID
1135
			),
1136
			'img' => $this->_generate_related_post_image_params( $post->ID ),
1137
			/**
1138
			 * Filter the post css classes added on HTML markup.
1139
			 *
1140
			 * @module related-posts
1141
			 *
1142
			 * @since 3.8.0
1143
			 *
1144
			 * @param array array() CSS classes added on post HTML markup.
1145
			 * @param string $post_id Post ID.
1146
			 */
1147
			'classes' => apply_filters(
1148
				'jetpack_relatedposts_filter_post_css_classes',
1149
				array(),
1150
				$post->ID
1151
			),
1152
		);
1153
	}
1154
1155
	/**
1156
	 * Returns either the title or a small excerpt to use as title for post.
1157
	 *
1158
	 * @param string $post_title
1159
	 * @param string $post_content
1160
	 * @uses strip_shortcodes, wp_trim_words, __
1161
	 * @return string
1162
	 */
1163
	protected function _get_title( $post_title, $post_content ) {
1164
		if ( ! empty( $post_title ) ) {
1165
			return wp_strip_all_tags( $post_title );
1166
		}
1167
1168
		$post_title = wp_trim_words( wp_strip_all_tags( strip_shortcodes( $post_content ) ), 5, '…' );
1169
		if ( ! empty( $post_title ) ) {
1170
			return $post_title;
1171
		}
1172
1173
		return __( 'Untitled Post', 'jetpack' );
1174
	}
1175
1176
	/**
1177
	 * Returns a plain text post excerpt for title attribute of links.
1178
	 *
1179
	 * @param string $post_excerpt
1180
	 * @param string $post_content
1181
	 * @uses strip_shortcodes, wp_strip_all_tags, wp_trim_words
1182
	 * @return string
1183
	 */
1184
	protected function _get_excerpt( $post_excerpt, $post_content ) {
1185
		if ( empty( $post_excerpt ) )
1186
			$excerpt = $post_content;
1187
		else
1188
			$excerpt = $post_excerpt;
1189
1190
		return wp_trim_words( wp_strip_all_tags( strip_shortcodes( $excerpt ) ), 50, '…' );
1191
	}
1192
1193
	/**
1194
	 * Generates the thumbnail image to be used for the post. Uses the
1195
	 * image as returned by Jetpack_PostImages::get_image()
1196
	 *
1197
	 * @param int $post_id
1198
	 * @uses self::get_options, apply_filters, Jetpack_PostImages::get_image, Jetpack_PostImages::fit_image_url
1199
	 * @return string
1200
	 */
1201
	protected function _generate_related_post_image_params( $post_id ) {
1202
		$options = $this->get_options();
1203
		$image_params = array(
1204
			'src' => '',
1205
			'width' => 0,
1206
			'height' => 0,
1207
		);
1208
1209
		if ( ! $options['show_thumbnails'] ) {
1210
			return $image_params;
1211
		}
1212
1213
		/**
1214
		 * Filter the size of the Related Posts images.
1215
		 *
1216
		 * @module related-posts
1217
		 *
1218
		 * @since 2.8.0
1219
		 *
1220
		 * @param array array( 'width' => 350, 'height' => 200 ) Size of the images displayed below each Related Post.
1221
		 */
1222
		$thumbnail_size = apply_filters(
1223
			'jetpack_relatedposts_filter_thumbnail_size',
1224
			array( 'width' => 350, 'height' => 200 )
1225
		);
1226
		if ( !is_array( $thumbnail_size ) ) {
1227
			$thumbnail_size = array(
1228
				'width' => (int)$thumbnail_size,
1229
				'height' => (int)$thumbnail_size
1230
			);
1231
		}
1232
1233
		// Try to get post image
1234
		if ( class_exists( 'Jetpack_PostImages' ) ) {
1235
			$img_url = '';
1236
			$post_image = Jetpack_PostImages::get_image(
1237
				$post_id,
1238
				$thumbnail_size
1239
			);
1240
1241
			if ( is_array($post_image) ) {
1242
				$img_url = $post_image['src'];
1243
			} elseif ( class_exists( 'Jetpack_Media_Summary' ) ) {
1244
				$media = Jetpack_Media_Summary::get( $post_id );
1245
1246
				if ( is_array($media) && !empty( $media['image'] ) ) {
1247
					$img_url = $media['image'];
1248
				}
1249
			}
1250
1251
			if ( !empty( $img_url ) ) {
1252
				$image_params['width'] = $thumbnail_size['width'];
1253
				$image_params['height'] = $thumbnail_size['height'];
1254
				$image_params['src'] = Jetpack_PostImages::fit_image_url(
1255
					$img_url,
1256
					$thumbnail_size['width'],
1257
					$thumbnail_size['height']
1258
				);
1259
			}
1260
		}
1261
1262
		return $image_params;
1263
	}
1264
1265
	/**
1266
	 * Returns the string UTF-8 encoded
1267
	 *
1268
	 * @param string $text
1269
	 * @return string
1270
	 */
1271
	protected function _to_utf8( $text ) {
1272
		if ( $this->_convert_charset ) {
1273
			return iconv( $this->_blog_charset, 'UTF-8', $text );
1274
		} else {
1275
			return $text;
1276
		}
1277
	}
1278
1279
	/**
1280
	 * =============================================
1281
	 * PROTECTED UTILITY FUNCTIONS EXTENDED BY WPCOM
1282
	 * =============================================
1283
	 */
1284
1285
	/**
1286
	 * Workhorse method to return array of related posts matched by ElasticSearch.
1287
	 *
1288
	 * @param int $post_id
1289
	 * @param int $size
1290
	 * @param array $filters
1291
	 * @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
1292
	 * @return array
1293
	 */
1294
	protected function _get_related_posts( $post_id, $size, array $filters ) {
1295
		$hits = $this->_filter_non_public_posts(
1296
			$this->_get_related_post_ids(
1297
				$post_id,
1298
				$size,
1299
				$filters
1300
			)
1301
		);
1302
1303
		/**
1304
		 * Filter the Related Posts matched by ElasticSearch.
1305
		 *
1306
		 * @module related-posts
1307
		 *
1308
		 * @since 2.9.0
1309
		 *
1310
		 * @param array $hits Array of Post IDs matched by ElasticSearch.
1311
		 * @param string $post_id Post ID of the post for which we are retrieving Related Posts.
1312
		 */
1313
		$hits = apply_filters( 'jetpack_relatedposts_filter_hits', $hits, $post_id );
1314
1315
		$related_posts = array();
1316
		foreach ( $hits as $i => $hit ) {
1317
			$related_posts[] = $this->_get_related_post_data_for_post( $hit['id'], $i, $post_id );
1318
		}
1319
		return $related_posts;
1320
	}
1321
1322
	/**
1323
	 * Get array of related posts matched by ElasticSearch.
1324
	 *
1325
	 * @param int $post_id
1326
	 * @param int $size
1327
	 * @param array $filters
1328
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body, get_post_meta, update_post_meta
1329
	 * @return array
1330
	 */
1331
	protected function _get_related_post_ids( $post_id, $size, array $filters ) {
1332
		$now_ts = time();
1333
		$cache_meta_key = '_jetpack_related_posts_cache';
1334
1335
		$body = array(
1336
			'size' => (int) $size,
1337
		);
1338
1339
		if ( !empty( $filters ) )
1340
			$body['filter'] = array( 'and' => $filters );
1341
1342
		// Build cache key
1343
		$cache_key = md5( serialize( $body ) );
1344
1345
		// Load all cached values
1346
		if ( wp_using_ext_object_cache() ) {
1347
			$transient_name = "{$cache_meta_key}_{$cache_key}_{$post_id}";
1348
			$cache = get_transient( $transient_name );
1349
			if ( false !== $cache ) {
1350
				return $cache;
1351
			}
1352
		} else {
1353
			$cache = get_post_meta( $post_id, $cache_meta_key, true );
1354
1355
			if ( empty( $cache ) )
1356
				$cache = array();
1357
1358
1359
			// Cache is valid! Return cached value.
1360
			if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) && $cache[ $cache_key ][ 'expires' ] > $now_ts ) {
1361
				return $cache[ $cache_key ][ 'payload' ];
1362
			}
1363
		}
1364
1365
		$response = wp_remote_post(
1366
			"https://public-api.wordpress.com/rest/v1/sites/{$this->_blog_id_wpcom}/posts/$post_id/related/",
1367
			array(
1368
				'timeout' => 10,
1369
				'user-agent' => 'jetpack_related_posts',
1370
				'sslverify' => true,
1371
				'body' => $body,
1372
			)
1373
		);
1374
1375
		// Oh no... return nothing don't cache errors.
1376
		if ( is_wp_error( $response ) ) {
1377
			if ( isset( $cache[ $cache_key ] ) && is_array( $cache[ $cache_key ] ) )
1378
				return $cache[ $cache_key ][ 'payload' ]; // return stale
1379
			else
1380
				return array();
1381
		}
1382
1383
		$results = json_decode( wp_remote_retrieve_body( $response ), true );
1384
		$related_posts = array();
1385
		if ( is_array( $results ) && !empty( $results['hits'] ) ) {
1386
			foreach( $results['hits'] as $hit ) {
1387
				$related_posts[] = array(
1388
					'id' => $hit['fields']['post_id'],
1389
				);
1390
			}
1391
		}
1392
1393
		// An empty array might indicate no related posts or that posts
1394
		// are not yet synced to WordPress.com, so we cache for only 1
1395
		// minute in this case
1396
		if ( empty( $related_posts ) ) {
1397
			$cache_ttl = 60;
1398
		} else {
1399
			$cache_ttl = 12 * HOUR_IN_SECONDS;
1400
		}
1401
1402
		// Update cache
1403
		if ( wp_using_ext_object_cache() ) {
1404
			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...
1405
		} else {
1406
			// Copy all valid cache values
1407
			$new_cache = array();
1408
			foreach ( $cache as $k => $v ) {
1409
				if ( is_array( $v ) && $v[ 'expires' ] > $now_ts ) {
1410
					$new_cache[ $k ] = $v;
1411
				}
1412
			}
1413
1414
			// Set new cache value
1415
			$cache_expires = $cache_ttl + $now_ts;
1416
			$new_cache[ $cache_key ] = array(
1417
				'expires' => $cache_expires,
1418
				'payload' => $related_posts,
1419
			);
1420
			update_post_meta( $post_id, $cache_meta_key, $new_cache );
1421
		}
1422
1423
		return $related_posts;
1424
	}
1425
1426
	/**
1427
	 * Filter out any hits that are not public anymore.
1428
	 *
1429
	 * @param array $related_posts
1430
	 * @uses get_post_stati, get_post_status
1431
	 * @return array
1432
	 */
1433
	protected function _filter_non_public_posts( array $related_posts ) {
1434
		$public_stati = get_post_stati( array( 'public' => true ) );
1435
1436
		$filtered = array();
1437
		foreach ( $related_posts as $hit ) {
1438
			if ( in_array( get_post_status( $hit['id'] ), $public_stati ) ) {
1439
				$filtered[] = $hit;
1440
			}
1441
		}
1442
		return $filtered;
1443
	}
1444
1445
	/**
1446
	 * Generates a context for the related content (second line in related post output).
1447
	 * Order of importance:
1448
	 *   - First category (Not 'Uncategorized')
1449
	 *   - First post tag
1450
	 *   - Number of comments
1451
	 *
1452
	 * @param int $post_id
1453
	 * @uses get_the_category, get_the_terms, get_comments_number, number_format_i18n, __, _n
1454
	 * @return string
1455
	 */
1456
	protected function _generate_related_post_context( $post_id ) {
1457
		$categories = get_the_category( $post_id );
1458 View Code Duplication
		if ( is_array( $categories ) ) {
1459
			foreach ( $categories as $category ) {
1460
				if ( 'uncategorized' != $category->slug && '' != trim( $category->name ) ) {
1461
					$post_cat_context = sprintf(
1462
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1463
						$category->name
1464
					);
1465
					/**
1466
					 * Filter the "In Category" line displayed in the post context below each Related Post.
1467
					 *
1468
					 * @module related-posts
1469
					 *
1470
					 * @since 3.2.0
1471
					 *
1472
					 * @param string $post_cat_context "In Category" line displayed in the post context below each Related Post.
1473
					 * @param array $category Array containing information about the category.
1474
					 */
1475
					return apply_filters( 'jetpack_relatedposts_post_category_context', $post_cat_context, $category );
1476
				}
1477
			}
1478
		}
1479
1480
		$tags = get_the_terms( $post_id, 'post_tag' );
1481 View Code Duplication
		if ( is_array( $tags ) ) {
1482
			foreach ( $tags as $tag ) {
1483
				if ( '' != trim( $tag->name ) ) {
1484
					$post_tag_context = sprintf(
1485
						_x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
1486
						$tag->name
1487
					);
1488
					/**
1489
					 * Filter the "In Tag" line displayed in the post context below each Related Post.
1490
					 *
1491
					 * @module related-posts
1492
					 *
1493
					 * @since 3.2.0
1494
					 *
1495
					 * @param string $post_tag_context "In Tag" line displayed in the post context below each Related Post.
1496
					 * @param array $tag Array containing information about the tag.
1497
					 */
1498
					return apply_filters( 'jetpack_relatedposts_post_tag_context', $post_tag_context, $tag );
1499
				}
1500
			}
1501
		}
1502
1503
		$comment_count = get_comments_number( $post_id );
1504
		if ( $comment_count > 0 ) {
1505
			return sprintf(
1506
				_n( 'With 1 comment', 'With %s comments', $comment_count, 'jetpack' ),
1507
				number_format_i18n( $comment_count )
1508
			);
1509
		}
1510
1511
		return __( 'Similar post', 'jetpack' );
1512
	}
1513
1514
	/**
1515
	 * Logs clicks for clickthrough analysis and related result tuning.
1516
	 *
1517
	 * @return null
1518
	 */
1519
	protected function _log_click( $post_id, $to_post_id, $link_position ) {
1520
1521
	}
1522
1523
	/**
1524
	 * Determines if the current post is able to use related posts.
1525
	 *
1526
	 * @uses self::get_options, is_admin, is_single, apply_filters
1527
	 * @return bool
1528
	 */
1529
	protected function _enabled_for_request() {
1530
		// Default to enabled
1531
		$enabled = true;
1532
1533
		// Must have feature enabled
1534
		$options = $this->get_options();
1535
		if ( ! $options['enabled'] ) {
1536
			$enabled = false;
1537
		}
1538
1539
		// Only run for frontend pages
1540
		if ( is_admin() ) {
1541
			$enabled = false;
1542
		}
1543
1544
		// Only run for standalone posts
1545
		if ( ! is_single() ) {
1546
			$enabled = false;
1547
		}
1548
1549
		/**
1550
		 * Filter the Enabled value to allow related posts to be shown on pages as well.
1551
		 *
1552
		 * @module related-posts
1553
		 *
1554
		 * @since 3.3.0
1555
		 *
1556
		 * @param bool $enabled Should Related Posts be enabled on the current page.
1557
		 */
1558
		return apply_filters( 'jetpack_relatedposts_filter_enabled_for_request', $enabled );
1559
	}
1560
1561
	/**
1562
	 * Adds filters and enqueues assets.
1563
	 *
1564
	 * @uses self::_enqueue_assets, self::_setup_shortcode, add_filter
1565
	 * @return null
1566
	 */
1567
	protected function _action_frontend_init_page() {
1568
		$this->_enqueue_assets( true, true );
1569
		$this->_setup_shortcode();
1570
1571
		add_filter( 'the_content', array( $this, 'filter_add_target_to_dom' ), 40 );
1572
	}
1573
1574
	/**
1575
	 * Enqueues assets needed to do async loading of related posts.
1576
	 *
1577
	 * @uses wp_enqueue_script, wp_enqueue_style, plugins_url
1578
	 * @return null
1579
	 */
1580
	protected function _enqueue_assets( $script, $style ) {
1581
		$dependencies = is_customize_preview() ? array( 'customize-base' ) : array( 'jquery' );
0 ignored issues
show
Unused Code introduced by
$dependencies is not used, you could remove the assignment.

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

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

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

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

Loading history...
1582
		if ( $script ) {
1583
			if ( $this->_citations_enabled )
1584
				wp_enqueue_script( 'jetpack_related-posts', plugins_url( 'auto-citations.js', __FILE__ ), array( 'jquery' ), self::VERSION );
1585
			else
1586
				wp_enqueue_script( 'jetpack_related-posts', plugins_url( 'related-posts.js', __FILE__ ), array( 'jquery' ), self::VERSION );
1587
1588
			$related_posts_js_options = array(
1589
				/**
1590
				 * Filter each Related Post Heading structure.
1591
				 *
1592
				 * @since 4.0.0
1593
				 *
1594
				 * @param string $str Related Post Heading structure. Default to h4.
1595
				 */
1596
				'post_heading' => apply_filters( 'jetpack_relatedposts_filter_post_heading', esc_attr( 'h4' ) ),
1597
			);
1598
			wp_localize_script( 'jetpack_related-posts', 'related_posts_js_options', $related_posts_js_options );
1599
		}
1600
		if ( $style ) {
1601
			if ( $this->_citations_enabled ) {
1602 View Code Duplication
				if ( is_rtl() ) {
1603
					wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'rtl/auto-citations-rtl.css', __FILE__ ), array(), self::VERSION );
1604
				} else {
1605
					wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'auto-citations.css', __FILE__ ), array(), self::VERSION );
1606
				}
1607 View Code Duplication
			} else {
1608
				if ( is_rtl() ) {
1609
					wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'rtl/related-posts-rtl.css', __FILE__ ), array(), self::VERSION );
1610
				} else {
1611
					wp_enqueue_style( 'jetpack_related-posts', plugins_url( 'related-posts.css', __FILE__ ), array(), self::VERSION );
1612
				}
1613
			}
1614
		}
1615
	}
1616
1617
	/**
1618
	 * Sets up the shortcode processing.
1619
	 *
1620
	 * @uses add_filter, add_shortcode
1621
	 * @return null
1622
	 */
1623
	protected function _setup_shortcode() {
1624
		add_filter( 'the_content', array( $this, 'test_for_shortcode' ), 0 );
1625
1626
		add_shortcode( self::SHORTCODE, array( $this, 'get_target_html' ) );
1627
	}
1628
1629
	protected function _allow_feature_toggle() {
1630
		if ( null === $this->_allow_feature_toggle ) {
1631
			/**
1632
			 * Filter the display of the Related Posts toggle in Settings > Reading.
1633
			 *
1634
			 * @module related-posts
1635
			 *
1636
			 * @since 2.8.0
1637
			 *
1638
			 * @param bool false Display a feature toggle. Default to false.
1639
			 */
1640
			$this->_allow_feature_toggle = apply_filters( 'jetpack_relatedposts_filter_allow_feature_toggle', false );
1641
		}
1642
		return $this->_allow_feature_toggle;
1643
	}
1644
1645
	/**
1646
	 * ===================================================
1647
	 * FUNCTIONS EXPOSING RELATED POSTS IN THE WP REST API
1648
	 * ===================================================
1649
	 */
1650
1651
	/**
1652
	 * Add Related Posts to the REST API Post response.
1653
	 *
1654
	 * @since 4.4.0
1655
	 *
1656
	 * @action rest_api_init
1657
	 * @uses register_rest_field, self::rest_get_related_posts
1658
	 * @return null
1659
	 */
1660
	public function rest_register_related_posts() {
1661
		register_rest_field( 'post',
1662
			'jetpack-related-posts',
1663
			array(
1664
				'get_callback' => array( $this, 'rest_get_related_posts' ),
1665
				'update_callback' => null,
1666
				'schema'          => null,
1667
			)
1668
		);
1669
	}
1670
1671
	/**
1672
	 * Build an array of Related Posts.
1673
	 *
1674
	 * @since 4.4.0
1675
	 *
1676
	 * @param array $object Details of current post.
1677
	 * @param string $field_name Name of field.
1678
	 * @param WP_REST_Request $request Current request
1679
	 *
1680
	 * @uses self::get_for_post_id
1681
	 *
1682
	 * @return array
1683
	 */
1684
	public function rest_get_related_posts( $object, $field_name, $request ) {
1685
		return $this->get_for_post_id( $object['id'], array() );
1686
	}
1687
}
1688
1689
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...
1690
	protected $_query_name;
1691
1692
	/**
1693
	 * Allows callers of this class to tag each query with a unique name for tracking purposes.
1694
	 *
1695
	 * @param string $name
1696
	 * @return Jetpack_RelatedPosts_Raw
1697
	 */
1698
	public function set_query_name( $name ) {
1699
		$this->_query_name = (string) $name;
1700
		return $this;
1701
	}
1702
1703
	/**
1704
	 * The raw related posts class can be used by other plugins or themes
1705
	 * to get related content. This class wraps the existing RelatedPosts
1706
	 * logic thus we never want to add anything to the DOM or do anything
1707
	 * for event hooks. We will also not present any settings for this
1708
	 * class and keep it enabled as calls to this class is done
1709
	 * programmatically.
1710
	 */
1711
	public function action_admin_init() {}
1712
	public function action_frontend_init() {}
1713
	public function get_options() {
1714
		return array(
1715
			'enabled' => true,
1716
		);
1717
	}
1718
1719
	/**
1720
	 * Workhorse method to return array of related posts ids matched by ElasticSearch.
1721
	 *
1722
	 * @param int $post_id
1723
	 * @param int $size
1724
	 * @param array $filters
1725
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body
1726
	 * @return array
1727
	 */
1728
	protected function _get_related_posts( $post_id, $size, array $filters ) {
1729
		$hits = $this->_filter_non_public_posts(
1730
			$this->_get_related_post_ids(
1731
				$post_id,
1732
				$size,
1733
				$filters
1734
			)
1735
		);
1736
1737
		/** This filter is already documented in modules/related-posts/related-posts.php */
1738
		$hits = apply_filters( 'jetpack_relatedposts_filter_hits', $hits, $post_id );
1739
1740
		return $hits;
1741
	}
1742
1743
	/**
1744
	 * Workhorse method to return array of auto citation posts ids matched by ElasticSearch.
1745
	 *
1746
	 * @param int $post_id
1747
	 * @param int $size
1748
	 * @param array $filters
1749
	 * @uses wp_remote_post, is_wp_error, wp_remote_retrieve_body
1750
	 * @return array
1751
	 */
1752
	protected function _get_auto_citation_posts( $post_id, $size, array $filters ) {
1753
		return array();
1754
	}
1755
1756
}
1757