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

wp:query-loop doesn't dynamically use the chosen category #11

Closed
2 of 6 tasks
bobbingwide opened this issue Nov 1, 2020 · 5 comments
Closed
2 of 6 tasks

wp:query-loop doesn't dynamically use the chosen category #11

bobbingwide opened this issue Nov 1, 2020 · 5 comments
Assignees
Labels
bug Something isn't working enhancement New feature or request

Comments

@bobbingwide
Copy link
Owner

bobbingwide commented Nov 1, 2020

I've implemented the category.html template as far as possible, with the current Gutenberg FSE functionality.

There are a number of problems:

  • the query loop doesn't dynamically use the chosen category.
  • pagination doesn't work at all

Requirement

The Gutenberg blocks wp:query, wp:query-loop and wp:query can be used in templates and template parts to create user defined queries and pagination.

Currently ( Gutenberg 9.2.2 ) they don't support the main query that WordPress has already parsed.

This makes it extremely difficult to create archive pages that support the selected taxonomy term ( category, tags or custom taxonomy ).

I need a simple solution that allows me to process the posts in the main query.

Proposed solution

In the current implementation the wp:query-loop block is nested in the wp:query block.
The wp:post-* blocks are nested within the wp:query-loop.

eg

<!-- wp:query {"queryId":1,"query":{"perPage":2,"pages":1,"offset":0,"postType":"post","categoryIds":[],"tagIds":[],"order":"desc","orderBy":"date","author":"","search":"","exclude":[542]}} -->
<!-- wp:query-loop -->
<!-- wp:post-title /-->
<!-- wp:post-featured-image {"isLink":true} /-->
<!-- wp:post-date /-->
<!-- wp:post-excerpt /-->
<!-- /wp:query-loop -->
<!-- /wp:query -->

The query-loop block uses the $block->context passed to it from the query block to construct the query.
When we want to process the main loop we need to execute the query already defined in global $wp_query.

This can be achieved using the following code:

function gutenberg_render_block_core_query_loop_main_query( $attributes, $content, $block ) {
    if ( have_posts() ) {
        $content = '';
        while ( have_posts() ) {
            the_post();
            $post = get_post();
            $content .= (
            new WP_Block(
                $block->parsed_block,
                array(
                    'postType' => $post->post_type,
                    'postId' => $post->ID,
                )
            )
            )->render(array('dynamic' => false));
        }
    } else {
        $content = "No posts found. So why isn't this a 404?";
    }
    return $content;
}

If we remove the outer wp:query block then the $block->context will not be set.
This will prompt us to run the main query.
eg

<!-- wp:query-loop -->
<!-- wp:post-title /-->
<!-- wp:post-featured-image {"isLink":true} /-->
<!-- wp:post-date /-->
<!-- wp:post-excerpt /-->
<!-- /wp:query-loop -->

Steps:

For query-loop:

  • Prototype a solution implemented in the callback function for the dynamic block wp:query-loop; gutenberg_render_block_core_query_loop() in query-loop.php.
  • Raise an issue against Gutenberg. . No need, there's one already: 25377
  • Create a pull request to implement the improvement.

For query-pagination:

  • take a similar approach as for query-loop
  • Raise a separate issue against Fizzie
  • Raise a separate issue against Gutenberg.
@bobbingwide bobbingwide self-assigned this Nov 1, 2020
@bobbingwide bobbingwide added bug Something isn't working enhancement New feature or request labels Nov 1, 2020
@bobbingwide
Copy link
Owner Author

bobbingwide commented Nov 1, 2020

Testing

  • Update templates and template parts so that they no longer use wp:query
  • Implement the 404 template. See Implement the 404.html template #12
  • Test with a variety of taxonomy URLs ( on s.b/cwiccer )
URL Expected output Passed?
/category/blocks Displays posts with category "Blocks" Yes
/category/blocks/sb Displays posts with category "Single blocks" within "Blocks" Yes
/category/invalid 404 page Yes
/category 404 page Yes
/letters/B Displays posts with letter taxonomy "B" Yes
/letters/B/page/2 Displays page 2 of posts with letter taxonomy "B" Yes
/letters/invalid 404 page Yes
/letters 404 page Yes
/tag/shortcodes Posts tagged "Shortcodes" Yes
/2020 Posts dated 2020 Yes
/2020/10 Posts dated 2020/10 Yes

@bobbingwide
Copy link
Owner Author

My new version of query-loop.php is

<?php
/**
 * Server-side rendering of the `core/query-loop` block.
 *
 * @package WordPress
 */

