mirror of
https://hk.gh-proxy.com/https://github.com/NodeBB/nodebb-plugin-poll.git
synced 2025-10-03 04:31:04 +08:00
275 lines
8.3 KiB
JavaScript
275 lines
8.3 KiB
JavaScript
var NodeBB = require('./nodebb'),
|
|
db = NodeBB.db,
|
|
|
|
async = require('async');
|
|
|
|
//To whoever reads this
|
|
//Please help improve
|
|
var Backend = {
|
|
addPoll: function(pollData, callback) {
|
|
db.incrObjectField('global', 'nextPollid', function(err, pollid) {
|
|
if (err) {
|
|
return callback(err, -1);
|
|
}
|
|
|
|
//These are separately saved, so we need to remove them from the main poll data
|
|
var pollOptions = pollData.options,
|
|
pollSettings = pollData.settings;
|
|
|
|
pollData.options = undefined;
|
|
pollData.settings = undefined;
|
|
pollData.pollid = pollid;
|
|
|
|
//Build new pollData without the options and settings keys
|
|
var poll = {};
|
|
for (var p in pollData) {
|
|
if (pollData.hasOwnProperty(p) && pollData[p] !== undefined) {
|
|
poll[p] = pollData[p];
|
|
}
|
|
}
|
|
|
|
//Save all the options to the database
|
|
for(var i = 0, l = pollOptions.length; i < l; i++) {
|
|
db.setObject('poll:' + pollid + ':options:' + i, pollOptions[i]);
|
|
db.setAdd('poll:' + pollid + ':options', i);
|
|
}
|
|
|
|
//Save the poll and settings to the database
|
|
db.setObject('poll:' + pollid, poll);
|
|
db.setObject('poll:' + pollid + ':settings', pollSettings);
|
|
db.listAppend('polls', pollid, function(){});
|
|
|
|
//Register poll with a topic and post
|
|
db.setObjectField('topic:' + poll.tid, 'poll:id', pollid);
|
|
db.setObjectField('post:' + poll.pid, 'poll:id', pollid);
|
|
|
|
//Check if this poll is scheduled to end
|
|
if (parseInt(pollSettings.end, 10) > 0) {
|
|
Backend.schedulePoll(pollid);
|
|
}
|
|
|
|
return callback(null, pollid);
|
|
});
|
|
},
|
|
getPoll: function(data, callback) {
|
|
var pollid = data.pollid,
|
|
uid = data.uid || false,
|
|
withVotes = (data.anon ? false : !!data.withVotes);
|
|
|
|
async.parallel({
|
|
info: function(next) {
|
|
Backend.getPollInfo(pollid, next);
|
|
},
|
|
options: function(next) {
|
|
Backend.getPollOptions(pollid, withVotes, next);
|
|
},
|
|
settings: function(next) {
|
|
Backend.getPollSettings(pollid, next);
|
|
},
|
|
hasvoted: function(next) {
|
|
if (uid) {
|
|
Backend.hasUidVoted(uid, pollid, next);
|
|
} else {
|
|
next(null, false);
|
|
}
|
|
}
|
|
}, callback);
|
|
},
|
|
getPollIdByTid: function(tid, callback) {
|
|
db.getObjectField('topic:' + tid, 'poll:id', callback);
|
|
},
|
|
getPollIdByPid: function(pid, callback) {
|
|
db.getObjectField('post:' + pid, 'poll:id', callback);
|
|
},
|
|
getPollInfo: function(pollid, callback) {
|
|
db.getObject('poll:' + pollid, callback);
|
|
},
|
|
getPollOptions: function(pollid, withVotes, callback) {
|
|
if (typeof withVotes === 'function') {
|
|
callback = withVotes;
|
|
withVotes = false;
|
|
}
|
|
|
|
db.getSetMembers('poll:' + pollid + ':options', function(err, options) {
|
|
async.map(options, function(option, next) {
|
|
Backend.getPollOption(pollid, option, withVotes, next);
|
|
}, callback);
|
|
});
|
|
},
|
|
getPollOption: function(pollid, option, withVotes, callback) {
|
|
async.parallel({
|
|
option: function(next) {
|
|
db.getObject('poll:' + pollid + ':options:' + option, next);
|
|
},
|
|
votes: function(next) {
|
|
if (withVotes) {
|
|
db.getSetMembers('poll:' + pollid + ':options:' + option + ':votes', next);
|
|
} else {
|
|
next();
|
|
}
|
|
}
|
|
}, function(err, results) {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
results.option = results.option || {title: 'option ' + option};
|
|
if (results.votes) {
|
|
results.option.votes = results.votes;
|
|
}
|
|
results.option.votecount = results.option.votecount || 0;
|
|
callback(null, results.option);
|
|
});
|
|
},
|
|
getPollSettings: function(pollid, callback) {
|
|
db.getObject('poll:' + pollid + ':settings', callback);
|
|
},
|
|
pollHasOption: function(pollid, option, callback) {
|
|
db.isSetMember('poll:' + pollid + ':options', option, callback);
|
|
},
|
|
pollHasOptions: function(pollid, options, callback) {
|
|
db.isSetMembers('poll:' + pollid + ':options', options, callback);
|
|
},
|
|
hasPollEnded: function(pollid, callback) {
|
|
Backend.getPollField(pollid, 'ended', function(err, result) {
|
|
callback(err, parseInt(result, 10) === 1);
|
|
});
|
|
},
|
|
endPoll: function(pollid) {
|
|
db.setRemove('polls:scheduled', pollid);
|
|
Backend.setPollField(pollid, 'ended', 1);
|
|
},
|
|
isPollDeleted: function(pollid, callback) {
|
|
Backend.getPollField(pollid, 'deleted', function(err, result) {
|
|
callback(err, parseInt(result, 10) === 1);
|
|
});
|
|
},
|
|
deletePoll: function(pollid) {
|
|
Backend.setPollField(pollid, 'deleted', 1);
|
|
},
|
|
restorePoll: function(pollid) {
|
|
Backend.setPollField(pollid, 'edited', 0);
|
|
Backend.setPollField(pollid, 'deleted', 0);
|
|
},
|
|
schedulePoll: function(pollid) {
|
|
db.setAdd('polls:scheduled', pollid);
|
|
require('./utils').scheduler.add(pollid);
|
|
},
|
|
getScheduledPolls: function(callback) {
|
|
db.getSetMembers('polls:scheduled', callback);
|
|
},
|
|
changePid: function(pollid, pid, callback) {
|
|
async.parallel([function(next) {
|
|
Backend.setPollField(pollid, 'pid', pid, next);
|
|
}, function(next) {
|
|
db.setObjectField('post:' + pid, 'poll:id', pollid, next);
|
|
}], callback);
|
|
},
|
|
changeTid: function(pollid, tid, callback) {
|
|
async.parallel([function(next) {
|
|
Backend.setPollField(pollid, 'tid', tid, next);
|
|
}, function(next) {
|
|
db.setObjectField('topic:' + tid, 'poll:id', pollid, next);
|
|
}], callback);
|
|
},
|
|
setPollField: function(pollid, field, value, callback) {
|
|
db.setObjectField('poll:' + pollid, field, value, callback);
|
|
},
|
|
setPollFields: function(pollid, fields, values, callback) {
|
|
db.setObjectFields('poll:' + pollid, fields, values, callback);
|
|
},
|
|
getPollField: function(pollid, field, callback) {
|
|
db.getObjectField('poll:' + pollid, field, callback);
|
|
},
|
|
getPollFields: function(pollid, fields, callback) {
|
|
db.getObjectFields('poll:' + pollid, fields, callback);
|
|
},
|
|
/***************************
|
|
* Vote methods start here *
|
|
***************************/
|
|
addVote: function(voteData, callback) {
|
|
var pollid = voteData.pollid,
|
|
options = voteData.options,
|
|
uid = voteData.uid;
|
|
|
|
async.parallel({
|
|
options: function(next) {
|
|
async.each(options, function(option, next) {
|
|
//Increase option vote count
|
|
//next is called here because the option votecount has been updated, it doesn't matter when the uid is added
|
|
db.incrObjectField('poll:' + pollid + ':options:' + option, 'votecount', next);
|
|
//Add uid to list of votes
|
|
db.setAdd('poll:' + pollid + ':options:' + option + ':votes', uid);
|
|
}, function(err) {
|
|
//Get poll options for callback
|
|
Backend.getPollOptions(pollid, next);
|
|
});
|
|
},
|
|
info: function(next) {
|
|
//Add uid to poll voters
|
|
db.setAdd('poll:' + pollid + ':voters', uid);
|
|
//Increase poll vote count
|
|
db.incrObjectFieldBy('poll:' + pollid, 'votecount', options.length, function(err, result){
|
|
next(err, {
|
|
votecount: result
|
|
})
|
|
});
|
|
}
|
|
}, callback);
|
|
},
|
|
removeVote: function(voteData, callback) {
|
|
var pollid = voteData.pollid,
|
|
options = voteData.options,
|
|
uid = voteData.uid;
|
|
|
|
async.parallel({
|
|
options: function(next) {
|
|
async.each(options, function(option, next) {
|
|
//Decrease option vote count
|
|
//next is called here because the option votecount has been updated, it doesn't matter when the uid is added
|
|
db.decrObjectField('poll:' + pollid + ':options:' + option, 'votecount', next);
|
|
//Remove uid from list of votes
|
|
db.setRemove('poll:' + pollid + ':options:' + option + ':votes', uid);
|
|
}, function(err) {
|
|
//Get poll options for callback
|
|
Backend.getPollOptions(pollid, next);
|
|
});
|
|
},
|
|
info: function(next) {
|
|
//Remove uid from poll voters
|
|
db.setRemove('poll:' + pollid + ':voters', uid);
|
|
//Decrease poll vote count
|
|
db.decrObjectFieldBy('poll:' + pollid, 'votecount', options.length, function(err, result){
|
|
next(err, {
|
|
votecount: result
|
|
})
|
|
});
|
|
}
|
|
}, callback);
|
|
},
|
|
canVote: function(voteData, callback) {
|
|
async.parallel([
|
|
function(next) {
|
|
//hasended
|
|
Backend.hasPollEnded(voteData.pollid, next);
|
|
},
|
|
function(next) {
|
|
//isdeleted
|
|
Backend.isPollDeleted(voteData.pollid, next);
|
|
},
|
|
function(next) {
|
|
//hasvoted
|
|
Backend.hasUidVoted(voteData.uid, voteData.pollid, next);
|
|
}
|
|
], function(err, result) {
|
|
callback(err, result.indexOf(true) === -1);
|
|
});
|
|
},
|
|
hasUidVoted: function(uid, pollid, callback) {
|
|
db.isSetMember('poll:' + pollid + ':voters', uid, callback);
|
|
},
|
|
hasUidVotedOnOption: function(uid, pollid, option, callback) {
|
|
db.isSetMember('poll:' + pollid + ':options:' + option + ':votes', uid, callback);
|
|
}
|
|
};
|
|
|
|
module.exports = Backend;
|