diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 34db859f71d1d..6ff01707e2376 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -777,6 +777,16 @@ Display the query title. ([Source](https://github.com/WordPress/gutenberg/tree/t - **Supports:** align (full, wide), color (background, gradients, text), interactivity (clientNavigation), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** level, levelOptions, showPrefix, showSearchTerm, textAlign, type +## Query Total + +Display the total number of results in a query. ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/query-total)) + +- **Name:** core/query-total +- **Category:** theme +- **Ancestor:** core/query +- **Supports:** align (full, wide), color (background, gradients, text), spacing (margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Attributes:** displayType + ## Quote Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Julio Cortázar ([Source](https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src/quote)) diff --git a/lib/blocks.php b/lib/blocks.php index c3fdb26700c58..342cd25191e68 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -108,6 +108,7 @@ function gutenberg_reregister_core_block_types() { 'query-pagination-numbers.php' => 'core/query-pagination-numbers', 'query-pagination-previous.php' => 'core/query-pagination-previous', 'query-title.php' => 'core/query-title', + 'query-total.php' => 'core/query-total', 'read-more.php' => 'core/read-more', 'rss.php' => 'core/rss', 'search.php' => 'core/search', diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 56365c87a268f..262f11de6ee22 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -99,6 +99,7 @@ import * as queryPaginationNext from './query-pagination-next'; import * as queryPaginationNumbers from './query-pagination-numbers'; import * as queryPaginationPrevious from './query-pagination-previous'; import * as queryTitle from './query-title'; +import * as queryTotal from './query-total'; import * as quote from './quote'; import * as reusableBlock from './block'; import * as readMore from './read-more'; @@ -211,6 +212,7 @@ const getAllBlocks = () => { queryPaginationNumbers, queryPaginationPrevious, queryNoResults, + queryTotal, readMore, comments, commentAuthorName, diff --git a/packages/block-library/src/query-total/block.json b/packages/block-library/src/query-total/block.json new file mode 100644 index 0000000000000..02dbbbbb00f74 --- /dev/null +++ b/packages/block-library/src/query-total/block.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "core/query-total", + "title": "Query Total", + "category": "theme", + "ancestor": [ "core/query" ], + "description": "Display the total number of results in a query.", + "textdomain": "default", + "attributes": { + "displayType": { + "type": "string", + "default": "total-results" + } + }, + "usesContext": [ "queryId", "query" ], + "supports": { + "align": [ "wide", "full" ], + "html": false, + "spacing": { + "margin": true, + "padding": true + }, + "color": { + "gradients": true, + "text": true, + "__experimentalDefaultControls": { + "background": true + } + }, + "typography": { + "fontSize": true, + "lineHeight": true, + "__experimentalFontFamily": true, + "__experimentalFontWeight": true, + "__experimentalFontStyle": true, + "__experimentalTextTransform": true, + "__experimentalTextDecoration": true, + "__experimentalLetterSpacing": true, + "__experimentalDefaultControls": { + "fontSize": true + } + } + } +} diff --git a/packages/block-library/src/query-total/edit.js b/packages/block-library/src/query-total/edit.js new file mode 100644 index 0000000000000..4824021ae99b0 --- /dev/null +++ b/packages/block-library/src/query-total/edit.js @@ -0,0 +1,83 @@ +/** + * WordPress dependencies + */ +import { useBlockProps, BlockControls } from '@wordpress/block-editor'; +import { ToolbarGroup, ToolbarDropdownMenu } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { resultsFound, displayingResults } from './icons'; + +export default function QueryTotalEdit( { attributes, setAttributes } ) { + const { displayType } = attributes; + + // Block properties and classes. + const blockProps = useBlockProps(); + + const getButtonPositionIcon = () => { + switch ( displayType ) { + case 'total-results': + return resultsFound; + case 'range-display': + return displayingResults; + } + }; + + const buttonPositionControls = [ + { + role: 'menuitemradio', + title: __( 'Total results' ), + isActive: displayType === 'total-results', + icon: resultsFound, + onClick: () => { + setAttributes( { displayType: 'total-results' } ); + }, + }, + { + role: 'menuitemradio', + title: __( 'Range display' ), + isActive: displayType === 'range-display', + icon: displayingResults, + onClick: () => { + setAttributes( { displayType: 'range-display' } ); + }, + }, + ]; + + // Controls for the block. + const controls = ( + <> + + + + + + + ); + + // Render output based on the selected display type. + const renderDisplay = () => { + if ( displayType === 'total-results' ) { + return
{ __( '12 results found' ) }
; + } + + if ( displayType === 'range-display' ) { + return
{ __( 'Displaying 1 – 10 of 12' ) }
; + } + + return null; + }; + + return ( +
+ { controls } + { renderDisplay() } +
+ ); +} diff --git a/packages/block-library/src/query-total/icons.js b/packages/block-library/src/query-total/icons.js new file mode 100644 index 0000000000000..8b285b99b1ade --- /dev/null +++ b/packages/block-library/src/query-total/icons.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/components'; + +export const resultsFound = ( + +); + +export const displayingResults = ( + +); + +export const queryTotal = ( + +); diff --git a/packages/block-library/src/query-total/index.js b/packages/block-library/src/query-total/index.js new file mode 100644 index 0000000000000..7950897229156 --- /dev/null +++ b/packages/block-library/src/query-total/index.js @@ -0,0 +1,18 @@ +/** + * Internal dependencies + */ +import metadata from './block.json'; +import edit from './edit'; +import initBlock from '../utils/init-block'; +import { queryTotal } from './icons'; + +/* Block settings */ +const { name } = metadata; +export { metadata, name }; + +export const settings = { + icon: queryTotal, + edit, +}; + +export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/query-total/index.php b/packages/block-library/src/query-total/index.php new file mode 100644 index 0000000000000..5a8ab76b5d1ef --- /dev/null +++ b/packages/block-library/src/query-total/index.php @@ -0,0 +1,92 @@ +context['query']['inherit'] ) && $block->context['query']['inherit'] ) { + $query_to_use = $wp_query; + $current_page = max( 1, get_query_var( 'paged', 1 ) ); + } else { + $page_key = isset( $block->context['queryId'] ) ? 'query-' . $block->context['queryId'] . '-page' : 'query-page'; + $current_page = isset( $_GET[ $page_key ] ) ? (int) $_GET[ $page_key ] : 1; + $query_to_use = new WP_Query( build_query_vars_from_query_block( $block, $current_page ) ); + } + + $max_rows = $query_to_use->found_posts; + $posts_per_page = $query_to_use->get( 'posts_per_page' ); + + // Calculate the range of posts being displayed. + $start = ( $current_page - 1 ) * $posts_per_page + 1; + $end = min( $start + $posts_per_page - 1, $max_rows ); + + // Prepare the display based on the `displayType` attribute. + $output = ''; + switch ( $attributes['displayType'] ) { + case 'range-display': + if ( $start === $end ) { + $range_text = sprintf( + /* translators: 1: Start index of posts, 2: Total number of posts */ + __( 'Displaying %1$s of %2$s' ), + '' . $start . '', + '' . $max_rows . '' + ); + } else { + $range_text = sprintf( + /* translators: 1: Start index of posts, 2: End index of posts, 3: Total number of posts */ + __( 'Displaying %1$s – %2$s of %3$s' ), + '' . $start . '', + '' . $end . '', + '' . $max_rows . '' + ); + } + + $output = sprintf( '

