0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Refactored members imporeter in preparation for jobs

no issue

- This refactor extracts labels related code into a separate module for easier reuse by the "job-aware" batched importer
This commit is contained in:
Nazar Gargol 2020-08-27 21:47:00 +12:00 committed by naz
parent 8f1691b052
commit 8ea9896622
2 changed files with 130 additions and 5 deletions

View file

@ -21,8 +21,8 @@ const handleUnrecognizedError = (error) => {
}
};
const doImport = async ({members, allLabelModels, importSetLabels, createdBy}) => {
debug(`Importing members: ${members.length}, labels: ${allLabelModels.length}, import lables: ${importSetLabels.length}, createdBy: ${createdBy}`);
const doImport = async ({members, labels, importSetLabels, createdBy}) => {
debug(`Importing members: ${members.length}, labels: ${labels.length}, import lables: ${importSetLabels.length}, createdBy: ${createdBy}`);
let {
invalidMembers,
@ -30,7 +30,7 @@ const doImport = async ({members, allLabelModels, importSetLabels, createdBy}) =
stripeCustomersToFetch,
stripeCustomersToCreate,
labelAssociationsToInsert
} = getMemberData({members, allLabelModels, importSetLabels, createdBy});
} = getMemberData({members, labels, importSetLabels, createdBy});
// NOTE: member insertion has to happen before the rest of insertions to handle validation
// errors - remove failed members from label/stripe sets
@ -213,8 +213,8 @@ function serializeMemberLabels(labels) {
}, []);
}
function getMemberData({members, allLabelModels, importSetLabels, createdBy}) {
const labelIdLookup = allLabelModels.reduce(function (labelIdLookupAcc, labelModel) {
function getMemberData({members, labels, importSetLabels, createdBy}) {
const labelIdLookup = labels.reduce(function (labelIdLookupAcc, labelModel) {
return Object.assign(labelIdLookupAcc, {
[labelModel.name]: labelModel.id
});

View file

@ -0,0 +1,125 @@
const _ = require('lodash');
const moment = require('moment-timezone');
const models = require('../../../models');
const findOrCreateLabels = async (labels, options) => {
const existingLabels = [];
const createdLabels = [];
for (const label of labels) {
const existingLabel = await models.Label.findOne({name: label.name});
if (existingLabel) {
existingLabels.push(existingLabel.toJSON());
} else {
try {
const createdLabel = await models.Label.add(label, options);
createdLabels.push(createdLabel.toJSON());
} catch (error) {
if (error.code && error.message.toLowerCase().indexOf('unique') !== -1) {
// ignore if label already exists
} else {
throw error;
}
}
}
}
return {existingLabels, createdLabels};
};
const getUniqueMemberLabels = (members) => {
const allLabels = [];
members.forEach((member) => {
const labels = (member.labels && member.labels.split(',')) || [];
if (labels.length) {
allLabels.push(...labels);
}
});
return _.uniq(allLabels);
};
function serializeMemberLabels(labels) {
if (_.isString(labels)) {
if (labels === '') {
return [];
}
return [{
name: labels.trim()
}];
} else if (labels) {
return labels.filter((label) => {
return !!label;
}).map((label) => {
if (_.isString(label)) {
return {
name: label.trim()
};
}
return label;
});
}
return [];
}
const handleImportSetLabels = async (labels, siteTimezone, options) => {
const importSetLabels = serializeMemberLabels(labels);
let importLabel;
const {existingLabels, createdLabels} = await findOrCreateLabels(importSetLabels, options);
// NOTE: an import label allows for imports to be "undone" via bulk delete
if (createdLabels.length) {
importLabel = createdLabels[0] && createdLabels[0];
} else {
const name = `Import ${moment().tz(siteTimezone).format('YYYY-MM-DD HH:mm')}`;
const result = await findOrCreateLabels([{name}], options);
const generatedLabel = result.createdLabels.length
? result.createdLabels[0]
: result.existingLabels[0];
importLabel = generatedLabel;
importLabel.generated = true;
createdLabels.push(generatedLabel);
}
return {
importSetLabels: [...existingLabels, ...createdLabels],
importLabel
};
};
const handleMemberLabels = async (members, options) => {
const memberLabels = serializeMemberLabels(getUniqueMemberLabels(members));
return await findOrCreateLabels(memberLabels, options);
};
const handleAllLabels = async (labels, members, siteTimezone, options) => {
let {
importSetLabels,
importLabel
} = await handleImportSetLabels(labels, siteTimezone, options);
const memberLabelsResult = await handleMemberLabels(members);
const allLabels = [
...importSetLabels,
...memberLabelsResult.existingLabels,
...memberLabelsResult.createdLabels
];
return {
allLabels,
importSetLabels,
importLabel
};
};
module.exports.handleAllLabels = handleAllLabels;
module.exports.serializeMemberLabels = serializeMemberLabels;