-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Don't resolve templates for non-queried editor entities #81868
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
base: trunk
Are you sure you want to change the base?
Changes from all commits
cbbe9d2
d3f4faf
977368b
5272a69
24c57bb
f0f8edc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| import { renderHook } from '@testing-library/react'; | ||
| import { createRegistry, RegistryProvider } from '@wordpress/data'; | ||
| import { store as coreStore } from '@wordpress/core-data'; | ||
| import { useTemplateId } from '../use-template-id'; | ||
|
|
||
| function createRegistryWithTemplates() { | ||
| const registry = createRegistry(); | ||
| registry.register( coreStore ); | ||
| const { receiveEntityRecords, addEntities } = | ||
| registry.dispatch( coreStore ); | ||
|
|
||
| // A static front page makes home page resolution synchronous. | ||
| receiveEntityRecords( 'root', '__unstableBase', { | ||
| show_on_front: 'page', | ||
| page_on_front: 2, | ||
| } ); | ||
| addEntities( [ | ||
| { kind: 'postType', name: 'wp_template', baseURL: '/wp/v2/templates' }, | ||
| ] ); | ||
| receiveEntityRecords( | ||
| 'postType', | ||
| 'wp_template', | ||
| [ { id: 'theme//custom', slug: 'custom' } ], | ||
| { per_page: -1 } | ||
| ); | ||
| return registry; | ||
| } | ||
|
|
||
| /** | ||
| * Seeds an entity that has a template assigned, which is the branch of the | ||
| * resolution that does not depend on how the template hierarchy builds its | ||
| * fallback slugs. The attachment test below resolves an identically shaped | ||
| * entity, so it doubles as proof that these seeds would otherwise resolve. | ||
| * | ||
| * @param {Object} registry Registry to seed. | ||
| * @param {string} postType Post type of the record. | ||
| * @param {string|number} postId ID of the record. | ||
| */ | ||
| function seedEntityWithAssignedTemplate( registry, postType, postId ) { | ||
| const { receiveEntityRecords, addEntities } = | ||
| registry.dispatch( coreStore ); | ||
| addEntities( [ | ||
| { kind: 'postType', name: postType, baseURL: `/wp/v2/${ postType }` }, | ||
| ] ); | ||
| receiveEntityRecords( 'postType', postType, [ | ||
| { id: postId, template: 'custom' }, | ||
| ] ); | ||
| } | ||
|
|
||
| function renderUseTemplateId( registry, postType, postId ) { | ||
| const { result } = renderHook( | ||
| () => useTemplateId( { postType, postId } ), | ||
| { | ||
| wrapper: ( { children } ) => ( | ||
| <RegistryProvider value={ registry }> | ||
| { children } | ||
| </RegistryProvider> | ||
| ), | ||
| } | ||
| ); | ||
| return result.current; | ||
| } | ||
|
|
||
| describe( 'useTemplateId', () => { | ||
| it( 'resolves the assigned template for a post', () => { | ||
| const registry = createRegistryWithTemplates(); | ||
| seedEntityWithAssignedTemplate( registry, 'post', 1 ); | ||
|
|
||
| expect( renderUseTemplateId( registry, 'post', '1' ) ).toBe( | ||
| 'theme//custom' | ||
| ); | ||
| } ); | ||
|
|
||
| it( 'returns the template itself when editing a template', () => { | ||
| const registry = createRegistryWithTemplates(); | ||
|
|
||
| expect( | ||
| renderUseTemplateId( registry, 'wp_template', 'theme//single' ) | ||
| ).toBe( 'theme//single' ); | ||
| } ); | ||
|
|
||
| it( 'returns undefined when there is no entity to resolve for', () => { | ||
| const registry = createRegistryWithTemplates(); | ||
|
|
||
| expect( | ||
| renderUseTemplateId( registry, undefined, undefined ) | ||
| ).toBeUndefined(); | ||
| } ); | ||
|
|
||
| it.each( [ | ||
| [ 'wp_template_part', 'theme//header' ], | ||
| [ 'wp_block', 7 ], | ||
| [ 'wp_navigation', 8 ], | ||
| ] )( | ||
| 'returns undefined for %s, which is never queried content', | ||
| ( postType, postId ) => { | ||
| const registry = createRegistryWithTemplates(); | ||
| seedEntityWithAssignedTemplate( registry, postType, postId ); | ||
|
|
||
| expect( | ||
| renderUseTemplateId( registry, postType, String( postId ) ) | ||
| ).toBeUndefined(); | ||
| } | ||
| ); | ||
|
|
||
| it( 'still resolves for an attachment, which has its own place in the template hierarchy', () => { | ||
| const registry = createRegistryWithTemplates(); | ||
| seedEntityWithAssignedTemplate( registry, 'attachment', 9 ); | ||
|
|
||
| expect( renderUseTemplateId( registry, 'attachment', '9' ) ).toBe( | ||
| 'theme//custom' | ||
| ); | ||
| } ); | ||
| } ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import { store as coreDataStore } from '@wordpress/core-data'; | ||
| import { useSelect } from '@wordpress/data'; | ||
| import { unlock } from '../lock-unlock'; | ||
|
|
||
| /* | ||
| * Post types that are never the queried object of a frontend request, so no | ||
| * request of theirs runs the template hierarchy and asking which template they | ||
| * render inside falls through to an unrelated one — ultimately `index`. | ||
| * Template parts and patterns do appear inside templates, but in many of them, | ||
| * and never as the thing being queried. | ||
| * | ||
| * `wp_template` is never queried either, but is answered before this list is | ||
| * consulted: the template being edited is its own answer. | ||
| * | ||
| * The site editor guards the same resolution in `use-resolve-edited-entity`, | ||
| * over a longer list that also reflects which entities that editor opens. | ||
| */ | ||
| const NEVER_QUERIED_POST_TYPES = [ | ||
| 'wp_template_part', | ||
| 'wp_block', | ||
| 'wp_navigation', | ||
| ]; | ||
|
|
||
| /** | ||
| * This is a React hook that provides the ID of the template an entity renders | ||
| * inside, matching the template WordPress would choose for it on the frontend. | ||
| * | ||
| * @param props The props object. | ||
| * @param props.postType The post type of the edited entity. | ||
| * @param props.postId The ID of the edited entity. | ||
| * @return The template ID, or `undefined` when there is no template to resolve. | ||
| */ | ||
| export function useTemplateId( { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this actually belong in core data?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure we have versions of this hook in a lot of places. And yes, maybe core-data is the right place for it. |
||
| postType, | ||
| postId, | ||
| }: { | ||
| postType?: string; | ||
| postId?: string; | ||
| } = {} ) { | ||
| return useSelect( | ||
| ( select ) => { | ||
| if ( ! postType || ! postId ) { | ||
| return undefined; | ||
| } | ||
|
|
||
| if ( postType === 'wp_template' ) { | ||
| return postId; | ||
| } | ||
|
|
||
| if ( NEVER_QUERIED_POST_TYPES.includes( postType ) ) { | ||
| return undefined; | ||
| } | ||
|
|
||
| return unlock( select( coreDataStore ) ).getTemplateId( | ||
| postType, | ||
| postId | ||
| ); | ||
| }, | ||
| [ postType, postId ] | ||
| ); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That name is a bit weird to me. this is more about the post type not having dedicated frontend pages? what is "queried" about?
Also isn't there already support flags for this, or is the static list mandatory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i don't really like the name. the original name was "post types that don't have parent templates" which I also found confusing as they do appear in templates. What about "post types not in template heirarchy"?