diff --git a/packages/e2e-test-utils-playwright/src/request-utils/site-settings.ts b/packages/e2e-test-utils-playwright/src/request-utils/site-settings.ts index 4540402ca827a9..d655f23c4f487c 100644 --- a/packages/e2e-test-utils-playwright/src/request-utils/site-settings.ts +++ b/packages/e2e-test-utils-playwright/src/request-utils/site-settings.ts @@ -19,6 +19,9 @@ type SiteSettings = { posts_per_page: number; default_ping_status: 'open' | 'closed'; default_comment_status: 'open' | 'closed'; + show_on_front: 'posts' | 'page'; + page_on_front: number; + page_for_posts: number; }; /** diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index 98f67e7e4ee5c6..103fbbae7c9f4a 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -577,36 +577,55 @@ export function areMetaBoxesInitialized( state ) { */ export const getEditedPostTemplate = createRegistrySelector( ( select ) => () => { + const { + id: postId, + type: postType, + slug, + } = select( editorStore ).getCurrentPost(); + const { getSite, getEditedEntityRecord, getEntityRecords } = + select( coreStore ); + const siteSettings = getSite(); + // First check if the current page is set as the posts page. + const isPostsPage = +postId === siteSettings?.page_for_posts; + if ( isPostsPage ) { + const defaultTemplateId = select( coreStore ).getDefaultTemplateId( + { slug: 'home' } + ); + return getEditedEntityRecord( + 'postType', + 'wp_template', + defaultTemplateId + ); + } const currentTemplate = select( editorStore ).getEditedPostAttribute( 'template' ); if ( currentTemplate ) { - const templateWithSameSlug = select( coreStore ) - .getEntityRecords( 'postType', 'wp_template', { per_page: -1 } ) - ?.find( ( template ) => template.slug === currentTemplate ); + const templateWithSameSlug = getEntityRecords( + 'postType', + 'wp_template', + { per_page: -1 } + )?.find( ( template ) => template.slug === currentTemplate ); if ( ! templateWithSameSlug ) { return templateWithSameSlug; } - return select( coreStore ).getEditedEntityRecord( + return getEditedEntityRecord( 'postType', 'wp_template', templateWithSameSlug.id ); } - - const post = select( editorStore ).getCurrentPost(); let slugToCheck; // In `draft` status we might not have a slug available, so we use the `single` // post type templates slug(ex page, single-post, single-product etc..). // Pages do not need the `single` prefix in the slug to be prioritized // through template hierarchy. - if ( post.slug ) { + if ( slug ) { slugToCheck = - post.type === 'page' - ? `${ post.type }-${ post.slug }` - : `single-${ post.type }-${ post.slug }`; + postType === 'page' + ? `${ postType }-${ slug }` + : `single-${ postType }-${ slug }`; } else { - slugToCheck = - post.type === 'page' ? 'page' : `single-${ post.type }`; + slugToCheck = postType === 'page' ? 'page' : `single-${ postType }`; } const defaultTemplateId = select( coreStore ).getDefaultTemplateId( { slug: slugToCheck, diff --git a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js index 839996e2ebdf9c..efd02a673874d2 100644 --- a/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js +++ b/packages/edit-site/src/components/sync-state-with-url/use-init-edited-entity-from-url.js @@ -28,42 +28,48 @@ const postTypesWithoutParentTemplate = [ ]; function useResolveEditedEntityAndContext( { path, postId, postType } ) { - const { hasLoadedAllDependencies, homepageId, url, frontPageTemplateId } = - useSelect( ( select ) => { - const { getSite, getUnstableBase, getEntityRecords } = - select( coreDataStore ); - const siteData = getSite(); - const base = getUnstableBase(); - const templates = getEntityRecords( - 'postType', - TEMPLATE_POST_TYPE, - { - per_page: -1, - } + const { + hasLoadedAllDependencies, + homepageId, + postsPageId, + url, + frontPageTemplateId, + } = useSelect( ( select ) => { + const { getSite, getUnstableBase, getEntityRecords } = + select( coreDataStore ); + const siteData = getSite(); + const base = getUnstableBase(); + const templates = getEntityRecords( 'postType', TEMPLATE_POST_TYPE, { + per_page: -1, + } ); + const _homepageId = + siteData?.show_on_front === 'page' && + [ 'number', 'string' ].includes( typeof siteData.page_on_front ) && + !! +siteData.page_on_front // We also need to check if it's not zero(`0`). + ? siteData.page_on_front.toString() + : null; + const _postsPageId = + siteData?.show_on_front === 'page' && + [ 'number', 'string' ].includes( typeof siteData.page_for_posts ) + ? siteData.page_for_posts.toString() + : null; + let _frontPageTemplateId; + if ( templates ) { + const frontPageTemplate = templates.find( + ( t ) => t.slug === 'front-page' ); - let _frontPateTemplateId; - if ( templates ) { - const frontPageTemplate = templates.find( - ( t ) => t.slug === 'front-page' - ); - _frontPateTemplateId = frontPageTemplate - ? frontPageTemplate.id - : false; - } - - return { - hasLoadedAllDependencies: !! base && !! siteData, - homepageId: - siteData?.show_on_front === 'page' && - [ 'number', 'string' ].includes( - typeof siteData.page_on_front - ) - ? siteData.page_on_front.toString() - : null, - url: base?.home, - frontPageTemplateId: _frontPateTemplateId, - }; - }, [] ); + _frontPageTemplateId = frontPageTemplate + ? frontPageTemplate.id + : false; + } + return { + hasLoadedAllDependencies: !! base && !! siteData, + homepageId: _homepageId, + postsPageId: _postsPageId, + url: base?.home, + frontPageTemplateId: _frontPageTemplateId, + }; + }, [] ); /** * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId @@ -114,6 +120,14 @@ function useResolveEditedEntityAndContext( { path, postId, postType } ) { if ( ! editedEntity ) { return undefined; } + // Check if the current page is the posts page. + if ( + postTypeToResolve === 'page' && + postsPageId === postIdToResolve + ) { + return __experimentalGetTemplateForLink( editedEntity.link ) + ?.id; + } // First see if the post/page has an assigned template and fetch it. const currentTemplateSlug = editedEntity.template; if ( currentTemplateSlug ) { @@ -177,6 +191,7 @@ function useResolveEditedEntityAndContext( { path, postId, postType } ) { }, [ homepageId, + postsPageId, hasLoadedAllDependencies, url, postId, diff --git a/test/e2e/specs/editor/various/template-resolution.spec.js b/test/e2e/specs/editor/various/template-resolution.spec.js new file mode 100644 index 00000000000000..13503ddaf23d5b --- /dev/null +++ b/test/e2e/specs/editor/various/template-resolution.spec.js @@ -0,0 +1,90 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +async function updateSiteSettings( { pageId, requestUtils } ) { + return requestUtils.updateSiteSettings( { + show_on_front: 'page', + page_on_front: 0, + page_for_posts: pageId, + } ); +} + +test.describe( 'Template resolution', () => { + test.beforeAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'emptytheme' ); + } ); + test.afterEach( async ( { requestUtils } ) => { + await Promise.all( [ + requestUtils.deleteAllPages(), + requestUtils.updateSiteSettings( { + show_on_front: 'posts', + page_on_front: 0, + page_for_posts: 0, + } ), + ] ); + } ); + test.afterAll( async ( { requestUtils } ) => { + await requestUtils.activateTheme( 'twentytwentyone' ); + } ); + test( 'Site editor proper front page template resolution when we have only set posts page in settings', async ( { + page, + admin, + requestUtils, + } ) => { + const newPage = await requestUtils.createPage( { + title: 'Posts Page', + status: 'publish', + } ); + await updateSiteSettings( { requestUtils, pageId: newPage.id } ); + await admin.visitSiteEditor(); + await expect( page.locator( '.edit-site-canvas-loader' ) ).toHaveCount( + 0 + ); + } ); + test.describe( '`page_for_posts` setting', () => { + test( 'Post editor proper template resolution', async ( { + page, + admin, + editor, + requestUtils, + } ) => { + const newPage = await requestUtils.createPage( { + title: 'Posts Page', + status: 'publish', + } ); + await admin.editPost( newPage.id ); + await editor.openDocumentSettingsSidebar(); + await expect( + page.getByRole( 'button', { name: 'Template options' } ) + ).toHaveText( 'Single Entries' ); + await updateSiteSettings( { requestUtils, pageId: newPage.id } ); + await page.reload(); + await expect( + page.getByRole( 'button', { name: 'Template options' } ) + ).toHaveText( 'Index' ); + } ); + test( 'Site editor proper template resolution', async ( { + page, + editor, + admin, + requestUtils, + } ) => { + const newPage = await requestUtils.createPage( { + title: 'Posts Page', + status: 'publish', + } ); + await updateSiteSettings( { requestUtils, pageId: newPage.id } ); + await admin.visitSiteEditor( { + postId: newPage.id, + postType: 'page', + canvas: 'edit', + } ); + await editor.openDocumentSettingsSidebar(); + await expect( + page.getByRole( 'button', { name: 'Template options' } ) + ).toHaveText( 'Index' ); + } ); + } ); +} );