166 lines
4.8 KiB
JavaScript
Raw Normal View History

'use strict';
2022-04-12 16:43:06 +02:00
const uuid = require('uuid').v4;
2022-04-29 09:51:55 +02:00
const { keys, sortBy, omit, map, isUndefined } = require('lodash/fp');
const { joinBy, setCreatorFields } = require('@strapi/utils');
const { NotFoundError } = require('@strapi/utils').errors;
2022-05-13 16:10:18 +02:00
const { FOLDER_MODEL_UID, FILE_MODEL_UID } = require('../constants');
2022-04-26 11:23:07 +02:00
const { getService } = require('../utils');
const generateUID = () => uuid();
2022-04-12 16:32:05 +02:00
const setPathAndUID = async folder => {
2022-04-05 17:36:09 +02:00
const uid = generateUID();
2022-04-12 16:32:05 +02:00
let parentPath = '/';
if (folder.parent) {
2022-05-13 16:10:18 +02:00
const parentFolder = await strapi.entityService.findOne(FOLDER_MODEL_UID, folder.parent);
2022-04-12 16:32:05 +02:00
parentPath = parentFolder.path;
}
return Object.assign(folder, {
2022-04-05 17:36:09 +02:00
uid,
2022-04-12 16:32:05 +02:00
path: joinBy('/', parentPath, uid),
});
};
2022-04-26 11:23:07 +02:00
/**
* Recursively delete folders and included files
* @param ids ids of the folders to delete
* @returns {Promise<Object[]>}
*/
const deleteByIds = async (ids = []) => {
2022-05-13 16:10:18 +02:00
const folders = await strapi.db.query(FOLDER_MODEL_UID).findMany({ where: { id: { $in: ids } } });
2022-04-26 11:23:07 +02:00
if (folders.length === 0) {
return [];
}
2022-04-26 11:23:07 +02:00
const pathsToDelete = map('path', folders);
// delete files
2022-05-13 16:10:18 +02:00
const filesToDelete = await strapi.db.query(FILE_MODEL_UID).findMany({
2022-04-26 11:23:07 +02:00
where: {
$or: pathsToDelete.map(path => ({ folderPath: { $startsWith: path } })),
},
});
await Promise.all(filesToDelete.map(file => getService('upload').remove(file)));
// delete folders
2022-05-13 16:10:18 +02:00
await strapi.db.query(FOLDER_MODEL_UID).deleteMany({
2022-04-26 11:23:07 +02:00
where: {
$or: pathsToDelete.map(path => ({ path: { $startsWith: path } })),
},
});
return folders;
};
2022-04-29 09:51:55 +02:00
/**
* Update name and location of a folder and its belonging folders and files
* @param params query params to find the folder
* @returns {Promise<boolean>}
*/
const update = async (id, { name, parent }, { user }) => {
2022-05-13 16:10:18 +02:00
const existingFolder = await strapi.entityService.findOne(FOLDER_MODEL_UID, id);
2022-04-29 09:51:55 +02:00
if (!existingFolder) {
throw new NotFoundError('folder not found');
}
if (!isUndefined(parent)) {
2022-05-13 16:10:18 +02:00
const folderPathColumnName = strapi.db.metadata.get(FILE_MODEL_UID).attributes.folderPath
2022-04-29 09:51:55 +02:00
.columnName;
2022-05-13 16:10:18 +02:00
const pathColumnName = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.path.columnName;
2022-04-29 09:51:55 +02:00
// Todo wrap into a transaction
const destinationFolder =
2022-05-13 16:10:18 +02:00
parent === null ? '/' : (await strapi.entityService.findOne(FOLDER_MODEL_UID, parent)).path;
2022-04-29 09:51:55 +02:00
2022-05-13 16:10:18 +02:00
const folderTable = strapi.getModel(FOLDER_MODEL_UID).collectionName;
const fileTable = strapi.getModel(FILE_MODEL_UID).collectionName;
2022-04-29 09:51:55 +02:00
await strapi.db
.connection(folderTable)
.where(pathColumnName, 'like', `${existingFolder.path}%`)
.update(
pathColumnName,
strapi.db.connection.raw('REPLACE(??, ?, ?)', [
pathColumnName,
existingFolder.path,
joinBy('/', destinationFolder, existingFolder.uid),
])
);
await strapi.db
.connection(fileTable)
.where(folderPathColumnName, 'like', `${existingFolder.path}%`)
.update(
folderPathColumnName,
strapi.db.connection.raw('REPLACE(??, ?, ?)', [
folderPathColumnName,
existingFolder.path,
joinBy('/', destinationFolder, existingFolder.uid),
])
);
}
const newFolder = setCreatorFields({ user, isEdition: true })({ name, parent });
2022-05-13 16:10:18 +02:00
const folder = await strapi.entityService.update(FOLDER_MODEL_UID, id, { data: newFolder });
2022-04-29 09:51:55 +02:00
return folder;
};
/**
* Check if a folder exists in database
* @param params query params to find the folder
* @returns {Promise<boolean>}
*/
const exists = async (params = {}) => {
2022-05-13 16:10:18 +02:00
const count = await strapi.query(FOLDER_MODEL_UID).count({ where: params });
return count > 0;
};
2022-04-29 09:51:55 +02:00
/**
* Returns the nested structure of folders
* @returns {Promise<array>}
*/
const getStructure = async () => {
2022-05-13 16:10:18 +02:00
const joinTable = strapi.db.metadata.get(FOLDER_MODEL_UID).attributes.parent.joinTable;
const qb = strapi.db.queryBuilder(FOLDER_MODEL_UID);
2022-04-07 18:00:21 +02:00
const alias = qb.getAlias();
const folders = await qb
.select(['id', 'name', `${alias}.${joinTable.inverseJoinColumn.name} as parent`])
.join({
alias,
referencedTable: joinTable.name,
referencedColumn: joinTable.joinColumn.name,
rootColumn: joinTable.joinColumn.referencedColumn,
rootTable: qb.alias,
})
.execute({ mapResults: false });
const folderMap = folders.reduce((map, f) => {
f.children = [];
map[f.id] = f;
return map;
}, {});
folderMap.null = { children: [] };
for (const id of keys(omit('null', folderMap))) {
const parentId = folderMap[id].parent;
folderMap[parentId].children.push(folderMap[id]);
folderMap[parentId].children = sortBy('name', folderMap[parentId].children);
delete folderMap[id].parent;
}
return folderMap.null.children;
};
module.exports = {
exists,
deleteByIds,
2022-04-29 09:51:55 +02:00
update,
2022-04-12 16:32:05 +02:00
setPathAndUID,
getStructure,
};