diff --git a/packages/core/content-manager/server/controllers/relations.js b/packages/core/content-manager/server/controllers/relations.js index f5b3d88518..e915690845 100644 --- a/packages/core/content-manager/server/controllers/relations.js +++ b/packages/core/content-manager/server/controllers/relations.js @@ -2,8 +2,8 @@ const { prop, isEmpty } = require('lodash/fp'); const { hasDraftAndPublish } = require('@strapi/utils').contentTypes; +const { isAnyToMany } = require('@strapi/utils').relations; const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants; -const { MANY_RELATIONS } = require('@strapi/utils').relations.constants; const { getService } = require('../utils'); const { validateFindAvailable, validateFindExisting } = require('./validation/relations'); @@ -191,7 +191,7 @@ module.exports = { fields: fieldsToSelect, }; - if (MANY_RELATIONS.includes(attribute.relation)) { + if (isAnyToMany(attribute)) { const res = await strapi.entityService.loadPages(sourceModelUid, { id }, targetField, { ...queryParams, page: query.page, diff --git a/packages/core/content-manager/server/services/entity-manager.js b/packages/core/content-manager/server/services/entity-manager.js index b4d22a34f6..a4779db56d 100644 --- a/packages/core/content-manager/server/services/entity-manager.js +++ b/packages/core/content-manager/server/services/entity-manager.js @@ -5,9 +5,9 @@ const strapiUtils = require('@strapi/utils'); const { ApplicationError } = require('@strapi/utils').errors; const { hasDraftAndPublish, isVisibleAttribute } = strapiUtils.contentTypes; +const { isAnyToMany } = strapiUtils.relations; const { PUBLISHED_AT_ATTRIBUTE, CREATED_BY_ATTRIBUTE } = strapiUtils.contentTypes.constants; const { ENTRY_PUBLISH, ENTRY_UNPUBLISH } = strapiUtils.webhook.webhookEvents; -const { MANY_RELATIONS } = strapiUtils.relations.constants; const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE); @@ -59,7 +59,7 @@ const getDeepPopulate = ( const attribute = model.attributes[attributeName]; if (attribute.type === 'relation') { - const isManyRelation = MANY_RELATIONS.includes(attribute.relation); + const isManyRelation = isAnyToMany(attribute); // always populate createdBy, updatedBy, localizations etc. if (!isVisibleAttribute(model, attributeName)) { populateAcc[attributeName] = true; diff --git a/packages/core/strapi/lib/services/entity-service/index.js b/packages/core/strapi/lib/services/entity-service/index.js index 5131b9554a..cc7e99187d 100644 --- a/packages/core/strapi/lib/services/entity-service/index.js +++ b/packages/core/strapi/lib/services/entity-service/index.js @@ -10,6 +10,7 @@ const { sanitize, } = require('@strapi/utils'); const { ValidationError } = require('@strapi/utils').errors; +const { isAnyToMany } = require('@strapi/utils').relations; const { transformParamsToQuery } = require('@strapi/utils').convertQueryParams; const uploadFiles = require('../utils/upload-files'); @@ -278,14 +279,14 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator }) loadPages(uid, entity, field, params = {}) { if (!_.isString(field)) { - throw new Error(`Invalid load. Expected ${field} to be a string`); + throw new Error(`Invalid load. Expected "${field}" to be a string`); } const { attributes } = strapi.getModel(uid); const attribute = attributes[field]; - if (!attribute || attribute.type !== 'relation') { - throw new Error(`Invalid load. Expected ${field} to be an anyToMany relational attribute`); + if (!isAnyToMany(attribute)) { + throw new Error(`Invalid load. Expected "${field}" to be an anyToMany relational attribute`); } return db.query(uid).loadPages(entity, field, transformParamsToQuery(attribute.target, params)); diff --git a/packages/core/utils/lib/content-types.js b/packages/core/utils/lib/content-types.js index 6c8e530102..cec115eab4 100644 --- a/packages/core/utils/lib/content-types.js +++ b/packages/core/utils/lib/content-types.js @@ -106,9 +106,10 @@ const isPrivateAttribute = (model = {}, attributeName) => { const isScalarAttribute = (attribute) => { return !['media', 'component', 'relation', 'dynamiczone'].includes(attribute.type); }; -const isMediaAttribute = (attribute) => attribute.type === 'media'; -const isRelationalAttribute = (attribute) => attribute.type === 'relation'; -const isComponentAttribute = (attribute) => ['component', 'dynamiczone'].includes(attribute.type); +const isMediaAttribute = (attribute) => attribute && attribute.type === 'media'; +const isRelationalAttribute = (attribute) => attribute && attribute.type === 'relation'; +const isComponentAttribute = (attribute) => + attribute && ['component', 'dynamiczone'].includes(attribute.type); const getComponentAttributes = (schema) => { return _.reduce( diff --git a/packages/core/utils/lib/relations.js b/packages/core/utils/lib/relations.js index 816cbdeb33..d3f2163600 100644 --- a/packages/core/utils/lib/relations.js +++ b/packages/core/utils/lib/relations.js @@ -1,5 +1,7 @@ 'use strict'; +const { isRelationalAttribute } = require('./content-types'); + const MANY_RELATIONS = ['oneToMany', 'manyToMany']; const getRelationalFields = (contentType) => { @@ -8,8 +10,21 @@ const getRelationalFields = (contentType) => { }); }; +const isOneToAny = (attribute) => + isRelationalAttribute(attribute) && ['oneToOne', 'oneToMany'].includes(attribute.relation); +const isManyToAny = (attribute) => + isRelationalAttribute(attribute) && ['manyToMany', 'manyToOne'].includes(attribute.relation); +const isAnyToOne = (attribute) => + isRelationalAttribute(attribute) && ['oneToOne', 'manyToOne'].includes(attribute.relation); +const isAnyToMany = (attribute) => + isRelationalAttribute(attribute) && ['oneToMany', 'manyToMany'].includes(attribute.relation); + module.exports = { getRelationalFields, + isOneToAny, + isManyToAny, + isAnyToOne, + isAnyToMany, constants: { MANY_RELATIONS, },