Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 8 additions & 2 deletions src/post-type/render.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
$display_type = $attributes['displayType'] ?? 'select';
$layout_direction = $attributes['layoutDirection'] ?? 'vertical';

if ( $block->context['query']['inherit'] ) {
// The query block's own attribute default carries `inherit`, but markup that
// names a `query` object without it (hand written patterns, third party query
// blocks) reaches render with the key absent. Read it as "not inherited"
// rather than warning about an undefined index.
$inherit = ! empty( $block->context['query']['inherit'] );

if ( $inherit ) {
$query_var = 'query-post_type';
$page_var = 'page';
$base_url = str_replace( '/page/' . get_query_var( 'paged' ), '', remove_query_arg( [ $query_var, $page_var ] ) );
Expand All @@ -29,7 +35,7 @@
}

// Fill in inherited query types.
if ( $block->context['query']['inherit'] ) {
if ( $inherit ) {
$inherited_post_types = $wp_query->get( 'query-filter-post_type' ) === 'any'
? get_post_types( [ 'public' => true, 'exclude_from_search' => false ] )
: (array) $wp_query->get( 'query-filter-post_type' );
Expand Down
6 changes: 5 additions & 1 deletion tests/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ run and `npm run playground:start`:
3. Activates this plugin, mounted from the working tree.
4. Copies `tests/mu-plugins/register-test-content.php` into `mu-plugins`, which
registers the post types and taxonomies the tests filter against — including
deliberately private ones.
deliberately private ones. It also records any PHP notice raised from this
plugin's files and prints it into the page as a `qf-php-error:` comment,
followed by a `qf-php-errors-checked` marker, so a spec can assert a page
rendered cleanly without depending on `display_errors`.
5. Runs `tests/seed.php`, which creates the fixture terms, posts and the demo
pages the specs visit.

Expand All @@ -44,6 +47,7 @@ Seeding is idempotent, guarded by the `query_filter_e2e_seeded` option.
| `/taxonomy-filter/` | 1 | Taxonomy filter (select) |
| `/taxonomy-checkboxes/` | 2 | Taxonomy filter (checkboxes) |
| `/post-type-filter/` | 3 | Post type filter and core search block |
| `/no-inherit-context/` | 4 | Both filters, in a query loop whose `query` context omits `inherit` |
| `/search-pagination/` | 5 | Core search block and pagination, two posts to a page |

Posts: `Alpha One` and `Alpha Two` in the `alpha` category, `Beta One` in
Expand Down
30 changes: 30 additions & 0 deletions tests/e2e/query-context.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const { test, expect, POSTS } = require( './fixtures' );

test.describe( 'Query context without inherit', () => {
test( 'the filters render without a PHP notice', async ( {
page,
loop,
} ) => {
await page.goto( '/no-inherit-context/' );
await loop.expectTitles( POSTS.all );

await expect( loop.postTypeSelect() ).toBeVisible();
await expect( loop.taxonomySelect() ).toBeVisible();

// The test mu-plugin collects anything this plugin's files raise and
// prints it as an HTML comment, so the assertion does not depend on
// how the environment is configured to display errors.
const html = await page.content();
expect( html ).toContain( 'qf-php-errors-checked' );
expect( html ).not.toContain( 'qf-php-error:' );
} );

test( 'the filters still narrow the loop', async ( { page, loop } ) => {
await page.goto( '/no-inherit-context/' );

await loop.taxonomySelect().selectOption( { label: 'Alpha' } );

await page.waitForURL( /query-4-category=alpha/ );
await loop.expectTitles( POSTS.alpha );
} );
} );
52 changes: 52 additions & 0 deletions tests/mu-plugins/register-test-content.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,55 @@ function register_test_content() : void {
'hierarchical' => false,
] );
}

/**
* PHP notices raised from inside this plugin during the current request.
*
* @var string[]
*/
$GLOBALS['query_filter_php_errors'] = [];

set_error_handler( __NAMESPACE__ . '\\record_plugin_php_error', E_ALL );
add_action( 'wp_footer', __NAMESPACE__ . '\\print_plugin_php_errors', 1000 );

/**
* Record diagnostics raised from this plugin's own files.
*
* A PHP warning only reaches the response when the server is configured to
* display errors, which is not something a test can rely on. Collecting them
* here instead means a spec can assert that a page rendered cleanly whatever
* the environment does with `display_errors`.
*
* Returns false so PHP's own handler still runs and the debug log is unchanged.
*
* @param int $errno Level of the error raised.
* @param string $errstr Error message.
* @param string $errfile File the error was raised in.
* @param int $errline Line the error was raised on.
* @return bool False, so the standard error handler also runs.
*/
function record_plugin_php_error( int $errno, string $errstr, string $errfile = '', int $errline = 0 ) : bool {
if ( strpos( $errfile, '/query-filter/' ) !== false ) {
$GLOBALS['query_filter_php_errors'][] = sprintf(
'%s in %s:%d',
$errstr,
basename( dirname( $errfile ) ) . '/' . basename( $errfile ),
$errline
);
}

return false;
}

/**
* Print the recorded notices, and a marker proving the handler was installed.
*
* @return void
*/
function print_plugin_php_errors() : void {
foreach ( array_unique( $GLOBALS['query_filter_php_errors'] ) as $error ) {
printf( "<!-- qf-php-error: %s -->\n", esc_html( $error ) );
}

echo "<!-- qf-php-errors-checked -->\n";
}
18 changes: 18 additions & 0 deletions tests/seed.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,24 @@ function query_loop_markup( int $query_id, string $filters ) : string {
),
] );

// Page 4: a query loop whose `query` context omits `inherit` altogether, as
// hand written pattern markup and third party query blocks do. The filters
// must render without warning about the missing key.
seed_post( 'No Inherit Context', 'page', [
'post_name' => 'no-inherit-context',
'post_content' => <<<HTML
<!-- wp:query {"queryId":4,"query":{"perPage":10,"postType":"post","order":"asc","orderBy":"title"}} -->
<div class="wp-block-query">
<!-- wp:query-filter/post-type /-->
<!-- wp:query-filter/taxonomy {"taxonomy":"category"} /-->
<!-- wp:post-template -->
<!-- wp:post-title /-->
<!-- /wp:post-template -->
</div>
<!-- /wp:query -->
HTML,
] );

// Page 5: a paginated loop with a search block, two posts to a page, so a
// search can be started from a page the results do not reach.
seed_post( 'Search Pagination', 'page', [
Expand Down
Loading