diff --git a/db/migrate/20190718152804_reclaim_from_disabled_category.rb b/db/migrate/20190718152804_reclaim_from_disabled_category.rb new file mode 100644 index 0000000..407edf5 --- /dev/null +++ b/db/migrate/20190718152804_reclaim_from_disabled_category.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class ReclaimFromDisabledCategory < ActiveRecord::Migration[5.2] + def up + aliases = { + votes: DiscourseVoting::VOTES, + votes_archive: DiscourseVoting::VOTES_ARCHIVE, + voting_enabled: DiscourseVoting::VOTING_ENABLED + } + + # archive votes in non-voting categories + DB.exec(<<~SQL, aliases) + UPDATE user_custom_fields ucf + SET name = :votes_archive + FROM topics t + WHERE ucf.name = :votes + AND t.id::text = ucf.value + AND t.category_id NOT IN ( + SELECT category_id FROM category_custom_fields WHERE name=:voting_enabled AND value='true' + ) + SQL + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/plugin.rb b/plugin.rb index 1e20c85..f4df820 100755 --- a/plugin.rb +++ b/plugin.rb @@ -115,11 +115,56 @@ after_initialize do end after_save :reset_voting_cache + after_find :track_voting_enabled + after_save :reclaim_release_votes protected def reset_voting_cache ::Category.reset_voting_cache end + + def track_voting_enabled + return unless SiteSetting.voting_enabled + @old_enable_voting = custom_fields[::DiscourseVoting::VOTING_ENABLED] + end + + def reclaim_release_votes + return unless SiteSetting.voting_enabled + + aliases = { + votes: DiscourseVoting::VOTES, + votes_archive: DiscourseVoting::VOTES_ARCHIVE, + category_id: id + } + + was_enabled = @old_enable_voting + is_enabled = custom_fields[::DiscourseVoting::VOTING_ENABLED] + + if !was_enabled && is_enabled + # Unarchive all votes in the category + DB.exec(<<~SQL, aliases) + UPDATE user_custom_fields ucf + SET name = :votes + FROM topics t + WHERE ucf.name = :votes_archive + AND NOT t.closed + AND NOT t.archived + AND t.deleted_at IS NULL + AND t.id::text = ucf.value + AND t.category_id = :category_id + SQL + elsif was_enabled && !is_enabled + # Archive all votes in category + DB.exec(<<~SQL, aliases) + UPDATE user_custom_fields ucf + SET name = :votes_archive + FROM topics t + WHERE ucf.name = :votes + AND t.id::text = ucf.value + AND t.category_id = :category_id + SQL + end + end end require_dependency 'user' diff --git a/spec/voting_spec.rb b/spec/voting_spec.rb index c8ac742..325e0c7 100644 --- a/spec/voting_spec.rb +++ b/spec/voting_spec.rb @@ -157,4 +157,46 @@ describe DiscourseVoting do expect(Jobs::VoteReclaim.jobs.size).to eq(0) end end + + context "when a category has voting enabled/disabled" do + let(:category3) { Fabricate(:category) } + let(:topic2) { Fabricate(:topic, category: category3) } + + before do + category1.custom_fields["enable_topic_voting"] = true + category1.save! + + category2.custom_fields["enable_topic_voting"] = true + category2.save! + + category3.custom_fields["enable_topic_voting"] = false + category3.save! + + user0.custom_fields[DiscourseVoting::VOTES] = [topic0.id, topic1.id] + user0.custom_fields[DiscourseVoting::VOTES_ARCHIVE] = [topic2.id] + user0.save! + end + + it "reclaims votes when voting is disabled on a category" do + category = Category.find(category1.id) + category.custom_fields["enable_topic_voting"] = false + category.save! + + user0.reload + + expect(user0.custom_fields[DiscourseVoting::VOTES]).to contain_exactly(topic1.id) + expect(user0.custom_fields[DiscourseVoting::VOTES_ARCHIVE]).to contain_exactly(topic0.id, topic2.id) + end + + it "restores votes when voting is enabled on a category" do + category = Category.find(category3.id) + category.custom_fields["enable_topic_voting"] = true + category.save! + + user0.reload + + expect(user0.custom_fields[DiscourseVoting::VOTES]).to contain_exactly(topic0.id, topic1.id, topic2.id) + expect(user0.custom_fields[DiscourseVoting::VOTES_ARCHIVE]).to eq(nil) + end + end end