From 052723644f0bb2debd24ab913d3a301d9217f6de Mon Sep 17 00:00:00 2001 From: Matthew Haines-Young Date: Thu, 22 May 2025 11:43:12 +0100 Subject: [PATCH] First pass at author filter --- inc/namespace.php | 3 +- src/author/block.json | 61 ++++++++++++++++++++++++++++++ src/author/edit.js | 58 +++++++++++++++++++++++++++++ src/author/index.js | 10 +++++ src/author/render.php | 86 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 src/author/block.json create mode 100644 src/author/edit.js create mode 100644 src/author/index.js create mode 100644 src/author/render.php diff --git a/inc/namespace.php b/inc/namespace.php index c451dc4..4cd1449 100644 --- a/inc/namespace.php +++ b/inc/namespace.php @@ -36,6 +36,7 @@ function bootstrap() : void { function register_blocks() : void { register_block_type( ROOT_DIR . '/build/taxonomy' ); register_block_type( ROOT_DIR . '/build/post-type' ); + register_block_type( ROOT_DIR . '/build/author' ); } /** @@ -67,8 +68,8 @@ function pre_get_posts_transpose_query_vars( WP_Query $query ) : void { } $prefix = $query->is_main_query() ? 'query-' : "query-{$query_id}-"; - $tax_query = []; $valid_keys = [ + 'author' => '', 'post_type' => $query->is_search() ? 'any' : 'post', 's' => '', ]; diff --git a/src/author/block.json b/src/author/block.json new file mode 100644 index 0000000..decad72 --- /dev/null +++ b/src/author/block.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "query-filter/author", + "version": "0.1.0", + "title": "Author Filter", + "category": "theme", + "icon": "filter", + "description": "Allows users to filter by author when placed wihin a query loop block", + "ancestor": [ "core/query" ], + "usesContext": [ "queryId", "query" ], + "supports": { + "html": false, + "className": true, + "customClassName": true, + "color": { + "background": true, + "text": true + }, + "typography": { + "fontSize": true, + "textAlign": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + }, + "spacing": { + "margin": true, + "padding": true, + "blockGap": true + }, + "interactivity": { + "clientNavigation": true + } + }, + "attributes": { + "emptyLabel": { + "type": "string", + "default": "" + }, + "label": { + "type": "string" + }, + "showLabel": { + "type": "boolean", + "default": true + } + }, + "textdomain": "query-filter", + "editorScript": "file:./index.js", + "viewScriptModule": "query-filter-author-view-script-module", + "style": "query-filter-view", + "render": "file:./render.php" +} diff --git a/src/author/edit.js b/src/author/edit.js new file mode 100644 index 0000000..984ee13 --- /dev/null +++ b/src/author/edit.js @@ -0,0 +1,58 @@ +import { __ } from '@wordpress/i18n'; +import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; +import { PanelBody, TextControl, ToggleControl } from '@wordpress/components'; + +export default function Edit( { attributes, setAttributes } ) { + const { emptyLabel, label, showLabel } = attributes; + + return ( + <> + + + setAttributes( { label: newLabel } ) } + /> + + setAttributes( { showLabel: newShowLabel } ) + } + /> + + setAttributes( { emptyLabel: newEmptyLabel } ) + } + /> + + +
+ { showLabel && ( + + ) } + +
+ + ); +} diff --git a/src/author/index.js b/src/author/index.js new file mode 100644 index 0000000..0157b8f --- /dev/null +++ b/src/author/index.js @@ -0,0 +1,10 @@ +import { registerBlockType } from '@wordpress/blocks'; +import Edit from './edit'; +import metadata from './block.json'; + +registerBlockType( metadata.name, { + /** + * @see ./edit.js + */ + edit: Edit, +} ); diff --git a/src/author/render.php b/src/author/render.php new file mode 100644 index 0000000..c6bde90 --- /dev/null +++ b/src/author/render.php @@ -0,0 +1,86 @@ +context['query']['inherit'] ) { + $query_var = 'query-author'; // Changed from query-post_type + $page_var = 'page'; + $base_url = str_replace( '/page/' . get_query_var( 'paged' ), '', remove_query_arg( [ $query_var, $page_var ] ) ); +} else { + $query_id = $block->context['queryId'] ?? 0; + $query_var = sprintf( 'query-%d-author', $query_id ); // Changed from query-%d-post_type + $page_var = isset( $block->context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $base_url = remove_query_arg( [ $query_var, $page_var ] ); +} + +// Determine relevant post types for filtering authors. +$relevant_post_types = []; + +// Get post types from block context if they are explicitly set. +if ( ! empty( $block->context['query']['postType'] ) ) { + $types = is_array( $block->context['query']['postType'] ) ? $block->context['query']['postType'] : explode( ',', $block->context['query']['postType'] ); + $relevant_post_types = array_merge( $relevant_post_types, array_map( 'trim', $types ) ); +} + +// Support for enhanced query block (multiple_posts). +if ( ! empty( $block->context['query']['multiple_posts'] ) && is_array( $block->context['query']['multiple_posts'] ) ) { + $relevant_post_types = array_merge( $relevant_post_types, $block->context['query']['multiple_posts'] ); +} + +// Handle inherited query. +if ( $block->context['query']['inherit'] ) { + $main_query_post_type = $wp_query->get( 'post_type' ); + + if ( empty( $main_query_post_type ) || 'any' === $main_query_post_type ) { + // If main query is 'any' or not specific, consider all public, viewable post types. + $public_types = get_post_types( [ 'public' => true, 'show_ui' => true ], 'names' ); + // Exclude 'attachment' by default, similar to how Query Loop block might treat 'any'. + if ( ! get_option( 'wp_attachment_pages_enabled' ) ) { + unset( $public_types['attachment'] ); + } + $relevant_post_types = array_merge( $relevant_post_types, array_values( $public_types ) ); + } else { + $relevant_post_types = array_merge( $relevant_post_types, (array) $main_query_post_type ); + } +} + +$relevant_post_types = array_values( array_unique( array_filter( $relevant_post_types ) ) ); + +$user_args = [ + 'capability' => [ 'publish_posts' ], // Users who can publish posts + 'fields' => [ 'ID', 'display_name' ], + 'orderby' => 'display_name', + 'order' => 'ASC', +]; + +// If specific post types are identified for the query, filter authors by those. +// Otherwise, get authors who have published any post (adhering to 'authors' role). +if ( ! empty( $relevant_post_types ) ) { + $user_args['has_published_posts'] = $relevant_post_types; +} else { + // If $relevant_post_types is empty, it implies the query is for "any" post type. + // So, we list authors who have published any type of content. + // `get_users` with `who => 'authors'` covers users with publishing roles. + // Setting `has_published_posts = true` explicitly queries for posts in public post types. + $user_args['has_published_posts'] = true; +} + +$authors = get_users( $user_args ); + +if ( empty( $authors ) ) { + return; +} +?> + +
'wp-block-query-filter' ] ); ?> data-wp-interactive="query-filter" data-wp-context="{}"> + + +