JSON Custom Query
Filter and order supported modern JReviews queries with strict, model-aware JSON, and migrate legacy Custom Where / Order safely.
Overview
JSON Custom Query is the recommended advanced-query format for supported modern JReviews pages and widgets. It lets you add model-aware filters and ordering without placing raw SQL in a setting.
Use the ordinary category, listing type, author, date, relationship, and ordering controls first. Add JSON only for requirements those controls cannot express. JSON where conditions can narrow the surface's eligible row set but cannot widen it; JSON ordering and the surface's limit can still change which eligible rows appear.
Choose an Approach
Use JSON Custom Query wherever the setting is available. It accepts only the JReviews fields, relationships, operations, and context values documented in this guide.
Keep Legacy Custom Where / Order only for legacy Joomla modules, legacy WordPress widgets, legacy shortcode/module controllers, and the legacy Related Reviews renderer. Those settings contain SQL fragments and are not valid JSON.
Supported Surfaces and Context
The setting is implemented on these surfaces:
- Listings, Comments, Media, and Calendar Site Widgets
- Listing and comment/review Custom List menu pages
- Related Listings on the modern listing detail page
- Related Comments on the modern listing detail page
Related Comments is a first-class Comment-model surface. Its relationship controls select comments related by comment author, commented-listing owner, or listing type. JSON then narrows those comments and can replace the selected comment order.
Context-token matrix
Tokens are values supplied by the surface. Viewer and server-date tokens are distinct from listing-context tokens. Merely placing a Site Widget on a listing page does not supply listing_id or listing_owner_id.
| Surface | Model | user_id |
Date tokens | listing_id |
listing_owner_id |
|---|---|---|---|---|---|
| Listings Site Widget | Listing | Yes, authenticated viewer | Yes | No | No |
| Comments Site Widget | Comment | Yes, authenticated viewer | Yes | No | No |
| Media Site Widget | Media | Yes, authenticated viewer | Yes | No | No |
| Calendar Site Widget | Listing | Yes, authenticated viewer | Yes | No | No |
| Listing Custom List page | Listing | Yes, authenticated viewer | Yes | No | No |
| Comment/review Custom List page | Comment | Yes, authenticated viewer | Yes | No | No |
| Related Listings | Listing | Yes, authenticated viewer | Yes | Yes | Yes, when the listing has an owner |
| Related Comments | Comment | Yes, authenticated viewer | Yes | Yes | Yes, when the listing has an owner |
The date tokens are current_year, current_month, and current_day, calculated by the server when the query is compiled. user_id is the authenticated person viewing the site—not the listing author or the administrator who saved the query. For an anonymous viewer, user_id is unavailable. A query that requires an unavailable token is rejected; the token never becomes 0 and its condition is never skipped.
How Queries Compose
JSON filtering is added to the widget or page's regular filters:
- JReviews applies the location's regular publication, access, and filtering rules first.
- Each top-level JSON
wherecondition is added withAND. AnORgroup applies only inside that added condition; it cannot bypass the regular rules. - If the JSON contains an
order, it replaces the regular ordering setting. Withoutorder, the regular setting remains active. - JSON uses a default limit of 100 when no smaller limit is already present. The widget or page can apply a smaller result limit afterward.
In practical terms, a JSON condition can narrow the available results, but it cannot make an otherwise hidden or excluded record eligible. Ordering and result limits still determine which matching records appear first.
The regular rules preserved by each supported location are:
| Location | Rules applied before JSON |
|---|---|
| Listings Site Widget | Published status and publication window when the selected listing model supports those scopes |
| Comments Site Widget | Published comments and a published parent listing; it does not apply the parent listing's publication window |
| Media Site Widget | Published and approved media, viewer media-access levels, and a published parent listing |
| Calendar Site Widget | Published status and publication window on all three listing-query paths |
| Listing Custom List page | Published status and publication window |
| Comment/review Custom List page | Its comment-visibility mode and a published parent listing; the parent publication window is not applied |
| Related Listings | Published status, publication window, and current-listing exclusion |
| Related Comments | Published comments, a published parent listing, current-listing exclusion, listing-type selection, and the selected relationship rule; the parent publication window is not applied |
JSON Custom Query does not add a new listing access policy. Your existing JReviews and CMS permissions continue to control access.
Regular selections such as explicit IDs, category, listing type, author, date window, media type, and Related Listings or Related Comments relationship rules stay active when JSON is applied.
When a non-random JSON order does not include the model's primary key, JReviews appends the primary key ascending as a deterministic tie-breaker. A JSON RAND() term uses random ordering instead.
Query-System Reference
Use the tabs for syntax and setting-reference material. Surface selection, composition, migration, AI assistance, and verification remain outside the tabs because they apply to the migration as a whole.
JSON Custom Query Reference
Root document
The root must be a JSON object containing where, order, or both. No other root keys are accepted, and an empty object is invalid.
{
"where": [
{"column": "id", "operator": ">", "value": 0}
]
}
Both values must be arrays. Duplicate object keys and unknown keys are rejected.
Conditions and groups
A condition accepts exactly these keys:
{
"column": "created_by",
"operator": "=",
"token": "user_id"
}
columnandoperatorare required.- Use exactly one of
valueortoken. IS NULLandIS NOT NULLaccept neithervaluenortoken.relationis optional and provides one allowlisted relationship hop.subqueryis explicitly unsupported.
A group accepts only conditions and optional logic:
{
"conditions": [
{"relation": "field_data", "column": "featured", "operator": "=", "value": 1},
{"column": "title", "operator": "LIKE", "value": "%featured%"}
],
"logic": "OR"
}
conditions must be a non-empty array. logic is AND by default and accepts only AND or OR. Condition keys and group keys cannot be mixed in one object. Items in the root where array are combined with AND.
Ordering
Each order term accepts only column, optional direction, and optional relation:
{
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
column is required. direction defaults to ASC and accepts ASC or DESC. Use {"column":"RAND()"} for random ordering; its direction has no effect. A relation can be ordered only when its schema marks that relation orderable.
Operators
The complete operator allowlist is:
| Operator | Value shape |
|---|---|
=, !=, <, <=, >, >= |
One scalar value or one available token |
LIKE, NOT LIKE |
One scalar value or one available token; only fields that allow these operators |
IN, NOT IN |
A non-empty list of up to 100 scalar values, or a token whose value is such a list |
BETWEEN, NOT BETWEEN |
Exactly two scalar values of compatible types, or a compatible token value |
IS NULL, IS NOT NULL |
No value and no token |
Operator input is normalized to uppercase. Arrays are rejected for scalar operators, and null is accepted only through the explicit null operators.
Column functions
Functions wrap one allowlisted field. Nested functions are rejected.
| Field kind | Functions |
|---|---|
| Date | MONTH, YEAR, DAY, WEEK, DAYOFWEEK, DAYOFMONTH, DAYOFYEAR, QUARTER, DATE |
| String | UPPER, LOWER, TRIM, LTRIM, RTRIM |
For example, MONTH(created) is valid on a model's created date field. A function is accepted only when that exact field's schema permits it.
Safe date values
Date comparisons can use these exact server-side expressions as string values:
NOW,NOW(),CURDATE, orCURDATE()DATE_ADD(NOW(), INTERVAL n UNIT)DATE_SUB(NOW(), INTERVAL n UNIT)- The same
DATE_ADD/DATE_SUBforms withCURDATE()
UNIT is one of DAY, WEEK, MONTH, or YEAR. The interval is a positive integer no greater than 3650. CURRENT_DATE, nested expressions, and HOUR, MINUTE, or SECOND intervals are not supported date expressions.
Relations
Only one relationship hop is accepted. These two condition forms are equivalent:
{"column":"field_data.jr_city","operator":"=","value":"Boston"}
{"relation":"field_data","column":"jr_city","operator":"=","value":"Boston"}
Do not combine both forms with different relation names. Relations are model-specific:
| Model | Relation | Allowed fields | Orderable |
|---|---|---|---|
| Listing | field_data |
contentid, featured, email, publish_down, and custom fields matching jr_[A-Za-z0-9_]+ |
Yes |
| Listing | aggregates |
user_rating, user_rating_count, user_rating_rank, editor_rating, editor_rating_count, editor_rating_rank, media_count, photo_count, video_count, audio_count, attachment_count |
Yes |
| Comment | field_data |
reviewid and custom fields matching jr_[A-Za-z0-9_]+ |
Yes |
| Media | — | No JSON relations | — |
Supported model fields
Use these exact schema names on both Joomla and WordPress. Root fields pass through the model's alias resolver before the builder qualifies the physical column. Do not substitute raw WordPress names such as post_title, post_author, or post_date_gmt; the strict schema rejects them.
| Model | Root fields accepted by the strict schema |
|---|---|
| Listing | id, title, alias, summary, description, created_by, state, created, modified |
| Comment | id, pid, listing_id, listing_type_id, userid, user_id, author, published, rating, title, comments, created, modified, vote_helpful, vote_total, extension, mode |
| Media | id, media_id, listing_id, review_id, user_id, media_type, media_function, published, approved, access, created, modified, views, likes_up, ordering, filename, title, description |
The Listing aliases resolve to these physical CMS columns:
| JSON field | Joomla | WordPress |
|---|---|---|
id |
id |
ID |
title |
title |
post_title |
alias |
alias |
post_name |
summary |
introtext |
post_excerpt |
description |
fulltext |
post_content |
created_by |
created_by |
post_author |
state |
state |
post_status |
created |
created |
post_date_gmt |
modified |
modified |
post_modified_gmt |
Comment compatibility aliases are also physical mappings: listing_id resolves to pid, user_id resolves to userid, and extension resolves to the real mode column. Both extension and mode are accepted JSON names for that stored value; extension is the database index name, not a separate comments-table column.
publish_down is not a Listing root field. In JSON it belongs to the Listing field_data relation, which targets jreviews_content on both CMSs. For the caller-owned publication window, Joomla reads the CMS content table's publish_down, while WordPress reads jreviews_content.publish_down. The repair migration adds that JReviews column only when a legacy jreviews_content table is missing it, using the standard nullable, indexed dateTime shape with no default. Fresh installs already receive the column from the create migration, and the repair intentionally does not drop it on rollback.
Context tokens
| Token | Value |
|---|---|
user_id |
ID of the authenticated viewer; unavailable to anonymous viewers |
listing_id |
ID of the listing whose modern detail page is being viewed |
listing_owner_id |
User ID of that listing's owner; unavailable when there is no positive owner ID |
current_year |
Current four-digit server year |
current_month |
Current server month, 1–12 |
current_day |
Current server day of month, 1–31 |
The model schemas recognize all six token names, but a query can use only the tokens its actual surface supplies. Consult the context-token matrix, not the schema list alone.
Complexity limits
| Rule | Value |
|---|---|
| JSON input | 16 KiB (16,384 bytes) |
Nested where depth |
3 |
| Conditions across the document | 25 |
| Children in one group | 10 |
| Order terms | 3 |
Values in one IN or NOT IN list |
100 |
| One scalar string or column expression | 1,000 characters |
| JSON-layer default result limit | 100 records when no smaller limit exists at application time; a later surface limit can replace it |
The grammar and size rows are hard validation limits. The 100-row result value is an advisory builder default, not a hard cap. BETWEEN and NOT BETWEEN always require exactly two values.
Legacy Custom Where / Order Reference
Legacy Custom Where and Custom Order are raw SQL-fragment settings retained for legacy Joomla modules, legacy WordPress widgets, legacy module/shortcode controllers, and the legacy Related Reviews renderer.
They are not alternate syntax for the JSON field. Their database columns, placeholders, and behavior are controller- and CMS-specific, so this page does not publish reusable raw-SQL examples.
When the modern listing detail page is enabled, Related Comments uses the Comment model and JSON Custom Query. It never executes the preserved Related Reviews custom_where or custom_order values. Those legacy values remain stored for the legacy renderer.
Verified Pattern Library
Every example uses the documented JReviews field and relationship names. Check the surface note before using a context token.
Current viewer's listings
Valid for a Listings Site Widget, a Listing Custom List page, or Related Listings when the viewer is authenticated. It fails closed for an anonymous viewer.
{
"where": [
{"column": "created_by", "operator": "=", "token": "user_id"}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Exclude the current listing
Use only in Related Listings. That component already excludes the current listing; this example shows how listing_id is resolved and is useful when adapting a more complex condition.
{
"where": [
{"column": "id", "operator": "!=", "token": "listing_id"}
]
}
Listings by the current listing owner
Use only in Related Listings. The query fails closed if the current listing has no available owner.
{
"where": [
{"column": "created_by", "operator": "=", "token": "listing_owner_id"}
]
}
Listings created this month
Valid on Listing-model surfaces.
{
"where": [
{"column": "YEAR(created)", "operator": "=", "token": "current_year"},
{"column": "MONTH(created)", "operator": "=", "token": "current_month"}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Custom field and rating relation
Valid on Listing-model surfaces. Replace jr_city with an existing listing custom field.
{
"where": [
{"relation": "field_data", "column": "jr_city", "operator": "=", "value": "Boston"},
{"relation": "aggregates", "column": "user_rating", "operator": ">=", "value": 4}
],
"order": [
{"relation": "aggregates", "column": "user_rating", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Upcoming listing dates
Valid on Listing-model surfaces. Replace jr_eventdate with an existing date custom field.
{
"where": [
{"relation": "field_data", "column": "jr_eventdate", "operator": ">=", "value": "CURDATE()"},
{"relation": "field_data", "column": "jr_eventdate", "operator": "<=", "value": "DATE_ADD(CURDATE(), INTERVAL 30 DAY)"}
],
"order": [
{"relation": "field_data", "column": "jr_eventdate", "direction": "ASC"},
{"column": "id", "direction": "ASC"}
]
}
Random featured listings
Valid on Listing-model surfaces.
{
"where": [
{"relation": "field_data", "column": "featured", "operator": "=", "value": 1}
],
"order": [
{"column": "RAND()"}
]
}
Current viewer's comments
Valid for a Comments Site Widget, a comment/review Custom List page, or Related Comments when the viewer is authenticated. It fails closed for an anonymous viewer.
{
"where": [
{"column": "user_id", "operator": "=", "token": "user_id"}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Related Comments from the current listing owner
Use only in Related Comments. This JSON runs after the component's selected relationship rule and listing-type filter.
{
"where": [
{"column": "user_id", "operator": "=", "token": "listing_owner_id"},
{"column": "listing_id", "operator": "!=", "token": "listing_id"}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Comments created this month
Valid on Comment-model surfaces.
{
"where": [
{"column": "YEAR(created)", "operator": "=", "token": "current_year"},
{"column": "MONTH(created)", "operator": "=", "token": "current_month"}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Comment custom field relation
Valid on Comment-model surfaces. Replace jr_verified with an existing comment custom field.
{
"where": [
{"relation": "field_data", "column": "jr_verified", "operator": "=", "value": 1}
],
"order": [
{"column": "created", "direction": "DESC"},
{"column": "id", "direction": "ASC"}
]
}
Migration Guide
1. Identify the actual surface and model
Record whether the target is a Site Widget, Custom List page, Related Listings, or Related Comments. Then select the correct model schema: Listing, Comment, or Media. Calendar uses the Listing schema.
Do not migrate a legacy module merely because a similar modern widget exists. Leave the legacy SQL on its legacy controller until you intentionally replace that placement with a modern Site Widget or component.
2. Separate ordinary settings from advanced intent
Move categories, listing types, explicit IDs, author selections, relationship modes, date windows, and ordinary limits into the surface's normal controls. JSON should express only the remaining filtering or ordering requirement.
3. Map to documented fields and relationships
- CMS listing title columns become
title. - CMS listing author columns become
created_by. - CMS listing creation-date columns become
created. - Listing custom fields become the
field_datarelation and theirjr_...names. - Listing rating/count data uses the
aggregatesrelation. - Comment custom fields use the Comment
field_datarelation.
Never carry table prefixes, table aliases, raw WordPress post_* names, joins, or SQL comments into JSON.
4. Replace supported dynamic values
Use a token only where the surface matrix supplies it. Replace supported relative-date intent with the exact safe date expressions. Rewrite straightforward boolean logic as conditions and groups.
5. Stop on unsupported intent
There is no automatic JSON equivalent for an arbitrary subquery, join, correlated query, database-specific expression, or unsupported function. Keep the old placement on its legacy controller, redesign the query using ordinary settings and allowlisted relations, or request a product enhancement. Do not invent a near-equivalent that changes who or what is selected.
6. Validate expected behavior
Save the query through the administration form, then test authenticated and anonymous viewers as applicable. Check known included records, excluded records, order ties, empty results, page/widget limits, and every CMS or extension model in use.
AI-Assisted SQL-to-JSON Migration
AI can help translate intent, but it must be constrained by the strict schema above. Use the prompt as an intake assistant: it must collect and confirm the required migration inputs before it attempts a conversion.
Required inputs
- CMS: Joomla or WordPress
- Target surface: exact Site Widget, Custom List, Related Listings, or Related Comments
- Target model: Listing, Comment, or Media
- Legacy Custom Where value, or an explicit confirmation that it is empty
- Legacy Custom Order value, or an explicit confirmation that it is empty
- Ordinary filters and relationship settings that must remain active
- Known records that must be included, excluded, and first/last in the result
You do not need to identify context tokens. Once the exact surface is known, the assistant must derive its allowed tokens from the context-token matrix.
Migration prompt
Convert the JReviews Legacy Custom Where / Order intent below to a
strict JSON Custom Query.
The required reference is:
https://www.jreviews.com/docs/v6/json-query-builder
Before conversion, confirm that you can access that reference and use
its context-token matrix and strict JSON grammar, including the model
fields, relations, operators, functions, date expressions, and limits.
If you cannot access the reference, output no JSON. State that a
reliable conversion cannot proceed without the reference material,
request that the user paste or attach the context-token matrix and the
relevant strict grammar/model reference sections, and wait. Never
reconstruct or guess the grammar.
Inputs:
- CMS: [Joomla or WordPress]
- Surface: [exact surface]
- Target model: [Listing, Comment, or Media]
- Legacy Custom Where: [paste exact value, or explicitly write "empty"]
- Legacy Custom Order: [paste exact value, or explicitly write "empty"]
- Ordinary filters/relationship settings that remain active:
[list them]
- Must include: [specific records/cases]
- Must exclude: [specific records/cases]
- Required order: [specific tie and boundary cases]
Intake gate — complete this before conversion:
1. Treat CMS, exact surface, target model, Legacy Custom Where, and
Legacy Custom Order as required. A blank, placeholder, broad label,
or uncertain value is missing or ambiguous. Do not infer it.
2. Treat Legacy Custom Where or Legacy Custom Order as empty only when
the user explicitly confirms that specific value is empty. An
omitted or blank value is not confirmation.
3. If any required item is missing or ambiguous, output no JSON and do
not perform a partial conversion. Ask only for the missing or
ambiguous items, explain where to find each one, and wait for the
user's reply:
- CMS: check the administration dashboard or site information for
Joomla or WordPress.
- Surface: copy the exact modern page/component or Site Widget type
from its editor; distinguish Listings, Comments, Media, Calendar,
Custom List, Related Listings, and Related Comments.
- Target model: use the model shown by the supported-surface matrix
or the target editor; Calendar uses Listing, and Related Comments
uses Comment.
- Legacy Custom Where / Order: copy each exact value from the old
module, widget, shortcode/controller, or Related Reviews
configuration; if one has no value, explicitly confirm that it is
empty.
4. Once the exact surface is known, derive the allowed context tokens
from the documented context-token matrix. Never ask the user to
provide or guess the token list. If the stated surface does not map
unambiguously to one matrix row, ask for the exact surface and wait.
Conversion rules — use only after the intake gate passes:
1. Preserve intent; do not preserve platform table or column syntax.
2. Use the documented cross-CMS model fields. Do not output raw post_* or
CMS table columns.
3. Do not output raw SQL, table names, joins, subqueries, comments, or
unsupported functions.
4. Do not assume a token merely because the model schema knows its
name; use only tokens supplied by the stated surface according to
the documented matrix.
5. If any intent is unsupported, do not invent an equivalent. Mark the
migration incomplete and explain the exact unsupported requirement.
6. Respect caller-owned eligibility predicates; JSON WHERE is
AND-composed with them and cannot widen the eligible row set. Do not
claim that ordering or limits preserve which eligible rows appear.
Return exactly these sections:
A. JSON Custom Query, or "INCOMPLETE — DO NOT USE" when a faithful
conversion is impossible
B. Field/relation mapping from each legacy expression
C. Assumptions
D. Unsupported or unresolved items
E. Verification cases covering included, excluded, order-tie,
anonymous-viewer, empty-result, and surface-token behavior
Review the output
Reject an AI result if it includes a key not documented here, raw table/column names, CURRENT_DATE, unsupported interval units, a subquery, or a token absent from the surface matrix. “Incomplete” is the correct output when the old SQL cannot be represented faithfully.
Saving and Checking Your Query
The JSON Custom Query setting is available in Listings, Comments, Media, and Calendar Site Widgets, as well as the supported Custom List and related-content settings described above. In a Site Widget editor, select Read the documentation below the setting to return to this guide.
Before saving, remember:
- A JSON
orderreplaces the widget's regular Order By setting. In a Calendar widget, it replaces Listings Order. If the JSON has noorder, the regular setting remains active. - Site Widgets can use information about the person viewing the site and the current date. They cannot use information from the listing page where the widget happens to appear.
- Comments and Media widgets can still use their regular settings to limit results to specific listings.
- JReviews does not attempt to convert an imported Legacy Custom Where value. Use the migration workflow to convert and verify it.
What happens when you click Save
JReviews checks the JSON before saving it. The check catches malformed JSON, misspelled or unavailable fields, unsupported operations, context values that are not available in that location, and queries that are too complex.
If there is a problem, the query is not saved. The error shows what went wrong and where it occurred. For example, $.where[0].token means the problem is in the token entry of the first condition inside where.
If the query passes, save the widget or page and preview the results. Confirm that known records are included or excluded as expected and that the order is correct. Test while signed in and signed out when the query depends on the current user.
Related Listings and Related Comments perform the same checks when you save their settings.
Common validation messages
| Message type | What to check |
|---|---|
| Invalid JSON or duplicate key | Check commas, brackets, quotation marks, and repeated property names. |
| Unknown field or relationship | Use the field and relationship names listed for the selected model in this guide. Do not use database table or column names. |
| Unsupported operation or function | Choose an operation or function from the supported grammar tables. |
| Unknown or unavailable context value | Confirm that the token appears in the row for the exact page or widget you are configuring. |
| Query limit exceeded | Simplify the query by reducing nested groups, conditions, ordering rules, or relationship filters. |
The technical JQ_... code shown with an error is useful when contacting support, but you normally only need the message and location to correct the query.
Troubleshooting
The form shows an error location and code
Use the location to find the affected part of the JSON. Keep the code if you need to contact support. Correct unknown or repeated entries instead of removing the widget's regular access and filtering settings, and use the field names in this guide rather than database column names.
A valid query returns no results
Check the regular widget or page filters first, then confirm the selected model, documented field or relationship, values, and current viewer or page context. For token queries, test both an authenticated viewer and an anonymous viewer. An unavailable token intentionally produces no matches.
A previously saved query stops returning results
JReviews checks the query every time it runs. A software update, configuration change, missing listing owner, or signed-out visitor can make a field or context value unavailable. Open and save the setting again to see the validation message, then check the JReviews logs for more detail.
Ordering is unexpected
If the JSON has no order, the widget or page uses its regular ordering setting. If the JSON includes order, it replaces that setting. When several records have the same value, add the model's ID field as the final ordering rule so the result is predictable.
Verification Checklist
- [ ] Identify the exact widget, Custom List, Related Listings, or Related Comments setting you are changing.
- [ ] Use only fields and relationships listed for its Listing, Comment, or Media model.
- [ ] If the query uses a context token, confirm that the supported-surfaces table lists it for this exact location.
- [ ] Keep the widget or page's regular access, publication, date, and content filters configured as intended.
- [ ] Confirm whether JSON ordering should replace the regular ordering setting.
- [ ] Preview a record that should appear, one that should not appear, an empty-result case, and records with matching order values.
- [ ] Test while signed in and signed out when the query uses information about the current user.
- [ ] Test Joomla and WordPress separately if you operate both.
- [ ] If a legacy requirement cannot be represented by the documented options, keep it on the legacy path or redesign it. Do not substitute a query that only approximates the requirement.