<?php
/**
* REST API: Gutenberg_REST_View_Config_Controller_7_1 class
*
* @package gutenberg
*/
/**
* Controller which provides a REST endpoint for retrieving the default
* view configuration for a given entity type.
*
* @since 7.1.0
*/
class Gutenberg_REST_View_Config_Controller_7_1 extends WP_REST_Controller {
/**
* Constructor.
*/
public function __construct() {
$this->namespace = 'wp/v2';
$this->rest_base = 'view-config';
}
/**
* Registers the routes for the controller.
*/
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' ),
'args' => array(
'kind' => array(
'description' => __( 'Entity kind.', 'gutenberg' ),
'type' => 'string',
'required' => true,
),
'name' => array(
'description' => __( 'Entity name.', 'gutenberg' ),
'type' => 'string',
'required' => true,
),
),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
);
}
/**
* Checks if a given request has access to read view config.
*
* @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(
// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$request
) {
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error(
'rest_cannot_read',
__( 'Sorry, you are not allowed to read view config.', 'gutenberg' ),
array( 'status' => rest_authorization_required_code() )
);
}
return true;
}
/**
* Returns the default view configuration for the given entity type.
*
* @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 ) {
$kind = $request->get_param( 'kind' );
$name = $request->get_param( 'name' );
// TODO: this data will come from a registry of view configs per entity.
$form = array();
$default_view = array(
'type' => 'table',
'filters' => array(),
'perPage' => 20,
'sort' => array(
'field' => 'title',
'direction' => 'asc',
),
'titleField' => 'title',
'fields' => array( 'author', 'status' ),
);
$default_layouts = array(
'table' => array(),
'grid' => array(),
'list' => array(),
);
$all_items_title = __( 'All items', 'gutenberg' );
if ( 'postType' === $kind ) {
$post_type_object = get_post_type_object( $name );
if ( $post_type_object && ! empty( $post_type_object->labels->all_items ) ) {
$all_items_title = $post_type_object->labels->all_items;
}
}
$view_list = array(
array(
'title' => $all_items_title,
'slug' => 'all',
),
);
if ( 'postType' === $kind && 'page' === $name ) {
$default_layouts = $this->get_default_layouts_for_page();
$default_view = $this->get_default_view_for_page();
$view_list = $this->get_view_list_for_page( $all_items_title, $default_layouts );
$form = $this->get_form_for_page();
} elseif ( 'postType' === $kind && 'post' === $name ) {
$form = $this->get_form_for_page();
} elseif ( 'postType' === $kind && 'wp_block' === $name ) {
$default_layouts = $this->get_default_layouts_for_wp_block();
$default_view = $this->get_default_view_for_wp_block( $default_layouts );
$view_list = $this->get_view_list_for_wp_block();
} elseif ( 'postType' === $kind && 'wp_template_part' === $name ) {
$default_layouts = $this->get_default_layouts_for_wp_template_part();
$default_view = $this->get_default_view_for_wp_template_part( $default_layouts );
$view_list = $this->get_view_list_for_wp_template_part();
} elseif ( 'postType' === $kind && 'wp_template' === $name ) {
$default_view = $this->get_default_view_for_wp_template();
$default_layouts = $this->get_default_layouts_for_wp_template();
$view_list = $this->get_view_list_for_wp_template();
}
$response = array(
'kind' => $kind,
'name' => $name,
'default_view' => $default_view,
'default_layouts' => $default_layouts,
'view_list' => $view_list,
'form' => $form,
);
return rest_ensure_response( $response );
}
/**
* Retrieves the item's schema, conforming to JSON Schema.
*
* @return array Item schema data.
*/
public function get_item_schema() {
if ( $this->schema ) {
return $this->add_additional_fields_schema( $this->schema );
}
$view_base_properties = $this->get_view_base_schema();
$this->schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'view-config',
'type' => 'object',
'properties' => array(
'kind' => array(
'description' => __( 'Entity kind.', 'gutenberg' ),
'type' => 'string',
'readonly' => true,
),
'name' => array(
'description' => __( 'Entity name.', 'gutenberg' ),
'type' => 'string',
'readonly' => true,
),
'default_view' => array(
'description' => __( 'Default view configuration.', 'gutenberg' ),
'type' => 'object',
'readonly' => true,
'properties' => array_merge(
array(
'type' => array(
'type' => 'string',
),
),
$view_base_properties
),
),
'default_layouts' => array(
'description' => __( 'Default layout configurations.', 'gutenberg' ),
'type' => 'object',
'readonly' => true,
'properties' => array(
'table' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_table_layout_schema(),
)
),
),
'list' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_list_layout_schema(),
)
),
),
'grid' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_grid_layout_schema(),
)
),
),
'activity' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_list_layout_schema(),
)
),
),
'pickerGrid' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_grid_layout_schema(),
)
),
),
'pickerTable' => array(
'type' => 'object',
'properties' => array_merge(
$view_base_properties,
array(
'layout' => $this->get_table_layout_schema(),
)
),
),
),
),
'view_list' => array(
'description' => __( 'List of default views.', 'gutenberg' ),
'type' => 'array',
'readonly' => true,
'items' => array(
'type' => 'object',
'properties' => array(
'title' => array(
'type' => 'string',
),
'slug' => array(
'type' => 'string',
),
'view' => array(
'type' => 'object',
'properties' => array_merge(
array(
'type' => array(
'type' => 'string',
),
'layout' => $this->get_combined_layout_schema(),
),
$view_base_properties
),
),
),
),
),
'form' => array(
'description' => __( 'Default form configuration.', 'gutenberg' ),
'type' => 'object',
'readonly' => true,
'properties' => $this->get_form_schema(),
),
),
);
return $this->add_additional_fields_schema( $this->schema );
}
/**
* Returns the schema properties shared by all view types (ViewBase), excluding 'type'.
*
* @return array Schema properties for the base view configuration.
*/
private function get_view_base_schema() {
return array(
'search' => array(
'type' => 'string',
),
'filters' => array(
'type' => 'array',
'items' => array(
'type' => 'object',
'properties' => array(
'field' => array(
'type' => 'string',
),
'operator' => array(
'type' => 'string',
'enum' => array(
'is',
'isNot',
'isAny',
'isNone',
'isAll',
'isNotAll',
'lessThan',
'greaterThan',
'lessThanOrEqual',
'greaterThanOrEqual',
'before',
'after',
),
),
'value' => array(),
'isLocked' => array(
'type' => 'boolean',
),
),
),
),
'sort' => array(
'type' => 'object',
'properties' => array(
'field' => array(
'type' => 'string',
),
'direction' => array(
'type' => 'string',
'enum' => array( 'asc', 'desc' ),
),
),
),
'page' => array(
'type' => 'integer',
),
'perPage' => array(
'type' => 'integer',
),
'fields' => array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
'titleField' => array(
'type' => 'string',
),
'mediaField' => array(
'type' => 'string',
),
'descriptionField' => array(
'type' => 'string',
),
'showTitle' => array(
'type' => 'boolean',
),
'showMedia' => array(
'type' => 'boolean',
),
'showDescription' => array(
'type' => 'boolean',
),
'showLevels' => array(
'type' => 'boolean',
),
'groupBy' => array(
'type' => 'object',
'properties' => array(
'field' => array(
'type' => 'string',
),
'direction' => array(
'type' => 'string',
'enum' => array( 'asc', 'desc' ),
),
'showLabel' => array(
'type' => 'boolean',
'default' => true,
),
),
),
'infiniteScrollEnabled' => array(
'type' => 'boolean',
),
);
}
/**
* Returns the schema for the ColumnStyle type.
*
* @return array Schema for a column style object.
*/
private function get_column_style_schema() {
return array(
'type' => 'object',
'properties' => array(
'width' => array(
'type' => array( 'string', 'number' ),
),
'maxWidth' => array(
'type' => array( 'string', 'number' ),
),
'minWidth' => array(
'type' => array( 'string', 'number' ),
),
'align' => array(
'type' => 'string',
'enum' => array( 'start', 'center', 'end' ),
),
),
);
}
/**
* Returns the layout schema for table-type views (ViewTable, ViewPickerTable).
*
* @return array Schema for a table layout object.
*/
private function get_table_layout_schema() {
return array(
'type' => 'object',
'properties' => array(
'styles' => array(
'type' => 'object',
'additionalProperties' => $this->get_column_style_schema(),
),
'density' => array(
'type' => 'string',
'enum' => array( 'compact', 'balanced', 'comfortable' ),
),
'enableMoving' => array(
'type' => 'boolean',
),
),
);
}
/**
* Returns the layout schema for list-type views (ViewList, ViewActivity).
*
* @return array Schema for a list layout object.
*/
private function get_list_layout_schema() {
return array(
'type' => 'object',
'properties' => array(
'density' => array(
'type' => 'string',
'enum' => array( 'compact', 'balanced', 'comfortable' ),
),
),
);
}
/**
* Returns a combined layout schema that accepts properties from all view types.
*
* This is useful for contexts where the view type is not known ahead of time
* (e.g. the `view` override in a view list item), so all possible layout
* properties must be accepted.
*
* @return array Schema for a combined layout object.
*/
private function get_combined_layout_schema() {
return array(
'type' => 'object',
'properties' => array_merge(
$this->get_table_layout_schema()['properties'],
$this->get_grid_layout_schema()['properties']
),
);
}
/**
* Returns the layout schema for grid-type views (ViewGrid, ViewPickerGrid).
*
* @return array Schema for a grid layout object.
*/
private function get_grid_layout_schema() {
return array(
'type' => 'object',
'properties' => array(
'badgeFields' => array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
'previewSize' => array(
'type' => 'number',
),
'density' => array(
'type' => 'string',
'enum' => array( 'compact', 'balanced', 'comfortable' ),
),
),
);
}
/**
* Returns the schema for a form layout object as a discriminated union.
*
* Each variant is discriminated by a single-value enum on its `type` property,
* matching the TypeScript Layout union in dataviews/src/types/dataform.ts.
*
* @return array Schema for a form layout object.
*/
private function get_form_layout_schema() {
return array(
'oneOf' => array(
// RegularLayout.
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'regular' ),
),
'labelPosition' => array(
'type' => 'string',
'enum' => array( 'top', 'side', 'none' ),
),
),
),
// PanelLayout.
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'panel' ),
),
'labelPosition' => array(
'type' => 'string',
'enum' => array( 'top', 'side', 'none' ),
),
'openAs' => array(
'oneOf' => array(
array(
'type' => 'string',
'enum' => array( 'dropdown', 'modal' ),
),
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'dropdown', 'modal' ),
),
'applyLabel' => array(
'type' => 'string',
),
'cancelLabel' => array(
'type' => 'string',
),
),
),
),
),
'summary' => array(
'oneOf' => array(
array( 'type' => 'string' ),
array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
),
),
'editVisibility' => array(
'type' => 'string',
'enum' => array( 'always', 'on-hover' ),
),
),
),
// CardLayout.
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'card' ),
),
'withHeader' => array(
'type' => 'boolean',
),
'isOpened' => array(
'type' => 'boolean',
),
'isCollapsible' => array(
'type' => 'boolean',
),
'summary' => array(
'oneOf' => array(
array( 'type' => 'string' ),
array(
'type' => 'array',
'items' => array(
'oneOf' => array(
array( 'type' => 'string' ),
array(
'type' => 'object',
'properties' => array(
'id' => array(
'type' => 'string',
),
'visibility' => array(
'type' => 'string',
'enum' => array( 'always', 'when-collapsed' ),
),
),
),
),
),
),
),
),
),
),
// RowLayout.
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'row' ),
),
'alignment' => array(
'type' => 'string',
'enum' => array( 'start', 'center', 'end' ),
),
'styles' => array(
'type' => 'object',
'additionalProperties' => array(
'type' => 'object',
'properties' => array(
'flex' => array(
'type' => array( 'string', 'number' ),
),
),
),
),
),
),
// DetailsLayout.
array(
'type' => 'object',
'properties' => array(
'type' => array(
'type' => 'string',
'enum' => array( 'details' ),
),
'summary' => array(
'type' => 'string',
),
),
),
),
);
}
/**
* Returns the schema for a form field item (string or object).
*
* @return array Schema for a form field.
*/
private function get_form_field_schema() {
return array(
'oneOf' => array(
array( 'type' => 'string' ),
array(
'type' => 'object',
'properties' => array(
'id' => array(
'type' => 'string',
),
'label' => array(
'type' => 'string',
),
'description' => array(
'type' => 'string',
),
'layout' => $this->get_form_layout_schema(),
'children' => array(
'type' => 'array',
'items' => array(
'oneOf' => array(
array( 'type' => 'string' ),
// This object can have the shape of a form field itself,
// allowing for recursive nesting of form fields.
// There's no easy way to codify this recursion via the JSON Schema draft-04
// supported by the REST API.
array( 'type' => 'object' ),
),
),
),
),
),
),
);
}
/**
* Returns the schema for the form configuration object.
*
* @return array Schema properties for the form configuration.
*/
private function get_form_schema() {
return array(
'layout' => $this->get_form_layout_schema(),
'fields' => array(
'type' => 'array',
'items' => $this->get_form_field_schema(),
),
);
}
private function get_default_view_for_page() {
return array(
'type' => 'list',
'filters' => array(),
'perPage' => 20,
'sort' => array(
'field' => 'title',
'direction' => 'asc',
),
'showLevels' => true,
'titleField' => 'title',
'mediaField' => 'featured_media',
'fields' => array( 'author', 'status' ),
);
}
private function get_default_layouts_for_page() {
return array(
'table' => array(
'layout' => array(
'styles' => array(
'author' => array(
'align' => 'start',
),
),
),
),
'grid' => array(),
'list' => array(),
);
}
private function get_form_for_page() {
return array(
'layout' => array( 'type' => 'panel' ),
'fields' => array(
array(
'id' => 'featured_media',
'layout' => array(
'type' => 'regular',
'labelPosition' => 'none',
),
),
array(
'id' => 'post-content-info',
'layout' => array(
'type' => 'regular',
'labelPosition' => 'none',
),
),
array(
'id' => 'excerpt',
'layout' => array(
'type' => 'panel',
'labelPosition' => 'top',
),
),
array(
'id' => 'status',
'label' => __( 'Status', 'gutenberg' ),
'children' => array(
array(
'id' => 'status',
'layout' => array(
'type' => 'regular',
'labelPosition' => 'none',
),
),
'scheduled_date',
'password',
'sticky',
),
),
'date',
'slug',
'author',
'template',
array(
'id' => 'discussion',
'label' => __( 'Discussion', 'gutenberg' ),
'children' => array(
array(
'id' => 'comment_status',
'layout' => array(
'type' => 'regular',
'labelPosition' => 'none',
),
),
'ping_status',
),
),
'parent',
'format',
),
);
}
private function get_view_list_for_page( $all_items_title, $default_layouts ) {
return array(
array(
'title' => $all_items_title,
'slug' => 'all',
),
array(
'title' => __( 'Published', 'gutenberg' ),
'slug' => 'published',
'view' => array(
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'publish',
'isLocked' => true,
),
),
),
),
array(
'title' => __( 'Scheduled', 'gutenberg' ),
'slug' => 'future',
'view' => array(
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'future',
'isLocked' => true,
),
),
),
),
array(
'title' => __( 'Drafts', 'gutenberg' ),
'slug' => 'drafts',
'view' => array(
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'draft',
'isLocked' => true,
),
),
),
),
array(
'title' => __( 'Pending', 'gutenberg' ),
'slug' => 'pending',
'view' => array(
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'pending',
'isLocked' => true,
),
),
),
),
array(
'title' => __( 'Private', 'gutenberg' ),
'slug' => 'private',
'view' => array(
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'private',
'isLocked' => true,
),
),
),
),
array(
'title' => __( 'Trash', 'gutenberg' ),
'slug' => 'trash',
'view' => array(
'type' => 'table',
'layout' => $default_layouts['table']['layout'],
'filters' => array(
array(
'field' => 'status',
'operator' => 'isAny',
'value' => 'trash',
'isLocked' => true,
),
),
),
),
);
}
private function get_default_layouts_for_wp_block() {
return array(
'table' => array(
'layout' => array(
'styles' => array(
'author' => array(
'width' => '1%',
),
),
),
),
'grid' => array(
'layout' => array(
'badgeFields' => array( 'sync-status' ),
),
),
);
}
private function get_default_view_for_wp_block( $default_layouts ) {
return array(
'type' => 'grid',
'perPage' => 20,
'titleField' => 'title',
'mediaField' => 'preview',
'fields' => array( 'sync-status' ),
'filters' => array(),
'layout' => $default_layouts['grid']['layout'],
);
}
private function get_default_layouts_for_wp_template_part() {
return array(
'table' => array(
'layout' => array(
'styles' => array(
'author' => array(
'width' => '1%',
),
),
),
),
'grid' => array(
'layout' => array(),
),
);
}
private function get_default_view_for_wp_template_part( $default_layouts ) {
return array(
'type' => 'grid',
'perPage' => 20,
'titleField' => 'title',
'mediaField' => 'preview',
'fields' => array( 'author' ),
'filters' => array(),
'layout' => $default_layouts['grid']['layout'],
);
}
/**
* Returns the original source of a template.
*
* @param WP_Block_Template $template_object Template instance.
* @return string The original source ('theme', 'plugin', 'site', or 'user').
*/
private static function get_wp_templates_original_source_field( $template_object ) {
if ( 'wp_template' === $template_object->type || 'wp_template_part' === $template_object->type ) {
/*
* Added by theme.
* Template originally provided by a theme, but customized by a user.
* Templates originally didn't have the 'origin' field so identify
* older customized templates by checking for no origin and a 'theme'
* or 'custom' source.
*/
if ( $template_object->has_theme_file &&
( 'theme' === $template_object->origin || (
empty( $template_object->origin ) && in_array(
$template_object->source,
array(
'theme',
'custom',
),
true
) )
)
) {
return 'theme';
}
// Added by plugin.
if ( 'plugin' === $template_object->origin ) {
return 'plugin';
}
/*
* Added by site.
* Template was created from scratch, but has no author. Author support
* was only added to templates in WordPress 5.9. Fallback to showing the
* site logo and title.
*/
if ( empty( $template_object->has_theme_file ) && 'custom' === $template_object->source && empty( $template_object->author ) ) {
return 'site';
}
}
// Added by user.
return 'user';
}
/**
* Returns a human readable text for the author of a template.
*
* @param WP_Block_Template $template_object Template instance.
* @return string Human readable text for the author.
*/
private static function get_wp_templates_author_text_field( $template_object ) {
$original_source = self::get_wp_templates_original_source_field( $template_object );
switch ( $original_source ) {
case 'theme':
$theme_name = wp_get_theme( $template_object->theme )->get( 'Name' );
return empty( $theme_name ) ? $template_object->theme : $theme_name;
case 'plugin':
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( isset( $template_object->plugin ) ) {
$plugins = wp_get_active_and_valid_plugins();
foreach ( $plugins as $plugin_file ) {
$plugin_basename = plugin_basename( $plugin_file );
list( $plugin_slug, ) = explode( '/', $plugin_basename );
if ( $plugin_slug === $template_object->plugin ) {
$plugin_data = get_plugin_data( $plugin_file );
if ( ! empty( $plugin_data['Name'] ) ) {
return $plugin_data['Name'];
}
break;
}
}
}
/*
* Fall back to the theme name if the plugin is not defined. That's needed to keep backwards
* compatibility with templates that were registered before the plugin attribute was added.
*/
$plugins = get_plugins();
$plugin_basename = plugin_basename( sanitize_text_field( $template_object->theme . '.php' ) );
if ( isset( $plugins[ $plugin_basename ] ) && isset( $plugins[ $plugin_basename ]['Name'] ) ) {
return $plugins[ $plugin_basename ]['Name'];
}
return $template_object->plugin ?? $template_object->theme;
case 'site':
return get_bloginfo( 'name' );
case 'user':
$author = get_user_by( 'id', $template_object->author );
if ( ! $author ) {
return __( 'Unknown author', 'gutenberg' );
}
return $author->get( 'display_name' );
}
// Fail-safe to return a string should the original source ever fall through.
return '';
}
/**
* Returns the view list for the wp_template_part post type.
*
* Builds entries from the registered template part areas (header, footer, etc.).
*
* @return array View list entries.
*/
private function get_view_list_for_wp_template_part() {
$view_list = array(
array(
'title' => __( 'All template parts', 'gutenberg' ),
'slug' => 'all-parts',
),
);
$areas = get_allowed_block_template_part_areas();
// Ensure default areas appear in a consistent order.
$preferred_order = array( 'header', 'footer', 'sidebar', 'navigation-overlay', 'uncategorized' );
$ordered_areas = array();
$remaining_areas = array();
foreach ( $areas as $area ) {
$position = array_search( $area['area'], $preferred_order, true );
if ( false !== $position ) {
$ordered_areas[ $position ] = $area;
} else {
$remaining_areas[] = $area;
}
}
ksort( $ordered_areas );
$areas = array_merge( array_values( $ordered_areas ), $remaining_areas );
foreach ( $areas as $area ) {
$view_list[] = array(
'title' => $area['label'],
'slug' => $area['area'],
'view' => array(
'filters' => array(
array(
'field' => 'area',
'operator' => 'is',
'value' => $area['area'],
'isLocked' => true,
),
),
),
);
}
return $view_list;
}
/**
* Returns the view list for the wp_block (patterns) post type.
*
* Builds entries from registered block pattern categories and user pattern categories.
*
* @return array View list entries.
*/
private function get_view_list_for_wp_block() {
$view_list = array(
array(
'title' => __( 'All patterns', 'gutenberg' ),
'slug' => 'all-patterns',
),
array(
'title' => __( 'My patterns', 'gutenberg' ),
'slug' => 'my-patterns',
),
);
// Gather categories from the block pattern categories registry.
$registry = WP_Block_Pattern_Categories_Registry::get_instance();
$categories = array();
foreach ( $registry->get_all_registered() as $category ) {
$categories[ $category['name'] ] = $category['label'];
}
// Ensure "Uncategorized" is always included for patterns
// that have no category assigned.
$categories['uncategorized'] ??= __( 'Uncategorized', 'gutenberg' );
// Also gather user-created pattern categories (wp_pattern_category taxonomy).
$user_terms = get_terms(
array(
'taxonomy' => 'wp_pattern_category',
'hide_empty' => false,
)
);
if ( ! is_wp_error( $user_terms ) ) {
foreach ( $user_terms as $term ) {
$categories[ $term->slug ] = $term->name;
}
}
// Sort categories alphabetically by label.
asort( $categories, SORT_NATURAL | SORT_FLAG_CASE );
foreach ( $categories as $name => $label ) {
$view_list[] = array(
'title' => $label,
'slug' => $name,
);
}
return $view_list;
}
private function get_default_view_for_wp_template() {
return array(
'type' => 'grid',
'perPage' => 20,
'sort' => array(
'field' => 'title',
'direction' => 'asc',
),
'titleField' => 'title',
'descriptionField' => 'description',
'mediaField' => 'preview',
'fields' => array( 'author', 'active', 'slug', 'theme' ),
'filters' => array(),
'showMedia' => true,
);
}
private function get_default_layouts_for_wp_template() {
return array(
'table' => array( 'showMedia' => false ),
'grid' => array( 'showMedia' => true ),
'list' => array( 'showMedia' => false ),
);
}
private function get_view_list_for_wp_template() {
$view_list = array(
array(
'title' => __( 'All templates', 'gutenberg' ),
'slug' => 'all',
),
);
$templates = get_block_templates( array(), 'wp_template' );
// Collect unique authors, tracking whether they come from a registered
// source (theme, plugin, site) so we can sort those before user ones.
$seen_authors = array();
$registered_authors = array();
$user_authors = array();
foreach ( $templates as $template ) {
$original_source = self::get_wp_templates_original_source_field( $template );
$author_text = self::get_wp_templates_author_text_field( $template );
if ( ! empty( $author_text ) && ! isset( $seen_authors[ $author_text ] ) ) {
$seen_authors[ $author_text ] = true;
$entry = array(
'title' => $author_text,
'slug' => $author_text,
'view' => array(
'filters' => array(
array(
'field' => 'author',
'operator' => 'is',
'value' => $author_text,
'isLocked' => true,
),
),
),
);
if ( 'user' === $original_source ) {
$user_authors[] = $entry;
} else {
$registered_authors[] = $entry;
}
}
}
$view_list = array_merge( $view_list, $registered_authors, $user_authors );
return $view_list;
}
}