Skip to content

Search 3.0: gate the Jetpack Search template on the Embedded experience (RSM-2381)#48562

Merged
adamwoodnz merged 3 commits intotrunkfrom
rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded
May 7, 2026
Merged

Search 3.0: gate the Jetpack Search template on the Embedded experience (RSM-2381)#48562
adamwoodnz merged 3 commits intotrunkfrom
rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded

Conversation

@adamwoodnz
Copy link
Copy Markdown
Contributor

@adamwoodnz adamwoodnz commented May 6, 2026

Fixes RSM-2381

Why

Sites that use the new feature-selector to choose Overlay or Inline (Theme search) still expect /?s=… to resolve through their theme's search.html. Today, behind the jetpack_search_blocks_enabled filter, the Jetpack Search block template is registered and prepended to search_template_hierarchy unconditionally, so its slug always wins resolution and the theme's template is never consulted — regardless of which experience the admin actually saved. After this PR, the template-takeover only happens when the saved experience is 'embedded'; everywhere else, the theme template renders again. Search blocks placed elsewhere (post content, sidebar widgets, custom templates) keep working on every experience, since block registration and Interactivity API state seeding stay on regardless.

Proposed changes

  • Search_Blocks::init() now splits its hooks into two groups:
    • Always when the feature flag is on:
      • register_blocks on init
      • register_block_category on block_categories_all
      • enqueue_editor_assets on enqueue_block_editor_assets
      • seed_interactivity_state on template_redirect and wp_enqueue_scripts
    • Embedded-only:
      • register_search_template on init
      • prepend_search_template on search_template_hierarchy
  • The block-level and IA-seeding hooks stay on regardless of experience because admins can insert Search blocks anywhere blocks are configurable. Those blocks need the seeded base state — apiRoot, nonce, URL-derived searchQuery / activeFilters / sortOrder, the filterConfigs: {} slot, locale — to hydrate. Per-block render.php files only contribute their own config (e.g. a filter-checkbox block's filterConfig entry) and rely on the global seed for the base.
  • The gate reads Module_Control::get_experience(), which consults get_option( 'jetpack_search_experience' ) with a legacy-boolean fallback. The option is object-cached and update_experience() writes synchronously, so the next request after a save sees the new gate — no cache-bust needed.
  • Tests for the four gate states:
    • test_init_always_registers_block_and_seed_hooks — block-level + IA-seeding hooks present regardless of experience.
    • test_init_does_not_register_template_hooks_when_not_embedded — template-takeover hooks absent off Embedded (option absent → falls back to inline).
    • test_init_registers_template_hooks_when_embedded — template-takeover hooks present when EXPERIENCE_EMBEDDED is saved.
    • test_init_does_not_register_template_hooks_when_module_inactive — even a stale 'embedded' value is overridden by is_active() === false; block-level and seed hooks still register so any post-content block keeps working.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

Set up a test site with the feature flag on:

add_filter( 'jetpack_search_blocks_enabled', '__return_true' );

Automated

cd projects/packages/search
composer phpunit -- --filter Search_Blocks_Test

Expected: 23 tests pass (4 new gate-behaviour tests).

Manual: template-takeover gate

  1. Activate the Search module and save Inline (Theme search) via the new feature-selector.
  2. Visit /?s=anything and confirm the page is rendered by the theme's search.html (or index.html fallback) — not the Jetpack Search template. The <body> class should be the theme's normal search-results class, no Jetpack Search blocks visible.
  3. Save Overlay and repeat — same expectation: theme renders, no Jetpack template takeover. (Overlay search is provided by the existing instant-search modal, not the block template, so this is correct.)
  4. Save Embedded and visit /?s=anything again. The page should now render the Jetpack Search template (results panel, filter blocks).
  5. Site Editor → Templates: the "Jetpack Search Results" template should be listed when Embedded is active. Customize it (change the heading text). Switch to Inline → reload /?s=… (theme template renders, customizations dormant). Switch back to Embedded → the customized template re-resolves with the changes intact.
  6. Save Off and confirm /?s=… falls back to the theme — same as Inline/Overlay.

Manual: blocks-anywhere parity (regardless of experience)

These steps verify that Search blocks placed off the Jetpack template still hydrate on every experience. The IA state seed is what makes this work — without it, blocks dropped into a post / sidebar / custom template would be missing apiRoot, nonce, URL-derived state, and the filterConfigs slot.

  1. Open the block inserter in any post or page (any experience). Confirm the "Jetpack Search" category and its blocks (search input, results panel, filter blocks, etc.) are still listed and insertable. They render correctly in the editor preview.
  2. Insert a jetpack/search-input block plus a jetpack/filter-checkbox (or any filter block) into a post's content. Save and view the post on the front end.
  3. With each non-Embedded experience saved (Inline, Overlay, Off), submit a query through the inline search input on that post. Confirm:
    • The block hydrates (no console errors, results panel updates).
    • URL-derived state works: open the post directly with ?q=test (or ?s=test if is_search()) and confirm the input is pre-populated and the filter UI reflects any active filters in the URL.
    • REST calls succeed (the block can reach apiRoot with the seeded nonce).
  4. With Embedded saved, repeat step 9 — same expected behaviour. Confirms there's no regression for the experience the global seed has always covered.

Network / cache sanity

  1. Toggle jetpack_search_blocks_enabled off. Confirm Search_Blocks::init() is not called and none of its hooks register (theme search.html resolves at /?s=…, no Jetpack blocks in the inserter).
  2. Switch the saved experience between Embedded and Inline a few times. The next request should reflect the new gate immediately — no manual cache flush.

@adamwoodnz adamwoodnz added the [Status] Needs Review This PR is ready for review. label May 6, 2026
@adamwoodnz adamwoodnz self-assigned this May 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions Bot added [Package] Search Contains core Search functionality for Jetpack and Search plugins [Tests] Includes Tests labels May 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control
Copy link
Copy Markdown

jp-launch-control Bot commented May 6, 2026

Code Coverage Summary

Coverage changed in 1 file.

File Coverage Δ% Δ Uncovered
projects/packages/search/src/search-blocks/class-search-blocks.php 141/329 (42.86%) 2.31% -7 💚

Full summary · PHP report · JS report

@adamwoodnz adamwoodnz added [Status] In Progress and removed [Status] Needs Review This PR is ready for review. labels May 6, 2026
@adamwoodnz adamwoodnz requested a review from kangzj May 6, 2026 09:17
@adamwoodnz adamwoodnz added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels May 6, 2026
return;
}

