Update algorithm to correctly add, edit and delete relationships between models and plugins' models

This commit is contained in:
Aurelsicoko 2017-12-16 17:03:34 +01:00
parent 1f55ca1d04
commit 6ac1bca417
3 changed files with 49 additions and 38 deletions

View File

@ -33,7 +33,7 @@ module.exports = {
}, },
createModel: async ctx => { createModel: async ctx => {
const { name, description, connection, collectionName, attributes = [] } = ctx.request.body; const { name, description, connection, collectionName, attributes = [], plugin } = ctx.request.body;
if (!name) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.name.missing' }] }]); if (!name) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.name.missing' }] }]);
if (!_.includes(Service.getConnections(), connection)) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.connection.unknow' }] }]); if (!_.includes(Service.getConnections(), connection)) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.connection.unknow' }] }]);
@ -50,20 +50,20 @@ module.exports = {
await Service.generateAPI(name, description, connection, collectionName, []); await Service.generateAPI(name, description, connection, collectionName, []);
const modelFilePath = Service.getModelPath(name); const modelFilePath = Service.getModelPath(name, plugin);
try { try {
const modelJSON = require(modelFilePath); const modelJSON = _.cloneDeep(require(modelFilePath));
modelJSON.attributes = formatedAttributes; modelJSON.attributes = formatedAttributes;
const clearRelationsErrors = Service.clearRelations(name); const clearRelationsErrors = Service.clearRelations(name, plugin);
if (!_.isEmpty(clearRelationsErrors)) { if (!_.isEmpty(clearRelationsErrors)) {
return ctx.badRequest(null, [{ messages: clearRelationsErrors }]); return ctx.badRequest(null, [{ messages: clearRelationsErrors }]);
} }
const createRelationsErrors = Service.createRelations(name, attributes); const createRelationsErrors = Service.createRelations(name, attributes, plugin);
if (!_.isEmpty(createRelationsErrors)) { if (!_.isEmpty(createRelationsErrors)) {
return ctx.badRequest(null, [{ messages: createRelationsErrors }]); return ctx.badRequest(null, [{ messages: createRelationsErrors }]);
@ -92,6 +92,8 @@ module.exports = {
if (strapi.models[_.toLower(name)] && name !== model) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.exist' }] }]); if (strapi.models[_.toLower(name)] && name !== model) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.exist' }] }]);
if (!strapi.models[_.toLower(model)]) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.unknow' }] }]); if (!strapi.models[_.toLower(model)]) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.unknow' }] }]);
if (!_.isNaN(parseFloat(name[0]))) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.name' }] }]); if (!_.isNaN(parseFloat(name[0]))) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.name' }] }]);
if (plugin && !strapi.plugins[_.toLower(plugin)]) return ctx.badRequest(null, [{ message: [{ id: 'request.error.plugin.name' }] }]);
if (plugin && !strapi.plugins[_.toLower(plugin)].models[_.toLower(model)]) return ctx.badRequest(null, [{ message: [{ id: 'request.error.model.unknow' }] }]);
const [formatedAttributes, attributesErrors] = Service.formatAttributes(attributes); const [formatedAttributes, attributesErrors] = Service.formatAttributes(attributes);
@ -108,7 +110,7 @@ module.exports = {
} }
try { try {
const modelJSON = require(modelFilePath); const modelJSON = _.cloneDeep(require(modelFilePath));
modelJSON.attributes = formatedAttributes; modelJSON.attributes = formatedAttributes;
modelJSON.info = { modelJSON.info = {
@ -118,13 +120,13 @@ module.exports = {
modelJSON.connection = connection; modelJSON.connection = connection;
modelJSON.collectionName = collectionName; modelJSON.collectionName = collectionName;
const clearRelationsErrors = Service.clearRelations(model); const clearRelationsErrors = Service.clearRelations(model, plugin);
if (!_.isEmpty(clearRelationsErrors)) { if (!_.isEmpty(clearRelationsErrors)) {
return ctx.badRequest(null, [{ messages: clearRelationsErrors }]); return ctx.badRequest(null, [{ messages: clearRelationsErrors }]);
} }
const createRelationsErrors = Service.createRelations(name, attributes); const createRelationsErrors = Service.createRelations(name, attributes, plugin);
if (!_.isEmpty(createRelationsErrors)) { if (!_.isEmpty(createRelationsErrors)) {
return ctx.badRequest(null, [{ messages: createRelationsErrors }]); return ctx.badRequest(null, [{ messages: createRelationsErrors }]);

View File

@ -74,8 +74,6 @@ module.exports = {
}, },
generateAPI: (name, description, connection, collectionName, attributes) => { generateAPI: (name, description, connection, collectionName, attributes) => {
description = _.replace(description, /\"/g, '\\"');
const template = _.get(strapi.config.currentEnvironment, `database.connections.${connection}.connector`, 'strapi-mongoose').split('-')[1]; const template = _.get(strapi.config.currentEnvironment, `database.connections.${connection}.connector`, 'strapi-mongoose').split('-')[1];
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -85,7 +83,7 @@ module.exports = {
rootPath: strapi.config.appPath, rootPath: strapi.config.appPath,
args: { args: {
api: name, api: name,
description, description: _.replace(description, /\"/g, '\\"'),
attributes, attributes,
connection, connection,
collectionName: !_.isEmpty(collectionName) ? collectionName : undefined, collectionName: !_.isEmpty(collectionName) ? collectionName : undefined,
@ -97,8 +95,8 @@ module.exports = {
success: () => { success: () => {
resolve(); resolve();
}, },
error: () => { error: (err) => {
reject(); reject(err);
} }
}); });
}); });
@ -106,8 +104,9 @@ module.exports = {
getModelPath: (model, plugin) => { getModelPath: (model, plugin) => {
// Retrieve where is located the model. // Retrieve where is located the model.
// Note: The target is not found when we are creating a new API. That's why, we are returning the lowercased model.
const target = Object.keys((plugin ? strapi.plugins : strapi.api) || {}) const target = Object.keys((plugin ? strapi.plugins : strapi.api) || {})
.filter(x => _.includes(Object.keys((plugin ? strapi.plugins : strapi.api)[x].models), model.toLowerCase()))[0]; .filter(x => _.includes(Object.keys((plugin ? strapi.plugins : strapi.api)[x].models), model.toLowerCase()))[0] || model.toLowerCase();
// Retrieve the filename of the model. // Retrieve the filename of the model.
const filename = fs.readdirSync(plugin ? path.join(strapi.config.appPath, 'plugins', target, 'models') : path.join(strapi.config.appPath, 'api', target, 'models')) const filename = fs.readdirSync(plugin ? path.join(strapi.config.appPath, 'plugins', target, 'models') : path.join(strapi.config.appPath, 'api', target, 'models'))
@ -148,6 +147,7 @@ module.exports = {
attr.via = relation.key; attr.via = relation.key;
attr.dominant = relation.dominant; attr.dominant = relation.dominant;
attr.plugin = relation.pluginValue;
attrs[attribute.name] = attr; attrs[attribute.name] = attr;
} }
@ -165,7 +165,7 @@ module.exports = {
return [attrs, errors]; return [attrs, errors];
}, },
clearRelations: model => { clearRelations: (model, source) => {
const errors = []; const errors = [];
const structure = { const structure = {
models: strapi.models, models: strapi.models,
@ -181,7 +181,13 @@ module.exports = {
// Method to delete the association of the models. // Method to delete the association of the models.
const deleteAssociations = (models, plugin) => { const deleteAssociations = (models, plugin) => {
Object.keys(models).forEach(name => { Object.keys(models).forEach(name => {
const relationsToDelete = _.get(plugin ? strapi.plugins[plugin].models[name] : strapi.models[name], 'associations', []).filter(association => association[association.type] === model); const relationsToDelete = _.get(plugin ? strapi.plugins[plugin].models[name] : strapi.models[name], 'associations', []).filter(association => {
if (source) {
return association[association.type] === model && association.plugin === source;
}
return association[association.type] === model;
});
if (!_.isEmpty(relationsToDelete)) { if (!_.isEmpty(relationsToDelete)) {
// Retrieve where is located the model. // Retrieve where is located the model.
@ -194,7 +200,9 @@ module.exports = {
.filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0]; .filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0];
// Path to access to the model. // Path to access to the model.
const pathToModel = path.join(strapi.config.appPath, 'api', target, 'models', filename); const pathToModel = plugin ?
path.resolve(strapi.config.appPath, 'plugins', target, 'models', filename):
path.resolve(strapi.config.appPath, 'api', target, 'models', filename);
// Require the model. // Require the model.
const modelJSON = require(pathToModel); const modelJSON = require(pathToModel);
@ -220,15 +228,15 @@ module.exports = {
// Update `./api` models. // Update `./api` models.
deleteAssociations(structure.models); deleteAssociations(structure.models);
// Object.keys(structure.plugins).forEach(name => { Object.keys(structure.plugins).forEach(name => {
// // Update `./plugins/${name}` models. // Update `./plugins/${name}` models.
// deleteAssociations(structure.plugins[name].models, name); deleteAssociations(structure.plugins[name].models, name);
// }); });
return errors; return errors;
}, },
createRelations: (model, attributes) => { createRelations: (model, attributes, source) => {
const errors = []; const errors = [];
const structure = { const structure = {
models: strapi.models, models: strapi.models,
@ -244,14 +252,12 @@ module.exports = {
// Method to update the model // Method to update the model
const update = (models, plugin) => { const update = (models, plugin) => {
Object.keys(models).forEach(name => { Object.keys(models).forEach(name => {
// TODO:
// - Retrieve right relation in plugin case.
const relationsToCreate = attributes.filter(attribute => { const relationsToCreate = attributes.filter(attribute => {
if (!plugin) { if (plugin) {
return _.get(attribute, 'params.target') === name && _.get(attribute, 'params.pluginValue', false) === false; return _.get(attribute, 'params.target') === name && _.get(attribute, 'params.pluginValue') === plugin;
} }
return _.get(attribute, 'params.target') === name && _.get(attribute, 'params.pluginValue', false) !== false; return _.get(attribute, 'params.target') === name && _.isEmpty(_.get(attribute, 'params.pluginValue', ''));
}); });
if (!_.isEmpty(relationsToCreate)) { if (!_.isEmpty(relationsToCreate)) {
@ -264,15 +270,15 @@ module.exports = {
.filter(x => x[0] !== '.') .filter(x => x[0] !== '.')
.filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0]; .filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0];
const pathToModel = path.join(strapi.config.appPath, 'api', target, 'models', filename); // Path to access to the model.
const pathToModel = plugin ?
path.resolve(strapi.config.appPath, 'plugins', target, 'models', filename):
path.resolve(strapi.config.appPath, 'api', target, 'models', filename);
const modelJSON = require(pathToModel); const modelJSON = require(pathToModel);
_.forEach(relationsToCreate, ({ name, params }) => { _.forEach(relationsToCreate, ({ name, params }) => {
const attr = { const attr = {};
columnName: params.targetColumnName,
plugin: params.pluginValue
};
switch (params.nature) { switch (params.nature) {
case 'oneToOne': case 'oneToOne':
@ -287,6 +293,8 @@ module.exports = {
} }
attr.via = name; attr.via = name;
attr.columnName = params.targetColumnName;
attr.plugin = source;
modelJSON.attributes[params.key] = attr; modelJSON.attributes[params.key] = attr;
@ -308,10 +316,10 @@ module.exports = {
// Update `./api` models. // Update `./api` models.
update(structure.models); update(structure.models);
// Object.keys(structure.plugins).forEach(name => { Object.keys(structure.plugins).forEach(name => {
// // Update `./plugins/${name}` models. // Update `./plugins/${name}` models.
// update(structure.plugins[name].models, name); update(structure.plugins[name].models, name);
// }); });
return errors; return errors;
}, },

View File

@ -28,5 +28,6 @@
"role": { "role": {
"type": "integer" "type": "integer"
} }
} },
"connection": "default"
} }