: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @param {Object} action Dispatched action.
* @return {Object<string,Object<string,boolean>>} Next state.
function itemIsComplete(state = {}, action) {
const context = getContextFromAction(action);
// An item is considered complete if it is received without an associated
// fields query. Ideally, this would be implemented in such a way where the
// complete aggregate of all fields would satisfy completeness. Since the
// fields are not consistent across all entities, this would require
// introspection on the REST schema for each entity to know which fields
// compose a complete item for that entity.
const queryParts = query ? get_query_parts(query) : {};
const isCompleteQuery = !query || !Array.isArray(queryParts.fields);
...action.items.reduce((result, item) => {
const itemId = item?.[key];
// Defer to completeness if already assigned. Technically the
// data may be outdated if receiving items for a field subset.
result[itemId] = state?.[context]?.[itemId] || isCompleteQuery;
return Object.fromEntries(Object.entries(state).map(([itemId, contextState]) => [itemId, removeEntitiesById(contextState, action.itemIds)]));
* Reducer tracking queries state, keyed by stable query key. Each reducer
* query object includes `itemIds` and `requestingPageByPerPage`.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Next state.
const receiveQueries = (0,external_wp_compose_namespaceObject.compose)([
// Limit to matching action type so we don't attempt to replace action on
if_matching_action(action => 'query' in action),
// Inject query parts into action for use both in `onSubKey` and reducer.
replace_action(action => {
// `ifMatchingAction` still passes on initialization, where state is
// undefined and a query is not assigned. Avoid attempting to parse
// parts. `onSubKey` will omit by lack of `stableKey`.
...get_query_parts(action.query)
}), on_sub_key('context'),
// Queries shape is shared, but keyed by query `stableKey` part. Original
// reducer tracks only a single query object.
on_sub_key('stableKey')])((state = {}, action) => {
if (type !== 'RECEIVE_ITEMS') {
itemIds: getMergedItemIds(state?.itemIds || [], action.items.map(item => item?.[key]).filter(Boolean), page, perPage),
* Reducer tracking queries state.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Next state.
const queries = (state = {}, action) => {
return receiveQueries(state, action);
const removedItems = action.itemIds.reduce((result, itemId) => {
return Object.fromEntries(Object.entries(state).map(([queryGroup, contextQueries]) => [queryGroup, Object.fromEntries(Object.entries(contextQueries).map(([query, queryItems]) => [query, {
itemIds: queryItems.itemIds.filter(queryId => !removedItems[queryId])
/* harmony default export */ const reducer = ((0,external_wp_data_namespaceObject.combineReducers)({
;// CONCATENATED MODULE: ./node_modules/@wordpress/core-data/build-module/reducer.js
/** @typedef {import('./types').AnyFunction} AnyFunction */
* Reducer managing terms state. Keyed by taxonomy slug, the value is either
* undefined (if no request has been made for given taxonomy), null (if a
* request is in-flight for given taxonomy), or the array of terms for the
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
function terms(state = {}, action) {
[action.taxonomy]: action.terms
* Reducer managing authors state. Keyed by id.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
case 'RECEIVE_USER_QUERY':
// Key users by their ID.
...action.users.reduce((newUsers, user) => ({
[action.queryID]: action.users.map(user => user.id)
* Reducer managing current user state.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
function currentUser(state = {}, action) {
case 'RECEIVE_CURRENT_USER':
return action.currentUser;
* Reducer managing taxonomies.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
function taxonomies(state = [], action) {
case 'RECEIVE_TAXONOMIES':
return action.taxonomies;
* Reducer managing the current theme.
* @param {string|undefined} state Current state.
* @param {Object} action Dispatched action.
* @return {string|undefined} Updated state.
function currentTheme(state = undefined, action) {
case 'RECEIVE_CURRENT_THEME':
return action.currentTheme.stylesheet;
* Reducer managing the current global styles id.
* @param {string|undefined} state Current state.
* @param {Object} action Dispatched action.
* @return {string|undefined} Updated state.
function currentGlobalStylesId(state = undefined, action) {
case 'RECEIVE_CURRENT_GLOBAL_STYLES_ID':
* Reducer managing the theme base global styles.
* @param {Record<string, object>} state Current state.
* @param {Object} action Dispatched action.
* @return {Record<string, object>} Updated state.
function themeBaseGlobalStyles(state = {}, action) {
case 'RECEIVE_THEME_GLOBAL_STYLES':
[action.stylesheet]: action.globalStyles
* Reducer managing the theme global styles variations.
* @param {Record<string, object>} state Current state.
* @param {Object} action Dispatched action.
* @return {Record<string, object>} Updated state.
function themeGlobalStyleVariations(state = {}, action) {
case 'RECEIVE_THEME_GLOBAL_STYLE_VARIATIONS':
[action.stylesheet]: action.variations
const withMultiEntityRecordEdits = reducer => (state, action) => {
if (action.type === 'UNDO' || action.type === 'REDO') {
newState = reducer(newState, {
type: 'EDIT_ENTITY_RECORD',
edits: Object.entries(changes).reduce((acc, [key, value]) => {
acc[key] = action.type === 'UNDO' ? value.from : value.to;
return reducer(state, action);
* Higher Order Reducer for a given entity config. It supports:
* @param {Object} entityConfig Entity config.
* @return {AnyFunction} Reducer.
function entity(entityConfig) {
return (0,external_wp_compose_namespaceObject.compose)([withMultiEntityRecordEdits,
// Limit to matching action type so we don't attempt to replace action on
if_matching_action(action => action.name && action.kind && action.name === entityConfig.name && action.kind === entityConfig.kind),
// Inject the entity config into the action.
replace_action(action => {
key: entityConfig.key || DEFAULT_ENTITY_KEY,
})])((0,external_wp_data_namespaceObject.combineReducers)({
edits: (state = {}, action) => {
var _action$query$context;
const context = (_action$query$context = action?.query?.context) !== null && _action$query$context !== void 0 ? _action$query$context : 'default';
if (context !== 'default') {
for (const record of action.items) {
const recordId = record?.[action.key];
const edits = nextState[recordId];
const nextEdits = Object.keys(edits).reduce((acc, key) => {
// If the edited value is still different to the persisted value,
// keep the edited value in edits.
// Edits are the "raw" attribute values, but records may have
// objects with more properties, so we use `get` here for the
!es6_default()(edits[key], (_record$key$raw = record[key]?.raw) !== null && _record$key$raw !== void 0 ? _record$key$raw : record[key]) && (
// Sometimes the server alters the sent value which means
// we need to also remove the edits before the api request.
!action.persistedEdits || !es6_default()(edits[key], action.persistedEdits[key]))) {
if (Object.keys(nextEdits).length) {
nextState[recordId] = nextEdits;
delete nextState[recordId];
case 'EDIT_ENTITY_RECORD':
...state[action.recordId],
Object.keys(nextEdits).forEach(key => {
// Delete cleared edits so that the properties
// are not considered dirty.
if (nextEdits[key] === undefined) {
[action.recordId]: nextEdits
saving: (state = {}, action) => {
case 'SAVE_ENTITY_RECORD_START':
case 'SAVE_ENTITY_RECORD_FINISH':
pending: action.type === 'SAVE_ENTITY_RECORD_START',
isAutosave: action.isAutosave
deleting: (state = {}, action) => {
case 'DELETE_ENTITY_RECORD_START':
case 'DELETE_ENTITY_RECORD_FINISH':
pending: action.type === 'DELETE_ENTITY_RECORD_START',
revisions: (state = {}, action) => {
// Use the same queriedDataReducer shape for revisions.
if (action.type === 'RECEIVE_ITEM_REVISIONS') {
const recordKey = action.recordKey;
const newState = reducer(state[recordKey], {
if (action.type === 'REMOVE_ITEMS') {
return Object.fromEntries(Object.entries(state).filter(([id]) => !action.itemIds.some(itemId => {
if (Number.isInteger(itemId)) {
* Reducer keeping track of the registered entities.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
function entitiesConfig(state = rootEntitiesConfig, action) {
return [...state, ...action.entities];
* Reducer keeping track of the registered entities config and data.
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
* @return {Object} Updated state.
const entities = (state = {}, action) => {
const newConfig = entitiesConfig(state.config, action);
// Generates a dynamic reducer for the entities.
let entitiesDataReducer = state.reducer;
if (!entitiesDataReducer || newConfig !== state.config) {
const entitiesByKind = newConfig.reduce((acc, record) => {