From 311a7ad5b929aa2fc244bb7004e0160393c71200 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 10 Jun 2014 16:56:55 -0400 Subject: [PATCH] #1281 topic purge --- public/language/en_GB/topic.json | 2 + public/src/forum/categoryTools.js | 58 ++++++++++++----- public/src/forum/topic/events.js | 5 ++ public/src/forum/topic/postTools.js | 4 +- public/src/forum/topic/threadTools.js | 73 +++++++++++---------- src/postTools.js | 2 +- src/posts/delete.js | 2 +- src/socket.io/topics.js | 4 ++ src/threadTools.js | 38 +++++++++++ src/topics.js | 69 +------------------- src/topics/delete.js | 92 +++++++++++++++++++++++---- src/user/delete.js | 4 +- 12 files changed, 221 insertions(+), 132 deletions(-) diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 2f29c76a7c..8df3a71ff2 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -58,6 +58,8 @@ "thread_tools.delete_confirm": "Are you sure you want to delete this thread?", "thread_tools.restore": "Restore Topic", "thread_tools.restore_confirm": "Are you sure you want to restore this thread?", + "thread_tools.purge": "Purge Topic", + "thread_tools.purge_confirm" : "Are you sure you want to purge this thread?", "topic_lock_success": "Topic has been successfully locked.", "topic_unlock_success": "Topic has been successfully unlocked.", diff --git a/public/src/forum/categoryTools.js b/public/src/forum/categoryTools.js index 13e6921ea8..30cdd3177d 100644 --- a/public/src/forum/categoryTools.js +++ b/public/src/forum/categoryTools.js @@ -15,34 +15,25 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move $('.delete_thread').on('click', function(e) { var tids = topicSelect.getSelectedTids(); + categoryCommand(isAny(isTopicDeleted, tids) ? 'restore' : 'delete', tids); + return false; + }); - if (tids.length) { - var command = isAny(isTopicDeleted, tids) ? 'restore' : 'delete'; - - translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) { - bootbox.confirm(msg, function(confirm) { - if (!confirm) { - return; - } - - socket.emit('topics.' + command, tids, onCommandComplete); - }); - }); - } - + $('.purge_thread').on('click', function() { + var tids = topicSelect.getSelectedTids(); + categoryCommand('purge', tids); return false; }); - $('.lock_thread').on('click', function(e) { + $('.lock_thread').on('click', function() { var tids = topicSelect.getSelectedTids(); if (tids.length) { socket.emit(isAny(isTopicLocked, tids) ? 'topics.unlock' : 'topics.lock', tids, onCommandComplete); } - return false; }); - $('.pin_thread').on('click', function(e) { + $('.pin_thread').on('click', function() { var tids = topicSelect.getSelectedTids(); if (tids.length) { socket.emit(isAny(isTopicPinned, tids) ? 'topics.unpin' : 'topics.pin', tids, onCommandComplete); @@ -84,6 +75,7 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move socket.on('event:topic_deleted', setDeleteState); socket.on('event:topic_restored', setDeleteState); + socket.on('event:topic_purged', onTopicPurged); socket.on('event:topic_locked', setLockedState); socket.on('event:topic_unlocked', setLockedState); socket.on('event:topic_pinned', setPinnedState); @@ -91,9 +83,25 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move socket.on('event:topic_moved', onTopicMoved); }; + function categoryCommand(command, tids) { + if (!tids.length) { + return; + } + + translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) { + bootbox.confirm(msg, function(confirm) { + if (!confirm) { + return; + } + socket.emit('topics.' + command, tids, onCommandComplete); + }); + }); + } + CategoryTools.removeListeners = function() { socket.removeListener('event:topic_deleted', setDeleteState); socket.removeListener('event:topic_restored', setDeleteState); + socket.removeListener('event:topic_purged', onTopicPurged); socket.removeListener('event:topic_locked', setLockedState); socket.removeListener('event:topic_unlocked', setLockedState); socket.removeListener('event:topic_pinned', setPinnedState); @@ -116,6 +124,7 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move function onTopicSelect() { var tids = topicSelect.getSelectedTids(); var isAnyDeleted = isAny(isTopicDeleted, tids); + var areAllDeleted = areAll(isTopicDeleted, tids); var isAnyPinned = isAny(isTopicPinned, tids); var isAnyLocked = isAny(isTopicLocked, tids); @@ -130,6 +139,8 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move translator.translate(' [[topic:thread_tools.' + (isAnyLocked ? 'un': '') + 'lock]]', function(translated) { $('.lock_thread').html(translated); }); + + $('.purge_thread').toggleClass('none', !areAllDeleted); } function isAny(method, tids) { @@ -141,6 +152,15 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect'], function(move return false; } + function areAll(method, tids) { + for(var i=0; i' : 'Reply'); - ThreadTools.threadState.locked = data.isLocked ? '1' : '0'; + ThreadTools.threadState.locked = data.isLocked; } }; ThreadTools.setDeleteState = function(data) { var threadEl = $('#post-container'); - if (parseInt(data.tid, 10) === parseInt(threadEl.attr('data-tid'), 10)) { - translator.translate(' [[topic:thread_tools.' + (data.isDelete ? 'restore' : 'delete') + ']]', function(translated) { - $('.delete_thread span').html(translated); - }); + if (parseInt(data.tid, 10) !== parseInt(threadEl.attr('data-tid'), 10)) { + return; + } - threadEl.toggleClass('deleted', data.isDelete); - ThreadTools.threadState.deleted = data.isDelete ? '1' : '0'; + translator.translate(' [[topic:thread_tools.' + (data.isDelete ? 'restore' : 'delete') + ']]', function(translated) { + $('.delete_thread span').html(translated); + }); + + threadEl.toggleClass('deleted', data.isDelete); + ThreadTools.threadState.deleted = data.isDelete; + $('.purge_thread').toggleClass('none', !data.isDelete); - if (data.isDelete) { - translator.translate('[[topic:deleted_message]]', function(translated) { - $('
' + translated + '
').insertBefore(threadEl); - }); - } else { - $('#thread-deleted').remove(); - } + if (data.isDelete) { + translator.translate('[[topic:deleted_message]]', function(translated) { + $('
' + translated + '
').insertBefore(threadEl); + }); + } else { + $('#thread-deleted').remove(); } }; @@ -130,7 +139,7 @@ define('forum/topic/threadTools', ['forum/topic/fork', 'forum/topic/move'], func translator.translate(' [[topic:thread_tools.' + (data.isPinned ? 'unpin' : 'pin') + ']]', function(translated) { $('.pin_thread').html(translated); - ThreadTools.threadState.pinned = data.isPinned ? '1' : '0'; + ThreadTools.threadState.pinned = data.isPinned; }); } } diff --git a/src/postTools.js b/src/postTools.js index 1a81eee48f..341405648a 100644 --- a/src/postTools.js +++ b/src/postTools.js @@ -183,7 +183,7 @@ var winston = require('winston'), return callback(err || new Error('[[error:no-privileges]]')); } - posts.delete(pid, callback); + posts.purge(pid, callback); }); }; diff --git a/src/posts/delete.js b/src/posts/delete.js index 865aac4a8d..d46e57a6a5 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -8,7 +8,7 @@ var async = require('async'), module.exports = function(Posts) { - Posts.delete = function(pid, callback) { + Posts.purge = function(pid, callback) { async.parallel([ function(next) { deletePostFromTopicAndUser(pid, next); diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 466859038a..732757d62f 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -160,6 +160,10 @@ SocketTopics.restore = function(socket, tids, callback) { doTopicAction('restore', socket, tids, callback); }; +SocketTopics.purge = function(socket, tids, callback) { + doTopicAction('purge', socket, tids, callback); +}; + SocketTopics.lock = function(socket, tids, callback) { doTopicAction('lock', socket, tids, callback); }; diff --git a/src/threadTools.js b/src/threadTools.js index c476e461f5..d322893f5b 100644 --- a/src/threadTools.js +++ b/src/threadTools.js @@ -70,6 +70,44 @@ var winston = require('winston'), }); } + ThreadTools.purge = function(tid, uid, callback) { + async.parallel({ + topic: function(next) { + topics.getTopicFields(tid, ['cid', 'mainPid'], next); + }, + pids: function(next) { + topics.getPids(tid, next); + } + }, function(err, results) { + if (err) { + return callback(err); + } + + var pids = []; + if (results.topic.mainPid) { + pids = [results.topic.mainPid].concat(results.pids); + } + + async.parallel([ + function(next) { + async.each(pids, posts.purge, next); + }, + function(next) { + topics.purge(tid, next); + } + ], function(err) { + if (err) { + return callback(err); + } + + websockets.emitTopicPostStats(); + websockets.in('topic_' + tid).emit('event:topic_purged', tid); + websockets.in('category_' + results.topic.cid).emit('event:topic_purged', tid); + callback(); + }); + }); + }; + ThreadTools.lock = function(tid, uid, callback) { toggleLock(tid, uid, true, callback); }; diff --git a/src/topics.js b/src/topics.js index f2f9e207e2..d91e02f463 100644 --- a/src/topics.js +++ b/src/topics.js @@ -316,6 +316,9 @@ var async = require('async'), topicData.thread_tools = results.threadTools; topicData.pageCount = results.pageCount; topicData.unreplied = parseInt(topicData.postcount, 10) === 1; + topicData.deleted = parseInt(topicData.deleted, 10) === 1; + topicData.locked = parseInt(topicData.locked, 10) === 1; + topicData.pinned = parseInt(topicData.pinned, 10) === 1; callback(null, topicData); }); @@ -433,71 +436,5 @@ var async = require('async'), }); }; - Topics.delete = function(tid, callback) { - async.parallel([ - function(next) { - Topics.setTopicField(tid, 'deleted', 1, next); - }, - function(next) { - db.sortedSetRemove('topics:recent', tid, next); - }, - function(next) { - db.sortedSetRemove('topics:posts', tid, next); - }, - function(next) { - db.sortedSetRemove('topics:views', tid, next); - }, - function(next) { - Topics.getTopicField(tid, 'cid', function(err, cid) { - if(err) { - return next(err); - } - db.incrObjectFieldBy('category:' + cid, 'topic_count', -1, next); - }); - } - ], function(err) { - if (err) { - return callback(err); - } - - Topics.updateTopicCount(callback); - }); - }; - - Topics.restore = function(tid, callback) { - Topics.getTopicFields(tid, ['lastposttime', 'postcount', 'viewcount'], function(err, topicData) { - if(err) { - return callback(err); - } - - async.parallel([ - function(next) { - Topics.setTopicField(tid, 'deleted', 0, next); - }, - function(next) { - db.sortedSetAdd('topics:recent', topicData.lastposttime, tid, next); - }, - function(next) { - db.sortedSetAdd('topics:posts', topicData.postcount, tid, next); - }, - function(next) { - db.sortedSetAdd('topics:views', topicData.viewcount, tid, next); - }, - function(next) { - Topics.getTopicField(tid, 'cid', function(err, cid) { - if(err) { - return next(err); - } - db.incrObjectFieldBy('category:' + cid, 'topic_count', 1, next); - }); - } - ], function(err) { - if (err) { - return callback(err); - } - Topics.updateTopicCount(callback); - }); - }); - }; }(exports)); diff --git a/src/topics/delete.js b/src/topics/delete.js index 6f3f432a6d..d8b7ee9472 100644 --- a/src/topics/delete.js +++ b/src/topics/delete.js @@ -7,7 +7,76 @@ var async = require('async'), module.exports = function(Topics) { + Topics.delete = function(tid, callback) { + async.parallel([ + function(next) { + Topics.setTopicField(tid, 'deleted', 1, next); + }, + function(next) { + db.sortedSetRemove('topics:recent', tid, next); + }, + function(next) { + db.sortedSetRemove('topics:posts', tid, next); + }, + function(next) { + db.sortedSetRemove('topics:views', tid, next); + }, + function(next) { + Topics.getTopicField(tid, 'cid', function(err, cid) { + if(err) { + return next(err); + } + db.incrObjectFieldBy('category:' + cid, 'topic_count', -1, next); + }); + } + ], function(err) { + if (err) { + return callback(err); + } + + Topics.updateTopicCount(callback); + }); + }; + + Topics.restore = function(tid, callback) { + Topics.getTopicFields(tid, ['lastposttime', 'postcount', 'viewcount'], function(err, topicData) { + if(err) { + return callback(err); + } + + async.parallel([ + function(next) { + Topics.setTopicField(tid, 'deleted', 0, next); + }, + function(next) { + db.sortedSetAdd('topics:recent', topicData.lastposttime, tid, next); + }, + function(next) { + db.sortedSetAdd('topics:posts', topicData.postcount, tid, next); + }, + function(next) { + db.sortedSetAdd('topics:views', topicData.viewcount, tid, next); + }, + function(next) { + Topics.getTopicField(tid, 'cid', function(err, cid) { + if(err) { + return next(err); + } + db.incrObjectFieldBy('category:' + cid, 'topic_count', 1, next); + }); + } + ], function(err) { + if (err) { + return callback(err); + } + + Topics.updateTopicCount(callback); + }); + }); + }; + + Topics.purge = function(tid, callback) { async.parallel([ function(next) { db.delete('tid:' + tid + ':followers', next); @@ -60,17 +129,18 @@ module.exports = function(Topics) { return callback(err); } - db.decrObjectField('category:' + topicData.cid, 'topic_count', function(err) { - if (err) { - return callback(err); - } - - if (parseInt(topicData.deleted, 10) === 0) { - db.decrObjectField('global', 'topicCount', callback); - } else { - callback(); - } - }); + if (parseInt(topicData.deleted, 10) === 0) { + async.parallel([ + function(next) { + db.decrObjectField('category:' + topicData.cid, 'topic_count', next); + }, + function(next) { + db.decrObjectField('global', 'topicCount', callback); + } + ], callback); + } else { + callback(); + } }); }); } diff --git a/src/user/delete.js b/src/user/delete.js index bd1c509cf8..1daa737992 100644 --- a/src/user/delete.js +++ b/src/user/delete.js @@ -28,11 +28,11 @@ module.exports = function(User) { }; function deletePosts(uid, callback) { - deleteSortedSetElements('uid:' + uid + ':posts', posts.delete, callback); + deleteSortedSetElements('uid:' + uid + ':posts', posts.purge, callback); } function deleteTopics(uid, callback) { - deleteSortedSetElements('uid:' + uid + ':topics', topics.delete, callback); + deleteSortedSetElements('uid:' + uid + ':topics', topics.purge, callback); } function deleteSortedSetElements(set, deleteMethod, callback) {