Merge branch 'develop' of github.com:strapi/strapi into ctm/repeatable-edit-view

This commit is contained in:
soupette 2019-07-29 13:53:13 +02:00
commit fdb0f86fcc
17 changed files with 296 additions and 144 deletions

View File

@ -59,8 +59,8 @@
"collection": "tag" "collection": "tag"
}, },
"manyTags": { "manyTags": {
"dominant": true,
"collection": "tag", "collection": "tag",
"dominant": true,
"via": "linkedArticles" "via": "linkedArticles"
}, },
"fb_cta": { "fb_cta": {
@ -82,4 +82,4 @@
"max": 10 "max": 10
} }
} }
} }

View File

@ -24,6 +24,9 @@
}, },
"article": { "article": {
"model": "article" "model": "article"
},
"articles": {
"collection": "article"
} }
} }
} }

View File

@ -623,7 +623,8 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
} else { } else {
options.withRelated = groupAttributes options.withRelated = groupAttributes
.map(key => `${key}.slice`) .map(key => `${key}.slice`)
.map(addPolymorphicRelated); .map(addPolymorphicRelated)
.reduce((acc, paths) => acc.concat(paths), []);
} }
return _.isFunction(target[model.toLowerCase()]['beforeFetchAll']) return _.isFunction(target[model.toLowerCase()]['beforeFetchAll'])

View File

