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) {