diff --git a/build/author/block.json b/build/author/block.json new file mode 100644 index 0000000..e49b166 --- /dev/null +++ b/build/author/block.json @@ -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" +} \ No newline at end of file diff --git a/build/author/index.asset.php b/build/author/index.asset.php new file mode 100644 index 0000000..156f142 --- /dev/null +++ b/build/author/index.asset.php @@ -0,0 +1 @@ + array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'd22a929de73f1aa107a9'); diff --git a/build/author/index.js b/build/author/index.js new file mode 100644 index 0000000..fba60fc --- /dev/null +++ b/build/author/index.js @@ -0,0 +1 @@ +(()=>{"use strict";const e=window.wp.blocks,l=window.wp.i18n,r=window.wp.blockEditor,t=window.wp.components,o=window.ReactJSXRuntime,i=JSON.parse('{"UU":"query-filter/author"}');(0,e.registerBlockType)(i.UU,{edit:function({attributes:e,setAttributes:i}){const{emptyLabel:s,label:n,showLabel:a}=e;return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.InspectorControls,{children:(0,o.jsxs)(t.PanelBody,{title:(0,l.__)("Author Filter Settings","query-filter"),children:[(0,o.jsx)(t.TextControl,{label:(0,l.__)("Label","query-filter"),value:n,defaultValue:(0,l.__)("Author","query-filter"),help:(0,l.__)("If empty then no label will be shown","query-filter"),onChange:e=>i({label:e})}),(0,o.jsx)(t.ToggleControl,{label:(0,l.__)("Show Label","query-filter"),checked:a,onChange:e=>i({showLabel:e})}),(0,o.jsx)(t.TextControl,{label:(0,l.__)("Empty Choice Label","query-filter"),value:s,placeholder:(0,l.__)("All Authors","query-filter"),onChange:e=>i({emptyLabel:e})})]})}),(0,o.jsxs)("div",{...(0,r.useBlockProps)({className:"wp-block-query-filter"}),children:[a&&(0,o.jsx)("label",{className:"wp-block-query-filter-author__label wp-block-query-filter__label",children:n||(0,l.__)("Author","query-filter")}),(0,o.jsxs)("select",{className:"wp-block-query-filter-author__select wp-block-query-filter__select",inert:!0,children:[(0,o.jsx)("option",{children:s||(0,l.__)("All Authors","query-filter")}),(0,o.jsx)("option",{children:(0,l.__)("Sample Author 1","query-filter")}),(0,o.jsx)("option",{children:(0,l.__)("Sample Author 2","query-filter")})]})]})]})}})})(); \ No newline at end of file diff --git a/build/author/render.php b/build/author/render.php new file mode 100644 index 0000000..88d344d --- /dev/null +++ b/build/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'] && 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; +} +?> + +
'wp-block-query-filter' ] ); ?> data-wp-interactive="query-filter" data-wp-context="{}"> + + +
diff --git a/inc/namespace.php b/inc/namespace.php index 0bd4afa..21cc3d0 100644 --- a/inc/namespace.php +++ b/inc/namespace.php @@ -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' ); } /** @@ -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' => '', ]; 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="{}"> + + +