Skip to content

Author filter #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
66 changes: 66 additions & 0 deletions build/author/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"$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"
}
1 change: 1 addition & 0 deletions build/author/index.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'd22a929de73f1aa107a9');
1 change: 1 addition & 0 deletions build/author/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 86 additions & 0 deletions build/author/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
global $wp_query;

$id = 'query-filter-author-' . wp_generate_uuid4();

if ( $block->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'] && empty( $relevant_post_types ) ) {
$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;
}
?>

<div <?php echo get_block_wrapper_attributes( [ 'class' => 'wp-block-query-filter' ] ); ?> data-wp-interactive="query-filter" data-wp-context="{}">
<label class="wp-block-query-filter-author__label wp-block-query-filter__label<?php echo $attributes['showLabel'] ? '' : ' screen-reader-text' ?>" for="<?php echo esc_attr( $id ); ?>">
<?php echo esc_html( $attributes['label'] ?? __( 'Author', 'query-filter' ) ); ?>
</label>
<select class="wp-block-query-filter-author__select wp-block-query-filter__select" id="<?php echo esc_attr( $id ); ?>" data-wp-on--change="actions.navigate">
<option value="<?php echo esc_attr( $base_url ) ?>"><?php echo esc_html( $attributes['emptyLabel'] ?: __( 'All Authors', 'query-filter' ) ); ?></option>
<?php foreach ( $authors as $author ) : ?>
<option value="<?php echo esc_attr( add_query_arg( [ $query_var => $author->ID, $page_var => false ], $base_url ) ) ?>" <?php selected( $author->ID, wp_unslash( $_GET[ $query_var ] ?? '' ) ); ?>><?php echo esc_html( $author->display_name ); ?></option>
<?php endforeach; ?>
</select>
</div>
3 changes: 2 additions & 1 deletion inc/namespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function action_wp_enqueue_scripts() : 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' );
}

/**
Expand Down Expand Up @@ -83,8 +84,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' => '',
];
Expand Down
61 changes: 61 additions & 0 deletions src/author/block.json
Original file line number Diff line number Diff line change
@@ -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"
}
58 changes: 58 additions & 0 deletions src/author/edit.js
Original file line number Diff line number Diff line change
@@ -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 (
<>
<InspectorControls>
<PanelBody title={ __( 'Author Filter Settings', 'query-filter' ) }>
<TextControl
label={ __( 'Label', 'query-filter' ) }
value={ label }
defaultValue={ __( 'Author', 'query-filter' ) }
help={ __(
'If empty then no label will be shown',
'query-filter'
) }
onChange={ ( newLabel ) => setAttributes( { label: newLabel } ) }
/>
<ToggleControl
label={ __( 'Show Label', 'query-filter' ) }
checked={ showLabel }
onChange={ ( newShowLabel ) =>
setAttributes( { showLabel: newShowLabel } )
}
/>
<TextControl
label={ __( 'Empty Choice Label', 'query-filter' ) }
value={ emptyLabel }
placeholder={ __( 'All Authors', 'query-filter' ) }
onChange={ ( newEmptyLabel ) =>
setAttributes( { emptyLabel: newEmptyLabel } )
}
/>
</PanelBody>
</InspectorControls>
<div { ...useBlockProps( { className: 'wp-block-query-filter' } ) }>
{ showLabel && (
<label className="wp-block-query-filter-author__label wp-block-query-filter__label">
{ label || __( 'Author', 'query-filter' ) }
</label>
) }
<select
className="wp-block-query-filter-author__select wp-block-query-filter__select"
inert
>
<option>
{ emptyLabel || __( 'All Authors', 'query-filter' ) }
</option>
<option>{ __( 'Sample Author 1', 'query-filter' ) }</option>
<option>{ __( 'Sample Author 2', 'query-filter' ) }</option>
</select>
</div>
</>
);
}
10 changes: 10 additions & 0 deletions src/author/index.js
Original file line number Diff line number Diff line change
@@ -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,
} );
86 changes: 86 additions & 0 deletions src/author/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
global $wp_query;

$id = 'query-filter-author-' . wp_generate_uuid4();

if ( $block->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;
}
?>

<div <?php echo get_block_wrapper_attributes( [ 'class' => 'wp-block-query-filter' ] ); ?> data-wp-interactive="query-filter" data-wp-context="{}">
<label class="wp-block-query-filter-author__label wp-block-query-filter__label<?php echo $attributes['showLabel'] ? '' : ' screen-reader-text' ?>" for="<?php echo esc_attr( $id ); ?>">
<?php echo esc_html( $attributes['label'] ?? __( 'Author', 'query-filter' ) ); ?>
</label>
<select class="wp-block-query-filter-author__select wp-block-query-filter__select" id="<?php echo esc_attr( $id ); ?>" data-wp-on--change="actions.navigate">
<option value="<?php echo esc_attr( $base_url ) ?>"><?php echo esc_html( $attributes['emptyLabel'] ?: __( 'All Authors', 'query-filter' ) ); ?></option>
<?php foreach ( $authors as $author ) : ?>
<option value="<?php echo esc_attr( add_query_arg( [ $query_var => $author->ID, $page_var => false ], $base_url ) ) ?>" <?php selected( $author->ID, wp_unslash( $_GET[ $query_var ] ?? '' ) ); ?>><?php echo esc_html( $author->display_name ); ?></option>
<?php endforeach; ?>
</select>
</div>