Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Build and release

on:
push:
branches:
- main

concurrency:
group: build-and-release
cancel-in-progress: true

jobs:
build:
name: Update release branch
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'

- name: Build
uses: humanmade/action-build-plugin@04c32a93e52ae987095f144105745a501d6207c8
with:
version-slug: 'release'
build-dir: 'build'
build-script: |
npm i
npm run build
36 changes: 36 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Lint

on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
- main
- master
- develop

jobs:
lint:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'

- name: Install dependencies
run: npm i

- name: Lint JavaScript
run: npm run lint:js

- name: Lint CSS
run: npm run lint:css
93 changes: 93 additions & 0 deletions .github/workflows/playwright-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Playwright Tests

on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
- main
- master
- develop

jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
strategy:
matrix:
php: ['8.3', '8.4']
wp: ['6.7', '6.8', 'latest']

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'

- name: Install dependencies
run: npm i

- name: Build
run: npm run build

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Start WordPress Playground
run: |
npx @wp-now/wp-now start \
--blueprint=blueprint.json \
--php=${{ matrix.php }} \
--wp=${{ matrix.wp }} \
--port=9400 \
--auto-mount &
echo $! > .wp-now-pid

- name: Wait for WordPress Playground to be ready
run: |
timeout 120 bash -c 'until curl -sf http://localhost:9400/wp-admin/ > /dev/null; do sleep 1; done' || exit 1

- name: Run Playwright tests
id: tests
continue-on-error: true
run: npm run test:e2e

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-results-php-${{ matrix.php }}-wp-${{ matrix.wp }}
path: test-results/
retention-days: 7

- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-php-${{ matrix.php }}-wp-${{ matrix.wp }}
path: playwright-report/
retention-days: 30

- name: Comment test results on PR
if: github.event_name == 'pull_request' && always()
uses: daun/playwright-report-comment@v3
with:
report-path: test-results/results.json

- name: Stop WordPress Playground
if: always()
run: |
if [ -f .wp-now-pid ]; then
kill $(cat .wp-now-pid) || true
fi

- name: Fail if tests failed
if: steps.tests.outcome == 'failure'
run: exit 1
82 changes: 82 additions & 0 deletions .github/workflows/pr-playground-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: PR Playground Preview

on:
pull_request:
types: [opened, synchronize, reopened, edited]

permissions:
contents: write
pull-requests: write

jobs:
preview:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'

- name: Install dependencies
run: npm i

- name: Replace __VERSION__ in plugin file
run: |
sed -i "s/__VERSION__/PR-${{ github.event.pull_request.number }}: ${{ github.event.pull_request.title }}/" query-filter.php

- name: Build
run: npm run build

- name: Generate preview
uses: WordPress/action-wp-playground-pr-preview@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
plugin-path: .
blueprint: |
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/",
"login": true,
"preferredVersions": {
"php": "8.3",
"wp": "6.8"
},
"features": {
"networking": true
},
"steps": [
{
"step": "installTheme",
"themeZipFile": {
"resource": "wordpress.org/themes",
"slug": "twentytwentyfive"
},
"options": {
"activate": true
}
},
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "wordpress.org/plugins",
"slug": "advanced-query-loop"
},
"options": {
"activate": true
}
},
{
"step": "defineWpConfigConsts",
"consts": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"SCRIPT_DEBUG": true
}
}
]
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
node_modules

/vendor/

# Build directory
/build/
80 changes: 80 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Query Loop Filters - Development Notes

This WordPress plugin adds interactive filtering capabilities to Query Loop blocks using the WordPress Interactivity API.

## Core Functionality

The plugin provides **two custom filter blocks** (Taxonomy Filter and Post Type Filter) that work seamlessly with the core Query Loop block and the Advanced Query Loop plugin. These filters enable users to interactively filter post listings without page reloads.

## Architecture

### PHP Components

**Block Registration** handles two primary blocks located in `src/taxonomy/` and `src/post-type/`, each with their own `block.json`, render templates, and editor scripts. The main bootstrap in `inc/namespace.php` registers these blocks and sets up the necessary server-side rendering.

**Server-Side Rendering** uses dynamic render callbacks (defined in `render.php` files) to output the filter controls with proper Interactivity API directives and data attributes.

### JavaScript Architecture

**Editor Scripts** (`edit.js`) provide the block editor interface with custom controls for:
- Taxonomy selection and label customization (Taxonomy Filter)
- Label and placeholder text options (Post Type Filter)
- Real-time preview of filter appearance

**View Scripts** (`view.js`) power the frontend interactivity using the WordPress Interactivity API, handling user interactions and triggering query updates without full page reloads.

## Interactivity API Integration

The plugin leverages WordPress's **Interactivity API** to create reactive filter controls. Each filter block:
- Uses `data-wp-interactive` attributes to define interactive regions
- Implements state management for selected filter values
- Triggers query block updates through the Interactivity API's routing system
- Maintains URL parameters to support direct linking and browser history

## Filter Types

### Taxonomy Filter
Allows filtering by any registered taxonomy (categories, tags, or custom taxonomies). Supports:
- Dynamic taxonomy selection in the editor
- Customizable labels and placeholder text
- Option to show/hide the label
- Integration with query loop block's taxonomy query parameters

### Post Type Filter
Enables filtering by post type when used with the **Advanced Query Loop plugin** (required for post type filtering). Features:
- Label customization
- Placeholder text for the "all posts" state
- Dynamic post type switching without page reload

### Search Integration
Works with the core Search block to enable keyword-based filtering alongside taxonomy and post type filters.

## Dependencies

**Required**: WordPress 6.6+ with Interactivity API support
**PHP**: 8.0 or higher
**For Post Type Filtering**: Advanced Query Loop plugin

## Development Workflow

### Build Commands
- `npm start` - Development build with file watching
- `npm run build` - Production build with optimized assets
- `npm run lint:js` - JavaScript linting
- `npm run lint:css` - CSS linting

### Local Development
- `npm run playground:start` - Launches WordPress Playground on port 9400 with the plugin pre-configured
- Blueprint includes Twenty Twenty-Five theme and debug mode enabled

### Testing
- `npm run test:e2e` - Runs Playwright end-to-end tests
- Tests validate filter functionality, query updates, and Interactivity API integration

## Key Implementation Details

**Query Loop Integration**: Filters work by updating the query parameters through the Interactivity API's router, which then triggers the Query Loop block to refetch and re-render with the new filters applied.

**State Management**: Filter selections are maintained in the URL and Interactivity API state, ensuring filters persist across browser navigation and can be shared via direct links.

**Block Variation Pattern**: While not using block variations like HM URL Tabs, this plugin follows a similar pattern of enhancing core blocks (Query Loop) with additional functionality through companion filter blocks.
42 changes: 42 additions & 0 deletions blueprint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/",
"login": true,
"preferredVersions": {
"php": "8.3",
"wp": "6.8"
},
"features": {
"networking": true
},
"steps": [
{
"step": "installTheme",
"themeZipFile": {
"resource": "wordpress.org/themes",
"slug": "twentytwentyfive"
},
"options": {
"activate": true
}
},
{
"step": "installPlugin",
"pluginZipFile": {
"resource": "wordpress.org/plugins",
"slug": "advanced-query-loop"
},
"options": {
"activate": true
}
},
{
"step": "defineWpConfigConsts",
"consts": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"SCRIPT_DEBUG": true
}
}
]
}
Loading
Loading