Skip to content

Commit ca61287

Browse files
smithjw1claude
andcommitted
RTC: Auto-register custom taxonomy rest_base values for CRDT sync
Auto-register all taxonomy rest_base values for CRDT sync when taxonomy entities are loaded from the REST API. This means custom taxonomies with show_in_rest enabled automatically work with real-time collaboration without any plugin-side registration. Taxonomies returned by /wp/v2/taxonomies already have show_in_rest enabled, and the REST API enforces assign_terms capabilities on save. Closes WordPress#75875 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c4e4fac commit ca61287

3 files changed

Lines changed: 63 additions & 0 deletions

File tree

‎packages/core-data/src/entities.js‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
applyPostChangesToCRDTDoc,
2020
defaultSyncConfig,
2121
getPostChangesFromCRDTDoc,
22+
registerTaxonomyRestBases,
2223
} from './utils/crdt';
2324

2425
export const DEFAULT_ENTITY_KEY = 'id';
@@ -417,6 +418,13 @@ async function loadTaxonomyEntities() {
417418
const taxonomies = await apiFetch( {
418419
path: '/wp/v2/taxonomies?context=view',
419420
} );
421+
422+
// Auto-register all taxonomy rest_base values for CRDT sync.
423+
const restBases = Object.values( taxonomies ?? {} )
424+
.map( ( taxonomy ) => taxonomy.rest_base )
425+
.filter( Boolean );
426+
registerTaxonomyRestBases( restBases );
427+
420428
return Object.entries( taxonomies ?? {} ).map( ( [ name, taxonomy ] ) => {
421429
const namespace = taxonomy?.rest_namespace ?? 'wp/v2';
422430
const entity = {

‎packages/core-data/src/utils/crdt.ts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ const allowedPostProperties = new Set< string >( [
9595
'title',
9696
] );
9797

98+
/**
99+
* Register taxonomy rest_base values as allowed post properties for CRDT sync.
100+
* Called during entity loading when taxonomies are fetched from the REST API.
101+
*
102+
* @param {string[]} restBases Array of taxonomy rest_base values to allow.
103+
*/
104+
export function registerTaxonomyRestBases( restBases: string[] ): void {
105+
for ( const restBase of restBases ) {
106+
allowedPostProperties.add( restBase );
107+
}
108+
}
109+
98110
// Post meta keys that should *not* be synced.
99111
const disallowedPostMetaKeys = new Set< string >( [
100112
WORDPRESS_META_KEY_FOR_CRDT_DOC_PERSISTENCE,

‎packages/core-data/src/utils/test/crdt.ts‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import {
1919
applyPostChangesToCRDTDoc,
2020
getPostChangesFromCRDTDoc,
21+
registerTaxonomyRestBases,
2122
type PostChanges,
2223
type YPostRecord,
2324
} from '../crdt';
@@ -630,4 +631,46 @@ describe( 'crdt', () => {
630631
);
631632
} );
632633
} );
634+
635+
describe( 'registerTaxonomyRestBases', () => {
636+
const mockPostType = {} as Type;
637+
638+
let map: YMapWrap< YPostRecord >;
639+
640+
beforeEach( () => {
641+
map = getRootMap< YPostRecord >( doc, CRDT_RECORD_MAP_KEY );
642+
} );
643+
644+
it( 'allows dynamically registered taxonomy properties to be synced', () => {
645+
registerTaxonomyRestBases( [ 'genres' ] );
646+
647+
const changes = {
648+
genres: [ 10, 15 ],
649+
} as unknown as PostChanges;
650+
651+
applyPostChangesToCRDTDoc( doc, changes, mockPostType );
652+
653+
expect( map.get( 'genres' ) ).toEqual( [ 10, 15 ] );
654+
} );
655+
656+
it( 'allows dynamically registered taxonomy properties to be read from CRDT', () => {
657+
registerTaxonomyRestBases( [ 'genres' ] );
658+
659+
map.set( 'genres' as keyof YPostRecord, [ 10, 15 ] );
660+
661+
const editedRecord = {
662+
genres: [ 10 ],
663+
} as unknown as Post;
664+
665+
const changes = getPostChangesFromCRDTDoc(
666+
doc,
667+
editedRecord,
668+
mockPostType
669+
);
670+
671+
expect( ( changes as Record< string, unknown > ).genres ).toEqual( [
672+
10, 15,
673+
] );
674+
} );
675+
} );
633676
} );

0 commit comments

Comments
 (0)