Repository navigation
Presets: carry the block instance, and the right post id, in the preset context - #41
Conversation
Playwright test results — WP 7.1Details
|
Playwright test results — WP 7.0Details
|
Playwright test results — WP 6.9Details
|
A preset callback could see query vars and a small context array, but never the WP_Block, so it could not read block context: no termId or taxonomy inside a Term Template, no postId, nothing core puts there. The frontend filter is handed the block, reads its context to find the preset name, and then throws it away. Put it in the context array as 'block_instance'. The callback signature does not change, so every preset already written keeps working. Not 'block': that key is taken, and holds perPage and page. It is misnamed, but presets read it, so renaming it is breaking and stays out of scope — which is exactly why the new key says "instance" out loud. modify_rest_query_for_preset() sets it to null rather than omitting it, so the context has one shape and a preset can write $context['block_instance']?-> without an isset dance. It is null there because the editor preview queries the collection endpoint instead of rendering a block: there is no instance. A preset leaning on block context will differ between preview and frontend, and the docs say so rather than implying otherwise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
filter_query_loop_block_query_vars() built 'post_id' from get_the_ID(), which reads whatever post the global loop is on. The block's own context already holds the post core resolved for that block, and the function reads that context one statement earlier to find the preset name. Prefer $block->context['postId'], falling back to get_the_ID(). On a singular template the two agree; they diverge wherever the global post is not what the block is rendering for. This is a behaviour change, not a refactor: a preset keying off 'post_id' in a context where the two differ will now get a different post. That is the post it should have had, but it is worth saying plainly rather than finding out in production. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8933955 to
8d8e560
Compare
Prose only; no executable line changes. CLAUDE.md describes how the plugin works now, so it cannot lean on a before and after. Drop "already holds" and the sentence about the signature being unchanged: backward compatibility is a fact about a change, not about the plugin, and a reader arriving later has nothing to compare it to. "Code for that rather than expecting a block" told nobody what to do. Say the actual instruction: check block_instance, return $query_vars unchanged when it is null. "isset dance" is a figure of speech. Say what it means. Likewise "front end" as a noun, and label the Term Template snippet as illustrative so nobody goes looking for a preset the plugin does not ship. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README still told the reader the callback signature was unchanged. That is a fact about a pull request, not about the plugin, and whoever opens the README later has no prior version to hold it against. Deleted rather than reworded: the new key lives inside the $context array, so there is no parameter for a callback to decline, and saying so would be noise. Split the CLAUDE.md REST line, which was a colon joining three clauses, into one idea per sentence. The reference to modify_rest_query_for_preset() moves into its own sentence rather than being carried parenthetically. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@mattheu is this one still something you can pursue? Sounds like a useful update |
|
@roborourke This is ready to go actually. I'd like to get it in as it would let me simplify some code I have on a project. Whilst I don't love that we now pass both 'block' which is an array of data e.g. pagination (legacy behaviour) and block_instance which is the actual block, this does maintain backwards compatibility. A quick scan of our Github repos it doesn't look like anyone is using this, but I realise there are projects not within our org so I think it's safest to do it like this. |
roborourke
left a comment
There was a problem hiding this comment.
nice to have the extended docs as well, cheers Matt
The gap
The
$contextparam passed toapply_query_presetpasses some data, but it would be great if it just passed the fullWP_Blockobject. (In all honesty, I'm not sure why the old code passes a property calledblockthat contains pagination data. But I don't want to break anything using this)Reson for this - a preset can't read block context: no
termId/taxonomyinside a Term Template, nopostId, nothing core puts there.$context['block']looks like it should be the block and isn't — it is a two-key array ofperPageandpage.The fix
Carry the block in the context array that already exists, as
block_instance:No signature change. The callback is still
function ( array $query_vars, array $context ): array, so every preset already registered keeps working without being touched.Not named
block— that key is taken and presets read it, so renaming it is breaking and out of scope.block_instancematches the "Block instance" vocabulary already in the file's docblocks, and says out loud what the older key isn't.modify_rest_query_for_preset()sets it tonullexplicitly rather than omitting the key, so the context has one shape in both paths and a preset can read it with?->and noisset()check.$blockis null on RESTThe editor preview fetches from the collection endpoint rather than rendering the block, so there is no instance to carry. That is inherent, not a gap being papered over: a preset depending on block context behaves differently in the preview from the front end, and the README says so plainly.
post_idnow prefers the block's contextpost_idwasget_the_ID(). It is now$block->context['postId'], falling back toget_the_ID().In practice these are the same value. Core's
post-templatesets the context from the global post:So inside a Query Loop the two agree by construction, and where there is no post context at all — an archive, a header, a footer — the fallback preserves today's behaviour exactly.
They diverge only if something has moved the global post without the block context following: a stray
setup_postdata(), or a secondaryWP_Queryrunningthe_post()without a reset, before the loop renders. In that case the block context is the correct post and the old behaviour was the bug.It is its own commit (
Presets: take post_id from the block, not the global loop) if you would rather weigh it separately.Testing instructions
npm run test:php— exit 0. Runs the existing exclusion planner tests (27 checks) plus the newtests/php/query-presets-test.php(10 checks), which drives the realinc/query-presets.phpagainst stubs: the block reaches the callback through$context['block_instance'], is null on REST with the key still present, a preset can readtermIdoff it,$context['block']is still pagination metadata, andpost_idprefers block context over the global.'block_instance' => $blockfails 2 checks; revertingpost_idtoget_the_ID()fails 1.composer install && vendor/bin/phpcs— exit 0.tests/mu-plugins/test-query-presets.php: the block instance has no frontend-observable effectquery-presets.spec.jscould assert without inventing one, so an unasserted fixture would be noise.No version bump (the release workflow stamps
__VERSION__), no built assets.🤖 Generated with Claude Code