Skip to content

feat(abilities): scope UpcomingCountAbilities by a filter taxonomy/term pair - #307

Merged
chubes4 merged 1 commit into
mainfrom
feat-upcoming-counts-filter-term
May 26, 2026
Merged

feat(abilities): scope UpcomingCountAbilities by a filter taxonomy/term pair#307
chubes4 merged 1 commit into
mainfrom
feat-upcoming-counts-filter-term

Conversation

@chubes4

@chubes4 chubes4 commented May 26, 2026

Copy link
Copy Markdown
Member

Refs Extra-Chill/extrachill-events#107.

Summary

Extends UpcomingCountAbilities::executeGetUpcomingCounts() with an optional co-occurrence filter pair so callers can count terms in one taxonomy scoped to events that are also tagged with a specific term in another taxonomy.

This unlocks per-archive upcoming-events stats lines on the consuming sites, e.g.:

  • Artist archive: N upcoming events at N venues in N locations
    • taxonomy=venue + filter_taxonomy=artist + filter_term_id=N
    • taxonomy=location + filter_taxonomy=artist + filter_term_id=N
  • Location archive: N upcoming events at N venues
    • taxonomy=venue + filter_taxonomy=location + filter_term_id=N

New input params

Key Type Required Notes
filter_taxonomy string with filter_term_id sanitize_key() applied. Must be a registered taxonomy.
filter_term_id integer with filter_taxonomy absint() applied. Must be > 0.

Both must be provided together. Misuse contract: providing only one returns WP_Error('invalid_filter_pair') (HTTP 400) rather than silently falling back to the unfiltered query — wiring bugs surface immediately instead of hiding as 'no filter applied' results.

A nonexistent filter_taxonomy returns the distinct code invalid_filter_taxonomy so callers can differentiate usage bugs from registration bugs.

SQL extension

When both filter params are provided, the query gains two additional INNER JOINs scoped with f_tr / f_tt aliases:

INNER JOIN {term_relationships} f_tr ON f_tr.object_id = tr.object_id
INNER JOIN {term_taxonomy}      f_tt ON f_tr.term_taxonomy_id = f_tt.term_taxonomy_id
WHERE ...
  AND f_tt.taxonomy = %s
  AND f_tt.term_id  = %d

All values flow through $wpdb->prepare() — no interpolation of caller-supplied data. Table prefixes use $wpdb->term_relationships / $wpdb->term_taxonomy (multisite-safe).

Backward-compatibility guarantee

When filter_taxonomy / filter_term_id are not provided, the unfiltered SQL branch is byte-identical to the pre-existing query. Existing callers (VenueMapAbilities, calendar-stats consumers, etc.) keep working unchanged. No widening of the existing contract.

The ability has no internal cache, so no cache-key updates were needed; consumers that wrap this ability with their own cache (e.g. extrachill-events follow-up PR) must include the new params in their key.

Before / after

Suppose Venue A has 2 upcoming events (both tagged Artist X), Venue B has 1 upcoming event (Artist X), Venue C has 1 upcoming event (Artist Y).

Unfiltered (existing behavior, unchanged):

executeGetUpcomingCounts([ 'taxonomy' => 'venue' ])
// → total: 3, terms: [A=2, B=1, C=1]

Filtered to Artist X:

executeGetUpcomingCounts([
    'taxonomy'        => 'venue',
    'filter_taxonomy' => 'artist',
    'filter_term_id'  => $artist_x_id,
])
// → total: 2, terms: [A=2, B=1]   // Venue C dropped — never co-occurs with Artist X

Tests

tests/Unit/UpcomingCountAbilitiesTest.php covers:

  • Regression: unfiltered call returns all venues with upcoming events and the existing shape.
  • Filtered call: returns only venues co-occurring with the filter term, with correct per-term counts.
  • Empty co-occurrence: filter for a term with zero upcoming events returns success: true, total: 0, terms: [] (not WP_Error, not unfiltered set).
  • Partial filter pair: providing only filter_taxonomy or only filter_term_id returns WP_Error('invalid_filter_pair').
  • Unknown filter taxonomy: returns WP_Error('invalid_filter_taxonomy').

Mirrors the existing VenueStatsAbilitiesTest direct-execute pattern.

Out of scope

  • No new ability, no public function wrapper, no REST controller changes, no caching infra changes.
  • The extrachill-events follow-up PR (per-archive stats block) consumes this directly via new UpcomingCountAbilities()->executeGetUpcomingCounts(...), same pattern as calendar-stats.php.

mention <@532385681268408341> when ready for review

…rm pair

Adds two optional inputs — filter_taxonomy + filter_term_id — to
data-machine-events/get-upcoming-counts. When both are provided, the
query additionally joins wp_term_relationships + wp_term_taxonomy to
require every counted post be ALSO tagged with the filter term in the
filter taxonomy.

This unlocks per-archive upcoming-events stats lines on the consuming
sites, e.g.:

  - Artist archive: 'N upcoming events at N venues in N locations'
    taxonomy=venue + filter_taxonomy=artist + filter_term_id=N
    taxonomy=location + filter_taxonomy=artist + filter_term_id=N

  - Location archive: 'N upcoming events at N venues'
    taxonomy=venue + filter_taxonomy=location + filter_term_id=N

Backward-compat: when filter_taxonomy/filter_term_id are not provided,
the SQL is byte-identical to the pre-existing query. Existing callers
(VenueMapAbilities, calendar-stats consumers) keep working unchanged.

Misuse contract: providing only one of the filter pair returns
WP_Error('invalid_filter_pair') instead of silently falling back to the
unfiltered query — this surfaces wiring bugs immediately rather than
hiding them as 'no filter applied' results.

Refs Extra-Chill/extrachill-events#107.
@homeboy-ci

homeboy-ci Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Homeboy Results — data-machine-events

Audit

audit — passed

  • requested_detectors — 5 finding(s)
  • Total: 5 finding(s)

Deep dive: homeboy audit data-machine-events --changed-since dac02a3

Artifacts and drill-down
  • CI results artifact: homeboy-ci-results-data-machine-events-audit-homeboy-Linux-node24 contains immediate command JSON for this action invocation.
  • Observation artifact: homeboy-observations-data-machine-events-audit-homeboy-Linux-node24 contains exported Homeboy run history for deeper queries.
  • Drill-down: download the observation artifact, then run homeboy runs import <dir>, homeboy runs list, and homeboy runs findings <run-id>.
  • Artifacts are attached to the workflow run: https://github.com/Extra-Chill/data-machine-events/actions/runs/26480489916
Tooling versions
  • Homeboy CLI: homeboy 0.199.2+8a6ccfb
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: b3e360ec
  • Action: Extra-Chill/homeboy-action@v2

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