Skip to content

Commit

Permalink
[Patterns]: Add new pattern categories (#46144)
Browse files Browse the repository at this point in the history
* [Patterns]: Add new pattern categories

* remove some categories

* update php code

* update php

* add php test and update/remove test that are in core

* map more categories

* migrate only `columns` to `text` and show `text` at the bottom of categories list

* address feedback
  • Loading branch information
ntsekouras authored Dec 12, 2022
1 parent 6690494 commit 30d4f2e
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 158 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* REST API: Gutenberg_REST_Block_Patterns_Controller class
* REST API: Gutenberg_REST_Block_Patterns_Controller_6_1 class
*
* @package Gutenberg
* @subpackage REST_API
Expand All @@ -13,104 +13,12 @@
*
* @see WP_REST_Controller
*/
class Gutenberg_REST_Block_Patterns_Controller extends WP_REST_Controller {

/**
* Defines whether remote patterns should be loaded.
*
* @since 6.0.0
* @var bool
*/
private $remote_patterns_loaded;

/**
* Constructs the controller.
*
* @since 6.0.0
*/
public function __construct() {
$this->namespace = 'wp/v2';
$this->rest_base = 'block-patterns/patterns';
}

/**
* Registers the routes for the objects of the controller.
*
* @since 6.0.0
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
),
'schema' => array( $this, 'get_public_item_schema' ),
),
true
);
}

/**
* Checks whether a given request has permission to read block patterns.
*
* @since 6.0.0
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access, WP_Error object otherwise.
*/
public function get_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( current_user_can( 'edit_posts' ) ) {
return true;
}

foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
if ( current_user_can( $post_type->cap->edit_posts ) ) {
return true;
}
}

return new WP_Error(
'rest_cannot_view',
__( 'Sorry, you are not allowed to view the registered block patterns.', 'gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}

/**
* Retrieves all block patterns.
*
* @since 6.0.0
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
if ( ! $this->remote_patterns_loaded ) {
// Load block patterns from w.org.
_load_remote_block_patterns(); // Patterns with the `core` keyword.
_load_remote_featured_patterns(); // Patterns in the `featured` category.
_register_remote_theme_patterns(); // Patterns requested by current theme.

$this->remote_patterns_loaded = true;
}

$response = array();
$patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
foreach ( $patterns as $pattern ) {
$prepared_pattern = $this->prepare_item_for_response( $pattern, $request );
$response[] = $this->prepare_response_for_collection( $prepared_pattern );
}
return rest_ensure_response( $response );
}

class Gutenberg_REST_Block_Patterns_Controller_6_1 extends WP_REST_Block_Patterns_Controller {
/**
* Prepare a raw block pattern before it gets output in a REST API response.
*
* @since 6.0.0
* @since 6.1.0 Added `postTypes` property.
*
* @param array $item Raw pattern as registered, before any changes.
* @param WP_REST_Request $request Request object.
Expand Down Expand Up @@ -147,6 +55,7 @@ public function prepare_item_for_response( $item, $request ) {
* Retrieves the block pattern schema, conforming to JSON Schema.
*
* @since 6.0.0
* @since 6.1.0 Added `post_types` property.
*
* @return array Item schema data.
*/
Expand Down
9 changes: 0 additions & 9 deletions lib/compat/wordpress-6.1/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,6 @@ function gutenberg_update_post_types_rest_response( $response, $post_type ) {
}
add_filter( 'rest_prepare_post_type', 'gutenberg_update_post_types_rest_response', 10, 2 );

/**
* Registers the block patterns REST API routes.
*/
function gutenberg_register_gutenberg_rest_block_patterns() {
$block_patterns = new Gutenberg_REST_Block_Patterns_Controller();
$block_patterns->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_gutenberg_rest_block_patterns', 100 );

/**
* Exposes the site logo URL through the WordPress REST API.
*
Expand Down
102 changes: 84 additions & 18 deletions lib/compat/wordpress-6.2/block-patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Registers the block pattern categories.
*/
function gutenberg_register_core_block_patterns_and_categories() {
function gutenberg_register_core_block_patterns_categories() {
register_block_pattern_category(
'banner',
array(
Expand All @@ -30,49 +30,115 @@ function gutenberg_register_core_block_patterns_and_categories() {
)
);
register_block_pattern_category(
'footer',
'text',
array(
'label' => _x( 'Footers', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A variety of footer designs displaying information and site navigation.', 'gutenberg' ),
'label' => _x( 'Text', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Patterns containing mostly text.', 'gutenberg' ),
)
);
register_block_pattern_category(
'gallery',
'query',
array(
'label' => _x( 'Gallery', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Patterns containing mostly images or other media.', 'gutenberg' ),
'label' => _x( 'Posts', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Display your latest posts in lists, grids or other layouts.', 'gutenberg' ),
)
);
register_block_pattern_category(
'header',
'featured',
array(
'label' => _x( 'Headers', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A variety of header designs displaying your site title and navigation.', 'gutenberg' ),
'label' => _x( 'Featured', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A set of high quality curated patterns.', 'gutenberg' ),
)
);

// Register new core block pattern categories.
register_block_pattern_category(
'text',
'call-to-action',
array(
'label' => _x( 'Text', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Patterns containing mostly text.', 'gutenberg' ),
'label' => _x( 'Call to Action', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Sections whose purpose is to trigger a specific action.', 'gutenberg' ),
)
);
register_block_pattern_category(
'query',
'team',
array(
'label' => _x( 'Team', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A variety of designs to display your team members.', 'gutenberg' ),
)
);
register_block_pattern_category(
'testimonials',
array(
'label' => _x( 'Testimonials', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Share reviews and feedback about your brand/business.', 'gutenberg' ),
)
);
register_block_pattern_category(
'services',
array(
'label' => _x( 'Services', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Briefly describe what your business does and how you can help.', 'gutenberg' ),
)
);
register_block_pattern_category(
'contact',
array(
'label' => _x( 'Contact', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Display your contact information.', 'gutenberg' ),
)
);
register_block_pattern_category(
'about',
array(
'label' => _x( 'About', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Introduce yourself.', 'gutenberg' ),
)
);
register_block_pattern_category(
'portfolio',
array(
'label' => _x( 'Portfolio', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Showcase your latest work.', 'gutenberg' ),
)
);
register_block_pattern_category(
'gallery',
array(
'label' => _x( 'Gallery', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Different layouts for displaying images.', 'gutenberg' ),
)
);
register_block_pattern_category(
'media',
array(
'label' => _x( 'Media', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Different layouts containing video or audio.', 'gutenberg' ),
)
);
register_block_pattern_category(
'posts',
array(
'label' => _x( 'Posts', 'Block pattern category', 'gutenberg' ),
'description' => __( 'Display your latest posts in lists, grids or other layouts.', 'gutenberg' ),
)
);
// Site building pattern categories.
register_block_pattern_category(
'featured',
'footer',
array(
'label' => _x( 'Featured', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A set of high quality curated patterns.', 'gutenberg' ),
'label' => _x( 'Footers', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A variety of footer designs displaying information and site navigation.', 'gutenberg' ),
)
);
register_block_pattern_category(
'header',
array(
'label' => _x( 'Headers', 'Block pattern category', 'gutenberg' ),
'description' => __( 'A variety of header designs displaying your site title and navigation.', 'gutenberg' ),
)
);
}
add_action( 'init', 'gutenberg_register_core_block_patterns_and_categories' );
add_action( 'init', 'gutenberg_register_core_block_patterns_categories' );

/**
* Registers Gutenberg-bundled patterns, with a focus on headers and footers
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php
/**
* REST API: Gutenberg_REST_Block_Patterns_Controller_6_2 class
*
* @package Gutenberg
* @subpackage REST_API
*/

/**
* Core class used to access block patterns via the REST API.
*
* @since 6.0.0
*
* @see WP_REST_Controller
*/
class Gutenberg_REST_Block_Patterns_Controller_6_2 extends Gutenberg_REST_Block_Patterns_Controller_6_1 {
/**
* Defines whether remote patterns should be loaded.
*
* @since 6.0.0
* @var bool
*/
private $remote_patterns_loaded;

/**
* An array that maps old categories names to new ones.
*
* @since 6.2.0
* @var array
*/
protected static $categories_migration = array(
'buttons' => 'call-to-action',
'columns' => 'text',
'query' => 'posts',
);

/**
* Registers the routes for the objects of the controller.
*
* @since 6.0.0
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
),
'schema' => array( $this, 'get_public_item_schema' ),
),
true
);
}
/**
* Retrieves all block patterns.
*
* @since 6.0.0
* @since 6.2.0 Added migration for old core pattern categories to the new ones.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
if ( ! $this->remote_patterns_loaded ) {
// Load block patterns from w.org.
_load_remote_block_patterns(); // Patterns with the `core` keyword.
_load_remote_featured_patterns(); // Patterns in the `featured` category.
_register_remote_theme_patterns(); // Patterns requested by current theme.

$this->remote_patterns_loaded = true;
}

$response = array();
$patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
foreach ( $patterns as $pattern ) {
$migrated_pattern = $this->migrate_pattern_categories( $pattern );
$prepared_pattern = $this->prepare_item_for_response( $migrated_pattern, $request );
$response[] = $this->prepare_response_for_collection( $prepared_pattern );
}
return rest_ensure_response( $response );
}

/**
* Migrates old core pattern categories to new ones.
*
* Core pattern categories are being revamped and we need to handle the migration
* to the new ones and ensure backwards compatibility.
*
* @since 6.2.0
*
* @param array $pattern Raw pattern as registered, before applying any changes.
* @return array Migrated pattern.
*/
protected function migrate_pattern_categories( $pattern ) {
if ( isset( $pattern['categories'] ) && is_array( $pattern['categories'] ) ) {
foreach ( $pattern['categories'] as $i => $category ) {
if ( array_key_exists( $category, static::$categories_migration ) ) {
$pattern['categories'][ $i ] = static::$categories_migration[ $category ];
}
}
}
return $pattern;
}
}
Loading

0 comments on commit 30d4f2e

Please sign in to comment.