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

Backport functions required by Comment Query Loop and related blocks #2543

Closed
17 changes: 17 additions & 0 deletions src/wp-includes/block-editor.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,23 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex

$editor_settings['localAutosaveInterval'] = 15;

$editor_settings['__experimentalDiscussionSettings'] = array(
'commentOrder' => get_option( 'comment_order' ),
'commentsPerPage' => get_option( 'comments_per_page' ),
'defaultCommentsPage' => get_option( 'default_comments_page' ),
'pageComments' => get_option( 'page_comments' ),
'threadComments' => get_option( 'thread_comments' ),
'threadCommentsDepth' => get_option( 'thread_comments_depth' ),
'avatarURL' => get_avatar_url(
'',
array(
'size' => 96,
'force_default' => true,
'default' => get_option( 'avatar_default' ),
)
),
);

/**
* Filters the settings to pass to the block editor for all editor type.
*
Expand Down
93 changes: 93 additions & 0 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -1358,3 +1358,96 @@ function _wp_multiple_block_styles( $metadata ) {
return $metadata;
}
add_filter( 'block_type_metadata', '_wp_multiple_block_styles' );

/**
* Helper function that constructs a comment query vars array from the passed
* block properties.
*
* It's used with the Comment Query Loop inner blocks.
*
* @since 6.0.0
*
* @param WP_Block $block Block instance.
*
* @return array Returns the comment query parameters to use with the
* WP_Comment_Query constructor.
*/
function build_comment_query_vars_from_block( $block ) {

$comment_args = array(
'orderby' => 'comment_date_gmt',
'order' => 'ASC',
'status' => 'approve',
'no_found_rows' => false,
'update_comment_meta_cache' => false, // We lazy-load comment meta for performance.
);

if ( ! empty( $block->context['postId'] ) ) {
$comment_args['post_id'] = (int) $block->context['postId'];
}

if ( get_option( 'thread_comments' ) ) {
$comment_args['hierarchical'] = 'threaded';
} else {
$comment_args['hierarchical'] = false;
}

$per_page = get_option( 'comments_per_page' );
$default_page = get_option( 'default_comments_page' );

if ( $per_page > 0 ) {
$comment_args['number'] = $per_page;

$page = (int) get_query_var( 'cpage' );
if ( $page ) {
$comment_args['paged'] = $page;
} elseif ( 'oldest' === $default_page ) {
$comment_args['paged'] = 1;
} elseif ( 'newest' === $default_page ) {
$comment_args['paged'] = (int) ( new WP_Comment_Query( $comment_args ) )->max_num_pages;
}
// Set the `cpage` query var to ensure the previous and next pagination links are correct
// when inheriting the Discussion Settings.
if ( 0 === $page && isset( $comment_args['paged'] ) && $comment_args['paged'] > 0 ) {
set_query_var( 'cpage', $comment_args['paged'] );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why write to a query variable here? It breaks everything else in WP. It should remain 0 on the first page, as it always had been.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-referencing #6291, where this is now being discussed, and WordPress/gutenberg#39227, where it was originally introduced.

}
}

return $comment_args;
}

