diff --git a/includes/class-newspack-blocks-api.php b/includes/class-newspack-blocks-api.php index d3656013a..304eda2f9 100644 --- a/includes/class-newspack-blocks-api.php +++ b/includes/class-newspack-blocks-api.php @@ -157,6 +157,17 @@ public static function newspack_blocks_sponsor_info( $object_info ) { return false; } + /** + * Get tag labels for the REST API. + * + * @param array $object_info The object info. + * @return array|bool Tag labels, or false if none. + */ + public static function newspack_blocks_get_tag_labels( $object_info ) { + $tag_labels = Newspack_Blocks::get_tag_labels( $object_info['id'] ); + return ! empty( $tag_labels ) ? array_values( $tag_labels ) : false; + } + /** * Pass whether there is a custom excerpt to the editor. * @@ -269,6 +280,7 @@ public static function posts_endpoint( $request ) { 'newspack_post_sponsors' => self::newspack_blocks_sponsor_info( $data ), 'newspack_sponsors_show_author' => Newspack_Blocks::newspack_display_sponsors_and_authors( $sponsors ), 'newspack_sponsors_show_categories' => Newspack_Blocks::newspack_display_sponsors_and_categories( $sponsors ), + 'newspack_tag_labels' => self::newspack_blocks_get_tag_labels( $data ), 'newspack_post_avatars' => \newspack_blocks_format_avatars( $author_info ), 'newspack_post_byline' => \newspack_blocks_format_byline( $author_info ), 'post_status' => $post->post_status, diff --git a/includes/class-newspack-blocks.php b/includes/class-newspack-blocks.php index 8d3ffc113..49de655b5 100644 --- a/includes/class-newspack-blocks.php +++ b/includes/class-newspack-blocks.php @@ -1096,6 +1096,35 @@ public static function newspack_display_sponsors_and_categories( $sponsors ) { return false; } + /** + * Support for Tag Labels. + * + * @param int|WP_Post|null $post Post to retrieve tag labels for. + * + * @return array|null Tag labels, if any, for this post. + */ + public static function get_tag_labels( $post = null ) { + if ( class_exists( '\Newspack\Tag_Labels' ) && method_exists( '\Newspack\Tag_Labels', 'get_labels_for_post' ) ) { + return \Newspack\Tag_Labels::get_labels_for_post( $post ); + } + + return null; + } + + /** + * Outputs HTML for given tag labels. + * + * @param array|null $labels Labels to display. + * @param bool $links Whether to include links to tag archives. + * + * @return void + */ + public static function display_tag_labels( $labels = null, $links = true ) { + if ( class_exists( '\Newspack\Tag_Labels' ) && method_exists( '\Newspack\Tag_Labels', 'display' ) ) { + \Newspack\Tag_Labels::display( $labels, $links, 'div' ); + } + } + /** * Closure for excerpt filtering that can be added and removed. * diff --git a/src/blocks/homepage-articles/block.json b/src/blocks/homepage-articles/block.json index 7d50ccc48..69ec5a10b 100644 --- a/src/blocks/homepage-articles/block.json +++ b/src/blocks/homepage-articles/block.json @@ -84,6 +84,10 @@ "type": "boolean", "default": false }, + "showTagLabels": { + "type": "boolean", + "default": true + }, "postLayout": { "type": "string", "default": "list" diff --git a/src/blocks/homepage-articles/edit.tsx b/src/blocks/homepage-articles/edit.tsx index 45498a22f..2767f721b 100644 --- a/src/blocks/homepage-articles/edit.tsx +++ b/src/blocks/homepage-articles/edit.tsx @@ -66,6 +66,7 @@ class Edit extends Component< HomepageArticlesProps > { showAvatar, showDate, showCategory, + showTagLabels, sectionHeader, } = attributes; @@ -112,6 +113,21 @@ class Edit extends Component< HomepageArticlesProps > { { decodeEntities( post.newspack_category_info ) } ) } + ) }{ ' ' } + { showTagLabels && post.newspack_tag_labels && ( +
+ { post.newspack_tag_labels.map( ( newspack_tag_label, index ) => { + return newspack_tag_label.link ? ( + + { newspack_tag_label.flag } + + ) : ( + + { newspack_tag_label.flag } + + ); + } ) } +
) } { RichText.isEmpty( sectionHeader ) ? (

@@ -208,6 +224,7 @@ class Edit extends Component< HomepageArticlesProps > { showAuthor, showAvatar, showCategory, + showTagLabels, postLayout, mediaPosition, specificMode, @@ -445,6 +462,11 @@ class Edit extends Component< HomepageArticlesProps > { checked={ showCategory } onChange={ () => setAttributes( { showCategory: ! showCategory } ) } /> + setAttributes( { showTagLabels: ! showTagLabels } ) } + /> { IS_SUBTITLE_SUPPORTED_IN_THEME && ( posts ), 'There is one post returned.' ); self::assertEquals( $post_id, $query->posts[0]->ID, 'The post returned is the one with the CAP author assigned.' ); } + + /** + * The newspack_tag_labels REST field exposes the { flag, link } shape + * returned by \Newspack\Tag_Labels, normalized to a 0-indexed list. + * + * Locks in the cross-repo contract: the field passes through whatever + * \Newspack\Tag_Labels::get_labels_for_post() returns, so the plugin, + * blocks, and theme must agree on this shape. + */ + public function test_tag_labels_rest_field_shape() { + if ( ! property_exists( '\Newspack\Tag_Labels', 'stub_labels' ) ) { + $this->markTestSkipped( 'Real \Newspack\Tag_Labels present; stub-based contract test skipped.' ); + } + $post_id = self::factory()->post->create(); + + // Keyed input (as returned by Tag_Labels::get_labels_for_post()). + \Newspack\Tag_Labels::$stub_labels = [ + 42 => [ + 'flag' => 'Breaking', + 'link' => 'https://example.org/tag/breaking/', + ], + ]; + + $result = Newspack_Blocks_API::newspack_blocks_get_tag_labels( [ 'id' => $post_id ] ); + + self::assertIsArray( $result ); + self::assertSame( [ 0 ], array_keys( $result ), 'Keyed input is normalized to a 0-indexed list.' ); + self::assertArrayHasKey( 'flag', $result[0] ); + self::assertArrayHasKey( 'link', $result[0] ); + self::assertSame( 'Breaking', $result[0]['flag'] ); + self::assertSame( 'https://example.org/tag/breaking/', $result[0]['link'] ); + + \Newspack\Tag_Labels::$stub_labels = null; + } + + /** + * The newspack_tag_labels REST field returns false when there are no labels. + */ + public function test_tag_labels_rest_field_empty_returns_false() { + if ( ! property_exists( '\Newspack\Tag_Labels', 'stub_labels' ) ) { + $this->markTestSkipped( 'Real \Newspack\Tag_Labels present; stub-based contract test skipped.' ); + } + $post_id = self::factory()->post->create(); + + \Newspack\Tag_Labels::$stub_labels = []; + self::assertFalse( Newspack_Blocks_API::newspack_blocks_get_tag_labels( [ 'id' => $post_id ] ) ); + + \Newspack\Tag_Labels::$stub_labels = null; + self::assertFalse( Newspack_Blocks_API::newspack_blocks_get_tag_labels( [ 'id' => $post_id ] ) ); + } }