diff --git a/package-lock.json b/package-lock.json index 0318a97778e11..44d5e1a7210ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52817,6 +52817,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", @@ -67661,6 +67662,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", diff --git a/packages/block-library/src/navigation-link/link-ui.js b/packages/block-library/src/navigation-link/link-ui.js index 6619c46253546..deed35145d6de 100644 --- a/packages/block-library/src/navigation-link/link-ui.js +++ b/packages/block-library/src/navigation-link/link-ui.js @@ -147,15 +147,18 @@ function LinkUIBlockInserter( { clientId, onBack, onSelectBlock } ) { } function UnforwardedLinkUI( props, ref ) { + const { label, url, opensInNewTab, type, kind } = props.link; + const postType = type || 'page'; + const [ addingBlock, setAddingBlock ] = useState( false ); const [ focusAddBlockButton, setFocusAddBlockButton ] = useState( false ); const { saveEntityRecord } = useDispatch( coreStore ); - const pagesPermissions = useResourcePermissions( 'pages' ); - const postsPermissions = useResourcePermissions( 'posts' ); + const permissions = useResourcePermissions( { + kind: 'postType', + name: postType, + } ); async function handleCreate( pageTitle ) { - const postType = props.link.type || 'page'; - const page = await saveEntityRecord( 'postType', postType, { title: pageTitle, status: 'draft', @@ -180,15 +183,6 @@ function UnforwardedLinkUI( props, ref ) { }; } - const { label, url, opensInNewTab, type, kind } = props.link; - - let userCanCreate = false; - if ( ! type || type === 'page' ) { - userCanCreate = pagesPermissions.canCreate; - } else if ( type === 'post' ) { - userCanCreate = postsPermissions.canCreate; - } - // Memoize link value to avoid overriding the LinkControl's internal state. // This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/50976#issuecomment-1568226407. const link = useMemo( @@ -241,7 +235,7 @@ function UnforwardedLinkUI( props, ref ) { hasRichPreviews value={ link } showInitialSuggestions - withCreateSuggestion={ userCanCreate } + withCreateSuggestion={ permissions.canCreate } createSuggestion={ handleCreate } createSuggestionButtonText={ ( searchTerm ) => { let format; diff --git a/packages/block-library/src/navigation/test/use-navigation-menu.js b/packages/block-library/src/navigation/test/use-navigation-menu.js index eb7e90aff22d1..7eaf648fab936 100644 --- a/packages/block-library/src/navigation/test/use-navigation-menu.js +++ b/packages/block-library/src/navigation/test/use-navigation-menu.js @@ -9,6 +9,12 @@ import { store as coreStore } from '@wordpress/core-data'; */ import useNavigationMenu from '../use-navigation-menu'; +const BASE_ENTITY = { + kind: 'postType', + name: 'wp_navigation', + id: undefined, +}; + function createRegistryWithStores() { // Create a registry and register used stores. const registry = createRegistry(); @@ -63,37 +69,70 @@ function resolveRecords( registry, menus ) { function resolveReadPermission( registry, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'read', 'navigation' ] ); - dispatch.finishResolution( 'canUser', [ 'read', 'navigation' ] ); + dispatch.receiveUserPermission( 'read/postType/wp_navigation', allowed ); + dispatch.startResolution( 'canUser', [ 'read', BASE_ENTITY ] ); + dispatch.finishResolution( 'canUser', [ 'read', BASE_ENTITY ] ); } function resolveReadRecordPermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'read', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'read', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `read/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'read', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'read', + { ...BASE_ENTITY, id: ref }, + ] ); } function resolveCreatePermission( registry, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( 'create/navigation', allowed ); - dispatch.startResolution( 'canUser', [ 'create', 'navigation' ] ); - dispatch.finishResolution( 'canUser', [ 'create', 'navigation' ] ); + dispatch.receiveUserPermission( 'create/postType/wp_navigation', allowed ); + dispatch.startResolution( 'canUser', [ + 'create', + { kind: 'postType', name: 'wp_navigation' }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'create', + { kind: 'postType', name: 'wp_navigation' }, + ] ); } function resolveUpdatePermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( `update/navigation/${ ref }`, allowed ); - dispatch.startResolution( 'canUser', [ 'update', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'update', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `update/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'update', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'update', + { ...BASE_ENTITY, id: ref }, + ] ); } function resolveDeletePermission( registry, ref, allowed ) { const dispatch = registry.dispatch( coreStore ); - dispatch.receiveUserPermission( `delete/navigation/${ ref }`, allowed ); - dispatch.startResolution( 'canUser', [ 'delete', 'navigation', ref ] ); - dispatch.finishResolution( 'canUser', [ 'delete', 'navigation', ref ] ); + dispatch.receiveUserPermission( + `delete/postType/wp_navigation/${ ref }`, + allowed + ); + dispatch.startResolution( 'canUser', [ + 'delete', + { ...BASE_ENTITY, id: ref }, + ] ); + dispatch.finishResolution( 'canUser', [ + 'delete', + { ...BASE_ENTITY, id: ref }, + ] ); } describe( 'useNavigationMenus', () => { diff --git a/packages/block-library/src/navigation/use-navigation-menu.js b/packages/block-library/src/navigation/use-navigation-menu.js index 3834661ed6101..5fd942c485bf8 100644 --- a/packages/block-library/src/navigation/use-navigation-menu.js +++ b/packages/block-library/src/navigation/use-navigation-menu.js @@ -14,7 +14,11 @@ import { useSelect } from '@wordpress/data'; import { PRELOADED_NAVIGATION_MENUS_QUERY } from './constants'; export default function useNavigationMenu( ref ) { - const permissions = useResourcePermissions( 'navigation', ref ); + const permissions = useResourcePermissions( { + kind: 'postType', + name: 'wp_navigation', + id: ref, + } ); const { navigationMenu, diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 2f2094bed7f4d..de28e4b86be4b 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -1173,7 +1173,10 @@ _Usage_ import { useResourcePermissions } from '@wordpress/core-data'; function PagesList() { - const { canCreate, isResolving } = useResourcePermissions( 'pages' ); + const { canCreate, isResolving } = useResourcePermissions( { + kind: 'postType', + name: 'page', + } ); if ( isResolving ) { return 'Loading ...'; @@ -1196,7 +1199,11 @@ import { useResourcePermissions } from '@wordpress/core-data'; function Page( { pageId } ) { const { canCreate, canUpdate, canDelete, isResolving } = - useResourcePermissions( 'pages', pageId ); + useResourcePermissions( { + kind: 'postType', + name: 'page', + id: pageId, + } ); if ( isResolving ) { return 'Loading ...'; @@ -1222,8 +1229,8 @@ the store state using `canUser()`, or resolved if missing. _Parameters_ -- _resource_ `string`: The resource in question, e.g. media. -- _id_ `IdType`: ID of a specific resource entry, if needed, e.g. 10. +- _resource_ `string | EntityResource`: Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }` or REST base as a string - `media`. +- _id_ `IdType`: Optional ID of the resource to check, e.g. 10. Note: This argument is discouraged when using an entity object as a resource to check permissions and will be ignored. _Returns_ diff --git a/packages/core-data/package.json b/packages/core-data/package.json index d94eb37528725..bed2ca97791bc 100644 --- a/packages/core-data/package.json +++ b/packages/core-data/package.json @@ -47,6 +47,7 @@ "@wordpress/sync": "file:../sync", "@wordpress/undo-manager": "file:../undo-manager", "@wordpress/url": "file:../url", + "@wordpress/warning": "file:../warning", "change-case": "^4.1.2", "equivalent-key-map": "^0.2.2", "fast-deep-equal": "^3.1.3", diff --git a/packages/core-data/src/hooks/test/use-resource-permissions.js b/packages/core-data/src/hooks/test/use-resource-permissions.js index bb6c3a85c191f..b1c43b7947874 100644 --- a/packages/core-data/src/hooks/test/use-resource-permissions.js +++ b/packages/core-data/src/hooks/test/use-resource-permissions.js @@ -93,4 +93,97 @@ describe( 'useResourcePermissions', () => { } ) ); } ); + + it( 'retrieves the relevant permissions for a id-less entity', async () => { + let data; + const TestComponent = () => { + data = useResourcePermissions( { + kind: 'root', + name: 'media', + } ); + return
; + }; + render( +