Skip to content
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

Add tags support in Query block #25005

Merged
merged 6 commits into from
Sep 7, 2020
Merged
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
21 changes: 21 additions & 0 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,27 @@ function gutenberg_render_block_with_assigned_block_context( $pre_render, $parse
}
}

if ( isset( $wp_query->tax_query->queried_terms['post_tag'] ) ) {
if ( isset( $context['query'] ) ) {
$context['query']['tagIds'] = array();
} else {
$context['query'] = array( 'tagIds' => array() );
}

foreach ( $wp_query->tax_query->queried_terms['post_tag']['terms'] as $tag_slug_or_id ) {
$tag_ID = $tag_slug_or_id;

if ( 'slug' === $wp_query->tax_query->queried_terms['post_tag']['field'] ) {
$tag = get_term_by( 'slug', $tag_slug_or_id, 'post_tag' );

if ( $tag ) {
$tag_ID = $tag->term_id;
}
}
$context['query']['tagIds'][] = $tag_ID;
}
}

/**
* Filters the default context provided to a rendered block.
*
Expand Down
12 changes: 10 additions & 2 deletions packages/block-library/src/query-loop/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ const TEMPLATE = [ [ 'core/post-title' ], [ 'core/post-content' ] ];
export default function QueryLoopEdit( {
clientId,
context: {
query: { perPage, offset, categoryIds, order, orderBy } = {},
query: {
perPage,
offset,
categoryIds,
tagIds = [],
order,
orderBy,
} = {},
queryContext,
},
} ) {
Expand All @@ -31,6 +38,7 @@ export default function QueryLoopEdit( {
const query = {
offset: perPage ? perPage * ( page - 1 ) + offset : 0,
categories: categoryIds,
tags: tagIds,
order,
orderby: orderBy,
};
Expand All @@ -46,7 +54,7 @@ export default function QueryLoopEdit( {
blocks: select( 'core/block-editor' ).getBlocks( clientId ),
};
},
[ perPage, page, offset, categoryIds, order, orderBy, clientId ]
[ perPage, page, offset, categoryIds, tagIds, order, orderBy, clientId ]
);

const blockContexts = useMemo(
Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/query-loop/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ function render_block_core_query_loop( $attributes, $content, $block ) {
if ( isset( $block->context['query']['categoryIds'] ) ) {
$query['category__in'] = $block->context['query']['categoryIds'];
}
if ( isset( $block->context['query']['tagIds'] ) ) {
$query['tag__in'] = $block->context['query']['tagIds'];
}
if ( isset( $block->context['query']['order'] ) ) {
$query['order'] = strtoupper( $block->context['query']['order'] );
}
Expand All @@ -42,6 +45,7 @@ function render_block_core_query_loop( $attributes, $content, $block ) {
$query['posts_per_page'] = $block->context['query']['perPage'];
}
}

$posts = get_posts( $query );

$content = '';
Expand Down
1 change: 1 addition & 0 deletions packages/block-library/src/query/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"pages": 1,
"offset": 0,
"categoryIds": [],
"tagIds": [],
"order": "desc",
"orderBy": "date"
}
Expand Down
5 changes: 5 additions & 0 deletions packages/block-library/src/query/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const MAX_FETCHED_TERMS = 100;

export default {
MAX_FETCHED_TERMS,
};
88 changes: 49 additions & 39 deletions packages/block-library/src/query/edit/query-toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,40 @@ import {
import { __ } from '@wordpress/i18n';
import { postList } from '@wordpress/icons';

/**
* Internal dependencies
*/
import { getTermsInfo } from '../utils';
import { MAX_FETCHED_TERMS } from '../constants';

