: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Returns an action object used in signalling that the current theme has been received.
* Ignored from documentation as it's internal to the data store.
* @param {Object} currentTheme The current theme.
* @return {Object} Action object.
function receiveCurrentTheme(currentTheme) {
type: 'RECEIVE_CURRENT_THEME',
* Returns an action object used in signalling that the current global styles id has been received.
* Ignored from documentation as it's internal to the data store.
* @param {string} currentGlobalStylesId The current global styles id.
* @return {Object} Action object.
function __experimentalReceiveCurrentGlobalStylesId(currentGlobalStylesId) {
type: 'RECEIVE_CURRENT_GLOBAL_STYLES_ID',
id: currentGlobalStylesId
* Returns an action object used in signalling that the theme base global styles have been received
* Ignored from documentation as it's internal to the data store.
* @param {string} stylesheet The theme's identifier
* @param {Object} globalStyles The global styles object.
* @return {Object} Action object.
function __experimentalReceiveThemeBaseGlobalStyles(stylesheet, globalStyles) {
type: 'RECEIVE_THEME_GLOBAL_STYLES',
* Returns an action object used in signalling that the theme global styles variations have been received.
* Ignored from documentation as it's internal to the data store.
* @param {string} stylesheet The theme's identifier
* @param {Array} variations The global styles variations.
* @return {Object} Action object.
function __experimentalReceiveThemeGlobalStyleVariations(stylesheet, variations) {
type: 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS',
* Returns an action object used in signalling that the index has been received.
* @deprecated since WP 5.9, this is not useful anymore, use the selector direclty.
* @return {Object} Action object.
function receiveThemeSupports() {
external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeSupports", {
* Returns an action object used in signalling that the theme global styles CPT post revisions have been received.
* Ignored from documentation as it's internal to the data store.
* @deprecated since WordPress 6.5.0. Callers should use `dispatch( 'core' ).receiveRevision` instead.
* @param {number} currentId The post id.
* @param {Array} revisions The global styles revisions.
* @return {Object} Action object.
function receiveThemeGlobalStyleRevisions(currentId, revisions) {
external_wp_deprecated_default()("wp.data.dispatch( 'core' ).receiveThemeGlobalStyleRevisions()", {
alternative: "wp.data.dispatch( 'core' ).receiveRevisions"
type: 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS',
* Returns an action object used in signalling that the preview data for
* a given URl has been received.
* Ignored from documentation as it's internal to the data store.
* @param {string} url URL to preview the embed for.
* @param {*} preview Preview data.
* @return {Object} Action object.
function receiveEmbedPreview(url, preview) {
type: 'RECEIVE_EMBED_PREVIEW',
* Action triggered to delete an entity record.
* @param {string} kind Kind of the deleted entity.
* @param {string} name Name of the deleted entity.
* @param {string} recordId Record ID of the deleted entity.
* @param {?Object} query Special query parameters for the
* @param {Object} [options] Delete options.
* @param {Function} [options.__unstableFetch] Internal use only. Function to
* call instead of `apiFetch()`.
* @param {boolean} [options.throwOnError=false] If false, this action suppresses all
* the exceptions. Defaults to false.
const deleteEntityRecord = (kind, name, recordId, query, {
__unstableFetch = (external_wp_apiFetch_default()),
const configs = await dispatch(getOrLoadEntitiesConfig(kind, name));
const entityConfig = configs.find(config => config.kind === kind && config.name === name);
let deletedRecord = false;
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId], {
type: 'DELETE_ENTITY_RECORD_START',
let path = `${entityConfig.baseURL}/${recordId}`;
path = (0,external_wp_url_namespaceObject.addQueryArgs)(path, query);
deletedRecord = await __unstableFetch({
await dispatch(removeItems(kind, name, recordId, true));
type: 'DELETE_ENTITY_RECORD_FINISH',
if (hasError && throwOnError) {
dispatch.__unstableReleaseStoreLock(lock);
* Returns an action object that triggers an
* edit to an entity record.
* @param {string} kind Kind of the edited entity record.
* @param {string} name Name of the edited entity record.
* @param {number|string} recordId Record ID of the edited entity record.
* @param {Object} edits The edits.
* @param {Object} options Options for the edit.
* @param {boolean} [options.undoIgnore] Whether to ignore the edit in undo history or not.
* @return {Object} Action object.
const editEntityRecord = (kind, name, recordId, edits, options = {}) => ({
const entityConfig = select.getEntityConfig(kind, name);
throw new Error(`The entity being edited (${kind}, ${name}) does not have a loaded config.`);
const record = select.getRawEntityRecord(kind, name, recordId);
const editedRecord = select.getEditedEntityRecord(kind, name, recordId);
// Clear edits when they are equal to their persisted counterparts
// so that the property is not considered dirty.
edits: Object.keys(edits).reduce((acc, key) => {
const recordValue = record[key];
const editedRecordValue = editedRecord[key];
const value = mergedEdits[key] ? {
acc[key] = es6_default()(recordValue, value) ? undefined : value;
if (window.__experimentalEnableSync && entityConfig.syncConfig) {
if (!options.undoIgnore) {
select.getUndoManager().addRecord([{
changes: Object.keys(edits).reduce((acc, key) => {
type: 'EDIT_ENTITY_RECORD',
* Action triggered to undo the last edit to
* an entity record, if any.
const undoRecord = select.getUndoManager().undo();
* Action triggered to redo the last undoed
* edit to an entity record, if any.
const redoRecord = select.getUndoManager().redo();
* Forces the creation of a new undo level.
* @return {Object} Action object.
const __unstableCreateUndoLevel = () => ({
select.getUndoManager().addRecord();
* Action triggered to save an entity record.
* @param {string} kind Kind of the received entity.
* @param {string} name Name of the received entity.
* @param {Object} record Record to be saved.
* @param {Object} options Saving options.
* @param {boolean} [options.isAutosave=false] Whether this is an autosave.
* @param {Function} [options.__unstableFetch] Internal use only. Function to
* call instead of `apiFetch()`.
* @param {boolean} [options.throwOnError=false] If false, this action suppresses all
* the exceptions. Defaults to false.
const saveEntityRecord = (kind, name, record, {
__unstableFetch = (external_wp_apiFetch_default()),
const configs = await dispatch(getOrLoadEntitiesConfig(kind, name));
const entityConfig = configs.find(config => config.kind === kind && config.name === name);
if (!entityConfig || entityConfig?.__experimentalNoFetch) {
const entityIdKey = entityConfig.key || DEFAULT_ENTITY_KEY;
const recordId = record[entityIdKey];
const lock = await dispatch.__unstableAcquireStoreLock(STORE_NAME, ['entities', 'records', kind, name, recordId || esm_browser_v4()], {
// Evaluate optimized edits.
// (Function edits that should be evaluated on save to avoid expensive computations on every edit.)
for (const [key, value] of Object.entries(record)) {
if (typeof value === 'function') {
const evaluatedValue = value(select.getEditedEntityRecord(kind, name, recordId));
dispatch.editEntityRecord(kind, name, recordId, {
record[key] = evaluatedValue;
type: 'SAVE_ENTITY_RECORD_START',
const path = `${entityConfig.baseURL}${recordId ? '/' + recordId : ''}`;
const persistedRecord = select.getRawEntityRecord(kind, name, recordId);
// Most of this autosave logic is very specific to posts.
// This is fine for now as it is the only supported autosave,
// but ideally this should all be handled in the back end,
// so the client just sends and receives objects.
const currentUser = select.getCurrentUser();
const currentUserId = currentUser ? currentUser.id : undefined;
const autosavePost = await resolveSelect.getAutosave(persistedRecord.type, persistedRecord.id, currentUserId);
// Autosaves need all expected fields to be present.
// So we fallback to the previous autosave and then
// to the actual persisted entity if the edits don't
data = Object.keys(data).reduce((acc, key) => {
if (['title', 'excerpt', 'content', 'meta'].includes(key)) {
// Do not update the `status` if we have edited it when auto saving.
// It's very important to let the user explicitly save this change,
// because it can lead to unexpected results. An example would be to
// have a draft post and change the status to publish.
status: data.status === 'auto-draft' ? 'draft' : undefined
updatedRecord = await __unstableFetch({
path: `${path}/autosaves`,
// An autosave may be processed by the server as a regular save
// when its update is requested by the author and the post had
// draft or auto-draft status.
if (persistedRecord.id === updatedRecord.id) {
newRecord = Object.keys(newRecord).reduce((acc, key) => {
// These properties are persisted in autosaves.
if (['title', 'excerpt', 'content'].includes(key)) {
acc[key] = newRecord[key];
} else if (key === 'status') {
// Status is only persisted in autosaves when going from
// "auto-draft" to "draft".
acc[key] = persistedRecord.status === 'auto-draft' && newRecord.status === 'draft' ? newRecord.status : persistedRecord.status;
// These properties are not persisted in autosaves.
acc[key] = persistedRecord[key];
dispatch.receiveEntityRecords(kind, name, newRecord, undefined, true);
dispatch.receiveAutosaves(persistedRecord.id, updatedRecord);
if (entityConfig.__unstablePrePersist) {
...entityConfig.__unstablePrePersist(persistedRecord, edits)
updatedRecord = await __unstableFetch({
method: recordId ? 'PUT' : 'POST',
dispatch.receiveEntityRecords(kind, name, updatedRecord, undefined, true, edits);
type: 'SAVE_ENTITY_RECORD_FINISH',
if (hasError && throwOnError) {
dispatch.__unstableReleaseStoreLock(lock);
* Runs multiple core-data actions at the same time using one API request.
* const [ savedRecord, updatedRecord, deletedRecord ] =
* await dispatch( 'core' ).__experimentalBatch( [
* ( { saveEntityRecord } ) => saveEntityRecord( 'root', 'widget', widget ),
* ( { saveEditedEntityRecord } ) => saveEntityRecord( 'root', 'widget', 123 ),
* ( { deleteEntityRecord } ) => deleteEntityRecord( 'root', 'widget', 123, null ),
* @param {Array} requests Array of functions which are invoked simultaneously.