add_action( 'init', array( static::class, 'register_search_template' ) );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would put those two statements in a if block rather than doing early returns. It's likely that we'll need more init actions here, which might be binary based on experience.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 2573a0e

Base automatically changed from copilot/add-backend-support-experience-field to trunk May 6, 2026 23:33
adamwoodnz and others added 2 commits May 7, 2026 11:35
…ce (RSM-2381)

`Search_Blocks::init()` was registering the Jetpack Search block template
and prepending it to `search_template_hierarchy` whenever the
`jetpack_search_blocks_enabled` filter was on. With four experiences now
on the dashboard (`embedded` / `overlay` / `inline` / `off`), only Embedded
should override the theme's `search.html` — a site that saves Overlay or
Inline still expects `/?s=…` to resolve through their theme.

Splits `init()` into two layers:

- **Always when the feature flag is on:** `register_blocks`,
  `register_block_category`, `enqueue_editor_assets`. Blocks remain
  insertable in the editor regardless of experience.
- **Embedded-only:** `register_search_template`, `prepend_search_template`,
  and the two `seed_interactivity_state` hooks.

`Module_Control::get_experience()` reads `get_option(...)` (object-cached)
with a legacy-boolean fallback, so this is cheap on every request.
`update_experience()` writes synchronously, so the next request after a
save sees the new gate — no cache-bust needed.

Site Editor customizations survive a switch because they're keyed by
template slug; switching back to Embedded re-registers the template and
the DB-stored override resolves automatically.

Tests cover all four gate states: always-registered block hooks regardless
of experience, template hooks absent off-Embedded (option absent / inline /
overlay), template hooks present on Embedded, and template hooks absent
when module is inactive even with a stale `'embedded'` value in the option.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Embedded-only (RSM-2381)

The original implementation followed the issue spec literally and gated
`seed_interactivity_state` behind the Embedded experience too. That was
wrong: admins can insert Search blocks anywhere blocks are configurable
(post content, sidebar widgets, custom templates), and those blocks need
the seeded base state — `apiRoot`, `nonce`, URL-derived `searchQuery` /
`activeFilters` / `sortOrder`, the `filterConfigs: {}` slot — to hydrate.
Per-block `render.php` files only contribute their own config (e.g. a
filter-checkbox block's filterConfig entry) and rely on the global seed
for the base.

So the gating splits cleanly between "blocks may be anywhere" (always on
when the feature flag is on) and "the Jetpack template replaces the
theme's search.html" (Embedded-only):

- Always when the feature flag is on: `register_blocks`,
  `register_block_category`, `enqueue_editor_assets`, and the two
  `seed_interactivity_state` hooks (`template_redirect` +
  `wp_enqueue_scripts`).
- Embedded-only: `register_search_template`, `prepend_search_template`.

Updates the docblock to reflect the corrected reasoning, the test names
and assertions, and the changelog wording.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@adamwoodnz adamwoodnz force-pushed the rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded branch from a0f46b3 to 31b1204 Compare May 6, 2026 23:37
Per review feedback (kangzj): the gate is likely to grow more init
actions, possibly per-experience. An if-block keeps both per-experience
branches and unconditional follow-up code possible without restructuring;
the early return forecloses both. Behavior-equivalent.
@adamwoodnz adamwoodnz added [Status] Ready to Merge Go ahead, you can push that green button! and removed [Status] Needs Review This PR is ready for review. labels May 7, 2026
@adamwoodnz adamwoodnz merged commit b4cbe68 into trunk May 7, 2026
79 checks passed
@adamwoodnz adamwoodnz deleted the rsm-2381-search-30-gate-the-jetpack-search-template-on-the-embedded branch May 7, 2026 21:28
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Ready to Merge Go ahead, you can push that green button! labels May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Search Contains core Search functionality for Jetpack and Search plugins [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants