diff --git a/packages/core-data/README.md b/packages/core-data/README.md
index 8c262ebeee8d19..f30a620c4a31ca 100644
--- a/packages/core-data/README.md
+++ b/packages/core-data/README.md
@@ -1132,7 +1132,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 ...';
@@ -1155,7 +1158,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 ...';
@@ -1181,8 +1188,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 rest resource to check. e.g. 10.
_Returns_
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 bb6c3a85c191f6..1ef35cab3353c9 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,75 @@ 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(
+
+
+
+ );
+ expect( data ).toEqual( {
+ status: 'IDLE',
+ isResolving: false,
+ hasResolved: false,
+ canCreate: false,
+ canRead: false,
+ } );
+
+ await waitFor( () =>
+ expect( data ).toEqual( {
+ status: 'SUCCESS',
+ isResolving: false,
+ hasResolved: true,
+ canCreate: true,
+ canRead: false,
+ } )
+ );
+ } );
+
+ it( 'retrieves the relevant permissions for an entity', async () => {
+ let data;
+ const TestComponent = () => {
+ data = useResourcePermissions( {
+ kind: 'root',
+ name: 'media',
+ id: 1,
+ } );
+ return ;
+ };
+ render(
+
+
+
+ );
+ expect( data ).toEqual( {
+ status: 'IDLE',
+ isResolving: false,
+ hasResolved: false,
+ canCreate: false,
+ canRead: false,
+ canUpdate: false,
+ canDelete: false,
+ } );
+
+ await waitFor( () =>
+ expect( data ).toEqual( {
+ status: 'SUCCESS',
+ isResolving: false,
+ hasResolved: true,
+ canCreate: true,
+ canRead: false,
+ canUpdate: false,
+ canDelete: false,
+ } )
+ );
+ } );
} );
diff --git a/packages/core-data/src/hooks/use-resource-permissions.ts b/packages/core-data/src/hooks/use-resource-permissions.ts
index 7da7189e2e5067..1f97ed5b45aa5e 100644
--- a/packages/core-data/src/hooks/use-resource-permissions.ts
+++ b/packages/core-data/src/hooks/use-resource-permissions.ts
@@ -2,6 +2,7 @@
* WordPress dependencies
*/
import deprecated from '@wordpress/deprecated';
+import { addQueryArgs } from '@wordpress/url';
/**
* Internal dependencies
@@ -41,20 +42,23 @@ type ResourcePermissionsResolution< IdType > = [
( IdType extends void ? SpecificResourcePermissionsResolution : {} ),
];
+type EntityResource = { kind: string; name: string; id?: string | number };
+
/**
* Resolves resource permissions.
*
* @since 6.1.0 Introduced in WordPress core.
*
- * @param resource The resource in question, e.g. media.
- * @param id ID of a specific resource entry, if needed, e.g. 10.
+ * @param resource Entity resource to check. Accepts entity object `{ kind: 'root', name: 'media', id: 1 }`
+ * or REST base as a string - `media`.
+ * @param id Optional ID of the rest resource to check. e.g. 10.
*
* @example
* ```js
* 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 ...';
@@ -82,7 +86,7 @@ type ResourcePermissionsResolution< IdType > = [
* canUpdate,
* canDelete,
* isResolving
- * } = useResourcePermissions( 'pages', pageId );
+ * } = useResourcePermissions( { kind: 'postType', name: 'page', id: pageId } );
*
* if ( isResolving ) {
* return 'Loading ...';
@@ -110,14 +114,23 @@ type ResourcePermissionsResolution< IdType > = [
* @template IdType
*/
export default function useResourcePermissions< IdType = void >(
- resource: string,
+ resource: string | EntityResource,
id?: IdType
): ResourcePermissionsResolution< IdType > {
+ // Serialize `resource` to a string that can be safely used as a React dep.
+ // We can't just pass `resource` as one of the deps, because if it is passed
+ // as an object literal, then it will be a different object on each call even
+ // if the values remain the same.
+ const resourceAsString =
+ typeof resource === 'object' ? addQueryArgs( '', resource ) : resource;
+
return useQuerySelect(
( resolve ) => {
const { canUser } = resolve( coreStore );
const create = canUser( 'create', resource );
- if ( ! id ) {
+
+ const hasId = typeof resource === 'object' ? !! resource.id : !! id;
+ if ( ! hasId ) {
const read = canUser( 'read', resource );
const isResolving = create.isResolving || read.isResolving;
@@ -168,7 +181,7 @@ export default function useResourcePermissions< IdType = void >(
canDelete: hasResolved && _delete.data,
};
},
- [ resource, id ]
+ [ resourceAsString, id ]
);
}