2019-05-29 05:21:06 -04:00
|
|
|
const path = require('path')
|
|
|
|
const DocstoreManager = require('../Docstore/DocstoreManager')
|
|
|
|
const Errors = require('../Errors/Errors')
|
|
|
|
const ProjectGetter = require('./ProjectGetter')
|
2019-09-09 07:52:25 -04:00
|
|
|
const { promisifyAll } = require('../../util/promises')
|
2022-03-21 10:47:17 -04:00
|
|
|
const OError = require('@overleaf/o-error')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-09-09 07:52:25 -04:00
|
|
|
const ProjectEntityHandler = {
|
2019-11-26 08:11:19 -05:00
|
|
|
getAllDocs(projectId, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
// We get the path and name info from the project, and the lines and
|
|
|
|
// version info from the doc store.
|
2019-11-26 08:11:19 -05:00
|
|
|
DocstoreManager.getAllDocs(projectId, (error, docContentsArray) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn array from docstore into a dictionary based on doc id
|
|
|
|
const docContents = {}
|
2021-05-05 09:05:04 -04:00
|
|
|
for (const docContent of docContentsArray) {
|
2019-05-29 05:21:06 -04:00
|
|
|
docContents[docContent._id] = docContent
|
|
|
|
}
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
ProjectEntityHandler._getAllFolders(projectId, (error, folders) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (error != null) {
|
|
|
|
return callback(error)
|
|
|
|
}
|
|
|
|
const docs = {}
|
2021-11-11 10:10:46 -05:00
|
|
|
for (const { path: folderPath, folder } of folders) {
|
2021-05-05 09:05:04 -04:00
|
|
|
for (const doc of folder.docs || []) {
|
2019-05-29 05:21:06 -04:00
|
|
|
const content = docContents[doc._id.toString()]
|
|
|
|
if (content != null) {
|
|
|
|
docs[path.join(folderPath, doc.name)] = {
|
|
|
|
_id: doc._id,
|
|
|
|
name: doc.name,
|
|
|
|
lines: content.lines,
|
2021-04-27 03:52:58 -04:00
|
|
|
rev: content.rev,
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-19 09:19:08 -05:00
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
callback(null, docs)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
getAllFiles(projectId, callback) {
|
|
|
|
ProjectEntityHandler._getAllFolders(projectId, (err, folders) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
const files = {}
|
2021-11-11 10:10:46 -05:00
|
|
|
for (const { path: folderPath, folder } of folders) {
|
2021-05-05 09:05:04 -04:00
|
|
|
for (const file of folder.fileRefs || []) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (file != null) {
|
|
|
|
files[path.join(folderPath, file.name)] = file
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-26 08:11:19 -05:00
|
|
|
callback(null, files)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
getAllEntities(projectId, callback) {
|
|
|
|
ProjectGetter.getProject(projectId, (err, project) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
2019-09-11 07:05:30 -04:00
|
|
|
if (project == null) {
|
|
|
|
return callback(new Errors.NotFoundError('project not found'))
|
|
|
|
}
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
const entities = ProjectEntityHandler.getAllEntitiesFromProject(project)
|
|
|
|
callback(null, entities)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
getAllEntitiesFromProject(project) {
|
|
|
|
const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
|
|
|
|
const docs = []
|
|
|
|
const files = []
|
|
|
|
for (const { path: folderPath, folder } of folders) {
|
|
|
|
for (const doc of folder.docs || []) {
|
|
|
|
if (doc != null) {
|
|
|
|
docs.push({ path: path.join(folderPath, doc.name), doc })
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-12-06 10:27:12 -05:00
|
|
|
}
|
|
|
|
for (const file of folder.fileRefs || []) {
|
|
|
|
if (file != null) {
|
|
|
|
files.push({ path: path.join(folderPath, file.name), file })
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
|
|
|
}
|
2021-12-06 10:27:12 -05:00
|
|
|
}
|
|
|
|
return { docs, files, folders }
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
getAllDocPathsFromProjectById(projectId, callback) {
|
|
|
|
ProjectGetter.getProjectWithoutDocLines(projectId, (err, project) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
|
|
|
return callback(Errors.NotFoundError('no project'))
|
|
|
|
}
|
2021-12-06 10:27:12 -05:00
|
|
|
const docPaths = ProjectEntityHandler.getAllDocPathsFromProject(project)
|
|
|
|
callback(null, docPaths)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
getAllDocPathsFromProject(project) {
|
|
|
|
const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
|
|
|
|
const docPath = {}
|
|
|
|
for (const { path: folderPath, folder } of folders) {
|
|
|
|
for (const doc of folder.docs || []) {
|
|
|
|
docPath[doc._id] = path.join(folderPath, doc.name)
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-12-06 10:27:12 -05:00
|
|
|
}
|
|
|
|
return docPath
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
getDoc(projectId, docId, options, callback) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (options == null) {
|
|
|
|
options = {}
|
|
|
|
}
|
|
|
|
if (typeof options === 'function') {
|
|
|
|
callback = options
|
|
|
|
options = {}
|
|
|
|
}
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
DocstoreManager.getDoc(projectId, docId, options, callback)
|
2019-05-29 05:21:06 -04:00
|
|
|
},
|
|
|
|
|
2021-06-23 09:13:49 -04:00
|
|
|
/**
|
|
|
|
* @param {ObjectID | string} projectId
|
|
|
|
* @param {ObjectID | string} docId
|
|
|
|
* @param {Function} callback
|
|
|
|
*/
|
2019-11-26 08:11:19 -05:00
|
|
|
getDocPathByProjectIdAndDocId(projectId, docId, callback) {
|
|
|
|
ProjectGetter.getProjectWithoutDocLines(projectId, (err, project) => {
|
2019-10-03 10:10:00 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
|
|
|
return callback(new Errors.NotFoundError('no project'))
|
|
|
|
}
|
2021-06-23 09:13:49 -04:00
|
|
|
ProjectEntityHandler.getDocPathFromProjectByDocId(
|
|
|
|
project,
|
|
|
|
docId,
|
|
|
|
(err, docPath) => {
|
|
|
|
if (err) return callback(Errors.OError.tag(err))
|
|
|
|
if (docPath == null) {
|
|
|
|
return callback(new Errors.NotFoundError('no doc'))
|
2019-10-03 10:10:00 -04:00
|
|
|
}
|
2021-06-23 09:13:49 -04:00
|
|
|
callback(null, docPath)
|
2019-10-03 10:10:00 -04:00
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2021-06-23 09:13:49 -04:00
|
|
|
/**
|
|
|
|
* @param {Project} project
|
|
|
|
* @param {ObjectID | string} docId
|
|
|
|
* @param {Function} callback
|
|
|
|
*/
|
|
|
|
getDocPathFromProjectByDocId(project, docId, callback) {
|
|
|
|
function recursivelyFindDocInFolder(basePath, docId, folder) {
|
|
|
|
const docInCurrentFolder = (folder.docs || []).find(
|
|
|
|
currentDoc => currentDoc._id.toString() === docId.toString()
|
|
|
|
)
|
|
|
|
if (docInCurrentFolder != null) {
|
|
|
|
return path.join(basePath, docInCurrentFolder.name)
|
|
|
|
} else {
|
|
|
|
let docPath, childFolder
|
|
|
|
for (childFolder of folder.folders || []) {
|
|
|
|
docPath = recursivelyFindDocInFolder(
|
|
|
|
path.join(basePath, childFolder.name),
|
|
|
|
docId,
|
|
|
|
childFolder
|
|
|
|
)
|
|
|
|
if (docPath != null) {
|
|
|
|
return docPath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const docPath = recursivelyFindDocInFolder(
|
|
|
|
'/',
|
|
|
|
docId,
|
|
|
|
project.rootFolder[0]
|
|
|
|
)
|
|
|
|
callback(null, docPath)
|
|
|
|
},
|
|
|
|
|
2019-11-26 08:11:19 -05:00
|
|
|
_getAllFolders(projectId, callback) {
|
|
|
|
ProjectGetter.getProjectWithoutDocLines(projectId, (err, project) => {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
if (project == null) {
|
2019-10-07 11:21:04 -04:00
|
|
|
return callback(new Errors.NotFoundError('no project'))
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-12-06 10:27:12 -05:00
|
|
|
const folders = ProjectEntityHandler._getAllFoldersFromProject(project)
|
|
|
|
callback(null, folders)
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
2021-12-06 10:27:12 -05:00
|
|
|
_getAllFoldersFromProject(project) {
|
2021-11-11 10:10:46 -05:00
|
|
|
const folders = []
|
2022-03-21 10:47:17 -04:00
|
|
|
try {
|
|
|
|
const processFolder = (basePath, folder) => {
|
|
|
|
folders.push({ path: basePath, folder })
|
|
|
|
if (folder.folders) {
|
|
|
|
for (const childFolder of folder.folders) {
|
|
|
|
if (childFolder.name != null) {
|
|
|
|
const childPath = path.join(basePath, childFolder.name)
|
|
|
|
processFolder(childPath, childFolder)
|
|
|
|
}
|
|
|
|
}
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2019-11-26 08:11:19 -05:00
|
|
|
}
|
2022-03-21 10:47:17 -04:00
|
|
|
processFolder('/', project.rootFolder[0])
|
|
|
|
return folders
|
|
|
|
} catch (err) {
|
|
|
|
throw OError.tag(err, 'Error getting folders', { projectId: project._id })
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2019-09-09 07:52:25 -04:00
|
|
|
|
|
|
|
module.exports = ProjectEntityHandler
|
2019-11-12 03:56:58 -05:00
|
|
|
module.exports.promises = promisifyAll(ProjectEntityHandler, {
|
2021-12-06 10:27:12 -05:00
|
|
|
without: ['getAllEntitiesFromProject'],
|
2019-11-12 03:56:58 -05:00
|
|
|
multiResult: {
|
|
|
|
getAllEntities: ['docs', 'files'],
|
2021-04-27 03:52:58 -04:00
|
|
|
getDoc: ['lines', 'rev', 'version', 'ranges'],
|
|
|
|
},
|
2019-11-12 03:56:58 -05:00
|
|
|
})
|