@ -38,6 +38,13 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
}); });
}; };
const wrapTransaction = (fn, { transacting } = {}) => {
const db = strapi.connections[model.connection];
if (transacting) return fn(transacting);
return db.transaction(trx => fn(trx));
};
/** /**
* Find one entry based on params * Find one entry based on params
*/ */
@ -60,12 +67,12 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
/** /**
* Find multiple entries based on params * Find multiple entries based on params
*/ */
function find(params, populate) { function find(params, populate, { transacting } = {}) {
const filters = convertRestQueryParams(params); const filters = convertRestQueryParams(params);
return model return model
.query(buildQuery({ model, filters })) .query(buildQuery({ model, filters }))
.fetchAll({ withRelated: populate || defaultPopulate }) .fetchAll({ withRelated: populate || defaultPopulate, transacting })
.then(results => results.toJSON()); .then(results => results.toJSON());
} }
@ -78,7 +85,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
return model.query(buildQuery({ model, filters: { where } })).count(); return model.query(buildQuery({ model, filters: { where } })).count();
} }
async function create(values) { async function create(values, { transacting } = {}) {
const relations = pickRelations(values); const relations = pickRelations(values);
const data = selectAttributes(values); const data = selectAttributes(values);
@ -89,14 +96,16 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
return entry; return entry;
}; };
const db = strapi.connections[model.connection]; const entry = await wrapTransaction(runCreate, { transacting });
const entry = await db.transaction(trx => runCreate(trx));
return model.updateRelations({ id: entry.id, values: relations }); return model.updateRelations(
{ id: entry.id, values: relations },
{ transacting }
);
} }
async function update(params, values) { async function update(params, values, { transacting } = {}) {
const entry = await model.forge(params).fetch(); const entry = await model.forge(params).fetch({ transacting });
if (!entry) { if (!entry) {
const err = new Error('entry.notFound'); const err = new Error('entry.notFound');
@ -121,20 +130,20 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
return updatedEntry; return updatedEntry;
}; };
const db = strapi.connections[model.connection]; await wrapTransaction(runUpdate, { transacting });
await db.transaction(trx => runUpdate(trx));
if (Object.keys(relations).length > 0) { if (Object.keys(relations).length > 0) {
return model.updateRelations( return model.updateRelations(
Object.assign(params, { values: relations }) Object.assign(params, { values: relations }),
{ transacting }
); );
} }
return await model.forge(params).fetch(); return await model.forge(params).fetch({ transacting });
} }
async function deleteOne(params) { async function deleteOne(params, { transacting } = {}) {
const entry = await model.forge(params).fetch(); const entry = await model.forge(params).fetch({ transacting });
if (!entry) { if (!entry) {
const err = new Error('entry.notFound'); const err = new Error('entry.notFound');
@ -151,6 +160,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
case 'oneToManyMorph': case 'oneToManyMorph':
values[association.alias] = null; values[association.alias] = null;
break; break;
case 'manyWay':
case 'oneToMany': case 'oneToMany':
case 'manyToMany': case 'manyToMany':
case 'manyToManyMorph': case 'manyToManyMorph':
@ -160,25 +170,26 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
} }
}); });
await model.updateRelations({ ...params, values }); await model.updateRelations({ ...params, values }, { transacting });
const runDelete = async trx => { const runDelete = async trx => {
await deleteGroups(entry, { transacting: trx }); await deleteGroups(entry, { transacting: trx });
await model.forge(params).destroy({ transacting: trx }); await model.forge(params).destroy({ transacting: trx, require: false });
return entry; return entry;
}; };
const db = strapi.connections[model.connection]; return wrapTransaction(runDelete, { transacting });
return db.transaction(trx => runDelete(trx));
} }
async function deleteMany(params) { async function deleteMany(params, { transacting } = {}) {
const primaryKey = params[model.primaryKey] || params.id; const primaryKey = params[model.primaryKey] || params.id;
if (primaryKey) return deleteOne(params); if (primaryKey) return deleteOne(params, { transacting });
const entries = await find(params); const entries = await find(params, null, { transacting });
return await Promise.all(entries.map(entry => deleteOne({ id: entry.id }))); return await Promise.all(
entries.map(entry => deleteOne({ id: entry.id }, { transacting }))
);
} }
function search(params, populate) { function search(params, populate) {
@ -210,7 +221,11 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
} }
function countSearch(params) { function countSearch(params) {
return model.query(qb => buildSearchQuery(qb, model, params)).count(); return model
.query(qb => {
buildSearchQuery(qb, model, params);
})
.count();
} }
async function createGroups(entry, values, { transacting }) { async function createGroups(entry, values, { transacting }) {
@ -221,14 +236,14 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
for (let key of groupKeys) { for (let key of groupKeys) {
const attr = model.attributes[key]; const attr = model.attributes[key];
const { group, required = false, repeatable = true } = attr; const { group, required = false, repeatable = false } = attr;
const groupModel = strapi.groups[group]; const groupModel = strapi.groups[group];
const createGroupAndLink = async ({ value, order }) => { const createGroupAndLink = async ({ value, order }) => {
return groupModel return strapi
.forge() .query(groupModel.uid)
.save(value, { transacting }) .create(value, { transacting })
.then(group => { .then(group => {
return joinModel.forge().save( return joinModel.forge().save(
{ {
@ -278,7 +293,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
if (!_.has(values, key)) continue; if (!_.has(values, key)) continue;
const attr = model.attributes[key]; const attr = model.attributes[key];
const { group, repeatable = true } = attr; const { group, repeatable = false } = attr;
const groupModel = strapi.groups[group]; const groupModel = strapi.groups[group];
@ -287,9 +302,15 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
const updateOrCreateGroupAndLink = async ({ value, order }) => { const updateOrCreateGroupAndLink = async ({ value, order }) => {
// check if value has an id then update else create // check if value has an id then update else create
if (_.has(value, groupModel.primaryKey)) { if (_.has(value, groupModel.primaryKey)) {
return groupModel return strapi
.forge(value) .query(groupModel.uid)
.save(value, { transacting, patch: true, require: false }) .update(
{
[groupModel.primaryKey]: value[groupModel.primaryKey],
},
value,
{ transacting }
)
.then(group => { .then(group => {
return joinModel return joinModel
.forge() .forge()
@ -310,9 +331,9 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
}); });
} }
// create // create
return groupModel return strapi
.forge() .query(groupModel.uid)
.save(value, { transacting }) .create(value, { transacting })
.then(group => { .then(group => {
return joinModel.forge().save( return joinModel.forge().save(
{ {
@ -367,7 +388,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
const idsToKeep = groupArr const idsToKeep = groupArr
.filter(el => _.has(el, groupModel.primaryKey)) .filter(el => _.has(el, groupModel.primaryKey))
.map(el => el[groupModel.primaryKey]); .map(el => el[groupModel.primaryKey].toString());
const allIds = await joinModel const allIds = await joinModel
.forge() .forge()
@ -379,7 +400,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
// verify the provided ids are realted to this entity. // verify the provided ids are realted to this entity.
idsToKeep.forEach(id => { idsToKeep.forEach(id => {
if (!allIds.includes(id.toString())) { if (!allIds.includes(id)) {
const err = new Error( const err = new Error(
`Some of the provided groups in ${key} are not related to the entity` `Some of the provided groups in ${key} are not related to the entity`
); );
@ -395,10 +416,12 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
.query(qb => qb.whereIn('slice_id', idsToDelete)) .query(qb => qb.whereIn('slice_id', idsToDelete))
.destroy({ transacting, require: false }); .destroy({ transacting, require: false });
await groupModel await strapi
.forge() .query(groupModel.uid)
.query(qb => qb.whereIn(groupModel.primaryKey, idsToDelete)) .delete(
.destroy({ transacting, require: false }); { [`${groupModel.primaryKey}_in`]: idsToDelete },
{ transacting }
);
} }
} }
@ -426,10 +449,10 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
.fetchAll({ transacting }) .fetchAll({ transacting })
.map(el => el.get('slice_id')); .map(el => el.get('slice_id'));
await groupModel await strapi
.forge() .query(groupModel.uid)
.query(qb => qb.whereIn(groupModel.primaryKey, ids)) .delete({ [`${groupModel.primaryKey}_in`]: ids }, { transacting });
.destroy({ transacting, require: false });
await joinModel await joinModel
.forge() .forge()
.query({ .query({
@ -497,13 +520,13 @@ const buildSearchQuery = (qb, model, params) => {
if (!_.isNaN(_.toNumber(query))) { if (!_.isNaN(_.toNumber(query))) {
searchInt.forEach(attribute => { searchInt.forEach(attribute => {
qb.orWhereRaw(attribute, _.toNumber(query)); qb.orWhere(attribute, _.toNumber(query));
}); });
} }
if (query === 'true' || query === 'false') { if (query === 'true' || query === 'false') {
searchBool.forEach(attribute => { searchBool.forEach(attribute => {
qb.orWhereRaw(attribute, _.toNumber(query === 'true')); qb.orWhere(attribute, _.toNumber(query === 'true'));
}); });
} }

View File

@ -46,10 +46,11 @@ const getModel = (model, plugin) => {
const removeUndefinedKeys = obj => _.pickBy(obj, _.negate(_.isUndefined)); const removeUndefinedKeys = obj => _.pickBy(obj, _.negate(_.isUndefined));
module.exports = { module.exports = {
findOne: async function(params, populate) { async findOne(params, populate, { transacting } = {}) {
const record = await this.forge({ const record = await this.forge({
[this.primaryKey]: getValuePrimaryKey(params, this.primaryKey), [this.primaryKey]: getValuePrimaryKey(params, this.primaryKey),
}).fetch({ }).fetch({
transacting,
withRelated: populate || this.associations.map(x => x.alias), withRelated: populate || this.associations.map(x => x.alias),
}); });
@ -70,7 +71,9 @@ module.exports = {
this.primaryKey this.primaryKey
), ),
}) })
.fetchAll(); .fetchAll({
transacting,
});
}); });
const related = await Promise.all(arrayOfPromises); const related = await Promise.all(arrayOfPromises);
@ -83,10 +86,12 @@ module.exports = {
return data; return data;
}, },
update: async function(params) { async update(params, { transacting } = {}) {
const relationUpdates = []; const relationUpdates = [];
const primaryKeyValue = getValuePrimaryKey(params, this.primaryKey); const primaryKeyValue = getValuePrimaryKey(params, this.primaryKey);
const response = await module.exports.findOne.call(this, params); const response = await module.exports.findOne.call(this, params, null, {
transacting,
});
// Only update fields which are on this document. // Only update fields which are on this document.
const values = const values =
@ -129,7 +134,12 @@ module.exports = {
}) })
.save( .save(
{ [details.via]: null }, { [details.via]: null },
{ method: 'update', patch: true, require: false } {
method: 'update',
patch: true,
require: false,
transacting,
}
); );
relationUpdates.push(updatePromise); relationUpdates.push(updatePromise);
@ -140,14 +150,24 @@ module.exports = {
const updateLink = this.where({ [current]: property }) const updateLink = this.where({ [current]: property })
.save( .save(
{ [current]: null }, { [current]: null },
{ method: 'update', patch: true, require: false } {
method: 'update',
patch: true,
require: false,
transacting,
}
) )
.then(() => { .then(() => {
return assocModel return assocModel
.where({ [this.primaryKey]: property }) .where({ [this.primaryKey]: property })
.save( .save(
{ [details.via]: primaryKeyValue }, { [details.via]: primaryKeyValue },
{ method: 'update', patch: true, require: false } {
method: 'update',
patch: true,
require: false,
transacting,
}
); );
}); });
@ -179,7 +199,12 @@ module.exports = {
) )
.save( .save(
{ [details.via]: null }, { [details.via]: null },
{ method: 'update', patch: true, require: false } {
method: 'update',
patch: true,
require: false,
transacting,
}
) )
.then(() => { .then(() => {
return assocModel return assocModel
@ -190,7 +215,12 @@ module.exports = {
) )
.save( .save(
{ [details.via]: primaryKeyValue }, { [details.via]: primaryKeyValue },
{ method: 'update', patch: true, require: false } {
method: 'update',
patch: true,
require: false,
transacting,
}
); );
}); });
@ -221,9 +251,10 @@ module.exports = {
const collection = this.forge({ const collection = this.forge({
[this.primaryKey]: primaryKeyValue, [this.primaryKey]: primaryKeyValue,
})[association.alias](); })[association.alias]();
const updatePromise = collection const updatePromise = collection
.detach(toRemove) .detach(toRemove, { transacting })
.then(() => collection.attach(toAdd)); .then(() => collection.attach(toAdd, { transacting }));
relationUpdates.push(updatePromise); relationUpdates.push(updatePromise);
return acc; return acc;
@ -242,31 +273,43 @@ module.exports = {
if (association.nature === 'manyMorphToOne') { if (association.nature === 'manyMorphToOne') {
relationUpdates.push( relationUpdates.push(
module.exports.removeRelationMorph module.exports.removeRelationMorph
.call(this, { .call(
alias: association.alias, this,
ref: model.collectionName, {
refId: obj.refId,
field: obj.field,
})
.then(() =>
module.exports.addRelationMorph.call(this, {
id: response[this.primaryKey],
alias: association.alias, alias: association.alias,
ref: model.collectionName, ref: model.collectionName,
refId: obj.refId, refId: obj.refId,
field: obj.field, field: obj.field,
}) },
{ transacting }
)
.then(() =>
module.exports.addRelationMorph.call(
this,
{
id: response[this.primaryKey],
alias: association.alias,
ref: model.collectionName,
refId: obj.refId,
field: obj.field,
},
{ transacting }
)
) )
); );
} else { } else {
relationUpdates.push( relationUpdates.push(
module.exports.addRelationMorph.call(this, { module.exports.addRelationMorph.call(
id: response[this.primaryKey], this,
alias: association.alias, {
ref: model.collectionName, id: response[this.primaryKey],
refId: obj.refId, alias: association.alias,
field: obj.field, ref: model.collectionName,
}) refId: obj.refId,
field: obj.field,
},
{ transacting }
)
); );
} }
}); });
@ -293,26 +336,34 @@ module.exports = {
toAdd.forEach(id => { toAdd.forEach(id => {
relationUpdates.push( relationUpdates.push(
module.exports.addRelationMorph.call(model, { module.exports.addRelationMorph.call(
id, model,
alias: association.via, {
ref: this.collectionName, id,
refId: response.id, alias: association.via,
field: association.alias, ref: this.collectionName,
}) refId: response.id,
field: association.alias,
},
{ transacting }
)
); );
}); });
// Update the relational array. // Update the relational array.
toRemove.forEach(id => { toRemove.forEach(id => {
relationUpdates.push( relationUpdates.push(
module.exports.removeRelationMorph.call(model, { module.exports.removeRelationMorph.call(
id, model,
alias: association.via, {
ref: this.collectionName, id,
refId: response.id, alias: association.via,
field: association.alias, ref: this.collectionName,
}) refId: response.id,
field: association.alias,
},
{ transacting }
)
); );
}); });
break; break;
@ -336,17 +387,19 @@ module.exports = {
[this.primaryKey]: getValuePrimaryKey(params, this.primaryKey), [this.primaryKey]: getValuePrimaryKey(params, this.primaryKey),
}).save(values, { }).save(values, {
patch: true, patch: true,
transacting,
}); });
} }
return await this.forge({ return await this.forge({
[this.primaryKey]: getValuePrimaryKey(params, this.primaryKey), [this.primaryKey]: getValuePrimaryKey(params, this.primaryKey),
}).fetch({ }).fetch({
transacting,
withRelated: this.associations.map(x => x.alias), withRelated: this.associations.map(x => x.alias),
}); });
}, },
addRelationMorph: async function(params) { async addRelationMorph(params, { transacting } = {}) {
const record = await this.morph const record = await this.morph
.forge() .forge()
.where({ .where({
@ -356,6 +409,7 @@ module.exports = {
field: params.field, field: params.field,
}) })
.fetch({ .fetch({
transacting,
withRelated: this.associations.map(x => x.alias), withRelated: this.associations.map(x => x.alias),
}); });
@ -372,10 +426,10 @@ module.exports = {
[`${params.alias}_type`]: params.ref, [`${params.alias}_type`]: params.ref,
field: params.field, field: params.field,
}) })
.save(); .save(null, { transacting });
}, },
removeRelationMorph: async function(params) { async removeRelationMorph(params, { transacting } = {}) {
return await this.morph return await this.morph
.forge() .forge()
.where( .where(
@ -391,6 +445,7 @@ module.exports = {
) )
.destroy({ .destroy({
require: false, require: false,
transacting,
}); });
}, },
}; };

View File

@ -38,7 +38,7 @@ module.exports = ({ model, modelKey, strapi }) => {
for (let key of groupKeys) { for (let key of groupKeys) {
const attr = model.attributes[key]; const attr = model.attributes[key];
const { group, required = false, repeatable = true } = attr; const { group, required = false, repeatable = false } = attr;
const groupModel = strapi.groups[group]; const groupModel = strapi.groups[group];
@ -55,23 +55,25 @@ module.exports = ({ model, modelKey, strapi }) => {
if (repeatable === true) { if (repeatable === true) {
validateRepeatableInput(groupValue, { key, ...attr }); validateRepeatableInput(groupValue, { key, ...attr });
const groups = await Promise.all( const groups = await Promise.all(
groupValue.map(value => groupModel.create(value)) groupValue.map(value => {
return strapi.query(group).create(value);
})
); );
const groupsArr = groups.map(group => ({ const groupsArr = groups.map(groupEntry => ({
kind: groupModel.globalId, kind: groupModel.globalId,
ref: group, ref: groupEntry,
})); }));
entry[key] = groupsArr; entry[key] = groupsArr;
await entry.save(); await entry.save();
} else { } else {
validateNonRepeatableInput(groupValue, { key, ...attr }); validateNonRepeatableInput(groupValue, { key, ...attr });
const group = await groupModel.create(groupValue); const groupEntry = await strapi.query(group).create(groupValue);
entry[key] = [ entry[key] = [
{ {
kind: groupModel.globalId, kind: groupModel.globalId,
ref: group, ref: groupEntry,
}, },
]; ];
await entry.save(); await entry.save();
@ -87,7 +89,7 @@ module.exports = ({ model, modelKey, strapi }) => {
if (!_.has(values, key)) continue; if (!_.has(values, key)) continue;
const attr = model.attributes[key]; const attr = model.attributes[key];
const { group, repeatable = true } = attr; const { group, repeatable = false } = attr;
const groupModel = strapi.groups[group]; const groupModel = strapi.groups[group];
const groupValue = values[key]; const groupValue = values[key];
@ -95,15 +97,14 @@ module.exports = ({ model, modelKey, strapi }) => {
const updateOrCreateGroup = async value => { const updateOrCreateGroup = async value => {
// check if value has an id then update else create // check if value has an id then update else create
if (hasPK(value)) { if (hasPK(value)) {
return groupModel.findOneAndUpdate( return strapi.query(group).update(
{ {
[model.primaryKey]: getPK(value), [model.primaryKey]: getPK(value),
}, },
value, value
{ new: true }
); );
} }
return groupModel.create(value); return strapi.query(group).create(value);
}; };
if (repeatable === true) { if (repeatable === true) {
@ -162,7 +163,9 @@ module.exports = ({ model, modelKey, strapi }) => {
}, []); }, []);
if (idsToDelete.length > 0) { if (idsToDelete.length > 0) {
await groupModel.deleteMany({ [model.primaryKey]: { $in: idsToDelete } }); await strapi
.query(groupModel.uid)
.delete({ [`${model.primaryKey}_in`]: idsToDelete });
} }
} }
@ -175,9 +178,10 @@ module.exports = ({ model, modelKey, strapi }) => {
const groupModel = strapi.groups[group]; const groupModel = strapi.groups[group];
if (Array.isArray(entry[key]) && entry[key].length > 0) { if (Array.isArray(entry[key]) && entry[key].length > 0) {
await groupModel.deleteMany({ const idsToDelete = entry[key].map(el => el.ref);
[model.primaryKey]: { $in: entry[key].map(el => el.ref) }, await strapi
}); .query(groupModel.uid)
.delete({ [`${model.primaryKey}_in`]: idsToDelete });
} }
} }
} }

View File

@ -208,17 +208,9 @@ module.exports = {
case 'manyMorphToOne': case 'manyMorphToOne':
// Update the relational array. // Update the relational array.
acc[current] = property.map(obj => { acc[current] = property.map(obj => {
const globalId =
obj.source && obj.source !== 'content-manager'
? strapi.plugins[obj.source].models[_.toLower(obj.ref)]
.globalId
: strapi.models[_.toLower(obj.ref)].globalId;
// Define the object stored in database.
// The shape is this object is defined by the strapi-hook-mongoose connector.
return { return {
ref: obj.refId, ref: obj.refId,
kind: globalId, kind: obj.ref,
[association.filter]: obj.field, [association.filter]: obj.field,
}; };
}); });

View File

@ -11,7 +11,7 @@ module.exports = {
strapi.plugins['content-manager'].services['contentmanager']; strapi.plugins['content-manager'].services['contentmanager'];
let entities = []; let entities = [];
if (!_.isEmpty(ctx.request.query._q)) { if (_.has(ctx.request.query, '_q')) {
entities = await contentManagerService.search( entities = await contentManagerService.search(
ctx.params, ctx.params,
ctx.request.query ctx.request.query
@ -51,7 +51,7 @@ module.exports = {
strapi.plugins['content-manager'].services['contentmanager']; strapi.plugins['content-manager'].services['contentmanager'];
let count; let count;
if (!_.isEmpty(ctx.request.query._q)) { if (_.has(ctx.request.query, '_q')) {
count = await contentManagerService.countSearch( count = await contentManagerService.countSearch(
ctx.params, ctx.params,
ctx.request.query ctx.request.query

View File

@ -127,23 +127,15 @@ module.exports = {
}, },
search(params, query) { search(params, query) {
const { limit, skip, sort, source, _q, populate = [] } = query; // eslint-disable-line no-unused-vars const { model } = params;
const filters = strapi.utils.models.convertParams(params.model, query); const { source } = query;
// Find entries using `queries` system return strapi.query(model, source).search(query);
return strapi.query(params.model, source).search(
{
limit: limit || filters.limit,
skip: skip || filters.start || 0,
sort: sort || filters.sort,
search: _q,
},
populate
);
}, },
countSearch(params, query) { countSearch(params, query) {
const { model } = params;
const { source, _q } = query; const { source, _q } = query;
return strapi.query(params.model, source).countSearch({ search: _q }); return strapi.query(model, source).countSearch({ _q });
}, },
}; };

View File

@ -105,4 +105,15 @@ module.exports = {
); );
return getModel(uid); return getModel(uid);
}, },
async updateUID({ oldUID, newUID, source }) {
const oldKey = uidToStoreKey({ uid: oldUID, source });
const newKey = uidToStoreKey({ uid: newUID, source });
await storeUtils.setModelConfiguration(oldKey, {
uid: oldUID,
});
return storeUtils.moveKey(oldKey, newKey);
},
}; };

View File

@ -29,4 +29,16 @@ module.exports = {
const storeKey = uidToStoreKey(uid); const storeKey = uidToStoreKey(uid);
return storeUtils.deleteKey(storeKey); return storeUtils.deleteKey(storeKey);
}, },
async updateUID(oldUID, newUID) {
const oldKey = uidToStoreKey(oldUID);
const newKey = uidToStoreKey(newUID);
await storeUtils.setModelConfiguration(oldKey, {
uid: oldUID,
isGroup: true,
});
return storeUtils.moveKey(oldKey, newKey);
},
}; };

View File

@ -89,6 +89,16 @@ function findByKeyQuery({ model }, key) {
} }
const findByKey = key => strapi.query('core_store').custom(findByKeyQuery)(key); const findByKey = key => strapi.query('core_store').custom(findByKeyQuery)(key);
const moveKey = (oldKey, newKey) => {
return strapi.query('core_store').update(
{
key: `plugin_content_manager_configuration_${oldKey}`,
},
{
key: `plugin_content_manager_configuration_${newKey}`,
}
);
};
const getAllConfigurations = () => const getAllConfigurations = () =>
findByKey('plugin_content_manager_configuration'); findByKey('plugin_content_manager_configuration');
@ -103,5 +113,6 @@ module.exports = {
setModelConfiguration, setModelConfiguration,
deleteKey, deleteKey,
moveKey,
keys, keys,
}; };

View File

@ -220,8 +220,8 @@ module.exports = {
]) ])
); );
modelJSON.connection = connection; modelJSON.connection = connection || modelJSON.connection;
modelJSON.collectionName = collectionName; modelJSON.collectionName = collectionName || modelJSON.collectionName;
modelJSON.info = { modelJSON.info = {
name, name,
description: _description, description: _description,
@ -256,6 +256,20 @@ module.exports = {
if (!_.isEmpty(removeModelErrors)) { if (!_.isEmpty(removeModelErrors)) {
return ctx.badRequest(null, [{ messages: removeModelErrors }]); return ctx.badRequest(null, [{ messages: removeModelErrors }]);
} }
if (
_.has(strapi.plugins, ['content-manager', 'services', 'contenttypes'])
) {
await _.get(strapi.plugins, [
'content-manager',
'services',
'contenttypes',
]).updateUID({
oldUID: model,
newUID: name.toLowerCase(),
source: plugin,
});
}
} }
try { try {

View File

@ -116,15 +116,34 @@ async function createGroup(uid, infos) {
* @param {Object} infos * @param {Object} infos
*/ */
async function updateGroup(group, infos) { async function updateGroup(group, infos) {
const { uid } = group; const { uid, schema: oldSchema } = group;
const newUid = createGroupUID(infos.name); // don't update collectionName if not provided
if (uid !== newUid) { const updatedSchema = {
info: {
name: infos.name || oldSchema.name,
description: infos.description || oldSchema.description,
},
connection: infos.connection || oldSchema.connection,
collectionName: infos.collectionName || oldSchema.collectionName,
attributes: convertAttributes(infos.attributes),
};
const newUID = createGroupUID(infos.name);
if (uid !== newUID) {
await deleteSchema(uid); await deleteSchema(uid);
return createGroup(newUid, infos);
}
const updatedSchema = { ...group.schema, ...createSchema(uid, infos) }; if (_.has(strapi.plugins, ['content-manager', 'services', 'groups'])) {
await _.get(strapi.plugins, [
'content-manager',
'services',
'groups',
]).updateUID(uid, newUID);
}
await writeSchema(newUID, updatedSchema);
return { uid: newUID };
}
await writeSchema(uid, updatedSchema); await writeSchema(uid, updatedSchema);
return { uid }; return { uid };
@ -137,7 +156,11 @@ async function updateGroup(group, infos) {
const createSchema = (uid, infos) => { const createSchema = (uid, infos) => {
const { const {
name, name,
connection = 'default', connection = _.get(
strapi,
['config', 'currentEnvironment', 'database', 'defaultConnection'],
'default'
),
description = '', description = '',
collectionName, collectionName,
attributes, attributes,
@ -149,7 +172,7 @@ const createSchema = (uid, infos) => {
description, description,
}, },
connection, connection,
collectionName: collectionName || `groups_${pluralize(uid)}`, collectionName: collectionName || `groups_${pluralize(uid).toLowerCase()}`,
attributes: convertAttributes(attributes), attributes: convertAttributes(attributes),
}; };
}; };

View File

@ -8,6 +8,16 @@ describe('Group Service', () => {
attributes: {}, attributes: {},
}; };
global.strapi = {
config: {
defaultEnvironment: {
database: {
defaultConnection: 'default',
},
},
},
};
const expected = { const expected = {
info: { info: {
name: 'Some name', name: 'Some name',

View File

@ -188,7 +188,7 @@ module.exports = {
.findOne({ id: roleID }, ['users', 'permissions']); .findOne({ id: roleID }, ['users', 'permissions']);
if (!role) { if (!role) {
throw new Error('Cannot found this role'); throw new Error('Cannot find this role');
} }
// Group by `type`. // Group by `type`.

View File

@ -51,6 +51,7 @@ module.exports = function(strapi) {
throw new Error(`Group ${key} is missing a collectionName attribute`); throw new Error(`Group ${key} is missing a collectionName attribute`);
return Object.assign(group, { return Object.assign(group, {
uid: key,
modelType: 'group', modelType: 'group',
globalId: group.globalId || _.upperFirst(_.camelCase(`group_${key}`)), globalId: group.globalId || _.upperFirst(_.camelCase(`group_${key}`)),
}); });