export default function QueryToolbar( { query, setQuery } ) {
const { categories, categoriesMapById, categoriesMapByName } = useSelect(
( select ) => {
const _categories = select( 'core' ).getEntityRecords(
'taxonomy',
'category'
);
return {
categories: _categories,
..._categories?.reduce(
( acc, category ) => ( {
categoriesMapById: {
...acc.categoriesMapById,
[ category.id ]: category,
},
categoriesMapByName: {
...acc.categoriesMapByName,
[ category.name ]: category,
},
} ),
{ categoriesMapById: {}, categoriesMapByName: {} }
),
};
},
[]
);
const { categories, tags } = useSelect( ( select ) => {
const { getEntityRecords } = select( 'core' );
const termsQuery = { per_page: MAX_FETCHED_TERMS };
const _categories = getEntityRecords(
'taxonomy',
'category',
termsQuery
);
const _tags = getEntityRecords( 'taxonomy', 'post_tag', termsQuery );
return {
categories: getTermsInfo( _categories ),
tags: getTermsInfo( _tags ),
};
}, [] );

// Handles categories and tags changes.
const onTermsChange = ( terms, queryProperty ) => ( newTermValues ) => {
const termIds = newTermValues.reduce( ( accumulator, termValue ) => {
const termId = termValue?.id || terms.mapByName[ termValue ]?.id;
if ( termId ) accumulator.push( termId );
return accumulator;
}, [] );
setQuery( { [ queryProperty ]: termIds } );
};
const onCategoriesChange = onTermsChange( categories, 'categoryIds' );
const onTagsChange = onTermsChange( tags, 'tagIds' );

return (
<Toolbar>
<Dropdown
Expand Down Expand Up @@ -77,30 +85,32 @@ export default function QueryToolbar( { query, setQuery } ) {
setQuery( { offset: value ?? 0 } )
}
/>
{ categories && (
{ categories?.terms && (
<FormTokenField
label={ __( 'Categories' ) }
value={ query.categoryIds.map(
( categoryId ) => ( {
id: categoryId,
value:
categoriesMapById[ categoryId ]
categories.mapById[ categoryId ]
.name,
} )
) }
suggestions={ categories.map(
( category ) => category.name
suggestions={ categories.names }
onChange={ onCategoriesChange }
/>
) }
{ tags?.terms && (
<FormTokenField
label={ __( 'Tags' ) }
value={ ( query.tagIds || [] ).map(
( tagId ) => ( {
id: tagId,
value: tags.mapById[ tagId ].name,
} )
) }
onChange={ ( newCategoryNames ) => {
const categoryIds = newCategoryNames.map(
( categoryName ) =>
categoriesMapByName[ categoryName ]
?.id
);
if ( categoryIds.includes( undefined ) )
return;
setQuery( { categoryIds } );
} }
suggestions={ tags.names }
onChange={ onTagsChange }
/>
) }
</>
Expand Down
21 changes: 21 additions & 0 deletions packages/block-library/src/query/test/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const terms = [
{
count: 2,
id: 4,
meta: [],
name: 'nba',
parent: 0,
slug: 'nba',
taxonomy: 'category',
},
{
count: 0,
id: 11,
link: 'http://localhost:8888/?tag=featured',
name: 'featured',
slug: 'featured',
taxonomy: 'post_tag',
},
];

export default { terms };
30 changes: 30 additions & 0 deletions packages/block-library/src/query/test/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Internal dependencies
*/
import { terms } from './fixtures';
import { getTermsInfo } from '../utils';

describe( 'Query block utils', () => {
describe( 'getTermsInfo', () => {
it( 'should return an empty object when no terms provided', () => {
expect( getTermsInfo() ).toEqual( { terms: undefined } );
} );
it( 'should return proper terms info object', () => {
expect( getTermsInfo( terms ) ).toEqual(
expect.objectContaining( {
mapById: expect.objectContaining( {
'4': expect.objectContaining( { name: 'nba' } ),
'11': expect.objectContaining( {
name: 'featured',
} ),
} ),
mapByName: expect.objectContaining( {
nba: expect.objectContaining( { id: 4 } ),
featured: expect.objectContaining( { id: 11 } ),
} ),
names: expect.arrayContaining( [ 'nba', 'featured' ] ),
} )
);
} );
} );
} );
47 changes: 47 additions & 0 deletions packages/block-library/src/query/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* WordPress term object from REST API.
* Categories ref: https://developer.wordpress.org/rest-api/reference/categories/
* Tags ref: https://developer.wordpress.org/rest-api/reference/tags/
*
* @typedef {Object} WPTerm
* @property {number} id Unique identifier for the term.
* @property {number} count Number of published posts for the term.
* @property {string} description HTML description of the term.
* @property {string} link URL of the term.
* @property {string} name HTML title for the term.
* @property {string} slug An alphanumeric identifier for the term unique to its type.
* @property {string} taxonomy Type attribution for the term.
* @property {Object} meta Meta fields
* @property {number} [parent] The parent term ID.
*/

/**
* The object used in Query block that contains info and helper mappings
* from an array of WPTerm.
*
* @typedef {Object} QueryTermsInfo
* @property {WPTerm[]} terms The array of terms.
* @property {Object<string, WPTerm>} mapById Object mapping with the term id as key and the term as value.
* @property {Object<string, WPTerm>} mapByName Object mapping with the term name as key and the term as value.
* @property {string[]} names Array with the terms' names.
*/

/**
* Returns a helper object with mapping from WPTerms.
*
* @param {WPTerm[]} terms The terms to extract of helper object.
* @return {QueryTermsInfo} The object with the terms information.
*/
export const getTermsInfo = ( terms ) => ( {
terms,
...terms?.reduce(
( accumulator, term ) => {
const { mapById, mapByName, names } = accumulator;
mapById[ term.id ] = term;
mapByName[ term.name ] = term;
names.push( term.name );
return accumulator;
},
{ mapById: {}, mapByName: {}, names: [] }
),
} );
1 change: 1 addition & 0 deletions packages/e2e-tests/fixtures/blocks/core__query.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"pages": 1,
"offset": 0,
"categoryIds": [],
"tagIds": [],
"order": "desc",
"orderBy": "date"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function Editor() {
const blockContext = useMemo(
() => ( {
...page?.context,
query: page?.context.query || { categoryIds: [] },
query: page?.context.query || { categoryIds: [], tagIds: [] },
queryContext: [
page?.context.queryContext || { page: 1 },
( newQueryContext ) =>
Expand Down