summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/modules/related-posts/jetpack-related-posts.php')
-rw-r--r--plugins/jetpack/modules/related-posts/jetpack-related-posts.php320
1 files changed, 255 insertions, 65 deletions
diff --git a/plugins/jetpack/modules/related-posts/jetpack-related-posts.php b/plugins/jetpack/modules/related-posts/jetpack-related-posts.php
index fcbe23e7..ebd91cf1 100644
--- a/plugins/jetpack/modules/related-posts/jetpack-related-posts.php
+++ b/plugins/jetpack/modules/related-posts/jetpack-related-posts.php
@@ -1,8 +1,9 @@
<?php
class Jetpack_RelatedPosts {
- const VERSION = '20150408';
+ const VERSION = '20190204';
const SHORTCODE = 'jetpack-related-posts';
- private static $instance = null;
+
+ private static $instance = null;
private static $instance_raw = null;
/**
@@ -15,10 +16,7 @@ class Jetpack_RelatedPosts {
if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init' ) ) {
self::$instance = WPCOM_RelatedPosts::init();
} else {
- self::$instance = new Jetpack_RelatedPosts(
- get_current_blog_id(),
- Jetpack_Options::get_option( 'id' )
- );
+ self::$instance = new Jetpack_RelatedPosts();
}
}
@@ -35,18 +33,13 @@ class Jetpack_RelatedPosts {
if ( class_exists('WPCOM_RelatedPosts') && method_exists( 'WPCOM_RelatedPosts', 'init_raw' ) ) {
self::$instance_raw = WPCOM_RelatedPosts::init_raw();
} else {
- self::$instance_raw = new Jetpack_RelatedPosts_Raw(
- get_current_blog_id(),
- Jetpack_Options::get_option( 'id' )
- );
+ self::$instance_raw = new Jetpack_RelatedPosts_Raw();
}
}
return self::$instance_raw;
}
- protected $_blog_id_local;
- protected $_blog_id_wpcom;
protected $_options;
protected $_allow_feature_toggle;
protected $_blog_charset;
@@ -57,14 +50,10 @@ class Jetpack_RelatedPosts {
/**
* Constructor for Jetpack_RelatedPosts.
*
- * @param int $blog_id_local
- * @param int $blog_id_wpcom
* @uses get_option, add_action, apply_filters
* @return null
*/
- public function __construct( $blog_id_local, $blog_id_wpcom ) {
- $this->_blog_id_local = $blog_id_local;
- $this->_blog_id_wpcom = $blog_id_wpcom;
+ public function __construct() {
$this->_blog_charset = get_option( 'blog_charset' );
$this->_convert_charset = ( function_exists( 'iconv' ) && ! preg_match( '/^utf\-?8$/i', $this->_blog_charset ) );
@@ -76,11 +65,18 @@ class Jetpack_RelatedPosts {
}
// Add Related Posts to the REST API Post response.
- if ( function_exists( 'register_rest_field' ) ) {
- add_action( 'rest_api_init', array( $this, 'rest_register_related_posts' ) );
- }
+ add_action( 'rest_api_init', array( $this, 'rest_register_related_posts' ) );
+
+ jetpack_register_block(
+ 'jetpack/related-posts',
+ array(
+ 'render_callback' => array( $this, 'render_block' ),
+ )
+ );
+ }
- jetpack_register_block( 'related-posts' );
+ protected function get_blog_id() {
+ return Jetpack_Options::get_option( 'id' );
}
/**
@@ -125,17 +121,7 @@ class Jetpack_RelatedPosts {
return;
if ( isset( $_GET['relatedposts'] ) ) {
- $excludes = array();
- if ( isset( $_GET['relatedposts_exclude'] ) ) {
- if ( is_string( $_GET['relatedposts_exclude'] ) ) {
- $excludes = explode( ',', $_GET['relatedposts_exclude'] );
- } elseif ( is_array( $_GET['relatedposts_exclude'] ) ) {
- $excludes = array_values( $_GET['relatedposts_exclude'] );
- }
-
- $excludes = array_unique( array_filter( array_map( 'absint', $excludes ) ) );
- }
-
+ $excludes = $this->parse_numeric_get_arg( 'relatedposts_exclude' );
$this->_action_frontend_init_ajax( $excludes );
} else {
if ( isset( $_GET['relatedposts_hit'], $_GET['relatedposts_origin'], $_GET['relatedposts_position'] ) ) {
@@ -172,13 +158,18 @@ class Jetpack_RelatedPosts {
/**
* Adds a target to the post content to load related posts into if a shortcode for it did not already exist.
+ * Will skip adding the target if the post content contains a Related Posts block.
*
* @filter the_content
* @param string $content
* @returns string
*/
public function filter_add_target_to_dom( $content ) {
- if ( !$this->_found_shortcode ) {
+ if ( has_block( 'jetpack/related-posts', $content ) ) {
+ return $content;
+ }
+
+ if ( ! $this->_found_shortcode ) {
$content .= "\n" . $this->get_target_html();
}
@@ -249,12 +240,203 @@ EOT;
}
/**
+ * ===============
+ * GUTENBERG BLOCK
+ * ===============
+ */
+
+ /**
+ * Echoes out items for the Gutenberg block
+ *
+ * @param array $related_post The post oject.
+ * @param array $block_attributes The block attributes.
+ */
+ public function render_block_item( $related_post, $block_attributes ) {
+ $instance_id = 'related-posts-item-' . uniqid();
+ $label_id = $instance_id . '-label';
+
+ $item_markup = sprintf(
+ '<ul id="%1$s" aria-labelledby="%2$s" class="jp-related-posts-i2__post" role="menuitem">',
+ esc_attr( $instance_id ),
+ esc_attr( $label_id )
+ );
+
+ $item_markup .= sprintf(
+ '<li class="jp-related-posts-i2__post-link"><a id="%1$s" href="%2$s" rel="%4$s">%3$s</a></li>',
+ esc_attr( $label_id ),
+ esc_url( $related_post['url'] ),
+ esc_attr( $related_post['title'] ),
+ esc_attr( $related_post['rel'] )
+ );
+
+ if ( ! empty( $block_attributes['show_thumbnails'] ) && ! empty( $related_post['img']['src'] ) ) {
+ $img_link = sprintf(
+ '<li class="jp-related-posts-i2__post-img-link"><a href="%1$s" rel="%2$s"><img src="%3$s" width="%4$s" alt="%5$s" /></a></li>',
+ esc_url( $related_post['url'] ),
+ esc_attr( $related_post['rel'] ),
+ esc_url( $related_post['img']['src'] ),
+ esc_attr( $related_post['img']['width'] ),
+ esc_attr( $related_post['img']['alt_text'] )
+ );
+
+ $item_markup .= $img_link;
+ }
+
+ if ( $block_attributes['show_date'] ) {
+ $date_tag = sprintf(
+ '<li class="jp-related-posts-i2__post-date">%1$s</li>',
+ esc_html( $related_post['date'] )
+ );
+
+ $item_markup .= $date_tag;
+ }
+
+ if ( ( $block_attributes['show_context'] ) && ! empty( $related_post['context'] ) ) {
+ $context_tag = sprintf(
+ '<li class="jp-related-posts-i2__post-context">%1$s</li>',
+ esc_html( $related_post['context'] )
+ );
+
+ $item_markup .= $context_tag;
+ }
+
+ $item_markup .= '</ul>';
+
+ return $item_markup;
+ }
+
+ /**
+ * Render a related posts row.
+ *
+ * @param array $posts The posts to render into the row.
+ * @param array $block_attributes Block attributes.
+ */
+ public function render_block_row( $posts, $block_attributes ) {
+ $rows_markup = '';
+ foreach ( $posts as $post ) {
+ $rows_markup .= $this->render_block_item( $post, $block_attributes );
+ }
+ return sprintf(
+ '<div class="jp-related-posts-i2__row" data-post-count="%1$s">%2$s</div>',
+ count( $posts ),
+ $rows_markup
+ );
+ }
+
+ /**
+ * Render the related posts markup.
+ *
+ * @param array $attributes Block attributes.
+ * @return string
+ */
+ public function render_block( $attributes ) {
+ $block_attributes = array(
+ 'show_thumbnails' => isset( $attributes['displayThumbnails'] ) && $attributes['displayThumbnails'],
+ 'show_date' => isset( $attributes['displayDate'] ) ? (bool) $attributes['displayDate'] : true,
+ 'show_context' => isset( $attributes['displayContext'] ) && $attributes['displayContext'],
+ 'layout' => isset( $attributes['postLayout'] ) && 'list' === $attributes['postLayout'] ? $attributes['postLayout'] : 'grid',
+ 'size' => ! empty( $attributes['postsToShow'] ) ? absint( $attributes['postsToShow'] ) : 3,
+ );
+
+ $excludes = $this->parse_numeric_get_arg( 'relatedposts_origin' );
+ $related_posts = $this->get_for_post_id(
+ get_the_ID(),
+ array(
+ 'size' => $block_attributes['size'],
+ 'exclude_post_ids' => $excludes,
+ )
+ );
+
+ $display_lower_row = $block_attributes['size'] > 3;
+
+ if ( empty( $related_posts ) ) {
+ return '';
+ }
+
+ switch ( count( $related_posts ) ) {
+ case 2:
+ case 4:
+ case 5:
+ $top_row_end = 2;
+ break;
+
+ default:
+ $top_row_end = 3;
+ break;
+ }
+
+ $upper_row_posts = array_slice( $related_posts, 0, $top_row_end );
+ $lower_row_posts = array_slice( $related_posts, $top_row_end );
+
+ $rows_markup = $this->render_block_row( $upper_row_posts, $block_attributes );
+ if ( $display_lower_row ) {
+ $rows_markup .= $this->render_block_row( $lower_row_posts, $block_attributes );
+ }
+
+ $target_to_dom_priority = has_filter(
+ 'the_content',
+ array( $this, 'filter_add_target_to_dom' )
+ );
+ remove_filter(
+ 'the_content',
+ array( $this, 'filter_add_target_to_dom' ),
+ $target_to_dom_priority
+ );
+
+ /*
+ Below is a hack to get the block content to render correctly.
+
+ This functionality should be covered in /inc/blocks.php but due to an error,
+ this has not been fixed as of this writing.
+
+ Alda has submitted a patch to Core in order to have this issue fixed at
+ https://core.trac.wordpress.org/attachment/ticket/45495/do_blocks.diff and
+ hopefully it makes to to the final RC of WP 5.1.
+ */
+ $priority = has_filter( 'the_content', 'wpautop' );
+ remove_filter( 'the_content', 'wpautop', $priority );
+ add_filter( 'the_content', '_restore_wpautop_hook', $priority + 1 );
+
+ return sprintf(
+ '<nav class="jp-relatedposts-i2" data-layout="%1$s">%2$s</nav>',
+ esc_attr( $block_attributes['layout'] ),
+ $rows_markup
+ );
+ }
+
+ /**
* ========================
* PUBLIC UTILITY FUNCTIONS
* ========================
*/
/**
+ * Parse a numeric GET variable to an array of values.
+ *
+ * @since 6.9.0
+ *
+ * @uses absint
+ *
+ * @param string $arg Name of the GET variable
+ * @return array $result Parsed value(s)
+ */
+ public function parse_numeric_get_arg( $arg ) {
+ $result = array();
+
+ if ( isset( $_GET[ $arg ] ) ) {
+ if ( is_string( $_GET[ $arg ] ) ) {
+ $result = explode( ',', $_GET[ $arg ] );
+ } elseif ( is_array( $_GET[ $arg ] ) ) {
+ $result = array_values( $_GET[ $arg ] );
+ }
+
+ $result = array_unique( array_filter( array_map( 'absint', $result ) ) );
+ }
+
+ return $result;
+ }
+
+ /**
* Gets options set for Jetpack_RelatedPosts and merge with defaults.
*
* @uses Jetpack_Options::get_option, apply_filters
@@ -364,6 +546,7 @@ EOT;
$options = $this->get_options();
$ui_settings_template = <<<EOT
+<p class="description">%s</p>
<ul id="settings-reading-relatedposts-customize">
<li>
<label><input name="jetpack_relatedposts[show_headline]" type="checkbox" value="1" %s /> %s</label>
@@ -385,6 +568,7 @@ EOT;
EOT;
$ui_settings = sprintf(
$ui_settings_template,
+ esc_html__( 'The following settings will impact all related posts on your site, except for those you created via the block editor:', 'jetpack' ),
checked( $options['show_headline'], true, false ),
esc_html__( 'Highlight related content with a heading', 'jetpack' ),
checked( $options['show_thumbnails'], true, false ),
@@ -456,7 +640,7 @@ EOT;
<div class="jp-relatedposts-items jp-relatedposts-items-visual">
<div class="jp-relatedposts-post jp-relatedposts-post0 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
<a $href_params>
- <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">
+ <img class="jp-relatedposts-post-img" src="https://jetpackme.files.wordpress.com/2019/03/cat-blog.png" width="350" alt="Big iPhone/iPad Update Now Available" scale="0">
</a>
<h4 class="jp-relatedposts-post-title">
<a $href_params>Big iPhone/iPad Update Now Available</a>
@@ -466,7 +650,7 @@ EOT;
</div>
<div class="jp-relatedposts-post jp-relatedposts-post1 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
<a $href_params>
- <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">
+ <img class="jp-relatedposts-post-img" src="https://jetpackme.files.wordpress.com/2019/03/devices.jpg" width="350" alt="The WordPress for Android App Gets a Big Facelift" scale="0">
</a>
<h4 class="jp-relatedposts-post-title">
<a $href_params>The WordPress for Android App Gets a Big Facelift</a>
@@ -476,7 +660,7 @@ EOT;
</div>
<div class="jp-relatedposts-post jp-relatedposts-post2 jp-relatedposts-post-thumbs" data-post-id="0" data-post-format="image">
<a $href_params>
- <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">
+ <img class="jp-relatedposts-post-img" src="https://jetpackme.files.wordpress.com/2019/03/mobile-wedding.jpg" width="350" alt="Upgrade Focus: VideoPress For Weddings" scale="0">
</a>
<h4 class="jp-relatedposts-post-title">
<a $href_params>Upgrade Focus: VideoPress For Weddings</a>
@@ -585,7 +769,7 @@ EOT;
/**
* Gets an array of related posts that match the given post_id.
*
- * @param int $post_id
+ * @param int $post_id Post which we want to find related posts for.
* @param array $args - params to use when building Elasticsearch filters to narrow down the search domain.
* @uses self::get_options, get_post_type, wp_parse_args, apply_filters
* @return array
@@ -597,19 +781,23 @@ EOT;
$options['size'] = $args['size'];
}
- if ( ! $options['enabled'] || 0 == (int)$post_id || empty( $options['size'] ) || get_post_status( $post_id) !== 'publish' ) {
+ if (
+ ! $options['enabled']
+ || 0 === (int) $post_id
+ || empty( $options['size'] )
+ ) {
return array();
}
$defaults = array(
- 'size' => (int)$options['size'],
- 'post_type' => get_post_type( $post_id ),
- 'post_formats' => array(),
- 'has_terms' => array(),
- 'date_range' => array(),
+ 'size' => (int) $options['size'],
+ 'post_type' => get_post_type( $post_id ),
+ 'post_formats' => array(),
+ 'has_terms' => array(),
+ 'date_range' => array(),
'exclude_post_ids' => array(),
);
- $args = wp_parse_args( $args, $defaults );
+ $args = wp_parse_args( $args, $defaults );
/**
* Filter the arguments used to retrieve a list of Related Posts.
*
@@ -796,7 +984,7 @@ EOT;
*/
protected function _get_coalesced_range( array $date_range ) {
$now = time();
- $coalesce_time = $this->_blog_id_wpcom % 86400;
+ $coalesce_time = $this->get_blog_id() % 86400;
$current_time = $now - strtotime( 'today', $now );
if ( $current_time < $coalesce_time && '01' == date( 'd', $now ) ) {
@@ -837,7 +1025,7 @@ EOT;
$related_posts = array(
array(
'id' => - 1,
- 'url' => 'https://jetpackme.files.wordpress.com/2014/08/1-wpios-ipad-3-1-viewsite.png?w=350&h=200&crop=1',
+ 'url' => 'https://jetpackme.files.wordpress.com/2019/03/cat-blog.png',
'url_meta' => array(
'origin' => 0,
'position' => 0
@@ -849,7 +1037,7 @@ EOT;
'rel' => 'nofollow',
'context' => esc_html__( 'In "Mobile"', 'jetpack' ),
'img' => array(
- 'src' => 'https://jetpackme.files.wordpress.com/2014/08/1-wpios-ipad-3-1-viewsite.png?w=350&h=200&crop=1',
+ 'src' => 'https://jetpackme.files.wordpress.com/2019/03/cat-blog.png',
'width' => 350,
'height' => 200
),
@@ -857,7 +1045,7 @@ EOT;
),
array(
'id' => - 1,
- 'url' => 'https://jetpackme.files.wordpress.com/2014/08/wordpress-com-news-wordpress-for-android-ui-update2.jpg?w=350&h=200&crop=1',
+ 'url' => 'https://jetpackme.files.wordpress.com/2019/03/devices.jpg',
'url_meta' => array(
'origin' => 0,
'position' => 0
@@ -869,7 +1057,7 @@ EOT;
'rel' => 'nofollow',
'context' => esc_html__( 'In "Mobile"', 'jetpack' ),
'img' => array(
- 'src' => 'https://jetpackme.files.wordpress.com/2014/08/wordpress-com-news-wordpress-for-android-ui-update2.jpg?w=350&h=200&crop=1',
+ 'src' => 'https://jetpackme.files.wordpress.com/2019/03/devices.jpg',
'width' => 350,
'height' => 200
),
@@ -877,7 +1065,7 @@ EOT;
),
array(
'id' => - 1,
- 'url' => 'https://jetpackme.files.wordpress.com/2014/08/videopresswedding.jpg?w=350&h=200&crop=1',
+ 'url' => 'https://jetpackme.files.wordpress.com/2019/03/mobile-wedding.jpg',
'url_meta' => array(
'origin' => 0,
'position' => 0
@@ -889,7 +1077,7 @@ EOT;
'rel' => 'nofollow',
'context' => esc_html__( 'In "Mobile"', 'jetpack' ),
'img' => array(
- 'src' => 'https://jetpackme.files.wordpress.com/2014/08/videopresswedding.jpg?w=350&h=200&crop=1',
+ 'src' => 'https://jetpackme.files.wordpress.com/2019/03/mobile-wedding.jpg',
'width' => 350,
'height' => 200
),
@@ -1087,15 +1275,12 @@ EOT;
protected function _generate_related_post_image_params( $post_id ) {
$options = $this->get_options();
$image_params = array(
- 'src' => '',
- 'width' => 0,
- 'height' => 0,
+ 'alt_text' => '',
+ 'src' => '',
+ 'width' => 0,
+ 'height' => 0,
);
- if ( ! $options['show_thumbnails'] ) {
- return $image_params;
- }
-
/**
* Filter the size of the Related Posts images.
*
@@ -1118,7 +1303,7 @@ EOT;
// Try to get post image
if ( class_exists( 'Jetpack_PostImages' ) ) {
- $img_url = '';
+ $img_url = '';
$post_image = Jetpack_PostImages::get_image(
$post_id,
$thumbnail_size
@@ -1134,10 +1319,15 @@ EOT;
}
}
- if ( !empty( $img_url ) ) {
- $image_params['width'] = $thumbnail_size['width'];
+ if ( ! empty( $img_url ) ) {
+ if ( ! empty( $post_image['alt_text'] ) ) {
+ $image_params['alt_text'] = $post_image['alt_text'];
+ } else {
+ $image_params['alt_text'] = '';
+ }
+ $image_params['width'] = $thumbnail_size['width'];
$image_params['height'] = $thumbnail_size['height'];
- $image_params['src'] = Jetpack_PostImages::fit_image_url(
+ $image_params['src'] = Jetpack_PostImages::fit_image_url(
$img_url,
$thumbnail_size['width'],
$thumbnail_size['height']
@@ -1249,7 +1439,7 @@ EOT;
}
$response = wp_remote_post(
- "https://public-api.wordpress.com/rest/v1/sites/{$this->_blog_id_wpcom}/posts/$post_id/related/",
+ "https://public-api.wordpress.com/rest/v1/sites/{$this->get_blog_id()}/posts/$post_id/related/",
array(
'timeout' => 10,
'user-agent' => 'jetpack_related_posts',
@@ -1345,7 +1535,7 @@ EOT;
foreach ( $categories as $category ) {
if ( 'uncategorized' != $category->slug && '' != trim( $category->name ) ) {
$post_cat_context = sprintf(
- _x( 'In "%s"', 'in {category/tag name}', 'jetpack' ),
+ esc_html_x( 'In ā€œ%sā€', 'in {category/tag name}', 'jetpack' ),
$category->name
);
/**
@@ -1551,7 +1741,7 @@ EOT;
* @return array
*/
public function rest_get_related_posts( $object, $field_name, $request ) {
- return $this->get_for_post_id( $object['id'], array() );
+ return $this->get_for_post_id( $object['id'], array( 'size' => 6 ) );
}
}