@wordpress/core-data
Version:
Access to and manipulation of core WordPress entities.
1,185 lines (1,119 loc) • 42.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__experimentalGetCurrentGlobalStylesId = __experimentalGetCurrentGlobalStylesId;
exports.__experimentalGetCurrentThemeBaseGlobalStyles = __experimentalGetCurrentThemeBaseGlobalStyles;
exports.__experimentalGetCurrentThemeGlobalStylesVariations = __experimentalGetCurrentThemeGlobalStylesVariations;
exports.__experimentalGetEntitiesBeingSaved = exports.__experimentalGetDirtyEntityRecords = void 0;
exports.__experimentalGetEntityRecordNoResolver = __experimentalGetEntityRecordNoResolver;
exports.canUser = canUser;
exports.canUserEditEntityRecord = canUserEditEntityRecord;
exports.getAuthors = getAuthors;
exports.getAutosave = getAutosave;
exports.getAutosaves = getAutosaves;
exports.getBlockPatternCategories = getBlockPatternCategories;
exports.getBlockPatterns = getBlockPatterns;
exports.getCurrentTheme = getCurrentTheme;
exports.getCurrentThemeGlobalStylesRevisions = getCurrentThemeGlobalStylesRevisions;
exports.getCurrentUser = getCurrentUser;
exports.getDefaultTemplateId = getDefaultTemplateId;
exports.getEditedEntityRecord = void 0;
exports.getEmbedPreview = getEmbedPreview;
exports.getEntitiesByKind = getEntitiesByKind;
exports.getEntitiesConfig = void 0;
exports.getEntity = getEntity;
exports.getEntityConfig = getEntityConfig;
exports.getEntityRecord = void 0;
exports.getEntityRecordEdits = getEntityRecordEdits;
exports.getEntityRecordsTotalPages = exports.getEntityRecordsTotalItems = exports.getEntityRecords = exports.getEntityRecordNonTransientEdits = void 0;
exports.getLastEntityDeleteError = getLastEntityDeleteError;
exports.getLastEntitySaveError = getLastEntitySaveError;
exports.getRawEntityRecord = void 0;
exports.getRedoEdit = getRedoEdit;
exports.getReferenceByDistinctEdits = getReferenceByDistinctEdits;
exports.getRevisions = exports.getRevision = void 0;
exports.getThemeSupports = getThemeSupports;
exports.getUndoEdit = getUndoEdit;
exports.getUserPatternCategories = getUserPatternCategories;
exports.getUserQueryResults = void 0;
exports.hasEditsForEntityRecord = hasEditsForEntityRecord;
exports.hasEntityRecord = hasEntityRecord;
exports.hasEntityRecords = hasEntityRecords;
exports.hasFetchedAutosaves = void 0;
exports.hasRedo = hasRedo;
exports.hasUndo = hasUndo;
exports.isAutosavingEntityRecord = isAutosavingEntityRecord;
exports.isDeletingEntityRecord = isDeletingEntityRecord;
exports.isPreviewEmbedFallback = isPreviewEmbedFallback;
exports.isRequestingEmbedPreview = void 0;
exports.isSavingEntityRecord = isSavingEntityRecord;
var _data = require("@wordpress/data");
var _url = require("@wordpress/url");
var _deprecated = _interopRequireDefault(require("@wordpress/deprecated"));
var _name = require("./name");
var _queriedData = require("./queried-data");
var _entities = require("./entities");
var _utils = require("./utils");
var _logEntityDeprecation = _interopRequireDefault(require("./utils/log-entity-deprecation"));
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
// This is an incomplete, high-level approximation of the State type.
// It makes the selectors slightly more safe, but is intended to evolve
// into a more detailed representation over time.
// See https://github.com/WordPress/gutenberg/pull/40025#discussion_r865410589 for more context.
/**
* HTTP Query parameters sent with the API request to fetch the entity records.
*/
/**
* Arguments for EntityRecord selectors.
*/
/**
* Shared reference to an empty object for cases where it is important to avoid
* returning a new object reference on every invocation, as in a connected or
* other pure component which performs `shouldComponentUpdate` check on props.
* This should be used as a last resort, since the normalized data should be
* maintained by the reducer result in state.
*/
const EMPTY_OBJECT = {};
/**
* Returns true if a request is in progress for embed preview data, or false
* otherwise.
*
* @param state Data state.
* @param url URL the preview would be for.
*
* @return Whether a request is in progress for an embed preview.
*/
const isRequestingEmbedPreview = exports.isRequestingEmbedPreview = (0, _data.createRegistrySelector)(select => (state, url) => {
return select(_name.STORE_NAME).isResolving('getEmbedPreview', [url]);
});
/**
* Returns all available authors.
*
* @deprecated since 11.3. Callers should use `select( 'core' ).getUsers({ who: 'authors' })` instead.
*
* @param state Data state.
* @param query Optional object of query parameters to
* include with request. For valid query parameters see the [Users page](https://developer.wordpress.org/rest-api/reference/users/) in the REST API Handbook and see the arguments for [List Users](https://developer.wordpress.org/rest-api/reference/users/#list-users) and [Retrieve a User](https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user).
* @return Authors list.
*/
function getAuthors(state, query) {
(0, _deprecated.default)("select( 'core' ).getAuthors()", {
since: '5.9',
alternative: "select( 'core' ).getUsers({ who: 'authors' })"
});
const path = (0, _url.addQueryArgs)('/wp/v2/users/?who=authors&per_page=100', query);
return getUserQueryResults(state, path);
}
/**
* Returns the current user.
*
* @param state Data state.
*
* @return Current user object.
*/
function getCurrentUser(state) {
return state.currentUser;
}
/**
* Returns all the users returned by a query ID.
*
* @param state Data state.
* @param queryID Query ID.
*
* @return Users list.
*/
const getUserQueryResults = exports.getUserQueryResults = (0, _data.createSelector)((state, queryID) => {
var _state$users$queries$;
const queryResults = (_state$users$queries$ = state.users.queries[queryID]) !== null && _state$users$queries$ !== void 0 ? _state$users$queries$ : [];
return queryResults.map(id => state.users.byId[id]);
}, (state, queryID) => [state.users.queries[queryID], state.users.byId]);
/**
* Returns the loaded entities for the given kind.
*
* @deprecated since WordPress 6.0. Use getEntitiesConfig instead
* @param state Data state.
* @param kind Entity kind.
*
* @return Array of entities with config matching kind.
*/
function getEntitiesByKind(state, kind) {
(0, _deprecated.default)("wp.data.select( 'core' ).getEntitiesByKind()", {
since: '6.0',
alternative: "wp.data.select( 'core' ).getEntitiesConfig()"
});
return getEntitiesConfig(state, kind);
}
/**
* Returns the loaded entities for the given kind.
*
* @param state Data state.
* @param kind Entity kind.
*
* @return Array of entities with config matching kind.
*/
const getEntitiesConfig = exports.getEntitiesConfig = (0, _data.createSelector)((state, kind) => state.entities.config.filter(entity => entity.kind === kind), /* eslint-disable @typescript-eslint/no-unused-vars */
(state, kind) => state.entities.config
/* eslint-enable @typescript-eslint/no-unused-vars */);
/**
* Returns the entity config given its kind and name.
*
* @deprecated since WordPress 6.0. Use getEntityConfig instead
* @param state Data state.
* @param kind Entity kind.
* @param name Entity name.
*
* @return Entity config
*/
function getEntity(state, kind, name) {
(0, _deprecated.default)("wp.data.select( 'core' ).getEntity()", {
since: '6.0',
alternative: "wp.data.select( 'core' ).getEntityConfig()"
});
return getEntityConfig(state, kind, name);
}
/**
* Returns the entity config given its kind and name.
*
* @param state Data state.
* @param kind Entity kind.
* @param name Entity name.
*
* @return Entity config
*/
function getEntityConfig(state, kind, name) {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityConfig');
return state.entities.config?.find(config => config.kind === kind && config.name === name);
}
/**
* GetEntityRecord is declared as a *callable interface* with
* two signatures to work around the fact that TypeScript doesn't
* allow currying generic functions:
*
* ```ts
* type CurriedState = F extends ( state: any, ...args: infer P ) => infer R
* ? ( ...args: P ) => R
* : F;
* type Selector = <K extends string | number>(
* state: any,
* kind: K,
* key: K extends string ? 'string value' : false
* ) => K;
* type BadlyInferredSignature = CurriedState< Selector >
* // BadlyInferredSignature evaluates to:
* // (kind: string number, key: false | "string value") => string number
* ```
*
* The signature without the state parameter shipped as CurriedSignature
* is used in the return value of `select( coreStore )`.
*
* See https://github.com/WordPress/gutenberg/pull/41578 for more details.
*/
/**
* Returns the Entity's record object by key. Returns `null` if the value is not
* yet received, undefined if the value entity is known to not exist, or the
* entity object if it exists and is received.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param key Optional record's key. If requesting a global record (e.g. site settings), the key can be omitted. If requesting a specific item, the key must always be included.
* @param query Optional query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available "Retrieve a [Entity kind]".
*
* @return Record.
*/
const getEntityRecord = exports.getEntityRecord = (0, _data.createSelector)((state, kind, name, key, query) => {
var _query$context, _getNormalizedCommaSe;
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecord');
// For back-compat, we allow querying for static templates through
// wp_template.
if (kind === 'postType' && name === 'wp_template' && typeof key === 'string' &&
// __experimentalGetDirtyEntityRecords always calls getEntityRecord
// with a string key, so we need that it's not a numeric ID.
!/^\d+$/.test(key)) {
name = 'wp_registered_template';
}
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
if (!queriedState) {
return undefined;
}
const context = (_query$context = query?.context) !== null && _query$context !== void 0 ? _query$context : 'default';
if (!query || !query._fields) {
// If expecting a complete item, validate that completeness.
if (!queriedState.itemIsComplete[context]?.[key]) {
return undefined;
}
return queriedState.items[context][key];
}
const item = queriedState.items[context]?.[key];
if (!item) {
return item;
}
const filteredItem = {};
const fields = (_getNormalizedCommaSe = (0, _utils.getNormalizedCommaSeparable)(query._fields)) !== null && _getNormalizedCommaSe !== void 0 ? _getNormalizedCommaSe : [];
for (let f = 0; f < fields.length; f++) {
const field = fields[f].split('.');
let value = item;
field.forEach(fieldName => {
value = value?.[fieldName];
});
(0, _utils.setNestedValue)(filteredItem, field, value);
}
return filteredItem;
}, (state, kind, name, recordId, query) => {
var _query$context2;
const context = (_query$context2 = query?.context) !== null && _query$context2 !== void 0 ? _query$context2 : 'default';
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
return [queriedState?.items[context]?.[recordId], queriedState?.itemIsComplete[context]?.[recordId]];
});
/**
* Normalizes `recordKey`s that look like numeric IDs to numbers.
*
* @param args EntityRecordArgs the selector arguments.
* @return EntityRecordArgs the normalized arguments.
*/
getEntityRecord.__unstableNormalizeArgs = args => {
const newArgs = [...args];
const recordKey = newArgs?.[2];
// If recordKey looks to be a numeric ID then coerce to number.
newArgs[2] = (0, _utils.isNumericID)(recordKey) ? Number(recordKey) : recordKey;
return newArgs;
};
/**
* Returns true if a record has been received for the given set of parameters, or false otherwise.
*
* Note: This action does not trigger a request for the entity record from the API
* if it's not available in the local state.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param key Record's key.
* @param query Optional query.
*
* @return Whether an entity record has been received.
*/
function hasEntityRecord(state, kind, name, key, query) {
var _query$context3, _getNormalizedCommaSe2;
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
if (!queriedState) {
return false;
}
const context = (_query$context3 = query?.context) !== null && _query$context3 !== void 0 ? _query$context3 : 'default';
// If expecting a complete item, validate that completeness.
if (!query || !query._fields) {
return !!queriedState.itemIsComplete[context]?.[key];
}
const item = queriedState.items[context]?.[key];
if (!item) {
return false;
}
// When `query._fields` is provided, check that each requested field exists,
// including any nested paths, on the item; return false if any part is missing.
const fields = (_getNormalizedCommaSe2 = (0, _utils.getNormalizedCommaSeparable)(query._fields)) !== null && _getNormalizedCommaSe2 !== void 0 ? _getNormalizedCommaSe2 : [];
for (let i = 0; i < fields.length; i++) {
const path = fields[i].split('.');
let value = item;
for (let p = 0; p < path.length; p++) {
const part = path[p];
if (!value || !Object.hasOwn(value, part)) {
return false;
}
value = value[part];
}
}
return true;
}
/**
* Returns the Entity's record object by key. Doesn't trigger a resolver nor requests the entity records from the API if the entity record isn't available in the local state.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param key Record's key
*
* @return Record.
*/
function __experimentalGetEntityRecordNoResolver(state, kind, name, key) {
return getEntityRecord(state, kind, name, key);
}
/**
* Returns the entity's record object by key,
* with its attributes mapped to their raw values.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param key Record's key.
*
* @return Object with the entity's raw attributes.
*/
const getRawEntityRecord = exports.getRawEntityRecord = (0, _data.createSelector)((state, kind, name, key) => {
(0, _logEntityDeprecation.default)(kind, name, 'getRawEntityRecord');
const record = getEntityRecord(state, kind, name, key);
return record && Object.keys(record).reduce((accumulator, _key) => {
if ((0, _utils.isRawAttribute)(getEntityConfig(state, kind, name), _key)) {
// Because edits are the "raw" attribute values,
// we return those from record selectors to make rendering,
// comparisons, and joins with edits easier.
accumulator[_key] = record[_key]?.raw !== undefined ? record[_key]?.raw : record[_key];
} else {
accumulator[_key] = record[_key];
}
return accumulator;
}, {});
}, (state, kind, name, recordId, query) => {
var _query$context4;
const context = (_query$context4 = query?.context) !== null && _query$context4 !== void 0 ? _query$context4 : 'default';
return [state.entities.config, state.entities.records?.[kind]?.[name]?.queriedData?.items[context]?.[recordId], state.entities.records?.[kind]?.[name]?.queriedData?.itemIsComplete[context]?.[recordId]];
});
/**
* Returns true if records have been received for the given set of parameters,
* or false otherwise.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param query Optional terms query. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
*
* @return Whether entity records have been received.
*/
function hasEntityRecords(state, kind, name, query) {
(0, _logEntityDeprecation.default)(kind, name, 'hasEntityRecords');
return Array.isArray(getEntityRecords(state, kind, name, query));
}
/**
* GetEntityRecord is declared as a *callable interface* with
* two signatures to work around the fact that TypeScript doesn't
* allow currying generic functions.
*
* @see GetEntityRecord
* @see https://github.com/WordPress/gutenberg/pull/41578
*/
/**
* Returns the Entity's records.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param query Optional terms query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
*
* @return Records.
*/
const getEntityRecords = (state, kind, name, query) => {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecords');
// Queried data state is prepopulated for all known entities. If this is not
// assigned for the given parameters, then it is known to not exist.
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
if (!queriedState) {
return null;
}
return (0, _queriedData.getQueriedItems)(queriedState, query);
};
/**
* Returns the Entity's total available records for a given query (ignoring pagination).
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param query Optional terms query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
*
* @return number | null.
*/
exports.getEntityRecords = getEntityRecords;
const getEntityRecordsTotalItems = (state, kind, name, query) => {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecordsTotalItems');
// Queried data state is prepopulated for all known entities. If this is not
// assigned for the given parameters, then it is known to not exist.
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
if (!queriedState) {
return null;
}
return (0, _queriedData.getQueriedTotalItems)(queriedState, query);
};
/**
* Returns the number of available pages for the given query.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param query Optional terms query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see the [Reference](https://developer.wordpress.org/rest-api/reference/) in the REST API Handbook and select the entity kind. Then see the arguments available for "List [Entity kind]s".
*
* @return number | null.
*/
exports.getEntityRecordsTotalItems = getEntityRecordsTotalItems;
const getEntityRecordsTotalPages = (state, kind, name, query) => {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecordsTotalPages');
// Queried data state is prepopulated for all known entities. If this is not
// assigned for the given parameters, then it is known to not exist.
const queriedState = state.entities.records?.[kind]?.[name]?.queriedData;
if (!queriedState) {
return null;
}
if (query?.per_page === -1) {
return 1;
}
const totalItems = (0, _queriedData.getQueriedTotalItems)(queriedState, query);
if (!totalItems) {
return totalItems;
}
// If `per_page` is not set and the query relies on the defaults of the
// REST endpoint, get the info from query's meta.
if (!query?.per_page) {
return (0, _queriedData.getQueriedTotalPages)(queriedState, query);
}
return Math.ceil(totalItems / query.per_page);
};
exports.getEntityRecordsTotalPages = getEntityRecordsTotalPages;
/**
* Returns the list of dirty entity records.
*
* @param state State tree.
*
* @return The list of updated records
*/
const __experimentalGetDirtyEntityRecords = exports.__experimentalGetDirtyEntityRecords = (0, _data.createSelector)(state => {
const {
entities: {
records
}
} = state;
const dirtyRecords = [];
Object.keys(records).forEach(kind => {
Object.keys(records[kind]).forEach(name => {
const primaryKeys = Object.keys(records[kind][name].edits).filter(primaryKey =>
// The entity record must exist (not be deleted),
// and it must have edits.
getEntityRecord(state, kind, name, primaryKey) && hasEditsForEntityRecord(state, kind, name, primaryKey));
if (primaryKeys.length) {
const entityConfig = getEntityConfig(state, kind, name);
primaryKeys.forEach(primaryKey => {
const entityRecord = getEditedEntityRecord(state, kind, name, primaryKey);
dirtyRecords.push({
// We avoid using primaryKey because it's transformed into a string
// when it's used as an object key.
key: entityRecord ? entityRecord[entityConfig.key || _entities.DEFAULT_ENTITY_KEY] : undefined,
title: entityConfig?.getTitle?.(entityRecord) || '',
name,
kind
});
});
}
});
});
return dirtyRecords;
}, state => [state.entities.records]);
/**
* Returns the list of entities currently being saved.
*
* @param state State tree.
*
* @return The list of records being saved.
*/
const __experimentalGetEntitiesBeingSaved = exports.__experimentalGetEntitiesBeingSaved = (0, _data.createSelector)(state => {
const {
entities: {
records
}
} = state;
const recordsBeingSaved = [];
Object.keys(records).forEach(kind => {
Object.keys(records[kind]).forEach(name => {
const primaryKeys = Object.keys(records[kind][name].saving).filter(primaryKey => isSavingEntityRecord(state, kind, name, primaryKey));
if (primaryKeys.length) {
const entityConfig = getEntityConfig(state, kind, name);
primaryKeys.forEach(primaryKey => {
const entityRecord = getEditedEntityRecord(state, kind, name, primaryKey);
recordsBeingSaved.push({
// We avoid using primaryKey because it's transformed into a string
// when it's used as an object key.
key: entityRecord ? entityRecord[entityConfig.key || _entities.DEFAULT_ENTITY_KEY] : undefined,
title: entityConfig?.getTitle?.(entityRecord) || '',
name,
kind
});
});
}
});
});
return recordsBeingSaved;
}, state => [state.entities.records]);
/**
* Returns the specified entity record's edits.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return The entity record's edits.
*/
function getEntityRecordEdits(state, kind, name, recordId) {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecordEdits');
return state.entities.records?.[kind]?.[name]?.edits?.[recordId];
}
/**
* Returns the specified entity record's non transient edits.
*
* Transient edits don't create an undo level, and
* are not considered for change detection.
* They are defined in the entity's config.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return The entity record's non transient edits.
*/
const getEntityRecordNonTransientEdits = exports.getEntityRecordNonTransientEdits = (0, _data.createSelector)((state, kind, name, recordId) => {
(0, _logEntityDeprecation.default)(kind, name, 'getEntityRecordNonTransientEdits');
const {
transientEdits
} = getEntityConfig(state, kind, name) || {};
const edits = getEntityRecordEdits(state, kind, name, recordId) || {};
if (!transientEdits) {
return edits;
}
return Object.keys(edits).reduce((acc, key) => {
if (!transientEdits[key]) {
acc[key] = edits[key];
}
return acc;
}, {});
}, (state, kind, name, recordId) => [state.entities.config, state.entities.records?.[kind]?.[name]?.edits?.[recordId]]);
/**
* Returns true if the specified entity record has edits,
* and false otherwise.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return Whether the entity record has edits or not.
*/
function hasEditsForEntityRecord(state, kind, name, recordId) {
(0, _logEntityDeprecation.default)(kind, name, 'hasEditsForEntityRecord');
return isSavingEntityRecord(state, kind, name, recordId) || Object.keys(getEntityRecordNonTransientEdits(state, kind, name, recordId)).length > 0;
}
/**
* Returns the specified entity record, merged with its edits.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return The entity record, merged with its edits.
*/
const getEditedEntityRecord = exports.getEditedEntityRecord = (0, _data.createSelector)((state, kind, name, recordId) => {
(0, _logEntityDeprecation.default)(kind, name, 'getEditedEntityRecord');
const raw = getRawEntityRecord(state, kind, name, recordId);
const edited = getEntityRecordEdits(state, kind, name, recordId);
// Never return a non-falsy empty object. Unfortunately we can't return
// undefined or null because we were previously returning an empty
// object, so trying to read properties from the result would throw.
// Using false here is a workaround to avoid breaking changes.
if (!raw && !edited) {
return false;
}
return {
...raw,
...edited
};
}, (state, kind, name, recordId, query) => {
var _query$context5;
const context = (_query$context5 = query?.context) !== null && _query$context5 !== void 0 ? _query$context5 : 'default';
return [state.entities.config, state.entities.records?.[kind]?.[name]?.queriedData.items[context]?.[recordId], state.entities.records?.[kind]?.[name]?.queriedData.itemIsComplete[context]?.[recordId], state.entities.records?.[kind]?.[name]?.edits?.[recordId]];
});
/**
* Returns true if the specified entity record is autosaving, and false otherwise.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return Whether the entity record is autosaving or not.
*/
function isAutosavingEntityRecord(state, kind, name, recordId) {
var _state$entities$recor;
(0, _logEntityDeprecation.default)(kind, name, 'isAutosavingEntityRecord');
const {
pending,
isAutosave
} = (_state$entities$recor = state.entities.records?.[kind]?.[name]?.saving?.[recordId]) !== null && _state$entities$recor !== void 0 ? _state$entities$recor : {};
return Boolean(pending && isAutosave);
}
/**
* Returns true if the specified entity record is saving, and false otherwise.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return Whether the entity record is saving or not.
*/
function isSavingEntityRecord(state, kind, name, recordId) {
var _state$entities$recor2;
(0, _logEntityDeprecation.default)(kind, name, 'isSavingEntityRecord');
return (_state$entities$recor2 = state.entities.records?.[kind]?.[name]?.saving?.[recordId]?.pending) !== null && _state$entities$recor2 !== void 0 ? _state$entities$recor2 : false;
}
/**
* Returns true if the specified entity record is deleting, and false otherwise.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return Whether the entity record is deleting or not.
*/
function isDeletingEntityRecord(state, kind, name, recordId) {
var _state$entities$recor3;
(0, _logEntityDeprecation.default)(kind, name, 'isDeletingEntityRecord');
return (_state$entities$recor3 = state.entities.records?.[kind]?.[name]?.deleting?.[recordId]?.pending) !== null && _state$entities$recor3 !== void 0 ? _state$entities$recor3 : false;
}
/**
* Returns the specified entity record's last save error.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return The entity record's save error.
*/
function getLastEntitySaveError(state, kind, name, recordId) {
(0, _logEntityDeprecation.default)(kind, name, 'getLastEntitySaveError');
return state.entities.records?.[kind]?.[name]?.saving?.[recordId]?.error;
}
/**
* Returns the specified entity record's last delete error.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record ID.
*
* @return The entity record's save error.
*/
function getLastEntityDeleteError(state, kind, name, recordId) {
(0, _logEntityDeprecation.default)(kind, name, 'getLastEntityDeleteError');
return state.entities.records?.[kind]?.[name]?.deleting?.[recordId]?.error;
}
/* eslint-disable @typescript-eslint/no-unused-vars */
/**
* Returns the previous edit from the current undo offset
* for the entity records edits history, if any.
*
* @deprecated since 6.3
*
* @param state State tree.
*
* @return The edit.
*/
function getUndoEdit(state) {
(0, _deprecated.default)("select( 'core' ).getUndoEdit()", {
since: '6.3'
});
return undefined;
}
/* eslint-enable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
/**
* Returns the next edit from the current undo offset
* for the entity records edits history, if any.
*
* @deprecated since 6.3
*
* @param state State tree.
*
* @return The edit.
*/
function getRedoEdit(state) {
(0, _deprecated.default)("select( 'core' ).getRedoEdit()", {
since: '6.3'
});
return undefined;
}
/* eslint-enable @typescript-eslint/no-unused-vars */
/**
* Returns true if there is a previous edit from the current undo offset
* for the entity records edits history, and false otherwise.
*
* @param state State tree.
*
* @return Whether there is a previous edit or not.
*/
function hasUndo(state) {
return state.undoManager.hasUndo();
}
/**
* Returns true if there is a next edit from the current undo offset
* for the entity records edits history, and false otherwise.
*
* @param state State tree.
*
* @return Whether there is a next edit or not.
*/
function hasRedo(state) {
return state.undoManager.hasRedo();
}
/**
* Return the current theme.
*
* @param state Data state.
*
* @return The current theme.
*/
function getCurrentTheme(state) {
if (!state.currentTheme) {
return null;
}
return getEntityRecord(state, 'root', 'theme', state.currentTheme);
}
/**
* Return the ID of the current global styles object.
*
* @param state Data state.
*
* @return The current global styles ID.
*/
function __experimentalGetCurrentGlobalStylesId(state) {
return state.currentGlobalStylesId;
}
/**
* Return theme supports data in the index.
*
* @param state Data state.
*
* @return Index data.
*/
function getThemeSupports(state) {
var _getCurrentTheme$them;
return (_getCurrentTheme$them = getCurrentTheme(state)?.theme_supports) !== null && _getCurrentTheme$them !== void 0 ? _getCurrentTheme$them : EMPTY_OBJECT;
}
/**
* Returns the embed preview for the given URL.
*
* @param state Data state.
* @param url Embedded URL.
*
* @return Undefined if the preview has not been fetched, otherwise, the preview fetched from the embed preview API.
*/
function getEmbedPreview(state, url) {
return state.embedPreviews[url];
}
/**
* Determines if the returned preview is an oEmbed link fallback.
*
* WordPress can be configured to return a simple link to a URL if it is not embeddable.
* We need to be able to determine if a URL is embeddable or not, based on what we
* get back from the oEmbed preview API.
*
* @param state Data state.
* @param url Embedded URL.
*
* @return Is the preview for the URL an oEmbed link fallback.
*/
function isPreviewEmbedFallback(state, url) {
const preview = state.embedPreviews[url];
const oEmbedLinkCheck = '<a href="' + url + '">' + url + '</a>';
if (!preview) {
return false;
}
return preview.html === oEmbedLinkCheck;
}
/**
* Returns whether the current user can perform the given action on the given
* REST resource.
*
* Calling this may trigger an OPTIONS request to the REST API via the
* `canUser()` resolver.
*
* https://developer.wordpress.org/rest-api/reference/
*
* @param state Data state.
* @param action Action to check. One of: 'create', 'read', 'update', 'delete'.
* @param resource Entity resource to check. Accepts entity object `{ kind: 'postType', name: 'attachment', id: 1 }`
* or REST base as a string - `media`.
* @param id Optional ID of the rest resource to check.
*
* @return Whether or not the user can perform the action,
* or `undefined` if the OPTIONS request is still being made.
*/
function canUser(state, action, resource, id) {
const isEntity = typeof resource === 'object';
if (isEntity && (!resource.kind || !resource.name)) {
return false;
}
if (isEntity) {
(0, _logEntityDeprecation.default)(resource.kind, resource.name, 'canUser');
}
const key = (0, _utils.getUserPermissionCacheKey)(action, resource, id);
return state.userPermissions[key];
}
/**
* Returns whether the current user can edit the given entity.
*
* Calling this may trigger an OPTIONS request to the REST API via the
* `canUser()` resolver.
*
* https://developer.wordpress.org/rest-api/reference/
*
* @param state Data state.
* @param kind Entity kind.
* @param name Entity name.
* @param recordId Record's id.
* @return Whether or not the user can edit,
* or `undefined` if the OPTIONS request is still being made.
*/
function canUserEditEntityRecord(state, kind, name, recordId) {
(0, _deprecated.default)(`wp.data.select( 'core' ).canUserEditEntityRecord()`, {
since: '6.7',
alternative: `wp.data.select( 'core' ).canUser( 'update', { kind, name, id } )`
});
return canUser(state, 'update', {
kind,
name,
id: recordId
});
}
/**
* Returns the latest autosaves for the post.
*
* May return multiple autosaves since the backend stores one autosave per
* author for each post.
*
* @param state State tree.
* @param postType The type of the parent post.
* @param postId The id of the parent post.
*
* @return An array of autosaves for the post, or undefined if there is none.
*/
function getAutosaves(state, postType, postId) {
return state.autosaves[postId];
}
/**
* Returns the autosave for the post and author.
*
* @param state State tree.
* @param postType The type of the parent post.
* @param postId The id of the parent post.
* @param authorId The id of the author.
*
* @return The autosave for the post and author.
*/
function getAutosave(state, postType, postId, authorId) {
if (authorId === undefined) {
return;
}
const autosaves = state.autosaves[postId];
return autosaves?.find(autosave => autosave.author === authorId);
}
/**
* Returns true if the REST request for autosaves has completed.
*
* @param state State tree.
* @param postType The type of the parent post.
* @param postId The id of the parent post.
*
* @return True if the REST request was completed. False otherwise.
*/
const hasFetchedAutosaves = exports.hasFetchedAutosaves = (0, _data.createRegistrySelector)(select => (state, postType, postId) => {
return select(_name.STORE_NAME).hasFinishedResolution('getAutosaves', [postType, postId]);
});
/**
* Returns a new reference when edited values have changed. This is useful in
* inferring where an edit has been made between states by comparison of the
* return values using strict equality.
*
* @example
*
* ```
* const hasEditOccurred = (
* getReferenceByDistinctEdits( beforeState ) !==
* getReferenceByDistinctEdits( afterState )
* );
* ```
*
* @param state Editor state.
*
* @return A value whose reference will change only when an edit occurs.
*/
function getReferenceByDistinctEdits(state) {
return state.editsReference;
}
/**
* Retrieve the current theme's base global styles
*
* @param state Editor state.
*
* @return The Global Styles object.
*/
function __experimentalGetCurrentThemeBaseGlobalStyles(state) {
const currentTheme = getCurrentTheme(state);
if (!currentTheme) {
return null;
}
return state.themeBaseGlobalStyles[currentTheme.stylesheet];
}
/**
* Return the ID of the current global styles object.
*
* @param state Data state.
*
* @return The current global styles ID.
*/
function __experimentalGetCurrentThemeGlobalStylesVariations(state) {
const currentTheme = getCurrentTheme(state);
if (!currentTheme) {
return null;
}
return state.themeGlobalStyleVariations[currentTheme.stylesheet];
}
/**
* Retrieve the list of registered block patterns.
*
* @param state Data state.
*
* @return Block pattern list.
*/
function getBlockPatterns(state) {
return state.blockPatterns;
}
/**
* Retrieve the list of registered block pattern categories.
*
* @param state Data state.
*
* @return Block pattern category list.
*/
function getBlockPatternCategories(state) {
return state.blockPatternCategories;
}
/**
* Retrieve the registered user pattern categories.
*
* @param state Data state.
*
* @return User patterns category array.
*/
function getUserPatternCategories(state) {
return state.userPatternCategories;
}
/**
* Returns the revisions of the current global styles theme.
*
* @deprecated since WordPress 6.5.0. Callers should use `select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )` instead, where `recordKey` is the id of the global styles parent post.
*
* @param state Data state.
*
* @return The current global styles.
*/
function getCurrentThemeGlobalStylesRevisions(state) {
(0, _deprecated.default)("select( 'core' ).getCurrentThemeGlobalStylesRevisions()", {
since: '6.5.0',
alternative: "select( 'core' ).getRevisions( 'root', 'globalStyles', ${ recordKey } )"
});
const currentGlobalStylesId = __experimentalGetCurrentGlobalStylesId(state);
if (!currentGlobalStylesId) {
return null;
}
return state.themeGlobalStyleRevisions[currentGlobalStylesId];
}
/**
* Returns the default template use to render a given query.
*
* @param state Data state.
* @param query Query.
*
* @return The default template id for the given query.
*/
function getDefaultTemplateId(state, query) {
return state.defaultTemplates[JSON.stringify(query)];
}
/**
* Returns an entity's revisions.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param recordKey The key of the entity record whose revisions you want to fetch.
* @param query Optional query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [Entity kind]".
*
* @return Record.
*/
const getRevisions = (state, kind, name, recordKey, query) => {
(0, _logEntityDeprecation.default)(kind, name, 'getRevisions');
const queriedStateRevisions = state.entities.records?.[kind]?.[name]?.revisions?.[recordKey];
if (!queriedStateRevisions) {
return null;
}
return (0, _queriedData.getQueriedItems)(queriedStateRevisions, query);
};
/**
* Returns a single, specific revision of a parent entity.
*
* @param state State tree
* @param kind Entity kind.
* @param name Entity name.
* @param recordKey The key of the entity record whose revisions you want to fetch.
* @param revisionKey The revision's key.
* @param query Optional query. If requesting specific
* fields, fields must always include the ID. For valid query parameters see revisions schema in [the REST API Handbook](https://developer.wordpress.org/rest-api/reference/). Then see the arguments available "Retrieve a [entity kind]".
*
* @return Record.
*/
exports.getRevisions = getRevisions;
const getRevision = exports.getRevision = (0, _data.createSelector)((state, kind, name, recordKey, revisionKey, query) => {
var _query$context6, _getNormalizedCommaSe3;
(0, _logEntityDeprecation.default)(kind, name, 'getRevision');
const queriedState = state.entities.records?.[kind]?.[name]?.revisions?.[recordKey];
if (!queriedState) {
return undefined;
}
const context = (_query$context6 = query?.context) !== null && _query$context6 !== void 0 ? _query$context6 : 'default';
if (!query || !query._fields) {
// If expecting a complete item, validate that completeness.
if (!queriedState.itemIsComplete[context]?.[revisionKey]) {
return undefined;
}
return queriedState.items[context][revisionKey];
}
const item = queriedState.items[context]?.[revisionKey];
if (!item) {
return item;
}
const filteredItem = {};
const fields = (_getNormalizedCommaSe3 = (0, _utils.getNormalizedCommaSeparable)(query._fields)) !== null && _getNormalizedCommaSe3 !== void 0 ? _getNormalizedCommaSe3 : [];
for (let f = 0; f < fields.length; f++) {
const field = fields[f].split('.');
let value = item;
field.forEach(fieldName => {
value = value?.[fieldName];
});
(0, _utils.setNestedValue)(filteredItem, field, value);
}
return filteredItem;
}, (state, kind, name, recordKey, revisionKey, query) => {
var _query$context7;
const context = (_query$context7 = query?.context) !== null && _query$context7 !== void 0 ? _query$context7 : 'default';
const queriedState = state.entities.records?.[kind]?.[name]?.revisions?.[recordKey];
return [queriedState?.items?.[context]?.[revisionKey], queriedState?.itemIsComplete?.[context]?.[revisionKey]];
});
//# sourceMappingURL=selectors.js.map