Skip to content

Commit

Permalink
Edit Site: Fetch template parts in Template Switcher from REST API (#…
Browse files Browse the repository at this point in the history
…21878)

This is to decouple `edit-site` even further from the `settings` variable that is at the moment directly passed from PHP, and will use the REST API instead. #21877 is complementary to this PR.
  • Loading branch information
ockham authored Jun 9, 2020
1 parent aa46f40 commit 670d800
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 57 deletions.
2 changes: 1 addition & 1 deletion lib/template-loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ function gutenberg_find_template_post_and_parts( $template_type, $template_hiera

if ( $current_template_post ) {
$template_part_ids = array();
if ( is_admin() ) {
if ( is_admin() || defined( 'REST_REQUEST' ) ) {
foreach ( parse_blocks( $current_template_post->post_content ) as $block ) {
$template_part_ids = array_merge( $template_part_ids, create_auto_draft_for_template_part_block( $block ) );
}
Expand Down
48 changes: 45 additions & 3 deletions lib/template-parts.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,22 @@ function gutenberg_render_template_part_list_table_column( $column_name, $post_i


/**
* Filter for adding a `theme` parameter to `wp_template_part` queries.
* Filter for adding a `resolved`, a `template`, and a `theme` parameter to `wp_template_part` queries.
*
* @param array $query_params The query parameters.
* @return array Filtered $query_params.
*/
function filter_rest_wp_template_part_collection_params( $query_params ) {
$query_params += array(
'theme' => array(
'resolved' => array(
'description' => __( 'Whether to filter for resolved template parts.', 'gutenberg' ),
'type' => 'boolean',
),
'template' => array(
'description' => __( 'The template slug for the template that the template part is used by.', 'gutenberg' ),
'type' => 'string',
),
'theme' => array(
'description' => __( 'The theme slug for the theme that created the template part.', 'gutenberg' ),
'type' => 'string',
),
Expand All @@ -158,13 +166,46 @@ function filter_rest_wp_template_part_collection_params( $query_params ) {
apply_filters( 'rest_wp_template_part_collection_params', 'filter_rest_wp_template_part_collection_params', 99, 1 );

/**
* Filter for supporting the `theme` parameter in `wp_template_part` queries.
* Filter for supporting the `resolved`, `template`, and `theme` parameters in `wp_template_part` queries.
*
* @param array $args The query arguments.
* @param WP_REST_Request $request The request object.
* @return array Filtered $args.
*/
function filter_rest_wp_template_part_query( $args, $request ) {
/**
* Unlike `filter_rest_wp_template_query`, we resolve queries also if there's only a `template` argument set.
* The difference is that in the case of templates, we can use the `slug` field that already exists (as part
* of the entities endpoint, wheras for template parts, we have to register the extra `template` argument),
* so we need the `resolved` flag to convey the different semantics (only return 'resolved' templates that match
* the `slug` vs return _all_ templates that match it (e.g. including all auto-drafts)).
*
* A template parts query with a `template` arg but not a `resolved` one is conceivable, but probably wouldn't be
* very useful: It'd be all template parts for all templates matching that `template` slug (including auto-drafts etc).
*
* @see filter_rest_wp_template_query
* @see filter_rest_wp_template_part_collection_params
* @see https://github.com/WordPress/gutenberg/pull/21878#discussion_r436961706
*/
if ( $request['resolved'] || $request['template'] ) {
$template_part_ids = array( 0 ); // Return nothing by default (the 0 is needed for `post__in`).
$template_types = $request['template'] ? array( $request['template'] ) : get_template_types();

foreach ( $template_types as $template_type ) {
// Skip 'embed' for now because it is not a regular template type.
if ( in_array( $template_type, array( 'embed' ), true ) ) {
continue;
}

$current_template = gutenberg_find_template_post_and_parts( $template_type );
if ( isset( $current_template ) ) {
$template_part_ids = $template_part_ids + $current_template['template_part_ids'];
}
}
$args['post__in'] = $template_part_ids;
$args['post_status'] = array( 'publish', 'auto-draft' );
}

if ( $request['theme'] ) {
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
$meta_query[] = array(
Expand All @@ -174,6 +215,7 @@ function filter_rest_wp_template_part_query( $args, $request ) {

$args['meta_query'] = $meta_query;
}

return $args;
}
add_filter( 'rest_wp_template_part_query', 'filter_rest_wp_template_part_query', 99, 2 );
8 changes: 0 additions & 8 deletions packages/edit-site/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,27 @@ export default function Header( {
const {
deviceType,
hasFixedToolbar,
homeTemplateId,
templateId,
templatePartId,
templateType,
templatePartIds,
page,
showOnFront,
} = useSelect( ( select ) => {
const {
__experimentalGetPreviewDeviceType,
isFeatureActive,
getHomeTemplateId,
getTemplateId,
getTemplatePartId,
getTemplateType,
getTemplatePartIds,
getPage,
getShowOnFront,
} = select( 'core/edit-site' );
return {
deviceType: __experimentalGetPreviewDeviceType(),
hasFixedToolbar: isFeatureActive( 'fixedToolbar' ),
homeTemplateId: getHomeTemplateId(),
templateId: getTemplateId(),
templatePartId: getTemplatePartId(),
templateType: getTemplateType(),
templatePartIds: getTemplatePartIds(),
page: getPage(),
showOnFront: getShowOnFront(),
};
Expand Down Expand Up @@ -116,11 +110,9 @@ export default function Header( {
/
</div>
<TemplateSwitcher
templatePartIds={ templatePartIds }
page={ page }
activeId={ templateId }
activeTemplatePartId={ templatePartId }
homeId={ homeTemplateId }
isTemplatePart={ templateType === 'wp_template_part' }
onActiveIdChange={ setTemplate }
onActiveTemplatePartIdChange={ setTemplatePart }
Expand Down
101 changes: 56 additions & 45 deletions packages/edit-site/src/components/template-switcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';
import { useRegistry, useSelect } from '@wordpress/data';
import { useEffect, useState } from '@wordpress/element';
import {
Tooltip,
DropdownMenu,
Expand All @@ -16,6 +16,7 @@ import { Icon, home, plus, undo } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { findTemplate } from '../../utils';
import TemplatePreview from './template-preview';
import ThemePreview from './theme-preview';

Expand Down Expand Up @@ -46,11 +47,9 @@ function TemplateLabel( { template, homeId } ) {
}

export default function TemplateSwitcher( {
templatePartIds,
page,
activeId,
activeTemplatePartId,
homeId,
isTemplatePart,
onActiveIdChange,
onActiveTemplatePartIdChange,
Expand All @@ -70,52 +69,64 @@ export default function TemplateSwitcher( {
setThemePreviewVisible( () => false );
};

const registry = useRegistry();
const [ homeId, setHomeId ] = useState();

useEffect( () => {
findTemplate(
'/',
registry.__experimentalResolveSelect( 'core' ).getEntityRecords
).then(
( newHomeId ) => setHomeId( newHomeId ),
() => setHomeId( null )
);
}, [ registry ] );

const { currentTheme, template, templateParts } = useSelect(
( select ) => {
const { getCurrentTheme, getEntityRecord } = select( 'core' );
const {
getCurrentTheme,
getEntityRecord,
getEntityRecords,
} = select( 'core' );

const _template = getEntityRecord(
'postType',
'wp_template',
activeId
);

return {
currentTheme: getCurrentTheme(),
template: {
label: _template ? (
<TemplateLabel
template={ _template }
homeId={ homeId }
/>
) : (
__( 'Loading…' )
),
value: activeId,
slug: _template ? _template.slug : __( 'Loading…' ),
content: _template?.content,
},
templateParts: templatePartIds.map( ( id ) => {
const templatePart = getEntityRecord(
'postType',
'wp_template_part',
id
);
return {
label: templatePart ? (
<TemplateLabel template={ templatePart } />
) : (
__( 'Loading…' )
),
value: id,
slug: templatePart
? templatePart.slug
: __( 'Loading…' ),
};
} ),
template: _template,
templateParts: _template
? getEntityRecords( 'postType', 'wp_template_part', {
resolved: true,
template: _template.slug,
} )
: null,
};
},
[ activeId, templatePartIds, homeId ]
[ activeId ]
);

const templateItem = {
label: template ? (
<TemplateLabel template={ template } homeId={ homeId } />
) : (
__( 'Loading…' )
),
value: activeId,
slug: template ? template.slug : __( 'Loading…' ),
content: template?.content,
};

const templatePartItems = templateParts?.map( ( templatePart ) => ( {
label: <TemplateLabel template={ templatePart } />,
value: templatePart.id,
slug: templatePart.slug,
} ) );

const overwriteSlug =
TEMPLATE_OVERRIDES[ page.type ] &&
page.slug &&
Expand All @@ -125,10 +136,10 @@ export default function TemplateSwitcher( {
slug: overwriteSlug,
title: overwriteSlug,
status: 'publish',
content: template.content.raw,
content: templateItem.content.raw,
} );
const revertToParent = async () => {
onRemoveTemplate( template.value );
onRemoveTemplate( activeId );
};
return (
<>
Expand All @@ -141,8 +152,8 @@ export default function TemplateSwitcher( {
label={ __( 'Switch Template' ) }
toggleProps={ {
children: ( isTemplatePart
? templateParts
: [ template ]
? templatePartItems
: [ templateItem ]
).find(
( choice ) =>
choice.value ===
Expand All @@ -156,18 +167,18 @@ export default function TemplateSwitcher( {
<MenuItem
onClick={ () => onActiveIdChange( activeId ) }
>
{ template.label }
{ templateItem.label }
</MenuItem>
{ overwriteSlug &&
overwriteSlug !== template.slug && (
overwriteSlug !== templateItem.slug && (
<MenuItem
icon={ plus }
onClick={ overwriteTemplate }
>
{ __( 'Overwrite Template' ) }
</MenuItem>
) }
{ overwriteSlug === template.slug && (
{ overwriteSlug === templateItem.slug && (
<MenuItem
icon={ undo }
onClick={ revertToParent }
Expand All @@ -178,7 +189,7 @@ export default function TemplateSwitcher( {
</MenuGroup>
<MenuGroup label={ __( 'Template Parts' ) }>
<MenuItemsChoice
choices={ templateParts }
choices={ templatePartItems }
value={
isTemplatePart
? activeTemplatePartId
Expand Down

0 comments on commit 670d800

Please sign in to comment.