%s

', $range_text ); + break; + + case 'total-results': + default: + $output = sprintf( + '

%d %s

', + $max_rows, + _n( 'result found', 'results found', $max_rows ) + ); + break; + } + + return sprintf( + '
%2$s
', + $wrapper_attributes, + $output + ); +} + +/** + * Registers the `query-total` block. + * + * @since 6.8.0 + */ +function register_block_core_query_total() { + register_block_type_from_metadata( + __DIR__ . '/query-total', + array( + 'render_callback' => 'render_block_core_query_total', + ) + ); +} +add_action( 'init', 'register_block_core_query_total' ); diff --git a/packages/block-library/src/query-total/init.js b/packages/block-library/src/query-total/init.js new file mode 100644 index 0000000000000..79f0492c2cb2f --- /dev/null +++ b/packages/block-library/src/query-total/init.js @@ -0,0 +1,6 @@ +/** + * Internal dependencies + */ +import { init } from './'; + +export default init(); diff --git a/test/integration/fixtures/blocks/core__query-total.html b/test/integration/fixtures/blocks/core__query-total.html new file mode 100644 index 0000000000000..c561ea6fcf7d8 --- /dev/null +++ b/test/integration/fixtures/blocks/core__query-total.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/integration/fixtures/blocks/core__query-total.json b/test/integration/fixtures/blocks/core__query-total.json new file mode 100644 index 0000000000000..cf342c6a35f14 --- /dev/null +++ b/test/integration/fixtures/blocks/core__query-total.json @@ -0,0 +1,10 @@ +[ + { + "name": "core/query-total", + "isValid": true, + "attributes": { + "displayType": "total-results" + }, + "innerBlocks": [] + } +] diff --git a/test/integration/fixtures/blocks/core__query-total.parsed.json b/test/integration/fixtures/blocks/core__query-total.parsed.json new file mode 100644 index 0000000000000..99a770a68adfb --- /dev/null +++ b/test/integration/fixtures/blocks/core__query-total.parsed.json @@ -0,0 +1,9 @@ +[ + { + "blockName": "core/query-total", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "", + "innerContent": [] + } +] diff --git a/test/integration/fixtures/blocks/core__query-total.serialized.html b/test/integration/fixtures/blocks/core__query-total.serialized.html new file mode 100644 index 0000000000000..059289daf7dad --- /dev/null +++ b/test/integration/fixtures/blocks/core__query-total.serialized.html @@ -0,0 +1 @@ +