mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-08-07 15:50:14 +02:00
closes #3447
recursively get all children calculate topic/post count from children new sorted set `cid:<id>:children` fix search query params
This commit is contained in:
@@ -503,7 +503,7 @@ app.cacheBuster = null;
|
||||
|
||||
app.load = function() {
|
||||
$('document').ready(function () {
|
||||
var url = ajaxify.start(window.location.pathname.slice(1), true, window.location.search);
|
||||
var url = ajaxify.start(window.location.pathname.slice(1) + window.location.search, true);
|
||||
ajaxify.end(url, app.template);
|
||||
|
||||
handleStatusChange();
|
||||
|
||||
@@ -103,10 +103,10 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
Categories.getCategoriesByPrivilege = function(uid, privilege, callback) {
|
||||
Categories.getCategoriesByPrivilege = function(set, uid, privilege, callback) {
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
db.getSortedSetRange('categories:cid', 0, -1, next);
|
||||
db.getSortedSetRange(set, 0, -1, next);
|
||||
},
|
||||
function(cids, next) {
|
||||
privileges.categories.filterCids(privilege, cids, uid, next);
|
||||
@@ -273,6 +273,7 @@ var async = require('async'),
|
||||
if (!category) {
|
||||
return;
|
||||
}
|
||||
|
||||
var postCount = parseInt(category.post_count, 10) || 0;
|
||||
var topicCount = parseInt(category.topic_count, 10) || 0;
|
||||
if (!Array.isArray(category.children) || !category.children.length) {
|
||||
@@ -282,9 +283,11 @@ var async = require('async'),
|
||||
}
|
||||
|
||||
category.children.forEach(function(child) {
|
||||
postCount += parseInt(child.post_count, 10) || 0;
|
||||
topicCount += parseInt(child.topic_count, 10) || 0;
|
||||
calculateTopicPostCount(child);
|
||||
postCount += parseInt(child.totalPostCount, 10) || 0;
|
||||
topicCount += parseInt(child.totalTopicCount, 10) || 0;
|
||||
});
|
||||
|
||||
category.totalPostCount = postCount;
|
||||
category.totalTopicCount = topicCount;
|
||||
}
|
||||
@@ -308,23 +311,58 @@ var async = require('async'),
|
||||
};
|
||||
|
||||
Categories.getChildren = function(cids, uid, callback) {
|
||||
var categories = cids.map(function(cid) {
|
||||
return {cid: cid};
|
||||
});
|
||||
|
||||
async.each(categories, function(category, next) {
|
||||
getChildrenRecursive(category, category.cid, uid, next);
|
||||
}, function (err) {
|
||||
callback(err, categories.map(function(c) {
|
||||
return c && c.children;
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
function getChildrenRecursive(category, parentCid, uid, callback) {
|
||||
async.waterfall([
|
||||
async.apply(db.getSortedSetRange, 'categories:cid', 0, -1),
|
||||
function(cids, next) {
|
||||
privileges.categories.filterCids('find', cids, uid, next);
|
||||
function (next) {
|
||||
db.getSortedSetRange('cid:' + parentCid + ':children', 0, -1, next);
|
||||
},
|
||||
function (cids, next) {
|
||||
Categories.getCategoriesData(cids, next);
|
||||
function (children, next) {
|
||||
privileges.categories.filterCids('find', children, uid, next);
|
||||
},
|
||||
function (categories, next) {
|
||||
async.map(cids, function(cid, next) {
|
||||
next(null, categories.filter(function(category) {
|
||||
return category && parseInt(category.parentCid, 10) === parseInt(cid, 10);
|
||||
}));
|
||||
function (children, next) {
|
||||
if (!children.length) {
|
||||
category.children = [];
|
||||
return callback();
|
||||
}
|
||||
Categories.getCategoriesData(children, next);
|
||||
},
|
||||
function (childrenData, next) {
|
||||
category.children = childrenData;
|
||||
async.each(category.children, function(child, next) {
|
||||
getChildrenRecursive(child, child.cid, uid, next);
|
||||
}, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
}
|
||||
|
||||
Categories.flattenCategories = function(allCategories, categoryData) {
|
||||
categoryData.forEach(function(category) {
|
||||
if (!category) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!category.parent) {
|
||||
allCategories.push(category);
|
||||
}
|
||||
|
||||
if (Array.isArray(category.children) && category.children.length) {
|
||||
Categories.flattenCategories(allCategories, category.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively build tree
|
||||
@@ -335,13 +373,13 @@ var async = require('async'),
|
||||
Categories.getTree = function(categories, parentCid) {
|
||||
var tree = [], i = 0, len = categories.length, category;
|
||||
|
||||
for(i; i < len; ++i) {
|
||||
for (i; i < len; ++i) {
|
||||
category = categories[i];
|
||||
if (!category.hasOwnProperty('parentCid')) {
|
||||
category.parentCid = 0;
|
||||
}
|
||||
|
||||
if(category.parentCid == parentCid){
|
||||
if (category.parentCid == parentCid){
|
||||
tree.push(category);
|
||||
category.children = Categories.getTree(categories, category.cid);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ module.exports = function(Categories) {
|
||||
|
||||
Categories.create = function(data, callback) {
|
||||
var category;
|
||||
var parentCid = data.parentCid ? data.parentCid : 0;
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
db.incrObjectField('global', 'nextCid', next);
|
||||
@@ -27,7 +29,7 @@ module.exports = function(Categories) {
|
||||
bgColor: data.bgColor || colours[0],
|
||||
color: data.color || colours[1],
|
||||
slug: slug,
|
||||
parentCid: ( data.parentCid ? data.parentCid : 0 ),
|
||||
parentCid: parentCid,
|
||||
topic_count: 0,
|
||||
post_count: 0,
|
||||
disabled: 0,
|
||||
@@ -48,6 +50,7 @@ module.exports = function(Categories) {
|
||||
async.series([
|
||||
async.apply(db.setObject, 'category:' + category.cid, category),
|
||||
async.apply(db.sortedSetAdd, 'categories:cid', category.order, category.cid),
|
||||
async.apply(db.sortedSetAdd, 'cid:' + parentCid + ':children', category.order, category.cid),
|
||||
async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'administrators'),
|
||||
async.apply(privileges.categories.give, defaultPrivileges, category.cid, 'registered-users'),
|
||||
async.apply(privileges.categories.give, ['find', 'read'], category.cid, 'guests')
|
||||
|
||||
@@ -30,15 +30,32 @@ module.exports = function(Categories) {
|
||||
function(next) {
|
||||
db.sortedSetRemove('categories:cid', cid, next);
|
||||
},
|
||||
function(next) {
|
||||
removeFromParent(cid, next);
|
||||
},
|
||||
function(next) {
|
||||
db.deleteAll([
|
||||
'cid:' + cid + ':tids',
|
||||
'cid:' + cid + ':tids:posts',
|
||||
'cid:' + cid + ':pids',
|
||||
'cid:' + cid + ':read_by_uid',
|
||||
'cid:' + cid + ':children',
|
||||
'category:' + cid
|
||||
], next);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
function removeFromParent(cid, callback) {
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
Categories.getCategoryField(cid, 'parentCid', next);
|
||||
},
|
||||
function(parentCid, next) {
|
||||
parentCid = parseInt(parentCid, 10) || 0;
|
||||
db.sortedSetRemove('cid:' + parentCid + ':children', cid, next);
|
||||
}
|
||||
], callback);
|
||||
|
||||
}
|
||||
};
|
||||
@@ -50,17 +50,63 @@ module.exports = function(Categories) {
|
||||
};
|
||||
|
||||
function updateCategoryField(cid, key, value, callback) {
|
||||
if (key === 'parentCid') {
|
||||
return updateParent(cid, value, callback);
|
||||
}
|
||||
|
||||
db.setObjectField('category:' + cid, key, value, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (key === 'order') {
|
||||
db.sortedSetAdd('categories:cid', value, cid, callback);
|
||||
updateOrder(cid, value, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateParent(cid, newParent, callback) {
|
||||
Categories.getCategoryField(cid, 'parentCid', function(err, oldParent) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.series([
|
||||
function (next) {
|
||||
oldParent = parseInt(oldParent, 10) || 0;
|
||||
db.sortedSetRemove('cid:' + oldParent + ':children', cid, next);
|
||||
},
|
||||
function (next) {
|
||||
newParent = parseInt(newParent, 10) || 0;
|
||||
db.sortedSetAdd('cid:' + newParent + ':children', cid, cid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.setObjectField('category:' + cid, 'parentCid', newParent, next);
|
||||
}
|
||||
], function(err, results) {
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateOrder(cid, order, callback) {
|
||||
Categories.getCategoryField(cid, 'parentCid', function(err, parentCid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.parallel([
|
||||
function (next) {
|
||||
db.sortedSetAdd('categories:cid', order, cid, next);
|
||||
},
|
||||
function (next) {
|
||||
parentCid = parseInt(parentCid, 10) || 0;
|
||||
db.sortedSetAdd('cid:' + parentCid + ':children', order, cid, next);
|
||||
}
|
||||
], callback);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ categoriesController.list = function(req, res, next) {
|
||||
content: 'website'
|
||||
}];
|
||||
|
||||
if(meta.config['brand:logo']) {
|
||||
if (meta.config['brand:logo']) {
|
||||
res.locals.metaTags.push({
|
||||
property: 'og:image',
|
||||
content: meta.config['brand:logo']
|
||||
@@ -46,22 +46,13 @@ categoriesController.list = function(req, res, next) {
|
||||
var categoryData;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
categories.getCategoriesByPrivilege(req.uid, 'find', next);
|
||||
categories.getCategoriesByPrivilege('cid:0:children', req.uid, 'find', next);
|
||||
},
|
||||
function(_categoryData, next) {
|
||||
categoryData = _categoryData;
|
||||
|
||||
var allCategories = [];
|
||||
|
||||
categoryData = categoryData.filter(function(category) {
|
||||
if (!category.parent) {
|
||||
allCategories.push(category);
|
||||
}
|
||||
|
||||
if (Array.isArray(category.children) && category.children.length) {
|
||||
allCategories.push.apply(allCategories, category.children);
|
||||
}
|
||||
return category && !category.parent;
|
||||
});
|
||||
categories.flattenCategories(allCategories, categoryData);
|
||||
|
||||
categories.getRecentTopicReplies(allCategories, req.uid, next);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ searchController.search = function(req, res, next) {
|
||||
|
||||
var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]);
|
||||
|
||||
categories.getCategoriesByPrivilege(req.uid, 'read', function(err, categories) {
|
||||
categories.getCategoriesByPrivilege('categories:cid', req.uid, 'read', function(err, categories) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -417,11 +417,14 @@ function getChildrenCids(cids, uid, callback) {
|
||||
}
|
||||
|
||||
var childrenCids = [];
|
||||
var allCategories = [];
|
||||
|
||||
childrenCategories.forEach(function(childrens) {
|
||||
childrenCids = childrenCids.concat(childrens.map(function(category) {
|
||||
return category && category.cid;
|
||||
}));
|
||||
});
|
||||
categories.flattenCategories(allCategories, childrens);
|
||||
childrenCids = childrenCids.concat(allCategories.map(function(category) {
|
||||
return category && category.cid;
|
||||
}));
|
||||
});
|
||||
|
||||
callback(null, childrenCids);
|
||||
});
|
||||
|
||||
@@ -61,7 +61,7 @@ sitemap.getDynamicUrls = function(callback) {
|
||||
async.parallel({
|
||||
categoryUrls: function(next) {
|
||||
var categoryUrls = [];
|
||||
categories.getCategoriesByPrivilege(0, 'find', function(err, categoriesData) {
|
||||
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Categories.create = function(socket, data, callback) {
|
||||
|
||||
Categories.getAll = function(socket, data, callback) {
|
||||
async.waterfall([
|
||||
async.apply(db.getSortedSetRangeByScore, 'categories:cid', 0, -1, 0, Date.now()),
|
||||
async.apply(db.getSortedSetRange, 'categories:cid', 0, -1),
|
||||
async.apply(categories.getCategoriesData),
|
||||
function(categories, next) {
|
||||
//Hook changes, there is no req, and res
|
||||
|
||||
@@ -15,7 +15,7 @@ SocketCategories.getRecentReplies = function(socket, cid, callback) {
|
||||
};
|
||||
|
||||
SocketCategories.get = function(socket, data, callback) {
|
||||
categories.getCategoriesByPrivilege(socket.uid, 'find', callback);
|
||||
categories.getCategoriesByPrivilege('categories:cid', socket.uid, 'find', callback);
|
||||
};
|
||||
|
||||
SocketCategories.getWatchedCategories = function(socket, data, callback) {
|
||||
@@ -117,7 +117,7 @@ SocketCategories.getUsersInCategory = function(socket, cid, callback) {
|
||||
};
|
||||
|
||||
SocketCategories.getCategoriesByPrivilege = function(socket, privilege, callback) {
|
||||
categories.getCategoriesByPrivilege(socket.uid, privilege, callback);
|
||||
categories.getCategoriesByPrivilege('categories:cid', socket.uid, privilege, callback);
|
||||
};
|
||||
|
||||
SocketCategories.watch = function(socket, cid, callback) {
|
||||
|
||||
@@ -21,7 +21,7 @@ var db = require('./database'),
|
||||
schemaDate, thisSchemaDate,
|
||||
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
|
||||
latestSchema = Date.UTC(2015, 6, 3);
|
||||
latestSchema = Date.UTC(2015, 7, 18);
|
||||
|
||||
Upgrade.check = function(callback) {
|
||||
db.get('schemaDate', function(err, value) {
|
||||
@@ -446,6 +446,46 @@ Upgrade.upgrade = function(callback) {
|
||||
winston.info('[2015/07/03] Enabling default composer plugin skipped');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
thisSchemaDate = Date.UTC(2015, 7, 18);
|
||||
if (schemaDate < thisSchemaDate) {
|
||||
updatesMade = true;
|
||||
winston.info('[2015/08/18] Creating children category sorted sets');
|
||||
|
||||
db.getSortedSetRange('categories:cid', 0, -1, function(err, cids) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
async.each(cids, function(cid, next) {
|
||||
db.getObjectFields('category:' + cid, ['parentCid', 'order'], function(err, category) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (!category) {
|
||||
return next();
|
||||
}
|
||||
if (parseInt(category.parentCid, 10)) {
|
||||
db.sortedSetAdd('cid:' + category.parentCid + ':children', parseInt(category.order, 10), cid, next);
|
||||
} else {
|
||||
db.sortedSetAdd('cid:0:children', parseInt(category.order, 10), cid, next);
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
winston.info('[2015/08/18] Creating children category sorted sets done');
|
||||
Upgrade.update(thisSchemaDate, next);
|
||||
});
|
||||
});
|
||||
|
||||
} else {
|
||||
winston.info('[2015/08/18] Creating children category sorted sets skipped');
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user