close
Skip to content

Core Data: Allow entity overrides#71046

Open
heavyweight wants to merge 3 commits intoWordPress:trunkfrom
heavyweight:allow-entity-overrides
Open

Core Data: Allow entity overrides#71046
heavyweight wants to merge 3 commits intoWordPress:trunkfrom
heavyweight:allow-entity-overrides

Conversation

@heavyweight
Copy link
Copy Markdown
Contributor

What?

Closes

Modifies the entitiesConfig reducer to override existing entities when addEntities is called with entities that have the same baseURL as previously registered entities, instead of simply adding duplicates.

Why?

Consumers of the api might want to extend or override exiting entities.
Currently, calling addEntities with entities that have the same baseURL results in duplicate entries in the entities configuration. This change ensures that newer entity configurations properly replace older ones with the same baseURL.

How?

  • Iterates through existing entities to build lookup map
  • Removes conflicting entities from map when new entities have same baseURL
  • Combines remaining existing entities with new entities

Testing Instructions

  • Checkout this PR and run npm run dev
  • Open gutenberg demo
  • Get the current entity config by executing wp.data.select(wp.coreData.store).getEntitiesByKind('root')
  • Add an modified entity as a test:
wp.data.dispatch(wp.coreData.store).addEntities([{
		label: 'Updated User',
		name: 'user',
		kind: 'root',
		baseURL: '/wp/v2/users',
		baseURLParams: { context: 'edit' },
		plural: 'users',
}])
  • Execute again wp.data.select(wp.coreData.store).getEntitiesByKind('root')
  • The updated user entity should be there with the different label, instead of having one more element in the array.

Testing Instructions for Keyboard

Screenshots or screencast

Before After

@heavyweight heavyweight requested a review from nerrad as a code owner August 4, 2025 12:25
@github-actions
Copy link
Copy Markdown

github-actions bot commented Aug 4, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: heavyweight <kpapazov@git.wordpress.org>
Co-authored-by: talldan <talldanwp@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@heavyweight heavyweight force-pushed the allow-entity-overrides branch from 69b6d86 to 0d1a992 Compare August 4, 2025 12:54
@Mamaduka Mamaduka added [Package] Core data /packages/core-data [Type] Enhancement A suggestion for improvement. labels Aug 4, 2025
@Mamaduka Mamaduka changed the title Allow entity overrides Core Data: Allow entity overrides Aug 4, 2025
@Mamaduka
Copy link
Copy Markdown
Member

Mamaduka commented Aug 5, 2025

The failing end-to-end test seems to be related to this change, which could mean it's not working as expected.

General notes:

  • I would assume the entity "ID" would be kind+name combo instead of a baseURL.
  • If we decide to allow entity config updates. Maybe we should consider changing the state structure + introducing a separate action for updates. E.g., editEntityConfig.

cc @youknowriad, @talldan, @jsnajdr

@talldan
Copy link
Copy Markdown
Contributor

talldan commented Aug 5, 2025

I would assume the entity "ID" would be kind+name combo instead of a baseURL.

Agree.

Maybe we should consider changing the state structure + introducing a separate action for updates. E.g., editEntityConfig.

Or like the register / unregister APIs, it could be addEntities / removeEntities, but then maybe it's not a good idea to remove an entity temporarily.

Comment on lines +404 to +424
const existingEntitiesMap = new Map();

state.forEach( ( currentEntity ) => {
if ( currentEntity.baseURL ) {
existingEntitiesMap.set(
currentEntity.baseURL,
currentEntity
);
}
} );

action.entities.forEach( ( newEntity ) => {
if (
newEntity.baseURL &&
existingEntitiesMap.has( newEntity.baseURL )
) {
existingEntitiesMap.delete( newEntity.baseURL );
}
} );

const existingEntities = Array.from( existingEntitiesMap.values() );
Copy link
Copy Markdown
Contributor

@talldan talldan Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably simplify this by doing something like the following to remove any matching entities:

const existingEntities = state.filter( ( entity ) => ! action.entities.some( 
    ( newEntity ) => entity.baseURL === newEntity.baseURL )
) );

I haven't tested it, so I might have gotten some part wrong, but I think the general idea should work.

@heavyweight
Copy link
Copy Markdown
Contributor Author

Seems like the test were failing because the order was not preserved.
Preserving the order wasn't a big change from the previous one so I updated the code.
Basing the map key on kind + name instead of baseURL seems reasonable for me.

@jsnajdr
Copy link
Copy Markdown
Member

jsnajdr commented Aug 13, 2025

The current version of the patch checks if there is an existing entity with the same kind and name and then merely updates it instead of adding a new one. Sounds innocent.

The original intent with detecting identical baseURL seems to be completely gone by now.

What is the motivation for this patch? Does the previous behavior cause any trouble in Gutenberg or in a plugin?

@heavyweight
Copy link
Copy Markdown
Contributor Author

The current version of the patch checks if there is an existing entity with the same kind and name and then merely updates it instead of adding a new one. Sounds innocent.

The original intent with detecting identical baseURL seems to be completely gone by now.

What is the motivation for this patch? Does the previous behavior cause any trouble in Gutenberg or in a plugin?

Seems like the test errors were from the way we deprecate entities.
There is the root:media entity with base url '/wp/v2/media' but in the editor we have postType:attachment with the same base url.
To keep the same approach to deprecate entities we have to check against entity name and kind instead of baseURL.

@heavyweight heavyweight requested a review from talldan September 1, 2025 09:50
@heavyweight
Copy link
Copy Markdown
Contributor Author

@talldan, @Mamaduka or @jsnajdr can someone take a look at this again.
I think this is fine to merge now.

@Mamaduka
Copy link
Copy Markdown
Member

Mamaduka commented Sep 8, 2025

Thanks for the ping, @heavyweight! Adding this to my to-do list.

Do you mind rebasing the feature branch on top of the latest trunk? That should resolve stalled CI checks.

@Mamaduka Mamaduka self-requested a review September 8, 2025 09:29
@heavyweight heavyweight force-pushed the allow-entity-overrides branch from c6eb423 to 8c02f9b Compare September 8, 2025 11:07
@heavyweight
Copy link
Copy Markdown
Contributor Author

Rebased and everything looks good.

@Mamaduka
Copy link
Copy Markdown
Member

Mamaduka commented Sep 9, 2025

Thanks for the follow-ups, @heavyweight!

My main reservation with the proposal is that allowing addEntities to replace an entity can be unexpected. If someone accidentally uses the same kind|name for their custom provider, it can break the editor. Similar overrides can be hard to debug.

Usually, registration APIs warn developers if they try to use an existing namespace, while also providing methods to unregister existing ones.

@talldan and I already shared related notes above. Pinging more folks for visibility. cc @WordPress/gutenberg-core

P.S. Changing entityConfig store shape, so that it's keyed by unique kind|name should make things a bit easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Core data /packages/core-data [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants