Problem/Motivation

When a Views exposed filter value contains a comma (e.g. a taxonomy term named "Arts, Science and Technology"), selecting that filter via AJAX and then submitting another exposed filter (e.g. a keyword search) causes a ghost duplicate entry to appear — the original correct result plus a second result with 0 items whose label contains a URL-encoded comma (`%2C`).

This is caused by a multi-step URL encoding bug in `ajax_view.js`:

Step 1 — First AJAX request (filter selected):

PHP's `http_build_query()` in `ViewAjaxController` encodes the comma in the filter value as `%2C` when building the `SetBrowserUrl` response. The browser URL becomes e.g.: "/results?field%5BSome+Term%2C+With+Comma%5D=Some+Term%2C+With+Comma"

Step 2 — Second AJAX request (another filter submitted):

`ajax_view.js` reads `window.location.search` and runs `decodeURI()` on it.
`decodeURI()` decodes `%5B`/`%5D` (brackets) but **intentionally leaves `%2C` encoded** because comma is a URI reserved character (RFC 3986 §2.2). The resulting name `field[Some+Term%2C+With+Comma]` does **not** match the actual DOM input `name` attribute `field[Some Term, With Comma]`, so the filter check: "this.$exposed_form.find(`input[name="${name}"]`).length === 0" returns `0` (no match found), and the stale URL parameter incorrectly passes the filter and is kept. `encodeURI()` then re-encodes `%` as `%25`, producing `%252C` in the AJAX request URL.

Step 3 — PHP receives the second request:

PHP decodes `%252C` once → literal `%2C` remains in `$_GET`. Both the correct value (from POST) and the malformed value (from GET) are now present as active filter items. The malformed value finds no match in the Solr/Search API index,
so a ghost result with count 0 is created alongside the real one.

Steps to reproduce

1. Set up a View with AJAX enabled and an exposed filter whose options contain a value with a comma in the label (e.g. a taxonomy term).
2. Select that filter value (triggers an AJAX request). The browser URL now contains the filter value percent-encoded (`%2C` for the comma).
3. Submit another exposed filter (e.g. a text search field).
4. Observe the filter list: the original item (correct, with count) AND a second item with the URL-encoded label (e.g. `Some Term%2C With Comma`, count 0) both appear.

The bug is reproducible with any filter value that contains a character PHP's `http_build_query()` encodes but `decodeURI()` does not decode. Comma is the most common case.

Proposed resolution

In the filter function inside the `ajaxView` constructor in `ajax_view.js`, replace the use of the `decodeURI()`-decoded name with a fully decoded name computed via `decodeURIComponent()` + `+`→space replacement before comparing
against DOM input names. This mirrors how form-encoded query strings are actually decoded (per the `application/x-www-form-urlencoded` spec).

Remaining tasks

  • Review and test the patch
  • Verify no regression for filter values without special characters
  • Verify fix with Views pager links (which also use `window.location.search`)
  • Add a JavaScript unit test if the Views test suite supports it

Comments

snap_x created an issue. See original summary.

smustgrave’s picture

Version: 11.3.x-dev » main
Status: Needs review » Needs work

Thanks for reporting. Issues need to be in MRs though with test coverage. Also need to verify an issue on the main branch as 11.3.x may be security coverage now.