diff --git a/_inc/client/traffic/related-posts.jsx b/_inc/client/traffic/related-posts.jsx
index 925f2d1e8f64c..f33671379ea88 100644
--- a/_inc/client/traffic/related-posts.jsx
+++ b/_inc/client/traffic/related-posts.jsx
@@ -66,6 +66,9 @@ class RelatedPostsComponent extends React.Component {
link: 'https://jetpack.com/support/related-posts/',
} }
>
+
+ { __( 'The following settings will impact all related posts on your site, except for those you created via the block editor:' ) }
+
selective_refresh ) ) {
$wp_customize->selective_refresh->add_partial( "$this->prefix", array(
- 'selector' => '.jp-relatedposts',
+ 'selector' => '.jp-relatedposts:not(.jp-relatedposts-block)',
'settings' => $selective_options,
'render_callback' => __CLASS__ . '::render_callback',
'container_inclusive' => false,
@@ -113,25 +113,56 @@ public static function render_callback() {
echo Jetpack_RelatedPosts::init()->get_headline();
}
+ /**
+ * Check whether the current post contains a Related Posts block.
+ * If we're on WP < 5.0, this automatically means it doesn't,
+ * because block support is intrododuced in WP 5.0.
+ *
+ * @since 6.9.0
+ *
+ * @return bool
+ */
+ public static function contains_related_posts_block() {
+ if ( ! function_exists( 'has_block' ) ) {
+ return false;
+ }
+
+ if ( has_block( 'jetpack/related-posts' ) ) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Check that we're in a single post view.
+ * Will return `false` if the current post contains a Related Posts block,
+ * because in that case we want to hide the Customizer controls.
*
* @since 4.4.0
*
* @return bool
*/
public static function is_single() {
+ if ( self::contains_related_posts_block() ) {
+ return false;
+ }
return is_single();
}
/**
* Check that we're not in a single post view.
+ * Will return `false` if the current post contains a Related Posts block,
+ * because in that case we want to hide the Customizer controls.
*
* @since 4.4.0
*
* @return bool
*/
public static function is_not_single() {
+ if ( self::contains_related_posts_block() ) {
+ return false;
+ }
return ! is_single();
}
diff --git a/modules/related-posts/jetpack-related-posts.php b/modules/related-posts/jetpack-related-posts.php
index fcbe23e771f0b..7ae8a1e0de11e 100644
--- a/modules/related-posts/jetpack-related-posts.php
+++ b/modules/related-posts/jetpack-related-posts.php
@@ -1,6 +1,6 @@
array( $this, 'render_block' ),
+ )
+ );
}
/**
@@ -125,17 +130,7 @@ public function action_frontend_init() {
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 +167,18 @@ public function get_headline() {
/**
* 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 ( function_exists( 'has_block' ) && has_block( 'jetpack/related-posts', $content ) ) {
+ return $content;
+ }
+
+ if ( ! $this->_found_shortcode ) {
$content .= "\n" . $this->get_target_html();
}
@@ -248,12 +248,147 @@ public function get_target_html_unsupported() {
return "\n\n\n\n";
}
+ /**
+ * ===============
+ * GUTENBERG BLOCK
+ * ===============
+ */
+
+ /**
+ * 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,
+ )
+ );
+
+ if ( ! $related_posts ) {
+ return '';
+ }
+
+ ob_start();
+ ?>
+
+
+ $related_post ) :
+ $classes = array_filter(
+ array(
+ 'jp-relatedposts-post',
+ 'jp-relatedposts-post' . $index,
+ ! empty( $block_attributes['show_thumbnails'] ) ? 'jp-relatedposts-post-thumbs' : '',
+ )
+ );
+ $title_attr = $related_post['title'];
+ if ( '' !== $related_post['excerpt'] ) {
+ $title_attr .= "\n\n" . $related_post['excerpt'];
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ get_options();
$ui_settings_template = <<%s
-
@@ -385,6 +521,7 @@ public function print_setting_html() {
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 ),
diff --git a/modules/related-posts/related-posts.js b/modules/related-posts/related-posts.js
index ac2eb0d4f1ed4..c3cc1c53e1197 100644
--- a/modules/related-posts/related-posts.js
+++ b/modules/related-posts/related-posts.js
@@ -194,6 +194,13 @@
}
};
+ function afterPostsHaveLoaded() {
+ jprp.setVisualExcerptHeights();
+ $( '#jp-relatedposts a.jp-relatedposts-post-a' ).click( function() {
+ this.href = jprp.getTrackedUrl( this );
+ } );
+ }
+
/**
* Initialize Related Posts.
*/
@@ -203,6 +210,11 @@
var endpointURL = jprp.getEndpointURL(),
$relatedPosts = $( '#jp-relatedposts' );
+ if ( $( '#jp-relatedposts .jp-relatedposts-post' ).length ) {
+ afterPostsHaveLoaded();
+ return;
+ }
+
$.getJSON( endpointURL, function( response ) {
if ( 0 === response.items.length || 0 === $relatedPosts.length ) {
return;
@@ -229,15 +241,11 @@
html = ! showThumbnails ? jprp.generateMinimalHtml( response.items, options ) : jprp.generateVisualHtml( response.items, options );
$relatedPosts.append( html );
- jprp.setVisualExcerptHeights();
if ( options.showDate ) {
$relatedPosts.find( '.jp-relatedposts-post-date' ).show();
}
$relatedPosts.show();
-
- $( '#jp-relatedposts a.jp-relatedposts-post-a' ).click(function() {
- this.href = jprp.getTrackedUrl( this );
- });
+ afterPostsHaveLoaded();
} );
}