Merge remote-tracking branch 'origin/search-cid-uid'

v1.18.x
Barış Soner Uşaklı 10 years ago
commit 877b2d51fc

@ -89,8 +89,8 @@ define('forum/category', [
}); });
}; };
Category.navigatorCallback = function(element, elementCount) { Category.navigatorCallback = function(topIndex, bottomIndex, elementCount) {
return parseInt(element.attr('data-index'), 10) + 1; return bottomIndex;
}; };
$(window).on('action:popstate', function(ev, data) { $(window).on('action:popstate', function(ev, data) {

@ -148,18 +148,18 @@ define('forum/topic', [
return index; return index;
}; };
Topic.navigatorCallback = function(element, elementCount) { Topic.navigatorCallback = function(topPostIndex, bottomPostIndex, elementCount) {
var path = ajaxify.removeRelativePath(window.location.pathname.slice(1)); var path = ajaxify.removeRelativePath(window.location.pathname.slice(1));
if (!path.startsWith('topic')) { if (!path.startsWith('topic')) {
return 1; return 1;
} }
var postIndex = parseInt(element.attr('data-index'), 10); var postIndex = topPostIndex;
var index = postIndex + 1; var index = bottomPostIndex;
if (config.topicPostSort !== 'oldest_to_newest') { if (config.topicPostSort !== 'oldest_to_newest') {
if (postIndex === 0) { if (bottomPostIndex === 0) {
index = 1; index = 1;
} else { } else {
index = Math.max(elementCount - postIndex + 1, 1); index = Math.max(elementCount - bottomPostIndex + 2, 1);
} }
} }
@ -175,8 +175,8 @@ define('forum/topic', [
var topicId = parts[1], var topicId = parts[1],
slug = parts[2]; slug = parts[2];
var newUrl = 'topic/' + topicId + '/' + (slug ? slug : ''); var newUrl = 'topic/' + topicId + '/' + (slug ? slug : '');
if (postIndex > 0) { if (postIndex > 1) {
newUrl += '/' + (postIndex + 1); newUrl += '/' + postIndex;
} }
if (newUrl !== currentUrl) { if (newUrl !== currentUrl) {

@ -90,18 +90,26 @@ define('navigator', ['forum/pagination'], function(pagination) {
navigator.update = function() { navigator.update = function() {
toggle(!!count); toggle(!!count);
$($(navigator.selector).get().reverse()).each(function() { var topIndex = 0;
var bottomIndex = 0;
$(navigator.selector).each(function() {
var el = $(this); var el = $(this);
if (elementInView(el)) { if (elementInView(el)) {
if (typeof navigator.callback === 'function') { if (!topIndex) {
index = navigator.callback(el, count); topIndex = parseInt(el.attr('data-index'), 10) + 1;
navigator.updateTextAndProgressBar(); } else {
bottomIndex = parseInt(el.attr('data-index'), 10) + 1;
} }
} else if (topIndex && bottomIndex) {
return false; return false;
} }
}); });
if (typeof navigator.callback === 'function' && topIndex && bottomIndex) {
index = navigator.callback(topIndex, bottomIndex, count);
navigator.updateTextAndProgressBar();
}
}; };
navigator.updateTextAndProgressBar = function() { navigator.updateTextAndProgressBar = function() {

@ -50,7 +50,7 @@ define('share', function() {
function getPostUrl(clickedElement) { function getPostUrl(clickedElement) {
var parts = window.location.pathname.split('/'); var parts = window.location.pathname.split('/');
var postIndex = parseInt(clickedElement.parents('data-index').attr('data-index'), 10); var postIndex = parseInt(clickedElement.parents('[data-index]').attr('data-index'), 10);
return '/' + parts[1] + '/' + parts[2] + (parts[3] ? '/' + parts[3] : '') + (postIndex ? '/' + (postIndex + 1) : ''); return '/' + parts[1] + '/' + parts[2] + (parts[3] ? '/' + parts[3] : '') + (postIndex ? '/' + (postIndex + 1) : '');
} }

@ -74,37 +74,29 @@ module.exports = function(Categories) {
}); });
}; };
Categories.onNewPostMade = function(postData, callback) { Categories.onNewPostMade = function(cid, pinned, postData, callback) {
topics.getTopicFields(postData.tid, ['cid', 'pinned'], function(err, topicData) { if (!cid || !postData) {
if (err) { return callback();
return callback(err); }
}
if (!topicData || !topicData.cid) {
return callback();
}
var cid = topicData.cid;
async.parallel([ async.parallel([
function(next) { function(next) {
db.sortedSetAdd('cid:' + cid + ':pids', postData.timestamp, postData.pid, next); db.sortedSetAdd('cid:' + cid + ':pids', postData.timestamp, postData.pid, next);
}, },
function(next) { function(next) {
db.incrObjectField('category:' + cid, 'post_count', next); db.incrObjectField('category:' + cid, 'post_count', next);
}, },
function(next) { function(next) {
if (parseInt(topicData.pinned, 10) === 1) { if (parseInt(pinned, 10) === 1) {
next(); next();
} else { } else {
db.sortedSetAdd('cid:' + cid + ':tids', postData.timestamp, postData.tid, next); db.sortedSetAdd('cid:' + cid + ':tids', postData.timestamp, postData.tid, next);
}
},
function(next) {
db.sortedSetIncrBy('cid:' + cid + ':tids:posts', 1, postData.tid, next);
} }
], callback); },
}); function(next) {
db.sortedSetIncrBy('cid:' + cid + ':tids:posts', 1, postData.tid, next);
}
], callback);
}; };
}; };

@ -110,8 +110,14 @@
createIndex('objects', {_key: 1, value: -1}, {background:true}); createIndex('objects', {_key: 1, value: -1}, {background:true});
createIndex('objects', {expireAt: 1}, {expireAfterSeconds:0, background:true}); createIndex('objects', {expireAt: 1}, {expireAfterSeconds:0, background:true});
createIndex('search', {content:'text'}, {background:true});
createIndex('search', {key: 1, id: 1}, {background:true}); createIndex('searchtopic', {content: 'text', uid: 1, cid: 1}, {background:true});
createIndex('searchtopic', {id: 1}, {background:true});
createIndex('searchpost', {content: 'text', uid: 1, cid: 1}, {background:true});
createIndex('searchpost', {id: 1}, {background:true});
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(); callback();

@ -5,15 +5,18 @@ var winston = require('winston');
module.exports = function(db, module) { module.exports = function(db, module) {
var helpers = module.helpers.mongo; var helpers = module.helpers.mongo;
module.searchIndex = function(key, content, id, callback) { module.searchIndex = function(key, data, id, callback) {
callback = callback || function() {}; callback = callback || function() {};
var data = { var setData = {
id: id, id: id
key: key,
content: content
}; };
for(var field in data) {
if (data.hasOwnProperty(field) && data[field]) {
setData[field] = data[field].toString();
}
}
db.collection('search').update({key:key, id:id}, {$set:data}, {upsert:true, w: 1}, function(err) { db.collection('search' + key).update({id: id}, {$set: setData}, {upsert:true, w: 1}, function(err) {
if(err) { if(err) {
winston.error('Error indexing ' + err.message); winston.error('Error indexing ' + err.message);
} }
@ -21,13 +24,35 @@ module.exports = function(db, module) {
}); });
}; };
module.search = function(key, term, limit, callback) { module.search = function(key, data, limit, callback) {
db.collection('search').find({ $text: { $search: term }, key: key}, {limit: limit}).toArray(function(err, results) { var searchQuery = {};
if(err) {
if (data.content) {
searchQuery.$text = {$search: data.content};
}
if (Array.isArray(data.cid) && data.cid.length) {
if (data.cid.length > 1) {
searchQuery.cid = {$in: data.cid.map(String)};
} else {
searchQuery.cid = data.cid[0].toString();
}
}
if (Array.isArray(data.uid) && data.uid.length) {
if (data.uid.length > 1) {
searchQuery.uid = {$in: data.uid.map(String)};
} else {
searchQuery.uid = data.uid[0].toString();
}
}
db.collection('search' + key).find(searchQuery, {limit: limit}).toArray(function(err, results) {
if (err) {
return callback(err); return callback(err);
} }
if(!results || !results.length) { if (!results || !results.length) {
return callback(null, []); return callback(null, []);
} }
@ -44,7 +69,9 @@ module.exports = function(db, module) {
if (!id) { if (!id) {
return callback(); return callback();
} }
db.collection('search').remove({key: key, id: id}, callback); db.collection('search' + key).remove({id: id}, function(err, res) {
callback(err);
});
}; };
module.flushdb = function(callback) { module.flushdb = function(callback) {

@ -9,7 +9,7 @@
utils = require('./../../public/src/utils.js'), utils = require('./../../public/src/utils.js'),
redis, redis,
connectRedis, connectRedis,
reds, redisSearch,
redisClient, redisClient,
postSearch, postSearch,
topicSearch; topicSearch;
@ -41,7 +41,7 @@
try { try {
redis = require('redis'); redis = require('redis');
connectRedis = require('connect-redis')(session); connectRedis = require('connect-redis')(session);
reds = require('reds'); redisSearch = require('redisearch');
} catch (err) { } catch (err) {
winston.error('Unable to initialize Redis! Is Redis installed? Error :' + err.message); winston.error('Unable to initialize Redis! Is Redis installed? Error :' + err.message);
process.exit(); process.exit();
@ -56,12 +56,8 @@
ttl: 60 * 60 * 24 * 14 ttl: 60 * 60 * 24 * 14
}); });
reds.createClient = function () { module.postSearch = redisSearch.createSearch('nodebbpostsearch', redisClient);
return reds.client || (reds.client = redisClient); module.topicSearch = redisSearch.createSearch('nodebbtopicsearch', redisClient);
};
module.postSearch = reds.createSearch('nodebbpostsearch');
module.topicSearch = reds.createSearch('nodebbtopicsearch');
require('./redis/main')(redisClient, module); require('./redis/main')(redisClient, module);
require('./redis/hash')(redisClient, module); require('./redis/hash')(redisClient, module);

@ -1,28 +1,18 @@
"use strict"; "use strict";
module.exports = function(redisClient, module) { module.exports = function(redisClient, module) {
module.searchIndex = function(key, content, id, callback) { module.searchIndex = function(key, data, id, callback) {
if (key === 'post') { var method = key === 'post' ? module.postSearch : module.topicSearch;
module.postSearch.index(content, id, callback);
} else if(key === 'topic') { method.index(data, id, function(err, res) {
module.topicSearch.index(content, id, callback); callback(err);
} });
}; };
module.search = function(key, term, limit, callback) { module.search = function(key, data, limit, callback) {
function search(searchObj, callback) { var method = key === 'post' ? module.postSearch : module.topicSearch;
searchObj
.query(term)
.between(0, limit - 1)
.type('or')
.end(callback);
}
if(key === 'post') { method.query(data, 0, limit - 1, callback);
search(module.postSearch, callback);
} else if(key === 'topic') {
search(module.topicSearch, callback);
}
}; };
module.searchRemove = function(key, id, callback) { module.searchRemove = function(key, id, callback) {
@ -30,12 +20,11 @@ module.exports = function(redisClient, module) {
if (!id) { if (!id) {
return callback(); return callback();
} }
var method = key === 'post' ? module.postSearch : module.topicSearch;
if (key === 'post') { method.remove(id, function(err, res) {
module.postSearch.remove(id, callback); callback(err);
} else if(key === 'topic') { });
module.topicSearch.remove(id, callback);
}
}; };
module.flushdb = function(callback) { module.flushdb = function(callback) {

@ -19,7 +19,7 @@ var winston = require('winston'),
var cache = LRU({ var cache = LRU({
max: 1048576, max: 1048576,
length: function (n) { return n.length }, length: function (n) { return n.length; },
maxAge: 1000 * 60 * 60 maxAge: 1000 * 60 * 60
}); });
@ -63,22 +63,32 @@ var cache = LRU({
}, },
topic: function(next) { topic: function(next) {
var tid = postData.tid; var tid = postData.tid;
posts.isMain(data.pid, function(err, isMainPost) { async.parallel({
cid: function(next) {
topics.getTopicField(tid, 'cid', next);
},
isMain: function(next) {
posts.isMain(data.pid, next);
}
}, function(err, results) {
if (err) { if (err) {
return next(err); return next(err);
} }
options.tags = options.tags || []; options.tags = options.tags || [];
if (!isMainPost) { if (!results.isMain) {
return next(null, { return next(null, {
tid: tid, tid: tid,
cid: results.cid,
isMainPost: false isMainPost: false
}); });
} }
var topicData = { var topicData = {
tid: tid, tid: tid,
cid: results.cid,
uid: postData.uid,
mainPid: data.pid, mainPid: data.pid,
title: title, title: title,
slug: tid + '/' + utils.slugify(title) slug: tid + '/' + utils.slugify(title)
@ -98,8 +108,10 @@ var cache = LRU({
topics.getTopicTagsObjects(tid, function(err, tags) { topics.getTopicTagsObjects(tid, function(err, tags) {
next(err, { next(err, {
tid: tid, tid: tid,
cid: results.cid,
uid: postData.uid,
title: validator.escape(title), title: validator.escape(title),
isMainPost: isMainPost, isMainPost: results.isMain,
tags: tags tags: tags
}); });
}); });
@ -114,6 +126,7 @@ var cache = LRU({
if (err) { if (err) {
return callback(err); return callback(err);
} }
postData.cid = results.topic.cid;
results.content = results.postData.content; results.content = results.postData.content;
plugins.fireHook('action:post.edit', postData); plugins.fireHook('action:post.edit', postData);

@ -68,7 +68,13 @@ module.exports = function(Posts) {
topics.onNewPostMade(postData, next); topics.onNewPostMade(postData, next);
}, },
function(next) { function(next) {
categories.onNewPostMade(postData, next); topics.getTopicFields(tid, ['cid', 'pinned'], function(err, topicData) {
if (err) {
return next(err);
}
postData.cid = topicData.cid;
categories.onNewPostMade(topicData.cid, topicData.pinned, postData, next);
});
}, },
function(next) { function(next) {
db.sortedSetAdd('posts:pid', timestamp, postData.pid, next); db.sortedSetAdd('posts:pid', timestamp, postData.pid, next);

@ -9,16 +9,19 @@ var async = require('async'),
module.exports = function(Posts) { module.exports = function(Posts) {
Posts.delete = function(pid, callback) { Posts.delete = function(pid, callback) {
Posts.setPostField(pid, 'deleted', 1, function(err) { var postData;
if (err) { async.waterfall([
return callback(err); function(next) {
} Posts.setPostField(pid, 'deleted', 1, next);
},
Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'timestamp'], function(err, postData) { function(next) {
if (err) { Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'timestamp'], next);
return callback(err); },
} function(_post, next) {
postData = _post;
topics.getTopicField(_post.tid, 'cid', next);
},
function(cid, next) {
plugins.fireHook('action:post.delete', pid); plugins.fireHook('action:post.delete', pid);
async.parallel([ async.parallel([
@ -26,7 +29,7 @@ module.exports = function(Posts) {
updateTopicTimestamp(postData.tid, next); updateTopicTimestamp(postData.tid, next);
}, },
function(next) { function(next) {
removeFromCategoryRecentPosts(pid, postData.tid, next); db.sortedSetRemove('cid:' + cid + ':pids', pid, next);
}, },
function(next) { function(next) {
Posts.dismissFlag(pid, next); Posts.dismissFlag(pid, next);
@ -34,21 +37,25 @@ module.exports = function(Posts) {
], function(err) { ], function(err) {
callback(err, postData); callback(err, postData);
}); });
}); }
}); ], callback);
}; };
Posts.restore = function(pid, callback) { Posts.restore = function(pid, callback) {
Posts.setPostField(pid, 'deleted', 0, function(err) { var postData;
if (err) { async.waterfall([
return callback(err); function(next) {
} Posts.setPostField(pid, 'deleted', 0, next);
},
Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'content', 'timestamp'], function(err, postData) { function(next) {
if (err) { Posts.getPostFields(pid, ['pid', 'tid', 'uid', 'content', 'timestamp'], next);
return callback(err); },
} function(_post, next) {
postData = _post;
topics.getTopicField(_post.tid, 'cid', next);
},
function(cid, next) {
postData.cid = cid;
plugins.fireHook('action:post.restore', postData); plugins.fireHook('action:post.restore', postData);
async.parallel([ async.parallel([
@ -56,13 +63,13 @@ module.exports = function(Posts) {
updateTopicTimestamp(postData.tid, next); updateTopicTimestamp(postData.tid, next);
}, },
function(next) { function(next) {
addToCategoryRecentPosts(pid, postData.tid, postData.timestamp, next); db.sortedSetAdd('cid:' + cid + ':pids', postData.timestamp, pid, next);
} }
], function(err) { ], function(err) {
callback(err, postData); callback(err, postData);
}); });
}); }
}); ], callback);
}; };
function updateTopicTimestamp(tid, callback) { function updateTopicTimestamp(tid, callback) {
@ -84,26 +91,6 @@ module.exports = function(Posts) {
}); });
} }
function removeFromCategoryRecentPosts(pid, tid, callback) {
topics.getTopicField(tid, 'cid', function(err, cid) {
if (err) {
return callback(err);
}
db.sortedSetRemove('cid:' + cid + ':pids', pid, callback);
});
}
function addToCategoryRecentPosts(pid, tid, timestamp, callback) {
topics.getTopicField(tid, 'cid', function(err, cid) {
if (err) {
return callback(err);
}
db.sortedSetAdd('cid:' + cid + ':pids', timestamp, pid, callback);
});
}
Posts.purge = function(pid, callback) { Posts.purge = function(pid, callback) {
Posts.exists(pid, function(err, exists) { Posts.exists(pid, function(err, exists) {
if (err || !exists) { if (err || !exists) {

@ -43,7 +43,7 @@ search.search = function(data, callback) {
}; };
if (searchIn === 'posts' || searchIn === 'titles' || searchIn === 'titlesposts') { if (searchIn === 'posts' || searchIn === 'titles' || searchIn === 'titlesposts') {
searchInContent(query, data, done); searchInContent(data, done);
} else if (searchIn === 'users') { } else if (searchIn === 'users') {
searchInUsers(query, data.uid, done); searchInUsers(query, data.uid, done);
} else if (searchIn === 'tags') { } else if (searchIn === 'tags') {
@ -53,89 +53,87 @@ search.search = function(data, callback) {
} }
}; };
function searchInContent(query, data, callback) { function searchInContent(data, callback) {
data.uid = data.uid || 0; data.uid = data.uid || 0;
async.parallel({ async.parallel({
pids: function(next) { searchCids: function(next) {
if (data.searchIn === 'posts' || data.searchIn === 'titlesposts') { getSearchCids(data, next);
search.searchQuery('post', query, next);
} else {
next(null, []);
}
},
tids: function(next) {
if (data.searchIn === 'titles' || data.searchIn === 'titlesposts') {
search.searchQuery('topic', query, next);
} else {
next(null, []);
}
}, },
searchCategories: function(next) { searchUids: function(next) {
getSearchCategories(data, next); getSearchUids(data, next);
} }
}, function (err, results) { }, function(err, results) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
var matchCount = 0; async.parallel({
if (!results || (!results.pids.length && !results.tids.length)) { pids: function(next) {
return callback(null, {matches: [], matchCount: matchCount}); if (data.searchIn === 'posts' || data.searchIn === 'titlesposts') {
} search.searchQuery('post', data.query, results.searchCids, results.searchUids, next);
} else {
async.waterfall([ next(null, []);
function(next) { }
topics.getMainPids(results.tids, next);
},
function(mainPids, next) {
results.pids = mainPids.concat(results.pids).filter(function(pid, index, array) {
return pid && array.indexOf(pid) === index;
});
privileges.posts.filter('read', results.pids, data.uid, next);
},
function(pids, next) {
filterAndSort(pids, data, results.searchCategories, next);
}, },
function(pids, next) { tids: function(next) {
matchCount = pids.length; if (data.searchIn === 'titles' || data.searchIn === 'titlesposts') {
if (data.page) { search.searchQuery('topic', data.query, results.searchCids, results.searchUids, next);
var start = Math.max(0, (data.page - 1)) * 10; } else {
pids = pids.slice(start, start + 10); next(null, []);
} }
}
}, function (err, results) {
if (err) {
return callback(err);
}
posts.getPostSummaryByPids(pids, data.uid, {stripTags: true, parse: false}, next); var matchCount = 0;
}, if (!results || (!results.pids.length && !results.tids.length)) {
function(posts, next) { return callback(null, {matches: [], matchCount: matchCount});
next(null, {matches: posts, matchCount: matchCount});
} }
], callback);
async.waterfall([
function(next) {
topics.getMainPids(results.tids, next);
},
function(mainPids, next) {
results.pids = mainPids.concat(results.pids).filter(function(pid, index, array) {
return pid && array.indexOf(pid) === index;
});
privileges.posts.filter('read', results.pids, data.uid, next);
},
function(pids, next) {
filterAndSort(pids, data, next);
},
function(pids, next) {
matchCount = pids.length;
if (data.page) {
var start = Math.max(0, (data.page - 1)) * 10;
pids = pids.slice(start, start + 10);
}
posts.getPostSummaryByPids(pids, data.uid, {stripTags: true, parse: false}, next);
},
function(posts, next) {
next(null, {matches: posts, matchCount: matchCount});
}
], callback);
});
}); });
} }
function filterAndSort(pids, data, searchCategories, callback) { function filterAndSort(pids, data, callback) {
async.parallel({ getMatchedPosts(pids, data, function(err, posts) {
posts: function(next) {
getMatchedPosts(pids, data, searchCategories, next);
},
postedByUid: function(next) {
if (data.postedBy) {
user.getUidByUsername(data.postedBy, next);
} else {
next();
}
}
}, function(err, results) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
if (!results.posts) {
if (!Array.isArray(posts) || !posts.length) {
return callback(null, pids); return callback(null, pids);
} }
var posts = results.posts.filter(Boolean); posts = posts.filter(Boolean);
posts = filterByUser(posts, results.postedByUid);
posts = filterByCategories(posts, searchCategories);
posts = filterByPostcount(posts, data.replies, data.repliesFilter); posts = filterByPostcount(posts, data.replies, data.repliesFilter);
posts = filterByTimerange(posts, data.timeRange, data.timeFilter); posts = filterByTimerange(posts, data.timeRange, data.timeFilter);
@ -149,25 +147,19 @@ function filterAndSort(pids, data, searchCategories, callback) {
}); });
} }
function getMatchedPosts(pids, data, searchCategories, callback) { function getMatchedPosts(pids, data, callback) {
var postFields = ['pid', 'tid', 'timestamp']; var postFields = ['pid', 'tid', 'timestamp'];
var topicFields = []; var topicFields = [];
var categoryFields = []; var categoryFields = [];
if (data.postedBy) {
postFields.push('uid');
}
if (searchCategories.length || (data.sortBy && data.sortBy.startsWith('category.'))) {
topicFields.push('cid');
}
if (data.replies) { if (data.replies) {
topicFields.push('postcount'); topicFields.push('postcount');
} }
if (data.sortBy) { if (data.sortBy) {
if (data.sortBy.startsWith('topic.')) { if (data.sortBy.startsWith('category')) {
topicFields.push('cid');
} else if (data.sortBy.startsWith('topic.')) {
topicFields.push(data.sortBy.split('.')[1]); topicFields.push(data.sortBy.split('.')[1]);
} else if (data.sortBy.startsWith('user.')) { } else if (data.sortBy.startsWith('user.')) {
postFields.push('uid'); postFields.push('uid');
@ -280,25 +272,6 @@ function getMatchedPosts(pids, data, searchCategories, callback) {
], callback); ], callback);
} }
function filterByUser(posts, postedByUid) {
if (postedByUid) {
postedByUid = parseInt(postedByUid, 10);
posts = posts.filter(function(post) {
return parseInt(post.uid, 10) === postedByUid;
});
}
return posts;
}
function filterByCategories(posts, searchCategories) {
if (searchCategories.length) {
posts = posts.filter(function(post) {
return post.topic && searchCategories.indexOf(post.topic.cid) !== -1;
});
}
return posts;
}
function filterByPostcount(posts, postCount, repliesFilter) { function filterByPostcount(posts, postCount, repliesFilter) {
postCount = parseInt(postCount, 10); postCount = parseInt(postCount, 10);
if (postCount) { if (postCount) {
@ -389,7 +362,7 @@ function sortPosts(posts, data) {
} }
} }
function getSearchCategories(data, callback) { function getSearchCids(data, callback) {
if (!Array.isArray(data.categories) || !data.categories.length || data.categories.indexOf('all') !== -1) { if (!Array.isArray(data.categories) || !data.categories.length || data.categories.indexOf('all') !== -1) {
return callback(null, []); return callback(null, []);
} }
@ -439,6 +412,14 @@ function getChildrenCids(cids, uid, callback) {
}); });
} }
function getSearchUids(data, callback) {
if (data.postedBy) {
user.getUidsByUsernames(Array.isArray(data.postedBy) ? data.postedBy : [data.postedBy], callback);
} else {
callback(null, []);
}
}
function searchInUsers(query, uid, callback) { function searchInUsers(query, uid, callback) {
user.search({query: query, uid: uid}, function(err, results) { user.search({query: query, uid: uid}, function(err, results) {
if (err) { if (err) {
@ -458,10 +439,12 @@ function searchInTags(query, callback) {
}); });
} }
search.searchQuery = function(index, query, callback) { search.searchQuery = function(index, content, cids, uids, callback) {
plugins.fireHook('filter:search.query', { plugins.fireHook('filter:search.query', {
index: index, index: index,
query: query content: content,
cid: cids,
uid: uids
}, callback); }, callback);
}; };

@ -183,13 +183,16 @@ var async = require('async'),
categories.moveRecentReplies(tid, oldCid, cid); categories.moveRecentReplies(tid, oldCid, cid);
topics.setTopicField(tid, 'cid', cid, callback); topics.setTopicField(tid, 'cid', cid, function(err) {
if (err) {
plugins.fireHook('action:topic.move', { return callback(err);
tid: tid, }
fromCid: oldCid, plugins.fireHook('action:topic.move', {
toCid: cid, tid: tid,
uid: uid fromCid: oldCid,
toCid: cid,
uid: uid
});
}); });
}); });
}; };

@ -158,7 +158,7 @@ var async = require('async'),
if (now - parseInt(userOnlineTime, 10) < 300000) { if (now - parseInt(userOnlineTime, 10) < 300000) {
return callback(); return callback();
} }
db.sortedSetAdd('users:online', now, uid, next); db.sortedSetAdd('users:online', now, uid, next);
}, },
function(next) { function(next) {
topics.pushUnreadCount(uid); topics.pushUnreadCount(uid);
@ -334,6 +334,18 @@ var async = require('async'),
db.getObjectField('username:uid', username, callback); db.getObjectField('username:uid', username, callback);
}; };
User.getUidsByUsernames = function(usernames, callback) {
db.getObjectFields('username:uid', usernames, function(err, users) {
if (err) {
return callback(err);
}
var uids = usernames.map(function(username) {
return users[username];
});
callback(null, uids);
});
};
User.getUidByUserslug = function(userslug, callback) { User.getUidByUserslug = function(userslug, callback) {
if (!userslug) { if (!userslug) {
return callback(); return callback();

Loading…
Cancel
Save