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

Patterns: Refactor pattern categories to use existing endpoint to merge in user categories #55822

Closed
wants to merge 12 commits into from
12 changes: 12 additions & 0 deletions docs/reference-guides/data/data-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ _Returns_

- `boolean | undefined`: Whether or not the user can edit, or `undefined` if the OPTIONS request is still being made.

### getAllPatternCategories

Retrieve the core and user pattern categories.

_Parameters_

- _state_ `State`: Data state.

_Returns_

- `Array< unknown >`: User patterns category array.

### getAuthors

> **Deprecated** since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
<?php
/**
* REST API: WP_REST_Block_Pattern_Categories_Controller class
*
* @package WordPress
* @subpackage REST_API
* @since 6.0.0
*/

/**
* Core class used to access block pattern categories via the REST API.
*
* @since 6.0.0
*
* @see WP_REST_Controller
*/
class Gutenberg_REST_Block_Pattern_Categories_Controller extends WP_REST_Block_Pattern_Categories_Controller {
/**
* Retrieves all block pattern categories.
*
* @since 6.0.0
* @since 6.5 Added user added categories from wp_pattern_category taxonomy
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
$valid_query_args = array(
'source' => true,
);

$query_args = array_intersect_key( $request->get_params(), $valid_query_args );
$response = array();
$unique_categories = array();
$categories = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered();
$user_categories = get_terms(
array(
'taxonomy' => 'wp_pattern_category',
'hide_empty' => false,
)
);

if ( isset( $query_args['source'] ) && is_array( $query_args['source'] ) && in_array( 'user', $query_args['source'], true ) ) {
foreach ( $user_categories as $user_category ) {
$prepared_category = $this->prepare_item_for_response(
array(
'name' => $user_category->slug,
'label' => $user_category->name,
'description' => $user_category->description,
'id' => $user_category->term_id,
),
$request
);
$response[] = $this->prepare_response_for_collection( $prepared_category );
$unique_categories[] = $user_category->name;
}
}

if ( ! isset( $query_args['source'] ) || in_array( 'core', $query_args['source'], true ) ) {
foreach ( $categories as $category ) {
if ( in_array( $category['label'], $unique_categories, true ) ) {
continue;
}
$prepared_category = $this->prepare_item_for_response( $category, $request );
$response[] = $this->prepare_response_for_collection( $prepared_category );
}
}

return rest_ensure_response( $response );
}

/**
* Prepare a raw block pattern category before it gets output in a REST API response.
*
* @since 6.0.0
* @since 6.5 Added `id` field for identifying user categories
*
* @param array $item Raw category as registered, before any changes.
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function prepare_item_for_response( $item, $request ) {
$fields = $this->get_fields_for_response( $request );
$keys = array( 'name', 'label', 'description' );
$data = array();
foreach ( $keys as $key ) {
if ( isset( $item[ $key ] ) && rest_is_field_included( $key, $fields ) ) {
$data[ $key ] = $item[ $key ];
}
}

// For backwards compatibility we only want to include the id if the field is explicitly requested.
if ( rest_is_field_included( 'id', $fields ) && isset( $item['id'] ) ) {
$data['id'] = $item['id'];
}

$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );

return rest_ensure_response( $data );
}

/**
* Retrieves the block pattern category schema, conforming to JSON Schema.
*
* @since 6.0.0
* @since 6.5 Added `id` field for identifying user categories
*
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}

$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'block-pattern-category',
'type' => 'object',
'properties' => array(
'name' => array(
'description' => __( 'The category name.' ),
'type' => 'string',
'readonly' => true,
'context' => array( 'view', 'edit', 'embed' ),
),
'label' => array(
'description' => __( 'The category label, in human readable format.' ),
'type' => 'string',
'readonly' => true,
'context' => array( 'view', 'edit', 'embed' ),
),
'description' => array(
'description' => __( 'The category description, in human readable format.' ),
'type' => 'string',
'readonly' => true,
'context' => array( 'view', 'edit', 'embed' ),
),
'id' => array(
'description' => __( 'An optional category id, currently used to provide id for user wp_pattern_category terms' ),
'type' => 'number',
'readonly' => true,
'context' => array( 'view', 'edit', 'embed' ),
),
),
);

$this->schema = $schema;

return $this->add_additional_fields_schema( $this->schema );
}

/**
* Retrieves the search parameters for the block pattern categories.
*
* @since 6.5.0 Added to request.
*
* @return array Collection parameters.
*/
public function get_collection_params() {
$query_params = parent::get_collection_params();

$query_params['source'] = array(
'description' => __( 'Limit result set to comments assigned to specific sources, `core` or `user`' ),
'type' => 'array',
'items' => array(
'type' => 'string',
),
);

/**
* Filter collection parameters for the block pattern categories controller.
*
* @since 5.8.0
*
* @param array $query_params JSON Schema-formatted collection parameters.
*/
return apply_filters( 'rest_pattern_directory_collection_params', $query_params );
}
}
10 changes: 9 additions & 1 deletion lib/compat/wordpress-6.5/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@ function gutenberg_register_global_styles_revisions_endpoints() {
$global_styles_revisions_controller = new Gutenberg_REST_Global_Styles_Revisions_Controller_6_5();
$global_styles_revisions_controller->register_routes();
}

add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' );

