mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 08:19:07 +00:00
Init populate cleanup
This commit is contained in:
parent
abf3954b7b
commit
72c7203e18
@ -8,47 +8,36 @@ module.exports = {
|
||||
// Before saving a value.
|
||||
// Fired before an `insert` or `update` query.
|
||||
// beforeSave: async (model, attrs, options) => {},
|
||||
|
||||
// After saving a value.
|
||||
// Fired after an `insert` or `update` query.
|
||||
// afterSave: async (model, response, options) => {},
|
||||
|
||||
// Before fetching a value.
|
||||
// Fired before a `fetch` operation.
|
||||
// beforeFetch: async (model, columns, options) => {},
|
||||
|
||||
// After fetching a value.
|
||||
// Fired after a `fetch` operation.
|
||||
// afterFetch: async (model, response, options) => {},
|
||||
|
||||
// Before fetching all values.
|
||||
// Fired before a `fetchAll` operation.
|
||||
// beforeFetchAll: async (model, columns, options) => {},
|
||||
|
||||
// After fetching all values.
|
||||
// Fired after a `fetchAll` operation.
|
||||
// afterFetchAll: async (model, response, options) => {},
|
||||
|
||||
// Before creating a value.
|
||||
// Fired before an `insert` query.
|
||||
// beforeCreate: async (model, attrs, options) => {},
|
||||
|
||||
// After creating a value.
|
||||
// Fired after an `insert` query.
|
||||
// afterCreate: async (model, attrs, options) => {},
|
||||
|
||||
// Before updating a value.
|
||||
// Fired before an `update` query.
|
||||
// beforeUpdate: async (model, attrs, options) => {},
|
||||
|
||||
// After updating a value.
|
||||
// Fired after an `update` query.
|
||||
// afterUpdate: async (model, attrs, options) => {},
|
||||
|
||||
// Before destroying a value.
|
||||
// Fired before a `delete` query.
|
||||
// beforeDestroy: async (model, attrs, options) => {},
|
||||
|
||||
// After destroying a value.
|
||||
// Fired after a `delete` query.
|
||||
// afterDestroy: async (model, attrs, options) => {}
|
||||
|
@ -31,10 +31,7 @@
|
||||
},
|
||||
"enum": {
|
||||
"type": "enumeration",
|
||||
"enum": [
|
||||
"morning,",
|
||||
"noon"
|
||||
]
|
||||
"enum": ["morning,", "noon"]
|
||||
},
|
||||
"bool": {
|
||||
"type": "boolean"
|
||||
@ -61,7 +58,6 @@
|
||||
"via": "linkedArticles"
|
||||
},
|
||||
"fb_cta": {
|
||||
"required": true,
|
||||
"type": "group",
|
||||
"group": "cta_facebook",
|
||||
"repeatable": false
|
||||
|
@ -5,4 +5,13 @@
|
||||
* to customize this service
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
module.exports = {
|
||||
find(params) {
|
||||
// return strapi.query('article').find(params, {
|
||||
// manyTags: () => {},
|
||||
// ['linkedTags.linkedArticles.pic']: () => {},
|
||||
// });
|
||||
|
||||
return strapi.query('article').find(params, ['ingredients']);
|
||||
},
|
||||
};
|
||||
|
@ -5,4 +5,8 @@
|
||||
* to customize this service
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
module.exports = {
|
||||
find(params) {
|
||||
return strapi.query('tag').find(params, null);
|
||||
},
|
||||
};
|
||||
|
@ -436,6 +436,15 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
});
|
||||
};
|
||||
|
||||
// Extract association except polymorphic.
|
||||
const associations = definition.associations.filter(
|
||||
association => association.nature.toLowerCase().indexOf('morph') === -1
|
||||
);
|
||||
// Extract polymorphic association.
|
||||
const polymorphicAssociations = definition.associations.filter(
|
||||
association => association.nature.toLowerCase().indexOf('morph') !== -1
|
||||
);
|
||||
|
||||
// Update serialize to reformat data for polymorphic associations.
|
||||
loadedModel.serialize = function(options) {
|
||||
const attrs = _.clone(this.attributes);
|
||||
@ -447,27 +456,16 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
const relations = this.relations;
|
||||
|
||||
groupAttributes.forEach(key => {
|
||||
const { repeatable } = definition.attributes[key];
|
||||
if (relations[key]) {
|
||||
const groups = relations[key].toJSON().map(el => el.slice);
|
||||
|
||||
attrs[key] =
|
||||
definition.attributes[key].repeatable === true
|
||||
? groups
|
||||
: _.first(groups) || null;
|
||||
attrs[key] = repeatable === true ? groups : _.first(groups) || null;
|
||||
} else {
|
||||
attrs[key] = repeatable === true ? [] : null;
|
||||
}
|
||||
});
|
||||
|
||||
// Extract association except polymorphic.
|
||||
const associations = definition.associations.filter(
|
||||
association =>
|
||||
association.nature.toLowerCase().indexOf('morph') === -1
|
||||
);
|
||||
// Extract polymorphic association.
|
||||
const polymorphicAssociations = definition.associations.filter(
|
||||
association =>
|
||||
association.nature.toLowerCase().indexOf('morph') !== -1
|
||||
);
|
||||
|
||||
polymorphicAssociations.map(association => {
|
||||
// Retrieve relation Bookshelf object.
|
||||
const relation = relations[association.alias];
|
||||
@ -489,7 +487,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
switch (association.nature) {
|
||||
case 'oneToManyMorph':
|
||||
attrs[association.alias] =
|
||||
attrs[association.alias][model.collectionName];
|
||||
attrs[association.alias][model.collectionName] || null;
|
||||
break;
|
||||
case 'manyToManyMorph':
|
||||
attrs[association.alias] = attrs[association.alias].map(
|
||||
@ -497,7 +495,8 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
);
|
||||
break;
|
||||
case 'oneMorphToOne':
|
||||
attrs[association.alias] = attrs[association.alias].related;
|
||||
attrs[association.alias] =
|
||||
attrs[association.alias].related || null;
|
||||
break;
|
||||
case 'manyMorphToOne':
|
||||
case 'manyMorphToMany':
|
||||
@ -548,11 +547,12 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
});
|
||||
|
||||
const findModelByAssoc = ({ assoc }) => {
|
||||
return assoc.plugin
|
||||
? strapi.plugins[assoc.plugin].models[
|
||||
assoc.collection || assoc.model
|
||||
]
|
||||
: strapi.models[assoc.collection || assoc.model];
|
||||
const target = assoc.collection || assoc.model;
|
||||
return assoc.plugin === 'admin'
|
||||
? strapi.admin.models[target]
|
||||
: assoc.plugin
|
||||
? strapi.plugins[assoc.plugin].models[target]
|
||||
: strapi.models[target];
|
||||
};
|
||||
|
||||
const isPolymorphic = ({ assoc }) => {
|
||||
@ -582,51 +582,165 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
|
||||
}
|
||||
};
|
||||
|
||||
const addPolymorphicRelated = path => {
|
||||
const assoc = definition.associations.find(
|
||||
assoc => assoc.alias === path || assoc.via === path
|
||||
);
|
||||
// const addPolymorphicRelated = path => {
|
||||
// const assoc = definition.associations.find(
|
||||
// assoc => assoc.alias === path || assoc.via === path
|
||||
// );
|
||||
|
||||
if (assoc && isPolymorphic({ assoc })) {
|
||||
return formatPolymorphicPopulate({
|
||||
assoc,
|
||||
path,
|
||||
});
|
||||
}
|
||||
// if (assoc && isPolymorphic({ assoc })) {
|
||||
// return formatPolymorphicPopulate({
|
||||
// assoc,
|
||||
// path,
|
||||
// });
|
||||
// }
|
||||
|
||||
let extraAssocs = [];
|
||||
if (assoc) {
|
||||
const assocModel = findModelByAssoc({ assoc });
|
||||
// let extraAssocs = [];
|
||||
// if (assoc) {
|
||||
// const assocModel = findModelByAssoc({ assoc });
|
||||
|
||||
extraAssocs = assocModel.associations
|
||||
.filter(assoc => isPolymorphic({ assoc }))
|
||||
.map(assoc =>
|
||||
formatPolymorphicPopulate({
|
||||
// extraAssocs = assocModel.associations
|
||||
// .filter(assoc => isPolymorphic({ assoc }))
|
||||
// .map(assoc =>
|
||||
// formatPolymorphicPopulate({
|
||||
// assoc,
|
||||
// path: assoc.alias,
|
||||
// prefix: `${path}.`,
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
// return [path, ...extraAssocs];
|
||||
// };
|
||||
|
||||
function createAssociationPopulate() {
|
||||
return definition.associations
|
||||
.filter(ast => ast.autoPopulate !== false)
|
||||
.map(assoc => {
|
||||
if (isPolymorphic({ assoc })) {
|
||||
return formatPolymorphicPopulate({
|
||||
assoc,
|
||||
path: assoc.alias,
|
||||
prefix: `${path}.`,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return [path, ...extraAssocs];
|
||||
};
|
||||
let path = assoc.alias;
|
||||
let extraAssocs = [];
|
||||
if (assoc) {
|
||||
const assocModel = findModelByAssoc({ assoc });
|
||||
|
||||
extraAssocs = assocModel.associations
|
||||
.filter(assoc => isPolymorphic({ assoc }))
|
||||
.map(assoc =>
|
||||
formatPolymorphicPopulate({
|
||||
assoc,
|
||||
path: assoc.alias,
|
||||
prefix: `${path}.`,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return [assoc.alias, ...extraAssocs];
|
||||
})
|
||||
.reduce((acc, val) => acc.concat(val), []);
|
||||
}
|
||||
|
||||
function populateGroup(key) {
|
||||
let paths = [];
|
||||
const group = strapi.groups[definition.attributes[key].group];
|
||||
const assocs = (group.associations || []).filter(
|
||||
assoc => assoc.autoPopulate === true
|
||||
);
|
||||
|
||||
assocs.forEach(assoc => {
|
||||
if (isPolymorphic({ assoc })) {
|
||||
const rel = formatPolymorphicPopulate({
|
||||
assoc,
|
||||
path: assoc.alias,
|
||||
prefix: `${key}.slice.`,
|
||||
});
|
||||
|
||||
paths.push(rel);
|
||||
} else {
|
||||
paths.push(`${key}.slice.${assoc.alias}`);
|
||||
}
|
||||
});
|
||||
|
||||
paths.push(`${key}.slice`);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
function createGroupsPopulate() {
|
||||
const groupsToPopulate = groupAttributes.reduce((acc, key) => {
|
||||
const attribute = definition.attributes[key];
|
||||
const autoPopulate = _.get(attribute, ['autoPopulate'], true);
|
||||
|
||||
if (autoPopulate === true) {
|
||||
return acc.concat(populateGroup(key));
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return groupsToPopulate;
|
||||
}
|
||||
|
||||
const isGroup = key => groupAttributes.includes(key);
|
||||
|
||||
function formatPopulateOptions(populate) {
|
||||
// if groups are no
|
||||
return populate
|
||||
.reduce((acc, opt) => {
|
||||
if (typeof opt === 'string') {
|
||||
// split in parts and check if some parts of the path are morph or groups and update them
|
||||
const parts = opt.split('.');
|
||||
|
||||
if (parts.length === 1) {
|
||||
if (isGroup(opt)) {
|
||||
// add group path and there relations / images
|
||||
return acc.concat(populateGroup(opt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof opt === 'object' && opt !== null) {
|
||||
return acc.concat(opt);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, [])
|
||||
.reduce((acc, val) => acc.concat(val), []);
|
||||
}
|
||||
|
||||
// Update withRelated level to bypass many-to-many association for polymorphic relationshiips.
|
||||
// Apply only during fetching.
|
||||
this.on('fetching fetching:collection', (instance, attrs, options) => {
|
||||
if (_.isArray(options.withRelated)) {
|
||||
options.withRelated = options.withRelated
|
||||
.concat(groupAttributes.map(key => `${key}.slice`))
|
||||
.map(addPolymorphicRelated)
|
||||
.reduce((acc, paths) => acc.concat(paths), []);
|
||||
} else {
|
||||
options.withRelated = groupAttributes
|
||||
.map(key => `${key}.slice`)
|
||||
.map(addPolymorphicRelated)
|
||||
.reduce((acc, paths) => acc.concat(paths), []);
|
||||
// do not populate anything
|
||||
if (options.withRelated === false) return;
|
||||
|
||||
if (_.isNil(options.withRelated)) {
|
||||
options.withRelated = []
|
||||
.concat(createGroupsPopulate())
|
||||
.concat(createAssociationPopulate());
|
||||
} else if (Array.isArray(options.withRelated)) {
|
||||
options.withRelated = formatPopulateOptions(options.withRelated);
|
||||
} else if (_.isObject(options.withRelated)) {
|
||||
options.withRelated = formatPopulateOptions([options.withRelated]);
|
||||
}
|
||||
|
||||
// if (_.isArray(options.withRelated)) {
|
||||
// options.withRelated = options.withRelated
|
||||
// .concat(groupAttributes.map(key => `${key}.slice`))
|
||||
// .map(addPolymorphicRelated)
|
||||
// .reduce((acc, paths) => acc.concat(paths), []);
|
||||
// } else {
|
||||
// options.withRelated = groupAttributes
|
||||
// .map(key => `${key}.slice`)
|
||||
// .map(addPolymorphicRelated)
|
||||
// .reduce((acc, paths) => acc.concat(paths), []);
|
||||
// }
|
||||
});
|
||||
|
||||
this.on('fetching fetching:collection', () => {
|
||||
return _.isFunction(target[model.toLowerCase()]['beforeFetchAll'])
|
||||
? target[model.toLowerCase()]['beforeFetchAll']
|
||||
: Promise.resolve();
|
||||
|
@ -58,7 +58,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
|
||||
}
|
||||
|
||||
const entry = await model.forge(params).fetch({
|
||||
withRelated: populate || defaultPopulate,
|
||||
withRelated: _.isNil(populate) ? defaultPopulate : populate,
|
||||
});
|
||||
|
||||
return entry ? entry.toJSON() : null;
|
||||
@ -72,7 +72,10 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
|
||||
|
||||
return model
|
||||
.query(buildQuery({ model, filters }))
|
||||
.fetchAll({ withRelated: populate || defaultPopulate, transacting })
|
||||
.fetchAll({
|
||||
withRelated: _.isNil(populate) ? defaultPopulate : populate,
|
||||
transacting,
|
||||
})
|
||||
.then(results => results.toJSON());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user