Skip to content

Commit

Permalink
Core Data: Add new useEntityRecordsWithPermissions hook (#63857)
Browse files Browse the repository at this point in the history
Co-authored-by: youknowriad <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: ellatrix <[email protected]>
Co-authored-by: jorgefilipecosta <[email protected]>
  • Loading branch information
5 people authored Jul 26, 2024
1 parent 654fef6 commit 1e28ca4
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { unlock } from '../private-apis';
import { unlock } from '../lock-unlock';

// TODO: The following line should have been:
//
Expand Down
50 changes: 50 additions & 0 deletions packages/core-data/src/hooks/use-entity-records.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { addQueryArgs } from '@wordpress/url';
import deprecated from '@wordpress/deprecated';
import { useSelect } from '@wordpress/data';
import { useMemo } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -12,6 +13,7 @@ import useQuerySelect from './use-query-select';
import { store as coreStore } from '../';
import type { Options } from './use-entity-record';
import type { Status } from './constants';
import { unlock } from '../lock-unlock';

interface EntityRecordsResolution< RecordType > {
/** The requested entity record */
Expand Down Expand Up @@ -152,3 +154,51 @@ export function __experimentalUseEntityRecords(
} );
return useEntityRecords( kind, name, queryArgs, options );
}

export function useEntityRecordsWithPermissions< RecordType >(
kind: string,
name: string,
queryArgs: Record< string, unknown > = {},
options: Options = { enabled: true }
): EntityRecordsResolution< RecordType > {
const entityConfig = useSelect(
( select ) => select( coreStore ).getEntityConfig( kind, name ),
[ kind, name ]
);
const { records: data, ...ret } = useEntityRecords(
kind,
name,
queryArgs,
options
);
const ids = useMemo(
() =>
data?.map(
// @ts-ignore
( record: RecordType ) => record[ entityConfig?.key ?? 'id' ]
) ?? [],
[ data, entityConfig?.key ]
);

const permissions = useSelect(
( select ) => {
const { getEntityRecordsPermissions } = unlock(
select( coreStore )
);
return getEntityRecordsPermissions( kind, name, ids );
},
[ ids, kind, name ]
);

const dataWithPermissions = useMemo(
() =>
data?.map( ( record, index ) => ( {
// @ts-ignore
...record,
permissions: permissions[ index ],
} ) ) ?? [],
[ data, permissions ]
);

return { records: dataWithPermissions, ...ret };
}
3 changes: 2 additions & 1 deletion packages/core-data/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
getMethodName,
} from './entities';
import { STORE_NAME } from './name';
import { unlock } from './private-apis';
import { unlock } from './lock-unlock';

// The entity selectors/resolvers and actions are shortcuts to their generic equivalents
// (getEntityRecord, getEntityRecords, updateEntityRecord, updateEntityRecords)
Expand Down Expand Up @@ -86,3 +86,4 @@ export * from './entity-provider';
export * from './entity-types';
export * from './fetch';
export * from './hooks';
export * from './private-apis';
10 changes: 10 additions & 0 deletions packages/core-data/src/lock-unlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* WordPress dependencies
*/
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';

export const { lock, unlock } =
__dangerousOptInToUnstableAPIsOnlyForCoreModules(
'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
'@wordpress/core-data'
);
14 changes: 7 additions & 7 deletions packages/core-data/src/private-apis.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* WordPress dependencies
* Internal dependencies
*/
import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis';
import { useEntityRecordsWithPermissions } from './hooks/use-entity-records';
import { lock } from './lock-unlock';

export const { lock, unlock } =
__dangerousOptInToUnstableAPIsOnlyForCoreModules(
'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.',
'@wordpress/core-data'
);
export const privateApis = {};
lock( privateApis, {
useEntityRecordsWithPermissions,
} );
23 changes: 23 additions & 0 deletions packages/core-data/src/private-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,26 @@ export const getBlockPatternsForPostType = createRegistrySelector(
() => [ select( STORE_NAME ).getBlockPatterns() ]
)
);

/**
* Returns the entity records permissions for the given entity record ids.
*/
export const getEntityRecordsPermissions = createRegistrySelector( ( select ) =>
createSelector(
( state: State, kind: string, name: string, ids: string[] ) => {
return ids.map( ( id ) => ( {
delete: select( STORE_NAME ).canUser( 'delete', {
kind,
name,
id,
} ),
update: select( STORE_NAME ).canUser( 'update', {
kind,
name,
id,
} ),
} ) );
},
( state ) => [ state.userPermissions ]
)
);
8 changes: 6 additions & 2 deletions packages/edit-site/src/components/post-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import { useEntityRecords, store as coreStore } from '@wordpress/core-data';
import {
store as coreStore,
privateApis as coreDataPrivateApis,
} from '@wordpress/core-data';
import { useState, useMemo, useCallback, useEffect } from '@wordpress/element';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useSelect, useDispatch } from '@wordpress/data';
Expand Down Expand Up @@ -33,6 +36,7 @@ import usePostFields from '../post-fields';

const { usePostActions } = unlock( editorPrivateApis );
const { useLocation, useHistory } = unlock( routerPrivateApis );
const { useEntityRecordsWithPermissions } = unlock( coreDataPrivateApis );
const EMPTY_ARRAY = [];

function useView( postType ) {
Expand Down Expand Up @@ -199,7 +203,7 @@ export default function PostList( { postType } ) {
isResolving: isLoadingMainEntities,
totalItems,
totalPages,
} = useEntityRecords( 'postType', postType, queryArgs );
} = useEntityRecordsWithPermissions( 'postType', postType, queryArgs );

const ids = records?.map( ( record ) => getItemId( record ) ) ?? [];
const prevIds = usePrevious( ids ) ?? [];
Expand Down

0 comments on commit 1e28ca4

Please sign in to comment.