/**
* Helper function that returns the proper pagination arrow html for
* `CommentsPaginationNext` and `CommentsPaginationPrevious` blocks based on the
* provided `paginationArrow` from `CommentsPagination` context.
*
* It's used in CommentsPaginationNext and CommentsPaginationPrevious blocks.
*
* @since 6.0.0
*
* @param WP_Block $block Block instance.
* @param string $pagination_type Type of the arrow we will be rendering.
* Default 'next'. Accepts 'next' or 'previous'.
*
* @return string|null Returns the constructed WP_Query arguments.
*/
function get_comments_pagination_arrow( $block, $pagination_type = 'next' ) {
$arrow_map = array(
'none' => '',
'arrow' => array(
'next' => '→',
'previous' => '←',
),
'chevron' => array(
'next' => '»',
'previous' => '«',
),
);
if ( ! empty( $block->context['comments/paginationArrow'] ) && ! empty( $arrow_map[ $block->context['comments/paginationArrow'] ][ $pagination_type ] ) ) {
$arrow_attribute = $block->context['comments/paginationArrow'];
$arrow = $arrow_map[ $block->context['comments/paginationArrow'] ][ $pagination_type ];
$arrow_classes = "wp-block-comments-pagination-$pagination_type-arrow is-arrow-$arrow_attribute";
return "<span class='$arrow_classes'>$arrow</span>";
}
return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,8 @@ protected function prepare_links( $comment ) {
$rest_url = add_query_arg( $args, rest_url( $this->namespace . '/' . $this->rest_base ) );

$links['children'] = array(
'href' => $rest_url,
'href' => $rest_url,
'embedded' => true,
);
}

Expand Down
206 changes: 206 additions & 0 deletions tests/phpunit/tests/block-library/commentTemplate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<?php
/**
* Comment Template block tests
*
* @package WordPress
* @subpackage Block Library
* @since 6.0.0
*/

/**
* Tests for the Comment Template block.
*
* @since 6.0.0
*
* @group block-library
*/
class Test_Block_Library_CommentTemplate extends WP_UnitTestCase {
Comment on lines +1 to +17
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've defined a new @subpackage and @group for this test, as this is the first one we have for a specific block (as far as I saw).

I've also modified the class name to follow the same format as the other test files.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if this file should be placed under a different folder/subpackage/etc. 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine as is. It's an implementation detail I can look at later.


private static $custom_post;
private static $comment_ids;
private static $per_page = 5;

public function set_up() {
parent::set_up();

update_option( 'page_comments', true );
update_option( 'comments_per_page', self::$per_page );
update_option( 'comment_order', 'ASC' );

self::$custom_post = self::factory()->post->create_and_get(
array(
'post_type' => 'dogs',
'post_status' => 'publish',
'post_name' => 'metaldog',
'post_title' => 'Metal Dog',
'post_content' => 'Metal Dog content',
'post_excerpt' => 'Metal Dog',
)
);

self::$comment_ids = self::factory()->comment->create_post_comments(
self::$custom_post->ID,
1,
array(
'comment_author' => 'Test',
'comment_author_email' => '[email protected]',
'comment_content' => 'Hello world',
)
);
}

function test_build_comment_query_vars_from_block_with_context() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed this test is failing in my local environment. I'm taking a look into that. 👀

1) Test_Block_Library_CommentTemplate::test_build_comment_query_vars_from_block_with_context
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
     'status' => 'approve'
     'no_found_rows' => false
     'update_comment_meta_cache' => false
-    'post_id' => 4
     'hierarchical' => 'threaded'
     'number' => 5
     'paged' => 1
 )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the same error locally. It's really surprising.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, the block is not being instantiated here with context; it's empty.

$block = new WP_Block(
$parsed_blocks[0],
array(
'postId' => self::$custom_post->ID,
)
);

I see the same happening in all the tests where context is used. Could it be related to the block not included in WordPress core yet? 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I know why, we need to have the block code first and we can then land the tests. All good then. Let's wait for #2564 and see how it looks afterwards. Good detective work 😄

$parsed_blocks = parse_blocks(
'<!-- wp:comment-template --><!-- wp:comment-author-name /--><!-- wp:comment-content /--><!-- /wp:comment-template -->'
);

$block = new WP_Block(
$parsed_blocks[0],
array(
'postId' => self::$custom_post->ID,
)
);

$this->assertEquals(
array(
'orderby' => 'comment_date_gmt',
'order' => 'ASC',
'status' => 'approve',
'no_found_rows' => false,
'update_comment_meta_cache' => false,
'post_id' => self::$custom_post->ID,
'hierarchical' => 'threaded',
'number' => 5,
'paged' => 1,
),
build_comment_query_vars_from_block( $block )
);
}

