oils-plugin-braziw-cms
Version:
Content and document management system plugin for oils js
396 lines (296 loc) • 8.92 kB
JavaScript
;
const _path = require('path');
module.exports = function(pluginConf, web) {
let self = this;
let mongoose = web.require('mongoose');
let Document = web.includeModel(pluginConf.models.Document);
self.handleFolder = async function(parentFolderId, req, res, callback, parentFolders) {
if (parentFolderId) {
try {
parentFolderId = mongoose.Types.ObjectId(parentFolderId)
} catch(e) {
console.error('Folder id error: ' + parentFolderId, e);
redirectToMainWithError(req, res, 'Invalid folder.');
return;
}
} else {
parentFolderId = null;
}
let folder = await Document.findOne({_id: parentFolderId});
if (parentFolderId) {
if (!folder) {
console.error('Folder not found error: ' + parentFolderId);
redirectToMainWithError(req, res, 'Folder not found.');
return
}
}
if (folder) {
if (parentFolders == null) {
parentFolders = [];
}
parentFolders.unshift(folder);
if (folder.parentFolderId) {
return await self.handleFolder(folder.parentFolderId.toString(), req, res, callback, parentFolders);
}
}
let folderId = null;
if (parentFolders) {
folder = parentFolders[parentFolders.length-1];
folderId = folder._id.toString();
}
if (callback) {
callback(null, folder, folderId, parentFolders);
}
return {folder, folderId, parentFolders};
}
let redirectToMainWithError = function(req, res, error) {
req.flash('error', error);
res.redirect(pluginConf.context);
};
self.toObjectId = function(idStr) {
try {
let id = mongoose.Types.ObjectId(idStr);
return id;
} catch(e) {
console.error('id error: ' + idStr, e);
}
return null;
};
self.initDocRoutes = async function() {
let docs = await Document.find({route: {'$ne': null}}, '', {lean: true});
for (let i in docs) {
let doc = docs[i];
self.addDocRoute(doc);
}
return docs;
};
self.addDocRoute = function(doc) {
if (console.isDebug) {
console.log('Adding DMS route: %s <--> %s', doc.route, doc.name);
}
web.app.get(doc.route, function(req, res) {
//TODO: stream
res.send(doc.content.toString('utf8'));
res.end();
})
};
self.removeDocRoute = function(doc) {
removeRoute(doc.route);
};
let removeRoute = function(routeStr) {
let routes = web.app.routes;
for (k in routes.get) {
if (routes.get[k].path + "" === routeStr + "") {
routes.get.splice(k,1);
break;
}
}
};
self.getChildren = async function(doc, cb) {
let docs = await Document.find({parentFolderId:doc._id});
if (cb) {
cb(null, docs);
}
return docs;
}
self.deleteDoc = async function(doc, cb) {
//breadth first search delete
await self._breadthFirstSearchDelete([doc]);
if (cb) {
cb();
}
}
//slower but more reliable than recursive
self._breadthFirstSearchDelete = async function(arrDocs, cb) {
while (arrDocs.length > 0) {
let lastDoc = arrDocs.pop();
if (lastDoc.isFolder) {
let docs = await self.getChildren(lastDoc);
for (let i in docs) {
arrDocs.unshift(docs[i]);
}
if (console.isDebug) {
console.debug('Deleting ' + lastDoc.name);
}
await lastDoc.remove();
} else {
if (console.isDebug) {
console.debug('Deleting ' + lastDoc.name);
}
await lastDoc.remove();
}
}
if (cb) {
cb();
}
}
self.deletePath = async function(path, callback) {
let doc = await self.retrieveDoc(path);
if (!doc) {
console.warn('Delete path do not exist ' + path);
} else {
await self.deleteDoc(doc);
}
if (callback) {
callback();
}
}
self.checkExistence = async function(name, parentDocId, optionalDocType, callback) {
if (web.objectUtils.isFunction(optionalDocType)) {
callback = optionalDocType;
optionalDocType = null;
}
let SpecificObject = null;
if (optionalDocType) {
SpecificObject = web.cms.getCmsModel(optionalDocType);
} else {
SpecificObject = Document;
}
let doc = await SpecificObject.findOne({parentFolderId: parentDocId, lowerCaseName: name.toLowerCase()});
if (callback) {
callback(null, doc);
}
return doc;
};
self.retrieveDoc = async function(path, callback) {
let arrPaths = self.getPathAsArray(path);
let doc = await self._retrieveDocFromArray(arrPaths);
if (callback) {
callback(null, doc);
}
return doc;
}
self.retrieveDocById = async function(id, callback) {
let doc = await Document.findOne({_id: id});
if (callback) {
callback(null, doc);
}
return doc;
}
self._retrieveDocFromArray = async function(arrPaths, callback, currDoc) {
if (arrPaths.length == 0) {
if (callback) {
callback(null, currDoc);
}
return currDoc;
}
let firstFile = arrPaths[0];
arrPaths.shift();
let parentDocId = currDoc ? currDoc._id : null;
let doc = await self.checkExistence(firstFile, parentDocId);
if (!doc) {
if (callback) {
callback();
}
return;
}
return await self._retrieveDocFromArray(arrPaths, callback, doc);
}
self.getFolderPath = async function(doc, cb, parentFolders) {
if (doc.folderPath && !parentFolders) {
if (cb) {
cb(null, doc.folderPath);
}
return doc.folderPath;
}
if (parentFolders == null) {
parentFolders = [];
}
if (!doc.parentFolderId) {
let folderPath = '/';
if (parentFolders && parentFolders.length > 0) {
folderPath = folderPath + parentFolders.join('/') + '/';
}
if (cb) {
cb(null, folderPath);
}
return folderPath;
}
let docParent = await self.retrieveDocById(doc.parentFolderId);
if (!docParent) {
throw new Error("[getFolderPath] Doc not found");
}
parentFolders.unshift(docParent.name);
return await self.getFolderPath(docParent, cb, parentFolders);
}
self.createFileIfNotExist = async function(path, optionalContent, callback) {
if (web.objectUtils.isFunction(optionalContent)) {
callback = optionalContent;
optionalContent = null;
}
if (optionalContent !== null && typeof optionalContent === 'string') {
let strValue = optionalContent;
optionalContent = new Object();
optionalContent.content = strValue;
}
let parentDir = _path.dirname(path);
let parentDoc = await self.mkdirs(parentDir);
let basename = _path.basename(path);
let parentDocId = parentDoc ? parentDoc._id : null
let myDocType = null;
if (optionalContent && optionalContent.docType) {
myDocType = optionalContent.docType;
}
let doc = await self.checkExistence(basename, parentDoc, myDocType);
if (!doc) {
if (myDocType) {
let SpecificObject = web.cms.getCmsModel(myDocType);
doc = new SpecificObject();
} else {
doc = new Document();
}
doc.name = basename;
if (parentDoc) {
doc.parentFolderId = parentDoc._id;
}
doc.docType = web.cms.constants.file;
if (optionalContent) {
for (let i in optionalContent) {
doc[i] = Buffer.from(optionalContent[i], "utf8");
}
}
await doc.save();
doc.existingDoc = false;
if (callback) {
callback(null, doc, false);
}
return doc;
} else {
doc.existingDoc = true;
if (callback) {
callback(null, doc, true);
}
return doc;
}
}
self.getPathAsArray = function(path) {
//console.log('!!!!' + path + ' ::: ' + path.substr(1).split('/'))
path = _path.normalize(path);
return path.substr(1).split(_path.sep);
}
self.mkdirs = async function(path, callback) {
let arrFolders = self.getPathAsArray(path);
//console.log('!' + arrFolders);
return await _mkdirs(arrFolders, callback, 0);
};
let _mkdirs = async function(arrFolders, callback) {
let parentFolderId = null;
let lastDoc = null;
for (let folderName of arrFolders) {
let doc = await Document.findOne({parentFolderId: parentFolderId, lowerCaseName: folderName.toLowerCase()});
if (!doc) {
doc = new Document();
doc.name = folderName;
doc.parentFolderId = parentFolderId;
doc.docType = web.cms.constants.folder;
await doc.save();
}
parentFolderId = doc._id;
lastDoc = doc;
}
if (callback) {
callback(null, lastDoc);
}
return lastDoc;
};
}