Repository navigation
Keep query-bound search on the current page - #74
Conversation
Build the search URL from the current location rather than the form action, run the search render filter after plugins such as Polylang that rewrite search actions, and carry current parameters as hidden inputs for no-JS submissions. Fixes #73. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Playwright — PHP 8.2 / WP latestDetails
|
kadamwhite
left a comment
There was a problem hiding this comment.
@goldenapples looks good! One optional change, and a docs wording preference. Nothing blocking.
| $block_content->set_attribute( 'data-wp-on--input', 'actions.search' ); | ||
|
|
||
| return (string) $block_content; | ||
| return add_filter_hidden_inputs( (string) $block_content, [ $query_var, $page_var ] ); |
There was a problem hiding this comment.
For an inherited loop, I believe that $page_var will be literal 'page', but that $paged will also be set. We deleted 'paged' in JS here, but in a non-JS environment with pretty permalinks disabled, this would leave a hidden input with paged set to whatever the on-load value was, and that would be passed along with a successive request.
This is an edge case, for our needs; pretty permalinks are ubiquitous. But I think this would make it more correct:
| return add_filter_hidden_inputs( (string) $block_content, [ $query_var, $page_var ] ); | |
| return add_filter_hidden_inputs( (string) $block_content, [ $query_var, $page_var, 'paged' ] ); |
Please feel free to pit your agent against mine, and this isn't blocking if you disagree 😁
There was a problem hiding this comment.
Good catch. I refined it just a little in d595417, so that we only strip the "paged" variable if this is the main/inherited query on a page.
Otherwise, if there's two queries on a page each with pagination, it might be possible for a navigation action in the custom query to lose the current page variable of the inherited query.
|
|
||
| // Only echoed back, escaped, as the current URL already is in the form action. | ||
| // phpcs:ignore WordPress.Security.NonceVerification.Recommended | ||
| foreach ( wp_unslash( $_GET ) as $key => $value ) { |
There was a problem hiding this comment.
TIL that unslash() takes an array. Nice!
Co-authored-by: K Adam White <kadamwhite@users.noreply.github.com>
Fixes #73.
Changes
updateURL()insrc/taxonomy/view.jsbuilds the next URL from thecore/routerstore'sstate.url, falling back towindow.location.href, instead ofform.action. A new search drops the query's page parameter (context.pageParamfor a loop with its own query;pagedand a trailing/page/N/for an inherited loop), matching the server.render_block_searchruns at priority 20, so it sets the action of query-bound search blocks after Polylang-style filters at 10.$_GETparameters, except this query's search and page parameters, are rendered as hidden inputs (sanitize_text_field()+esc_attr()), so a GET submission keeps applied filters.get_query_param()(added in 0.6.0) names the search and page parameters on both sides, so they match what the pagination block writes.Testing
New Playwright specs in
tests/e2e/search-action.spec.jsfail onmainand pass with the fix:form.actionis changed in the DOM;query-3-post_type.npx playwright test: 48 passed. PHPCS clean.wp-scripts lint-jsreports pre-existing errors only (includingview.js:86, unchanged frommain).Also checked against a real Polylang Pro install (Solace, pretty permalinks): the search action stays on
/blog/and/fr/blog/instead of being rewritten to the site/language root, and on a page with two loops the hidden inputs carry the other loop's page parameter.Compatibility notes
render_block_core/searchfilters at 10–19, but only for search blocks inside a Query Loop. Code that needs to change those blocks after this plugin can hook later than 20.form.action, so changing the action on the client has no effect on a query-bound search. The server-rendered action is still used for no-JS submissions.pre_get_posts_transpose_query_vars()already ignores them.langhidden input andlangmay also be in$_GET, which may produce a duplicatelangfield with the same value. Not tested; harmless for GET, but worth excluding if confirmed./page/N/path in JS has no dedicated test; only Chromium was run.🤖 Generated with Claude Code