/**
 * Renders the `core/query-loop` block on the server.
 *
 * @param array    $attributes Block attributes.
 * @param string   $content    Block default content.
 * @param WP_Block $block      Block instance.
 *
 * @return string Returns the output of the query, structured using the layout defined by the block's inner blocks.
 */
function gutenberg_render_block_core_query_loop( $attributes, $content, $block ) {
	$page_key = isset( $block->context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page';
	$page     = empty( $_GET[ $page_key ] ) ? 1 : filter_var( $_GET[ $page_key ], FILTER_VALIDATE_INT );

    if ( isset( $block->context['query'] ) ) {
        $query = array(
            'post_type' => 'post',
            'offset' => 0,
            'order' => 'DESC',
            'orderby' => 'date',
        );
        if (isset($block->context['query']['postType'])) {
            $query['post_type'] = $block->context['query']['postType'];
        }
        if (isset($block->context['query']['exclude'])) {
            $query['post__not_in'] = $block->context['query']['exclude'];
        }
        if (isset($block->context['query']['perPage'])) {
            $query['offset'] = ($block->context['query']['perPage'] * ($page - 1)) + $block->context['query']['offset'];
        }
        if (isset($block->context['query']['categoryIds'])) {
            $query['category__in'] = $block->context['query']['categoryIds'];
        }
        if (isset($block->context['query']['tagIds'])) {
            $query['tag__in'] = $block->context['query']['tagIds'];
        }
        if (isset($block->context['query']['order'])) {
            $query['order'] = strtoupper($block->context['query']['order']);
        }
        if (isset($block->context['query']['orderBy'])) {
            $query['orderby'] = $block->context['query']['orderBy'];
        }
        if (isset($block->context['query']['perPage'])) {
            $query['posts_per_page'] = $block->context['query']['perPage'];
        }
        if (isset($block->context['query']['author'])) {
            $query['author'] = $block->context['query']['author'];
        }
        if (isset($block->context['query']['search'])) {
            $query['s'] = $block->context['query']['search'];
        }
    }

    if ( isset( $block->context['queryId']) ) {

        $posts = get_posts($query);

        $content = '';
        foreach ($posts as $post) {
            $content .= (
            new WP_Block(
                $block->parsed_block,
                array(
                    'postType' => $post->post_type,
                    'postId' => $post->ID,
                )
            )
            )->render(array('dynamic' => false));
        }
    } else {
        /**
         * Not in context of a `core/query` block; assume this is the main query and perform the loop.
         */
        $content = gutenberg_render_block_core_query_loop_main_query($attributes, $content, $block);
    }
	return $content;
}

/**
 * Renders the `core/query-loop` block for the main query on the server.
 *
 * @param array    $attributes Block attributes.
 * @param string   $content    Block default content.
 * @param WP_Block $block      Block instance.
 *
 * @return string Returns the output of the query, structured using the layout defined by the block's inner blocks.
 */
function gutenberg_render_block_core_query_loop_main_query( $attributes, $content, $block ) {
    if ( have_posts() ) {
        $content = '';
        while ( have_posts() ) {
            the_post();
            $post = get_post();
            $content .= (
            new WP_Block(
                $block->parsed_block,
                array(
                    'postType' => $post->post_type,
                    'postId' => $post->ID,
                )
            )
            )->render(array('dynamic' => false));
        }
    } else {
        $content = __( "No posts found." );
    }
    return $content;
}

/**
 * Registers the `core/query-loop` block on the server.
 */
function gutenberg_register_block_core_query_loop() {
	register_block_type_from_metadata(
		__DIR__ . '/query-loop',
		array(
			'render_callback'   => 'gutenberg_render_block_core_query_loop',
			'skip_inner_blocks' => true,
		)
	);
}
add_action( 'init', 'gutenberg_register_block_core_query_loop', 20 );

@bobbingwide
Copy link
Owner Author

bobbingwide commented Feb 25, 2021

Gutenberg's Query loop logic now uses $block->context['inherit'] to indicate whether or not the main query should be inherited.
I thought that the logic that tests $block->context['queryId'] would need changing so that I can use Gutenberg's pagination rather than the override logic.

I'm now of the opinion that my override logic still works when the core/query-loop and core/query-pagination blocks are used without being inner blocks of core/query.

Note: Instead of using core/query-pagination I have to use core/query-pagination-numbers.

I need to test and/or change:

  • archive-query.html
  • category-query.html
  • home-query.html

@bobbingwide
Copy link
Owner Author

I need to test and/or change:

I've changed archive-query.html and category-query.html to implement the query block with inherit true.

@bobbingwide
Copy link
Owner Author

It appears that the commit in 0c3f331 didn't have inherit: true. This has now been resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant