mirror of
https://github.com/discourse/discourse.git
synced 2025-05-25 00:32:52 +08:00
FEATURE: new 'poll:migrate_old_polls' rake task
This commit is contained in:
41
plugins/poll/lib/tasks/migrate_old_polls.rake
Normal file
41
plugins/poll/lib/tasks/migrate_old_polls.rake
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
desc "Migrate old polls to new syntax"
|
||||||
|
task "poll:migrate_old_polls" => :environment do
|
||||||
|
# iterate over all polls
|
||||||
|
PluginStoreRow.where(plugin_name: "poll")
|
||||||
|
.where("key LIKE 'poll_options_%'")
|
||||||
|
.pluck(:key)
|
||||||
|
.each do |poll_options_key|
|
||||||
|
# extract the post_id
|
||||||
|
post_id = poll_options_key["poll_options_".length..-1].to_i
|
||||||
|
# load the post from the db
|
||||||
|
if post = Post.find_by(id: post_id)
|
||||||
|
putc "."
|
||||||
|
# go back in time
|
||||||
|
Timecop.freeze(post.created_at + 1.minute) do
|
||||||
|
# fix the RAW when needed
|
||||||
|
if post.raw !~ /\[poll\]/
|
||||||
|
first_list = /(^- .+?$\n)\n/m.match(post.raw)[0]
|
||||||
|
post.raw = post.raw.sub(first_list, "[poll]\n#{first_list}\n[/poll]")
|
||||||
|
else
|
||||||
|
post.raw = post.raw + " "
|
||||||
|
end
|
||||||
|
# save the poll
|
||||||
|
post.save
|
||||||
|
# iterate over all votes
|
||||||
|
PluginStoreRow.where(plugin_name: "poll")
|
||||||
|
.where("key LIKE 'poll_vote_#{post_id}_%'")
|
||||||
|
.pluck(:key, :value)
|
||||||
|
.each do |poll_vote_key, vote|
|
||||||
|
# extract the user_id
|
||||||
|
user_id = poll_vote_key["poll_vote_#{post_id}_%".length..-1].to_i
|
||||||
|
# conver to MD5 (use the same algorithm as the client-side poll dialect)
|
||||||
|
options = [Digest::MD5.hexdigest([vote].to_json)]
|
||||||
|
# submit vote
|
||||||
|
DiscoursePoll::Poll.vote(post_id, "poll", options, user_id) rescue nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "", "Done!"
|
||||||
|
end
|
@ -26,6 +26,81 @@ after_initialize do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DiscoursePoll::Poll
|
||||||
|
class << self
|
||||||
|
|
||||||
|
def vote(post_id, poll_name, options, user_id)
|
||||||
|
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post_id}") do
|
||||||
|
post = Post.find_by(id: post_id)
|
||||||
|
|
||||||
|
# topic must be open
|
||||||
|
if post.topic.try(:closed) || post.topic.try(:archived)
|
||||||
|
raise StandardError.new I18n.t("poll.topic_must_be_open_to_vote")
|
||||||
|
end
|
||||||
|
|
||||||
|
polls = post.custom_fields[POLLS_CUSTOM_FIELD]
|
||||||
|
|
||||||
|
raise StandardError.new I18n.t("poll.no_polls_associated_with_this_post") if polls.blank?
|
||||||
|
|
||||||
|
poll = polls[poll_name]
|
||||||
|
|
||||||
|
raise StandardError.new I18n.t("poll.no_poll_with_this_name", name: poll_name) if poll.blank?
|
||||||
|
raise StandardError.new I18n.t("poll.poll_must_be_open_to_vote") if poll["status"] != "open"
|
||||||
|
|
||||||
|
votes = post.custom_fields["#{VOTES_CUSTOM_FIELD}-#{user_id}"] || {}
|
||||||
|
vote = votes[poll_name] || []
|
||||||
|
|
||||||
|
poll["total_votes"] += 1 if vote.size == 0
|
||||||
|
|
||||||
|
poll["options"].each do |option|
|
||||||
|
option["votes"] -= 1 if vote.include?(option["id"])
|
||||||
|
option["votes"] += 1 if options.include?(option["id"])
|
||||||
|
end
|
||||||
|
|
||||||
|
votes[poll_name] = options
|
||||||
|
|
||||||
|
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
|
||||||
|
post.custom_fields["#{VOTES_CUSTOM_FIELD}-#{user_id}"] = votes
|
||||||
|
post.save_custom_fields(true)
|
||||||
|
|
||||||
|
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
|
||||||
|
|
||||||
|
return [poll, options]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_status(post_id, poll_name, status, user_id)
|
||||||
|
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post_id}") do
|
||||||
|
post = Post.find_by(id: post_id)
|
||||||
|
user = User.find_by(id: user_id)
|
||||||
|
|
||||||
|
# either staff member or OP
|
||||||
|
unless user_id == post.user_id || user.try(:staff?)
|
||||||
|
raise StandardError.new I18n.t("poll.only_staff_or_op_can_toggle_status")
|
||||||
|
end
|
||||||
|
|
||||||
|
# topic must be open
|
||||||
|
if post.topic.try(:closed) || post.topic.try(:archived)
|
||||||
|
raise StandardError.new I18n.t("poll.topic_must_be_open_to_toggle_status")
|
||||||
|
end
|
||||||
|
|
||||||
|
polls = post.custom_fields[POLLS_CUSTOM_FIELD]
|
||||||
|
|
||||||
|
raise StandardError.new I18n.t("poll.no_polls_associated_with_this_post") if polls.blank?
|
||||||
|
raise StandardError.new I18n.t("poll.no_poll_with_this_name", name: poll_name) if polls[poll_name].blank?
|
||||||
|
|
||||||
|
polls[poll_name]["status"] = status
|
||||||
|
|
||||||
|
post.save_custom_fields(true)
|
||||||
|
|
||||||
|
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
|
||||||
|
|
||||||
|
polls[poll_name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
require_dependency "application_controller"
|
require_dependency "application_controller"
|
||||||
class DiscoursePoll::PollsController < ::ApplicationController
|
class DiscoursePoll::PollsController < ::ApplicationController
|
||||||
requires_plugin PLUGIN_NAME
|
requires_plugin PLUGIN_NAME
|
||||||
@ -38,42 +113,11 @@ after_initialize do
|
|||||||
options = params.require(:options)
|
options = params.require(:options)
|
||||||
user_id = current_user.id
|
user_id = current_user.id
|
||||||
|
|
||||||
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post_id}") do
|
begin
|
||||||
post = Post.find(post_id)
|
poll, options = DiscoursePoll::Poll.vote(post_id, poll_name, options, user_id)
|
||||||
|
|
||||||
# topic must be open
|
|
||||||
if post.topic.try(:closed) || post.topic.try(:archived)
|
|
||||||
return render_json_error I18n.t("poll.topic_must_be_open_to_vote")
|
|
||||||
end
|
|
||||||
|
|
||||||
polls = post.custom_fields[POLLS_CUSTOM_FIELD]
|
|
||||||
|
|
||||||
return render_json_error I18n.t("poll.no_polls_associated_with_this_post") if polls.blank?
|
|
||||||
|
|
||||||
poll = polls[poll_name]
|
|
||||||
|
|
||||||
return render_json_error I18n.t("poll.no_poll_with_this_name", name: poll_name) if poll.blank?
|
|
||||||
return render_json_error I18n.t("poll.poll_must_be_open_to_vote") if poll["status"] != "open"
|
|
||||||
|
|
||||||
votes = post.custom_fields["#{VOTES_CUSTOM_FIELD}-#{user_id}"] || {}
|
|
||||||
vote = votes[poll_name] || []
|
|
||||||
|
|
||||||
poll["total_votes"] += 1 if vote.size == 0
|
|
||||||
|
|
||||||
poll["options"].each do |option|
|
|
||||||
option["votes"] -= 1 if vote.include?(option["id"])
|
|
||||||
option["votes"] += 1 if options.include?(option["id"])
|
|
||||||
end
|
|
||||||
|
|
||||||
votes[poll_name] = options
|
|
||||||
|
|
||||||
post.custom_fields[POLLS_CUSTOM_FIELD] = polls
|
|
||||||
post.custom_fields["#{VOTES_CUSTOM_FIELD}-#{user_id}"] = votes
|
|
||||||
post.save_custom_fields(true)
|
|
||||||
|
|
||||||
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
|
|
||||||
|
|
||||||
render json: { poll: poll, vote: options }
|
render json: { poll: poll, vote: options }
|
||||||
|
rescue StandardError => e
|
||||||
|
render_json_error e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -81,32 +125,13 @@ after_initialize do
|
|||||||
post_id = params.require(:post_id)
|
post_id = params.require(:post_id)
|
||||||
poll_name = params.require(:poll_name)
|
poll_name = params.require(:poll_name)
|
||||||
status = params.require(:status)
|
status = params.require(:status)
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post_id}") do
|
begin
|
||||||
post = Post.find(post_id)
|
poll = DiscoursePoll::Poll.toggle_status(post_id, poll_name, status, user_id)
|
||||||
|
render json: { poll: poll }
|
||||||
# either staff member or OP
|
rescue StandardError => e
|
||||||
unless current_user.try(:staff?) || current_user.try(:id) == post.user_id
|
render_json_error e.message
|
||||||
return render_json_error I18n.t("poll.only_staff_or_op_can_toggle_status")
|
|
||||||
end
|
|
||||||
|
|
||||||
# topic must be open
|
|
||||||
if post.topic.try(:closed) || post.topic.try(:archived)
|
|
||||||
return render_json_error I18n.t("poll.topic_must_be_open_to_toggle_status")
|
|
||||||
end
|
|
||||||
|
|
||||||
polls = post.custom_fields[POLLS_CUSTOM_FIELD]
|
|
||||||
|
|
||||||
return render_json_error I18n.t("poll.no_polls_associated_with_this_post") if polls.blank?
|
|
||||||
return render_json_error I18n.t("poll.no_poll_with_this_name", name: poll_name) if polls[poll_name].blank?
|
|
||||||
|
|
||||||
polls[poll_name]["status"] = status
|
|
||||||
|
|
||||||
post.save_custom_fields(true)
|
|
||||||
|
|
||||||
DiscourseBus.publish("/polls/#{post_id}", { polls: polls })
|
|
||||||
|
|
||||||
render json: { poll: polls[poll_name] }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user