function test_build_comment_query_vars_from_block_no_context() {
$parsed_blocks = parse_blocks(
'<!-- wp:comment-template --><!-- wp:comment-author-name /--><!-- wp:comment-content /--><!-- /wp:comment-template -->'
);

$block = new WP_Block( $parsed_blocks[0] );

$this->assertEquals(
array(
'orderby' => 'comment_date_gmt',
'order' => 'ASC',
'status' => 'approve',
'no_found_rows' => false,
'update_comment_meta_cache' => false,
'hierarchical' => 'threaded',
'number' => 5,
'paged' => 1,
),
build_comment_query_vars_from_block( $block )
);
}

/**
* Test rendering a single comment
*/
function test_rendering_comment_template() {
$parsed_blocks = parse_blocks(
'<!-- wp:comment-template --><!-- wp:comment-author-name /--><!-- wp:comment-content /--><!-- /wp:comment-template -->'
);

$block = new WP_Block(
$parsed_blocks[0],
array(
'postId' => self::$custom_post->ID,
)
);

// Here we use the function prefixed with 'gutenberg_*' because it's added
// in the build step.
$this->assertEquals(
'<ol ><li><div class="wp-block-comment-author-name">Test</div><div class="wp-block-comment-content">Hello world</div></li></ol>',
render_block_core_comment_template( null, null, $block )
);
}

/**
* Test rendering 3 nested comments:
*
* └─ comment 1
*   └─ comment 2
*    └─ comment 3
*/
function test_rendering_comment_template_nested() {
$nested_comment_ids = self::factory()->comment->create_post_comments(
self::$custom_post->ID,
1,
array(
'comment_parent' => self::$comment_ids[0],
'comment_author' => 'Test',
'comment_author_email' => '[email protected]',
'comment_content' => 'Hello world',
)
);

self::factory()->comment->create_post_comments(
self::$custom_post->ID,
1,
array(
'comment_parent' => $nested_comment_ids[0],
'comment_author' => 'Test',
'comment_author_email' => '[email protected]',
'comment_content' => 'Hello world',
)
);

$parsed_blocks = parse_blocks(
'<!-- wp:comment-template --><!-- wp:comment-author-name /--><!-- wp:comment-content /--><!-- /wp:comment-template -->'
);

$block = new WP_Block(
$parsed_blocks[0],
array(
'postId' => self::$custom_post->ID,
)
);

$this->assertEquals(
'<ol ><li><div class="wp-block-comment-author-name">Test</div><div class="wp-block-comment-content">Hello world</div><ol><li><div class="wp-block-comment-author-name">Test</div><div class="wp-block-comment-content">Hello world</div><ol><li><div class="wp-block-comment-author-name">Test</div><div class="wp-block-comment-content">Hello world</div></li></ol></li></ol></li></ol>',
render_block_core_comment_template( null, null, $block )
);
}
/**
* Test that both "Older Comments" and "Newer Comments" are displayed in the correct order
* inside the Comment Query Loop when we enable pagination on Discussion Settings.
* In order to do that, it should exist a query var 'cpage' set with the $comment_args['paged'] value.
*/
function test_build_comment_query_vars_from_block_sets_cpage_var() {

// This could be any number, we set a fixed one instead of a random for better performance.
$comment_query_max_num_pages = 5;
// We substract 1 because we created 1 comment at the beggining.
$post_comments_numbers = ( self::$per_page * $comment_query_max_num_pages ) - 1;
self::factory()->comment->create_post_comments(
self::$custom_post->ID,
$post_comments_numbers,
array(
'comment_author' => 'Test',
'comment_author_email' => '[email protected]',
'comment_content' => 'Hello world',
)
);
$parsed_blocks = parse_blocks(
'<!-- wp:comment-template --><!-- wp:comment-author-name /--><!-- wp:comment-content /--><!-- /wp:comment-template -->'
);

$block = new WP_Block(
$parsed_blocks[0],
array(
'postId' => self::$custom_post->ID,
'comments/inherit' => true,
)
);
$actual = build_comment_query_vars_from_block( $block );
$this->assertEquals( $comment_query_max_num_pages, $actual['paged'] );
$this->assertEquals( $comment_query_max_num_pages, get_query_var( 'cpage' ) );
}
}