/**
* Registers the block pattern categories REST API routes.
*/
function gutenberg_register_rest_block_pattern_categories_routes() {
$block_patterns = new Gutenberg_REST_Block_Pattern_Categories_Controller();
$block_patterns->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_rest_block_pattern_categories_routes' );
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function gutenberg_is_experiment_enabled( $name ) {

// WordPress 6.5 compat.
require_once __DIR__ . '/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php';
require __DIR__ . '/compat/wordpress-6.5/class-gutenberg-rest-block-pattern-categories-controller.php';
require_once __DIR__ . '/compat/wordpress-6.5/rest-api.php';

// Plugin specific code.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { useCallback, useMemo } from '@wordpress/element';
import { useCallback } from '@wordpress/element';
import { cloneBlock, createBlock } from '@wordpress/blocks';
import { useDispatch, useSelect } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';
Expand All @@ -21,38 +21,19 @@ import { store as blockEditorStore } from '../../../store';
* @return {Array} Returns the patterns state. (patterns, categories, onSelect handler)
*/
const usePatternsState = ( onInsert, rootClientId ) => {
const { patternCategories, patterns, userPatternCategories } = useSelect(
const { patternCategories, patterns } = useSelect(
( select ) => {
const { __experimentalGetAllowedPatterns, getSettings } =
select( blockEditorStore );
const {
__experimentalUserPatternCategories,
__experimentalBlockPatternCategories,
} = getSettings();
const { __experimentalBlockPatternCategories } = getSettings();
return {
patterns: __experimentalGetAllowedPatterns( rootClientId ),
userPatternCategories: __experimentalUserPatternCategories,
patternCategories: __experimentalBlockPatternCategories,
};
},
[ rootClientId ]
);

const allCategories = useMemo( () => {
const categories = [ ...patternCategories ];
userPatternCategories?.forEach( ( userCategory ) => {
if (
! categories.find(
( existingCategory ) =>
existingCategory.name === userCategory.name
)
) {
categories.push( userCategory );
}
} );
return categories;
}, [ patternCategories, userPatternCategories ] );

const { createSuccessNotice } = useDispatch( noticesStore );
const onClickPattern = useCallback(
( pattern, blocks ) => {
Expand All @@ -79,7 +60,7 @@ const usePatternsState = ( onInsert, rootClientId ) => {
[ createSuccessNotice, onInsert ]
);

return [ patterns, allCategories, onClickPattern ];
return [ patterns, patternCategories, onClickPattern ];
};

export default usePatternsState;
20 changes: 12 additions & 8 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2277,20 +2277,23 @@ const checkAllowListRecursive = ( blocks, allowedBlockTypes ) => {
function getUserPatterns( state ) {
const userPatterns =
state?.settings?.__experimentalReusableBlocks ?? EMPTY_ARRAY;
const userPatternCategories =
state?.settings?.__experimentalUserPatternCategories ?? [];
const patternCategories =
state?.settings?.__experimentalBlockPatternCategories ?? [];
const categories = new Map();
userPatternCategories.forEach( ( userCategory ) =>
categories.set( userCategory.id, userCategory )
);
patternCategories.forEach( ( category ) => {
if ( category.id ) {
categories.set( category.id, category );
}
} );

return userPatterns.map( ( userPattern ) => {
return {
name: `core/block/${ userPattern.id }`,
id: userPattern.id,
title: userPattern.title.raw,
categories: userPattern.wp_pattern_category.map( ( catId ) =>
categories && categories.get( catId )
? categories.get( catId ).slug
? categories.get( catId ).name
: catId
),
content: userPattern.content.raw,
Expand Down Expand Up @@ -2327,7 +2330,7 @@ export const __experimentalGetParsedPattern = createSelector(
( state ) => [
state.settings.__experimentalBlockPatterns,
state.settings.__experimentalReusableBlocks,
state?.settings?.__experimentalUserPatternCategories,
state.settings.__experimentalBlockPatternCategories,
]
);

Expand All @@ -2352,7 +2355,7 @@ const getAllAllowedPatterns = createSelector(
state.settings.__experimentalBlockPatterns,
state.settings.__experimentalReusableBlocks,
state.settings.allowedBlockTypes,
state?.settings?.__experimentalUserPatternCategories,
state.settings.__experimentalBlockPatternCategories,
]
);

Expand All @@ -2379,6 +2382,7 @@ export const __experimentalGetAllowedPatterns = createSelector(
( state, rootClientId ) => [
state.settings.__experimentalBlockPatterns,
state.settings.__experimentalReusableBlocks,
state.settings.__experimentalBlockPatternCategories,
state.settings.allowedBlockTypes,
state.settings.templateLock,
state.blockListSettings[ rootClientId ],
Expand Down
12 changes: 12 additions & 0 deletions packages/core-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,18 @@ _Returns_

- `boolean | undefined`: Whether or not the user can edit, or `undefined` if the OPTIONS request is still being made.

### getAllPatternCategories

Retrieve the core and user pattern categories.

_Parameters_

- _state_ `State`: Data state.

_Returns_

- `Array< unknown >`: User patterns category array.

### getAuthors

> **Deprecated** since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead.
Expand Down
9 changes: 9 additions & 0 deletions packages/core-data/src/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,14 @@ export function userPatternCategories( state = [], action ) {
return state;
}

export function allPatternCategories( state = [], action ) {
switch ( action.type ) {
case 'RECEIVE_ALL_PATTERN_CATEGORIES':
return action.allPatternCategories;
}
return state;
}

export function navigationFallbackId( state = null, action ) {
switch ( action.type ) {
case 'RECEIVE_NAVIGATION_FALLBACK_ID':
Expand Down Expand Up @@ -611,6 +619,7 @@ export default combineReducers( {
blockPatterns,
blockPatternCategories,
userPatternCategories,
allPatternCategories,
navigationFallbackId,
defaultTemplates,
} );
Loading
Loading