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 a post categories block #22471

Closed
wants to merge 5 commits into from
Closed
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
1 change: 1 addition & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import * as postDate from './post-date';
import * as postExcerpt from './post-excerpt';
import * as postFeaturedImage from './post-featured-image';
import * as postTags from './post-tags';
import * as postCategories from './post-categories';

/**
* Function to register an individual block.
Expand Down
20 changes: 20 additions & 0 deletions packages/block-library/src/post-categories/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "core/post-categories",
"category": "layout",
"context": [ "postId" ],
"attributes": {
"align": {
"type": "string",
"enum": [
"left",
"center",
"right",
"wide",
"full"
]
},
"className": {
"type": "string"
}
}
}
42 changes: 42 additions & 0 deletions packages/block-library/src/post-categories/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* WordPress dependencies
*/
import { useEntityProp, useEntityId } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

function PostCategoriesDisplay() {
const [ categories ] = useEntityProp( 'postType', 'post', 'categories' );
const categoryLinks = useSelect(
( select ) => {
const { getEntityRecord } = select( 'core' );
let loaded = true;
const links = categories.map( ( categoryId ) => {
const category = getEntityRecord('taxonomy', 'category', categoryId );
if ( ! category ) {
return ( loaded = false );
}
return (
<a key={categoryId } href={ category.link }>
{ category.name }
</a>
);
} );
return loaded && links;
},
[ categories ]
);
return (
categoryLinks &&
( categoryLinks.length === 0
? __( 'No categories.' )
: categoryLinks.reduce( ( prev, curr ) => [ prev, ', ', curr ] ) )
);
}

export default function PostCategoriesEdit() {
if ( ! useEntityId( 'postType', 'post' ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the introduction of block context, the client-side implementation should also reference the context values as well, rather than via useEntityId and useEntityProp. At least in getting the postId and postType, it should largely amount to using context as a property of the edit function.

export default function PostCategoriesEdit( { context } ) {
    const { postId, postType } = context;
}

(postType will need to be listed in block.json context alongside the existing postId)

To get the categories, it's a little more work using core-data entities to get the post's categories:

const categories = useSelect( ( select ) => 
    select( 'core' ).getEditedEntityRecord( 'postType', postType, postId )?.categories )
);

See also for reference example: #22359 (specifically, #22359 (comment))

Related: #21665

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not been able to figure out how to get all taxonomies from core-data, or a named custom taxonomy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a list of all hierarchical taxonomies, but I don't know if I can use this core-data to check if a post uses that taxonomy.

return 'Post Categories Placeholder';
}
return <PostCategoriesDisplay />;
}
25 changes: 25 additions & 0 deletions packages/block-library/src/post-categories/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* WordPress dependencies
*/
import { category as icon } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';

const { name } = metadata;

export { metadata, name };

export const settings = {
title: __( 'Post Categories' ),
description: __('Display a list of categories for this post.'),
icon,
supports: {
align: true,
},
edit,
};
57 changes: 57 additions & 0 deletions packages/block-library/src/post-categories/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
* Server-side rendering of the `core/post-categories` block.
*
* @package WordPress
*/

/**
* Renders the `core/post-categories` block on the server.
*
* @param array $attributes Block attributes.
* @param string $content Block default content.
* @param WP_Block $block Block instance.
* @return string Returns the filtered post categories for the current post wrapped inside "a" tags.
*/
function render_block_core_post_categories( $attributes, $content, $block ) {
if ( ! isset( $block->context['postId'] ) ) {
return '';
}

$class = 'wp-block-post-categories';

if ( isset( $attributes['align'] ) ) {
$class .= " align{$attributes['align']}";
}

if ( isset( $attributes['className'] ) ) {
$class .= " {$attributes['className']}";
}

$post_categories = get_the_category( $block->context['postId'] );
if ( ! empty( $post_categories ) ) {
$output = '';
foreach ( $post_categories as $category ) {
$output .= '<a href="' . get_category_link( $category->term_id ) . '">' . $category->name . '</a>' . ', ';
}
return sprintf(
'<div class="%1$s"><span class="screen-reader-text">' . __( 'Categories' ) . '</span> %2$s</div>',
esc_attr( $class ),
trim( $output, ', ' )
);

}
}

/**
* Registers the `core/post-categories` block on the server.
*/
function register_block_core_post_categories() {
register_block_type_from_metadata(
__DIR__ . '/post-categories',
array(
'render_callback' => 'render_block_core_post_categories',
)
);
}
add_action( 'init', 'register_block_core_post_categories' );
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- wp:post-categories /-->
10 changes: 10 additions & 0 deletions packages/e2e-tests/fixtures/blocks/core__post-categories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"clientId": "_clientId_0",
"name": "core/post-categories",
"isValid": true,
"attributes": {},
"innerBlocks": [],
"originalContent": ""
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"blockName": "core/post-categories",
"attrs": {},
"innerBlocks": [],
"innerHTML": "",
"innerContent": []
},
{
"blockName": null,
"attrs": {},
"innerBlocks": [],
"innerHTML": "\n",
"innerContent": [
"\n"
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- wp:post-categories /-->