Skip to content

Analyse the facets proposal - #166

Open
titouanmathis wants to merge 4 commits into
mainfrom
docs/facets-planning
Open

Analyse the facets proposal#166
titouanmathis wants to merge 4 commits into
mainfrom
docs/facets-planning

Conversation

@titouanmathis

Copy link
Copy Markdown
Contributor

.planning/research_facets.md — whether Føhn can already do what wordpress-project!715 proposes, and what the page cache still needs before a facet can be cached. No code changes.

The short version

The filtering already exists. QueryFiltersHook and QueryFiltersConfig are the allowlisted version of the proposal's FacetsManager, and the native WP vars (?s=, ?cat=, ?tag=, ?orderby=) need no code at all. The proposal's client-side half — a real GET form enhanced by Frame/FrameTarget — is good and worth keeping.

Its parameter naming must not be ported, and the reason is not style:

  • facets[tag_id] cannot be a cache key. It reaches the wire as facets%5Btag_id%5D; QueryKey never decodes, getCacheQueryArgs() only keys names matching ^[A-Za-z0-9_-]{1,32}$, and nginx has no $arg_facets[tag_id] to read it with. Every faceted request is a bypass on every hit.
  • It is an unauthenticated query var injection. $query->query_vars[$key] = $value for every key in the request makes ?facets[posts_per_page]=-1, ?facets[orderby]=rand and arbitrary meta_query public URLs.

What the analysis found beyond the proposal

Flattening the names is not enough. Two walls remain in Føhn itself:

  • ?genre__and=rock,jazz — the format docs/guide/query-filters.md documents — bypasses the cache, because QueryKey::VALUE_CHARACTER_CLASS has no comma and a project pattern can only narrow it. The array form fails too: [ is invalid in a keyed name and a repeated name is an explicit bypass. The framework's own documented filter URL format is exactly the format its page cache refuses.
  • A keyword field bypasses everything, since is_search is an unconditional BypassReason::Search.

So the work, in order: a multi-value encoding the cache can key (with canonical ordering as the real design question, since nginx cannot sort), then deriving cacheQueryArgs from the declared filters so the two lists cannot drift, then a bound on the key space, and search only if the keyword field has to be cached.

Two decisions are recorded as open: Section Rendering and a cached facet response are mutually exclusive today (foehn_sections is no-store and unkeyable), and filtered counts stay out of scope.

The document also lists six defects in the proposal's diff itself, including filters applied to every query on the page for want of an is_main_query() guard, and a "Last" pagination button that links to the first page.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KZusb9DU8coizq3CDgHEqi

wordpress-project!715 proposes facet filtering by copying a request array into
WP_Query. Record why that must not be ported — it is an unauthenticated query
var injection, and its parameter names cannot be a cache key in nginx at all —
and what the page cache still needs before a facet can be cached.

Co-authored-by: Claude <claude@anthropic.com>
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.66%. Comparing base (66ead81) to head (86cb4ab).

Additional details and impacted files
@@            Coverage Diff            @@
##               main     #166   +/-   ##
=========================================
  Coverage     85.66%   85.66%           
  Complexity     2535     2535           
=========================================
  Files           194      194           
  Lines          6988     6988           
=========================================
  Hits           5986     5986           
  Misses         1002     1002           
Flag Coverage Δ
unittests 85.66% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

titouanmathis and others added 3 commits August 28, 2026 13:22
Two of the four items are done and one was built and removed. Record the
differences — ordering did not need solving, the two configs stayed
independent, search needed no new switch — and what is left: a bound on the key
space, and an example that shows a filter form working end to end.

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude <claude@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant