mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
refactor(socket.io): deprecate categories.categorySearch in favour of api.search.categories
THIS IS WIP
This commit is contained in:
@@ -9,6 +9,7 @@ module.exports = {
|
|||||||
posts: require('./posts'),
|
posts: require('./posts'),
|
||||||
chats: require('./chats'),
|
chats: require('./chats'),
|
||||||
categories: require('./categories'),
|
categories: require('./categories'),
|
||||||
|
search: require('./search'),
|
||||||
flags: require('./flags'),
|
flags: require('./flags'),
|
||||||
files: require('./files'),
|
files: require('./files'),
|
||||||
utils: require('./utils'),
|
utils: require('./utils'),
|
||||||
|
|||||||
104
src/api/search.js
Normal file
104
src/api/search.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
const categories = require('../categories');
|
||||||
|
const privileges = require('../privileges');
|
||||||
|
const meta = require('../meta');
|
||||||
|
const plugins = require('../plugins');
|
||||||
|
|
||||||
|
const controllersHelpers = require('../controllers/helpers');
|
||||||
|
|
||||||
|
const searchApi = module.exports;
|
||||||
|
|
||||||
|
searchApi.categories = async (caller, data) => {
|
||||||
|
// used by categorySearch module
|
||||||
|
|
||||||
|
let cids = [];
|
||||||
|
let matchedCids = [];
|
||||||
|
const privilege = data.privilege || 'topics:read';
|
||||||
|
data.states = (data.states || ['watching', 'notwatching', 'ignoring']).map(
|
||||||
|
state => categories.watchStates[state]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (data.search) {
|
||||||
|
({ cids, matchedCids } = await findMatchedCids(caller.uid, data));
|
||||||
|
} else {
|
||||||
|
cids = await loadCids(caller.uid, data.parentCid);
|
||||||
|
}
|
||||||
|
|
||||||
|
const visibleCategories = await controllersHelpers.getVisibleCategories({
|
||||||
|
cids, uid: caller.uid, states: data.states, privilege, showLinks: data.showLinks, parentCid: data.parentCid,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Array.isArray(data.selectedCids)) {
|
||||||
|
data.selectedCids = data.selectedCids.map(cid => parseInt(cid, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
let categoriesData = categories.buildForSelectCategories(visibleCategories, ['disabledClass'], data.parentCid);
|
||||||
|
categoriesData = categoriesData.slice(0, 200);
|
||||||
|
|
||||||
|
categoriesData.forEach((category) => {
|
||||||
|
category.selected = data.selectedCids ? data.selectedCids.includes(category.cid) : false;
|
||||||
|
if (matchedCids.includes(category.cid)) {
|
||||||
|
category.match = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const result = await plugins.hooks.fire('filter:categories.categorySearch', {
|
||||||
|
categories: categoriesData,
|
||||||
|
...data,
|
||||||
|
uid: caller.uid,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { categories: result.categories };
|
||||||
|
};
|
||||||
|
|
||||||
|
async function findMatchedCids(uid, data) {
|
||||||
|
const result = await categories.search({
|
||||||
|
uid: uid,
|
||||||
|
query: data.search,
|
||||||
|
qs: data.query,
|
||||||
|
paginate: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let matchedCids = result.categories.map(c => c.cid);
|
||||||
|
// no need to filter if all 3 states are used
|
||||||
|
const filterByWatchState = !Object.values(categories.watchStates)
|
||||||
|
.every(state => data.states.includes(state));
|
||||||
|
|
||||||
|
if (filterByWatchState) {
|
||||||
|
const states = await categories.getWatchState(matchedCids, uid);
|
||||||
|
matchedCids = matchedCids.filter((cid, index) => data.states.includes(states[index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootCids = _.uniq(_.flatten(await Promise.all(matchedCids.map(categories.getParentCids))));
|
||||||
|
const allChildCids = _.uniq(_.flatten(await Promise.all(matchedCids.map(categories.getChildrenCids))));
|
||||||
|
|
||||||
|
return {
|
||||||
|
cids: _.uniq(rootCids.concat(allChildCids).concat(matchedCids)),
|
||||||
|
matchedCids: matchedCids,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCids(uid, parentCid) {
|
||||||
|
let resultCids = [];
|
||||||
|
async function getCidsRecursive(cids) {
|
||||||
|
const categoryData = await categories.getCategoriesFields(cids, ['subCategoriesPerPage']);
|
||||||
|
const cidToData = _.zipObject(cids, categoryData);
|
||||||
|
await Promise.all(cids.map(async (cid) => {
|
||||||
|
const allChildCids = await categories.getAllCidsFromSet(`cid:${cid}:children`);
|
||||||
|
if (allChildCids.length) {
|
||||||
|
const childCids = await privileges.categories.filterCids('find', allChildCids, uid);
|
||||||
|
resultCids.push(...childCids.slice(0, cidToData[cid].subCategoriesPerPage));
|
||||||
|
await getCidsRecursive(childCids);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const allRootCids = await categories.getAllCidsFromSet(`cid:${parentCid}:children`);
|
||||||
|
const rootCids = await privileges.categories.filterCids('find', allRootCids, uid);
|
||||||
|
const pageCids = rootCids.slice(0, meta.config.categoriesPerPage);
|
||||||
|
resultCids = pageCids;
|
||||||
|
await getCidsRecursive(pageCids);
|
||||||
|
return resultCids;
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ Write.tags = require('./tags');
|
|||||||
Write.posts = require('./posts');
|
Write.posts = require('./posts');
|
||||||
Write.chats = require('./chats');
|
Write.chats = require('./chats');
|
||||||
Write.flags = require('./flags');
|
Write.flags = require('./flags');
|
||||||
|
Write.search = require('./search');
|
||||||
Write.admin = require('./admin');
|
Write.admin = require('./admin');
|
||||||
Write.files = require('./files');
|
Write.files = require('./files');
|
||||||
Write.utilities = require('./utilities');
|
Write.utilities = require('./utilities');
|
||||||
|
|||||||
10
src/controllers/write/search.js
Normal file
10
src/controllers/write/search.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const api = require('../../api');
|
||||||
|
const helpers = require('../helpers');
|
||||||
|
|
||||||
|
const Search = module.exports;
|
||||||
|
|
||||||
|
Search.categories = async (req, res) => {
|
||||||
|
helpers.formatApiResponse(200, res, await api.search.categories(req, req.query));
|
||||||
|
};
|
||||||
@@ -41,6 +41,7 @@ Write.reload = async (params) => {
|
|||||||
router.use('/api/v3/posts', require('./posts')());
|
router.use('/api/v3/posts', require('./posts')());
|
||||||
router.use('/api/v3/chats', require('./chats')());
|
router.use('/api/v3/chats', require('./chats')());
|
||||||
router.use('/api/v3/flags', require('./flags')());
|
router.use('/api/v3/flags', require('./flags')());
|
||||||
|
router.use('/api/v3/search', require('./search')());
|
||||||
router.use('/api/v3/admin', require('./admin')());
|
router.use('/api/v3/admin', require('./admin')());
|
||||||
router.use('/api/v3/files', require('./files')());
|
router.use('/api/v3/files', require('./files')());
|
||||||
router.use('/api/v3/utilities', require('./utilities')());
|
router.use('/api/v3/utilities', require('./utilities')());
|
||||||
|
|||||||
19
src/routes/write/search.js
Normal file
19
src/routes/write/search.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const router = require('express').Router();
|
||||||
|
// const middleware = require('../../middleware');
|
||||||
|
const controllers = require('../../controllers');
|
||||||
|
const routeHelpers = require('../helpers');
|
||||||
|
|
||||||
|
const { setupApiRoute } = routeHelpers;
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
// const middlewares = [];
|
||||||
|
|
||||||
|
// maybe redirect to /search/posts?
|
||||||
|
// setupApiRoute(router, 'post', '/', [...middlewares], controllers.write.search.TBD);
|
||||||
|
|
||||||
|
setupApiRoute(router, 'get', '/categories', [], controllers.write.search.categories);
|
||||||
|
|
||||||
|
return router;
|
||||||
|
};
|
||||||
@@ -1,101 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const sockets = require('..');
|
||||||
|
const api = require('../../api');
|
||||||
const meta = require('../../meta');
|
|
||||||
const categories = require('../../categories');
|
|
||||||
const privileges = require('../../privileges');
|
|
||||||
const controllersHelpers = require('../../controllers/helpers');
|
|
||||||
const plugins = require('../../plugins');
|
|
||||||
|
|
||||||
module.exports = function (SocketCategories) {
|
module.exports = function (SocketCategories) {
|
||||||
// used by categorySearch module
|
|
||||||
SocketCategories.categorySearch = async function (socket, data) {
|
SocketCategories.categorySearch = async function (socket, data) {
|
||||||
let cids = [];
|
sockets.warnDeprecated(socket, 'GET /api/v3/search/categories');
|
||||||
let matchedCids = [];
|
|
||||||
const privilege = data.privilege || 'topics:read';
|
|
||||||
data.states = (data.states || ['watching', 'notwatching', 'ignoring']).map(
|
|
||||||
state => categories.watchStates[state]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data.search) {
|
const { categories } = await api.search.categories(socket, data);
|
||||||
({ cids, matchedCids } = await findMatchedCids(socket.uid, data));
|
return categories;
|
||||||
} else {
|
|
||||||
cids = await loadCids(socket.uid, data.parentCid);
|
|
||||||
}
|
|
||||||
|
|
||||||
const visibleCategories = await controllersHelpers.getVisibleCategories({
|
|
||||||
cids, uid: socket.uid, states: data.states, privilege, showLinks: data.showLinks, parentCid: data.parentCid,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Array.isArray(data.selectedCids)) {
|
|
||||||
data.selectedCids = data.selectedCids.map(cid => parseInt(cid, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
let categoriesData = categories.buildForSelectCategories(visibleCategories, ['disabledClass'], data.parentCid);
|
|
||||||
categoriesData = categoriesData.slice(0, 200);
|
|
||||||
|
|
||||||
categoriesData.forEach((category) => {
|
|
||||||
category.selected = data.selectedCids ? data.selectedCids.includes(category.cid) : false;
|
|
||||||
if (matchedCids.includes(category.cid)) {
|
|
||||||
category.match = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const result = await plugins.hooks.fire('filter:categories.categorySearch', {
|
|
||||||
categories: categoriesData,
|
|
||||||
...data,
|
|
||||||
uid: socket.uid,
|
|
||||||
});
|
|
||||||
return result.categories;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function findMatchedCids(uid, data) {
|
|
||||||
const result = await categories.search({
|
|
||||||
uid: uid,
|
|
||||||
query: data.search,
|
|
||||||
qs: data.query,
|
|
||||||
paginate: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let matchedCids = result.categories.map(c => c.cid);
|
|
||||||
// no need to filter if all 3 states are used
|
|
||||||
const filterByWatchState = !Object.values(categories.watchStates)
|
|
||||||
.every(state => data.states.includes(state));
|
|
||||||
|
|
||||||
if (filterByWatchState) {
|
|
||||||
const states = await categories.getWatchState(matchedCids, uid);
|
|
||||||
matchedCids = matchedCids.filter((cid, index) => data.states.includes(states[index]));
|
|
||||||
}
|
|
||||||
|
|
||||||
const rootCids = _.uniq(_.flatten(await Promise.all(matchedCids.map(categories.getParentCids))));
|
|
||||||
const allChildCids = _.uniq(_.flatten(await Promise.all(matchedCids.map(categories.getChildrenCids))));
|
|
||||||
|
|
||||||
return {
|
|
||||||
cids: _.uniq(rootCids.concat(allChildCids).concat(matchedCids)),
|
|
||||||
matchedCids: matchedCids,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadCids(uid, parentCid) {
|
|
||||||
let resultCids = [];
|
|
||||||
async function getCidsRecursive(cids) {
|
|
||||||
const categoryData = await categories.getCategoriesFields(cids, ['subCategoriesPerPage']);
|
|
||||||
const cidToData = _.zipObject(cids, categoryData);
|
|
||||||
await Promise.all(cids.map(async (cid) => {
|
|
||||||
const allChildCids = await categories.getAllCidsFromSet(`cid:${cid}:children`);
|
|
||||||
if (allChildCids.length) {
|
|
||||||
const childCids = await privileges.categories.filterCids('find', allChildCids, uid);
|
|
||||||
resultCids.push(...childCids.slice(0, cidToData[cid].subCategoriesPerPage));
|
|
||||||
await getCidsRecursive(childCids);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const allRootCids = await categories.getAllCidsFromSet(`cid:${parentCid}:children`);
|
|
||||||
const rootCids = await privileges.categories.filterCids('find', allRootCids, uid);
|
|
||||||
const pageCids = rootCids.slice(0, meta.config.categoriesPerPage);
|
|
||||||
resultCids = pageCids;
|
|
||||||
await getCidsRecursive(pageCids);
|
|
||||||
return resultCids;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user