Fix morph populate

This commit is contained in:
Alexandre Bodin
2021-07-30 20:45:51 +02:00
parent 16b01043d7
commit 680040fbda
9 changed files with 51 additions and 52 deletions
+1 -1
View File
@@ -4,5 +4,5 @@
"target": "es6"
},
"include": ["packages/**/*"],
"exclude": ["node_modules", "**/node_modules/*"]
"exclude": ["**/node_modules/*"]
}
@@ -1,6 +1,6 @@
'use strict';
const { has, pipe, prop, pick } = require('lodash/fp');
const { pipe, prop, pick } = require('lodash/fp');
const { MANY_RELATIONS } = require('@strapi/utils').relations.constants;
const { setCreatorFields } = require('@strapi/utils');
@@ -34,7 +34,7 @@ describe('Content-Manager', () => {
expect(strapi.entityService.update).toBeCalledWith(uid, entity.id, {
data: { published_at: expect.any(Date) },
params: {
populate: [],
populate: {},
},
});
});
@@ -63,7 +63,7 @@ describe('Content-Manager', () => {
expect(strapi.entityService.update).toHaveBeenCalledWith(uid, entity.id, {
data: { published_at: null },
params: {
populate: [],
populate: {},
},
});
});
@@ -61,6 +61,10 @@ const getDeepPopulate = (uid, populate, depth = 0) => {
};
}
if (attribute.type === 'media') {
populateAcc[attributeName] = true;
}
if (attribute.type === 'dynamiczone') {
populateAcc[attributeName] = {
populate: (attribute.components || []).reduce((acc, componentUID) => {
@@ -82,7 +86,9 @@ const getBasePopulate = (uid, populate) => {
const { attributes } = strapi.getModel(uid);
return Object.keys(attributes).filter(attributeName => {
return ['relation', 'component', 'dynamiczone'].includes(attributes[attributeName].type);
return ['relation', 'component', 'dynamiczone', 'media'].includes(
attributes[attributeName].type
);
});
};
@@ -121,7 +127,7 @@ module.exports = {
},
async findOne(id, uid, populate) {
const params = { populate: getBasePopulate(uid, populate) };
const params = { populate: getDeepPopulate(uid, populate) };
return strapi.entityService.findOne(uid, id, { params });
},
@@ -144,7 +150,7 @@ module.exports = {
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
}
const params = { populate: getBasePopulate(uid) };
const params = { populate: getDeepPopulate(uid) };
return strapi.entityService.create(uid, { params, data: publishData });
},
@@ -152,13 +158,13 @@ module.exports = {
update(entity, body, uid) {
const publishData = omitPublishedAtField(body);
const params = { populate: getBasePopulate(uid) };
const params = { populate: getDeepPopulate(uid) };
return strapi.entityService.update(uid, entity.id, { params, data: publishData });
},
delete(entity, uid) {
const params = { populate: getBasePopulate(uid) };
const params = { populate: getDeepPopulate(uid) };
return strapi.entityService.delete(uid, entity.id, { params });
},
@@ -180,7 +186,7 @@ module.exports = {
const data = { [PUBLISHED_AT_ATTRIBUTE]: new Date() };
const params = { populate: getBasePopulate(uid) };
const params = { populate: getDeepPopulate(uid) };
return strapi.entityService.update(uid, entity.id, { params, data });
}),
@@ -192,7 +198,7 @@ module.exports = {
const data = { [PUBLISHED_AT_ATTRIBUTE]: null };
const params = { populate: getBasePopulate(uid) };
const params = { populate: getDeepPopulate(uid) };
return strapi.entityService.update(uid, entity.id, { params, data });
}),
+28 -36
View File
@@ -53,13 +53,24 @@ const toRow = (metadata, data = {}) => {
const value = data[attributeName];
if (value === null) {
Object.assign(obj, {
[idColumn.name]: null,
[typeColumn.name]: null,
});
continue;
}
if (!_.isUndefined(value)) {
if (!_.has('id', value) || !_.has(typeField, value)) {
throw new Error(`Expects properties ${typeField} an id to make a morph association`);
}
obj[idColumn.name] = value.id;
obj[typeColumn.name] = value[typeField];
Object.assign(obj, {
[idColumn.name]: value.id,
[typeColumn.name]: value[typeField],
});
}
}
}
@@ -280,7 +291,7 @@ const createEntityManager = db => {
.update({ [idColumn.name]: id, [typeColumn.name]: uid })
.where({ id: data[attributeName] })
.execute();
} else if (targetAttribute.type === 'morphToMany') {
} else if (targetAttribute.relation === 'morphToMany') {
const { joinTable } = targetAttribute;
const { joinColumn, morphColumn } = joinTable;
@@ -426,17 +437,6 @@ const createEntityManager = db => {
continue;
}
/*
if morphOne | morphMany
clear previous:
if morphBy is morphToOne
set null
set new
if morphBy is morphToMany
delete links
add links
*/
if (attribute.relation === 'morphOne' || attribute.relation === 'morphMany') {
const { target, morphBy } = attribute;
@@ -451,11 +451,13 @@ const createEntityManager = db => {
.where({ [idColumn.name]: id, [typeColumn.name]: uid })
.execute();
await this.createQueryBuilder(target)
.update({ [idColumn.name]: id, [typeColumn.name]: uid })
.where({ id: data[attributeName] })
.execute();
} else if (targetAttribute.type === 'morphToMany') {
if (!_.isNull(data[attributeName])) {
await this.createQueryBuilder(target)
.update({ [idColumn.name]: id, [typeColumn.name]: uid })
.where({ id: data[attributeName] })
.execute();
}
} else if (targetAttribute.relation === 'morphToMany') {
const { joinTable } = targetAttribute;
const { joinColumn, morphColumn } = joinTable;
@@ -470,7 +472,7 @@ const createEntityManager = db => {
})
.execute();
const rows = _.castArray(data[attributeName]).map((dataID, idx) => ({
const rows = _.castArray(data[attributeName] || []).map((dataID, idx) => ({
[joinColumn.name]: dataID,
[idColumn.name]: id,
[typeColumn.name]: uid,
@@ -490,21 +492,11 @@ const createEntityManager = db => {
continue;
}
/*
if morphToOne
set new values in morph columns
*/
if (attribute.relation === 'morphToOne') {
// do nothing
// handled on the entry itself
continue;
}
/*
if morphToMany
delete old links
create new links
*/
if (attribute.relation === 'morphToMany') {
const { joinTable } = attribute;
const { joinColumn, morphColumn } = joinTable;
@@ -519,7 +511,7 @@ const createEntityManager = db => {
})
.execute();
const rows = _.castArray(data[attributeName]).map((data, idx) => ({
const rows = _.castArray(data[attributeName] || []).map((data, idx) => ({
[joinColumn.name]: id,
[idColumn.name]: data.id,
[typeColumn.name]: data[typeField],
@@ -577,13 +569,13 @@ const createEntityManager = db => {
if (['oneToOne', 'oneToMany'].includes(attribute.relation)) {
await this.createQueryBuilder(joinTable.name)
.delete()
.where({ [inverseJoinColumn.name]: _.castArray(data[attributeName]) })
.where({ [inverseJoinColumn.name]: _.castArray(data[attributeName] || []) })
.where(joinTable.on || {})
.execute();
}
if (!_.isNull(data[attributeName])) {
const insert = _.castArray(data[attributeName]).map(datum => {
const insert = _.castArray(data[attributeName] || []).map(datum => {
return {
[joinColumn.name]: id,
[inverseJoinColumn.name]: datum,
@@ -644,7 +636,7 @@ const createEntityManager = db => {
.update({ [idColumn.name]: null, [typeColumn.name]: null })
.where({ [idColumn.name]: id, [typeColumn.name]: uid })
.execute();
} else if (targetAttribute.type === 'morphToMany') {
} else if (targetAttribute.relation === 'morphToMany') {
const { joinTable } = targetAttribute;
const { morphColumn } = joinTable;
@@ -168,7 +168,7 @@ const createManyToMany = (attributeName, attribute, meta, metadata) => {
* @param {ModelMetadata} meta
* @param {Metadata} metadata
*/
const createMorphToOne = (attributeName, attribute, meta, metadata) => {
const createMorphToOne = (attributeName, attribute /*meta, metadata*/) => {
const idColumnName = 'target_id';
const typeColumnName = 'target_type';
@@ -344,7 +344,7 @@ const createJoinColum = (metadata, { attribute, attributeName /*meta */ }) => {
if (isBidirectional(attribute)) {
const inverseAttribute = targetMeta.attributes[attribute.inversedBy];
// TODO: do not invert here but invert in the query ? => means we need to use owner info in the query layer
Object.assign(inverseAttribute, {
joinColumn: {
name: joinColumn.referencedColumn,
+2 -2
View File
@@ -799,7 +799,7 @@ const applyPopulate = async (results, populate, ctx) => {
});
continue;
} else if (attribute.relation in ['morphOne', 'morphMany']) {
} else if (['morphOne', 'morphMany'].includes(attribute.relation)) {
const { target, morphBy } = attribute;
const targetAttribute = db.metadata.get(target).attributes[morphBy];
@@ -849,7 +849,7 @@ const applyPopulate = async (results, populate, ctx) => {
if (_.isEmpty(referencedValues)) {
results.forEach(result => {
result[key] = [];
result[key] = attribute.relation === 'morphOne' ? null : [];
});
continue;
@@ -56,6 +56,7 @@ const createTable = meta => {
// NOTE: we could pass uniquness for oneToOne to avoid creating more than one to one
const { name: columnName, referencedColumn, referencedTable } = attribute.joinColumn;
table.columns.push(
createColumn(columnName, {
type: 'integer',
@@ -6,7 +6,7 @@ const transformAttribute = attribute => {
// TODO: handle a filter on field
return {
type: 'relation',
relation: attribute.single === true ? 'morphOne' : 'morphMany',
relation: attribute.multiple === true ? 'morphMany' : 'morphOne',
target: 'plugins::upload.file',
morphBy: 'related',
};