From 0c37ba88d286651c9bc5d38710e3e30190203352 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Mon, 20 Apr 2020 14:37:43 -0400 Subject: [PATCH] Latest Posts: Fix selected category on existing blocks (#21359) * Add fallback for displaying single-category restrictions * Add a block deprecation to convert string-categories to an array * Remove extra suggestions object * Latest Posts: Fix type schema for array "categories" * Latest Posts: Shim server-side deprecation for string-based categories * Reverts the change to `render_block_core_latest_posts` * Update packages/block-library/src/latest-posts/index.php Co-Authored-By: Andrew Duthie Co-authored-by: Miguel Fonseca Co-authored-by: Andrew Duthie --- .../block-library/src/latest-posts/block.json | 5 ++- .../src/latest-posts/deprecated.js | 31 +++++++++++++++++++ .../block-library/src/latest-posts/edit.js | 14 +++------ .../block-library/src/latest-posts/index.js | 2 ++ .../block-library/src/latest-posts/index.php | 31 +++++++++++++++++++ 5 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 packages/block-library/src/latest-posts/deprecated.js diff --git a/packages/block-library/src/latest-posts/block.json b/packages/block-library/src/latest-posts/block.json index e730d86162650..96285d1f2705e 100644 --- a/packages/block-library/src/latest-posts/block.json +++ b/packages/block-library/src/latest-posts/block.json @@ -10,7 +10,10 @@ "type": "string" }, "categories": { - "type": "array" + "type": "array", + "items": { + "type": "object" + } }, "postsToShow": { "type": "number", diff --git a/packages/block-library/src/latest-posts/deprecated.js b/packages/block-library/src/latest-posts/deprecated.js new file mode 100644 index 0000000000000..d49b8abab56c0 --- /dev/null +++ b/packages/block-library/src/latest-posts/deprecated.js @@ -0,0 +1,31 @@ +/** + * Internal dependencies + */ +import metadata from './block.json'; + +const { attributes } = metadata; + +export default [ + { + attributes: { + ...attributes, + categories: { + type: 'string', + }, + }, + supports: { + align: true, + html: false, + }, + migrate: ( oldAttributes ) => { + // This needs the full category object, not just the ID. + return { + ...oldAttributes, + categories: [ { id: Number( oldAttributes.categories ) } ], + }; + }, + isEligible: ( { categories } ) => + categories && 'string' === typeof categories, + save: () => null, + }, +]; diff --git a/packages/block-library/src/latest-posts/edit.js b/packages/block-library/src/latest-posts/edit.js index 8e58ddd726055..9f21499510367 100644 --- a/packages/block-library/src/latest-posts/edit.js +++ b/packages/block-library/src/latest-posts/edit.js @@ -104,13 +104,6 @@ class LatestPostsEdit extends Component { featuredImageSizeWidth, featuredImageSizeHeight, } = attributes; - const suggestions = categoriesList.reduce( - ( accumulator, category ) => ( { - ...accumulator, - [ category.name ]: category, - } ), - {} - ); const categorySuggestions = categoriesList.reduce( ( accumulator, category ) => ( { ...accumulator, @@ -120,7 +113,8 @@ class LatestPostsEdit extends Component { ); const selectCategories = ( tokens ) => { const hasNoSuggestion = tokens.some( - ( token ) => typeof token === 'string' && ! suggestions[ token ] + ( token ) => + typeof token === 'string' && ! categorySuggestions[ token ] ); if ( hasNoSuggestion ) { return; @@ -128,7 +122,9 @@ class LatestPostsEdit extends Component { // Categories that are already will be objects, while new additions will be strings (the name). // allCategories nomalizes the array so that they are all objects. const allCategories = tokens.map( ( token ) => { - return typeof token === 'string' ? suggestions[ token ] : token; + return typeof token === 'string' + ? categorySuggestions[ token ] + : token; } ); // We do nothing if the category is not selected // from suggestions. diff --git a/packages/block-library/src/latest-posts/index.js b/packages/block-library/src/latest-posts/index.js index 63f7b7bfae638..df11a4dda161a 100644 --- a/packages/block-library/src/latest-posts/index.js +++ b/packages/block-library/src/latest-posts/index.js @@ -7,6 +7,7 @@ import { postList as icon } from '@wordpress/icons'; /** * Internal dependencies */ +import deprecated from './deprecated'; import edit from './edit'; import metadata from './block.json'; @@ -23,4 +24,5 @@ export const settings = { html: false, }, edit, + deprecated, }; diff --git a/packages/block-library/src/latest-posts/index.php b/packages/block-library/src/latest-posts/index.php index f9002ebde627d..ea35484569e02 100644 --- a/packages/block-library/src/latest-posts/index.php +++ b/packages/block-library/src/latest-posts/index.php @@ -173,3 +173,34 @@ function register_block_core_latest_posts() { ); } add_action( 'init', 'register_block_core_latest_posts' ); + +/** + * Handles outdated versions of the `core/latest-posts` block by converting + * attribute `categories` from a numeric string to an array with key `id`. + * + * This is done to accommodate the changes introduced in #20781 that sought to + * add support for multiple categories to the block. However, given that this + * block is dynamic, the usual provisions for block migration are insufficient, + * as they only act when a block is loaded in the editor. + * + * TODO: Remove when and if the bottom client-side deprecation for this block + * is removed. + * + * @param array $block A single parsed block object. + * + * @return array The migrated block object. + */ +function block_core_latest_posts_migrate_categories( $block ) { + if ( + 'core/latest-posts' === $block['blockName'] && + ! empty( $block['attrs']['categories'] ) && + is_string( $block['attrs']['categories'] ) + ) { + $block['attrs']['categories'] = array( + array( 'id' => absint( $block['attrs']['categories'] ) ), + ); + } + + return $block; +} +add_filter( 'render_block_data', 'block_core_latest_posts_migrate_categories' );