Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gutenberg: Add a Related Posts block #10132

Merged
merged 23 commits into from
Dec 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9fcf308
Add server rendering for Related Posts block
tyxla Sep 11, 2018
d88aaf7
Setting block attributes properly
tyxla Sep 12, 2018
2222f29
Use a custom block rendering markup
tyxla Sep 12, 2018
57c0ac3
Add some semicolons
tyxla Sep 12, 2018
0d77733
Remove headline from server side rendering
tyxla Oct 17, 2018
bc188e6
Default to off for displayContext
sirreal Oct 18, 2018
5b0485f
Pass render callback to jetpack_register_block()
tyxla Dec 13, 2018
83c982f
Exclude previously visited post properly
tyxla Dec 13, 2018
6534728
Do not load posts when they have loaded already
tyxla Dec 13, 2018
50710d4
Add excerpt to title attribute
tyxla Dec 13, 2018
c589430
Prevent the customizer from modifying block output
tyxla Dec 13, 2018
923bb27
Remove legacy wrapper if we have a Related Posts block in the content
tyxla Dec 13, 2018
c1d13d8
Conditionally add jp-relatedposts-items-visual class
tyxla Dec 13, 2018
30a23e6
Some phpcs fixes
tyxla Dec 13, 2018
923107b
Simplify block attribute retrieval
tyxla Dec 14, 2018
f3af2bd
Add some spacing
tyxla Dec 14, 2018
6c2c322
Disable customize controls when content has a related posts block
tyxla Dec 19, 2018
5373b7b
Add disclaimer that blocks are not affected to Settings
tyxla Dec 19, 2018
6f01b4a
Add disclaimer that blocks are not affected to Jetpack Traffic settings
tyxla Dec 19, 2018
814b7e3
Support for WP < 5.0
tyxla Dec 19, 2018
6b560e2
Improve how we disable the legacy widget when block is present in con…
tyxla Dec 19, 2018
d73314b
Introduce a parse_numeric_get_arg helper
tyxla Dec 19, 2018
5434d3c
Fixup
tyxla Dec 19, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions _inc/client/traffic/related-posts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class RelatedPostsComponent extends React.Component {
link: 'https://jetpack.com/support/related-posts/',
} }
>
<p className="jp-form-setting-explanation">
{ __( 'The following settings will impact all related posts on your site, except for those you created via the block editor:' ) }
</p>
<ModuleToggle
slug="related-posts"
disabled={ unavailableInDevMode }
Expand Down
33 changes: 32 additions & 1 deletion modules/related-posts/class.related-posts-customize.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ function customize_register( $wp_customize ) {
// If selective refresh is available, implement it.
if ( isset( $wp_customize->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,
Expand All @@ -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();
}

Expand Down
167 changes: 152 additions & 15 deletions modules/related-posts/jetpack-related-posts.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
class Jetpack_RelatedPosts {
const VERSION = '20150408';
const VERSION = '20181213';
const SHORTCODE = 'jetpack-related-posts';
private static $instance = null;
private static $instance_raw = null;
Expand Down Expand Up @@ -77,10 +77,15 @@ public function __construct( $blog_id_local, $blog_id_wpcom ) {

// 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( 'related-posts' );
jetpack_register_block(
'related-posts',
array(
'render_callback' => array( $this, 'render_block' ),
)
);
}

/**
Expand Down Expand Up @@ -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'] ) ) {
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -248,12 +248,147 @@ public function get_target_html_unsupported() {
return "\n\n<!-- Jetpack Related Posts is not supported in this context. -->\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();
?>
<div id="jp-relatedposts" class="jp-relatedposts jp-relatedposts-block" style="display: block;">
tyxla marked this conversation as resolved.
Show resolved Hide resolved
<div class="jp-relatedposts-items <?php echo $block_attributes['show_thumbnails'] ? 'jp-relatedposts-items-visual ' : ''; ?>jp-relatedposts-<?php echo esc_attr( $block_attributes['layout'] ); ?>">
<?php
foreach ( $related_posts as $index => $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'];
}
?>
tyxla marked this conversation as resolved.
Show resolved Hide resolved
<div
class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"
data-post-id="<?php echo esc_attr( $related_post['id'] ); ?>"
data-post-format="<?php echo esc_attr( ! empty( $related_post['format'] ) ? $related_post['format'] : 'false' ); ?>"
>
<?php if ( ! empty( $block_attributes['show_thumbnails'] ) && ! empty( $related_post['img']['src'] ) ) : ?>
<a class="jp-relatedposts-post-a"
href="<?php echo esc_url( $related_post['url'] ); ?>"
title="<?php echo esc_attr( $title_attr ); ?>"
rel="<?php echo esc_attr( $related_post['rel'] ); ?>"
data-origin="<?php echo esc_attr( $related_post['url_meta']['origin'] ); ?>"
data-position="<?php echo esc_attr( $related_post['url_meta']['position'] ); ?>"
>
<img class="jp-relatedposts-post-img"
src="<?php echo esc_url( $related_post['img']['src'] ); ?>"
width="<?php echo esc_attr( $related_post['img']['width'] ); ?>"
alt="<?php echo esc_attr( $title_attr ); ?>"
/>
</a>
<?php endif; ?>

<h4 class="jp-relatedposts-post-title">
tyxla marked this conversation as resolved.
Show resolved Hide resolved
<a
class="jp-relatedposts-post-a"
href="<?php echo esc_url( $related_post['url'] ); ?>"
title="<?php echo esc_attr( $title_attr ); ?>"
rel="<?php echo esc_attr( $related_post['rel'] ); ?>"
data-origin="<?php echo esc_attr( $related_post['url_meta']['origin'] ); ?>"
data-position="<?php echo esc_attr( $related_post['url_meta']['position'] ); ?>"
>
<?php echo esc_html( $related_post['title'] ); ?>
</a>
</h4>

<p class="jp-relatedposts-post-excerpt"><?php echo esc_html( $related_post['excerpt'] ); ?></p>

<?php if ( $block_attributes['show_date'] ) : ?>
<p class="jp-relatedposts-post-date" style="display: block;">
tyxla marked this conversation as resolved.
Show resolved Hide resolved
<?php echo esc_html( $related_post['date'] ); ?>
</p>
<?php endif; ?>

<?php if ( $block_attributes['show_context'] ) : ?>
<p class="jp-relatedposts-post-context">
<?php echo esc_html( $related_post['context'] ); ?>
</p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
$html = ob_get_clean();

return $html;
}

/**
* ========================
* 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.
*
Expand Down Expand Up @@ -364,6 +499,7 @@ public function print_setting_html() {
$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>
Expand All @@ -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 ),
Expand Down
18 changes: 13 additions & 5 deletions modules/related-posts/related-posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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;
Expand All @@ -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();
} );
}

Expand Down