Store when a topic was first set to auto-close and report that amount of time when it closes. And do some refactoring.

This commit is contained in:
Neil Lalonde
2013-06-06 17:04:10 -04:00
parent b758427572
commit a151bfc7ec
7 changed files with 119 additions and 22 deletions

View File

@ -119,8 +119,7 @@ class TopicsController < ApplicationController
raise Discourse::InvalidParameters.new(:auto_close_days) unless params.has_key?(:auto_close_days) raise Discourse::InvalidParameters.new(:auto_close_days) unless params.has_key?(:auto_close_days)
@topic = Topic.where(id: params[:topic_id].to_i).first @topic = Topic.where(id: params[:topic_id].to_i).first
guardian.ensure_can_moderate!(@topic) guardian.ensure_can_moderate!(@topic)
@topic.auto_close_days = params[:auto_close_days] @topic.set_auto_close(params[:auto_close_days], current_user)
@topic.auto_close_user = current_user
@topic.save @topic.save
render nothing: true render nothing: true
end end

View File

@ -107,8 +107,7 @@ class Topic < ActiveRecord::Base
self.bumped_at ||= Time.now self.bumped_at ||= Time.now
self.last_post_user_id ||= user_id self.last_post_user_id ||= user_id
if !@ignore_category_auto_close and self.category and self.category.auto_close_days and self.auto_close_at.nil? if !@ignore_category_auto_close and self.category and self.category.auto_close_days and self.auto_close_at.nil?
self.auto_close_at = self.category.auto_close_days.days.from_now set_auto_close(self.category.auto_close_days)
self.auto_close_user = (self.user.staff? ? self.user : Discourse.system_user)
end end
end end
@ -124,6 +123,7 @@ class Topic < ActiveRecord::Base
before_save do before_save do
if (auto_close_at_changed? and !auto_close_at_was.nil?) or (auto_close_user_id_changed? and auto_close_at) if (auto_close_at_changed? and !auto_close_at_was.nil?) or (auto_close_user_id_changed? and auto_close_at)
self.auto_close_started_at ||= Time.zone.now
Jobs.cancel_scheduled_job(:close_topic, {topic_id: id}) Jobs.cancel_scheduled_job(:close_topic, {topic_id: id})
true true
end end
@ -583,8 +583,23 @@ class Topic < ActiveRecord::Base
def auto_close_days=(num_days) def auto_close_days=(num_days)
@ignore_category_auto_close = true @ignore_category_auto_close = true
set_auto_close(num_days)
end
def set_auto_close(num_days, by_user=nil)
num_days = num_days.to_i num_days = num_days.to_i
self.auto_close_at = (num_days > 0 ? num_days.days.from_now : nil) self.auto_close_at = (num_days > 0 ? num_days.days.from_now : nil)
if num_days > 0
self.auto_close_started_at ||= Time.zone.now
if by_user and by_user.staff?
self.auto_close_user = by_user
else
self.auto_close_user ||= (self.user.staff? ? self.user : Discourse.system_user)
end
else
self.auto_close_started_at = nil
end
self
end end
def secure_category? def secure_category?
@ -641,6 +656,7 @@ end
# slug :string(255) # slug :string(255)
# auto_close_at :datetime # auto_close_at :datetime
# auto_close_user_id :integer # auto_close_user_id :integer
# auto_close_started_at :datetime
# #
# Indexes # Indexes
# #

View File

@ -25,7 +25,12 @@ TopicStatusUpdate = Struct.new(:topic, :user) do
end end
def message_for(status) def message_for(status)
I18n.t status.locale_key, count: topic.age_in_days if status.autoclosed?
num_days = topic.auto_close_started_at ? ((Time.zone.now - topic.auto_close_started_at) / 1.day).round : topic.age_in_days
I18n.t status.locale_key, count: num_days
else
I18n.t status.locale_key
end
end end
def options_for(status) def options_for(status)

View File

@ -0,0 +1,5 @@
class AddAutoCloseStartedAtToTopics < ActiveRecord::Migration
def change
add_column :topics, :auto_close_started_at, :datetime
end
end

View File

@ -612,17 +612,12 @@ describe TopicsController do
end end
it "can set a topic's auto close time" do it "can set a topic's auto close time" do
Topic.any_instance.expects(:auto_close_days=).with { |arg| arg.to_i == 3 } Topic.any_instance.expects(:set_auto_close).with("3", @admin)
xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: 3 xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: 3
end end
it "can remove a topic's auto close time" do it "can remove a topic's auto close time" do
Topic.any_instance.expects(:auto_close_days=).with(nil) Topic.any_instance.expects(:set_auto_close).with(nil, anything)
xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: nil
end
it "sets the topic closer to the current user" do
Topic.any_instance.expects(:auto_close_user=).with(@admin)
xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: nil xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: nil
end end
end end

View File

@ -52,6 +52,7 @@ describe Topic do
context 'category has a default auto-close' do context 'category has a default auto-close' do
Given(:category) { Fabricate(:category, auto_close_days: 2.0) } Given(:category) { Fabricate(:category, auto_close_days: 2.0) }
Then { topic.auto_close_at.should == 2.days.from_now } Then { topic.auto_close_at.should == 2.days.from_now }
And { topic.auto_close_started_at.should == Time.zone.now }
And { scheduled_jobs_for(:close_topic, {topic_id: topic.id}).should have(1).job } And { scheduled_jobs_for(:close_topic, {topic_id: topic.id}).should have(1).job }
And { scheduled_jobs_for(:close_topic, {topic_id: category.topic.id}).should be_empty } And { scheduled_jobs_for(:close_topic, {topic_id: category.topic.id}).should be_empty }

View File

@ -657,15 +657,25 @@ describe Topic do
let(:status) { 'autoclosed' } let(:status) { 'autoclosed' }
it_should_behave_like 'a status that closes a topic' it_should_behave_like 'a status that closes a topic'
context 'topic was set to close when it was created' do
it 'puts the autoclose duration in the moderator post' do it 'puts the autoclose duration in the moderator post' do
@topic.created_at = 3.days.ago @topic.created_at = 3.days.ago
@topic.update_status(status, true, @user) @topic.update_status(status, true, @user)
expect(@topic.posts.last.raw).to include "closed after 3 days" expect(@topic.posts.last.raw).to include "closed after 3 days"
end end
end end
context 'topic was set to close after it was created' do
it 'puts the autoclose duration in the moderator post' do
@topic.created_at = 7.days.ago
Timecop.freeze(2.days.ago) do
@topic.set_auto_close(2)
end
@topic.update_status(status, true, @user)
expect(@topic.posts.last.raw).to include "closed after 2 days"
end
end
end
end end
describe 'toggle_star' do describe 'toggle_star' do
@ -1027,7 +1037,7 @@ describe Topic do
it 'queues a job to close the topic' do it 'queues a job to close the topic' do
Timecop.freeze(Time.zone.now) do Timecop.freeze(Time.zone.now) do
Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) )) Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
Fabricate(:topic, auto_close_at: 7.days.from_now, user: Fabricate(:admin)) Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin))
end end
end end
@ -1036,7 +1046,7 @@ describe Topic do
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args| Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
job_args[:user_id] == topic_creator.id job_args[:user_id] == topic_creator.id
end end
Fabricate(:topic, auto_close_at: 7.days.from_now, user: topic_creator) Fabricate(:topic, auto_close_days: 7, user: topic_creator)
end end
it 'when auto_close_user_id is set, it will use it as the topic closer' do it 'when auto_close_user_id is set, it will use it as the topic closer' do
@ -1045,13 +1055,20 @@ describe Topic do
Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args| Jobs.expects(:enqueue_at).with do |datetime, job_name, job_args|
job_args[:user_id] == topic_closer.id job_args[:user_id] == topic_closer.id
end end
Fabricate(:topic, auto_close_at: 7.days.from_now, auto_close_user: topic_closer, user: topic_creator) Fabricate(:topic, auto_close_days: 7, auto_close_user: topic_closer, user: topic_creator)
end end
it "ignores the category's default auto-close" do it "ignores the category's default auto-close" do
Timecop.freeze(Time.zone.now) do Timecop.freeze(Time.zone.now) do
Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) )) Jobs.expects(:enqueue_at).with(7.days.from_now, :close_topic, all_of( has_key(:topic_id), has_key(:user_id) ))
Fabricate(:topic, auto_close_at: 7.days.from_now, user: Fabricate(:admin), category: Fabricate(:category, auto_close_days: 2)) Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin), category: Fabricate(:category, auto_close_days: 2))
end
end
it 'sets the time when auto_close timer starts' do
Timecop.freeze(Time.zone.now) do
topic = Fabricate(:topic, auto_close_days: 7, user: Fabricate(:admin))
expect(topic.auto_close_started_at).to eq(Time.zone.now)
end end
end end
end end
@ -1142,6 +1159,65 @@ describe Topic do
end end
end end
describe 'set_auto_close' do
let(:topic) { Fabricate.build(:topic) }
let(:closing_topic) { Fabricate.build(:topic, auto_close_days: 5) }
let(:admin) { Fabricate.build(:user, id: 123) }
before { Discourse.stubs(:system_user).returns(admin) }
it 'sets auto_close_at' do
Timecop.freeze(Time.zone.now) do
topic.set_auto_close(3, admin)
expect(topic.auto_close_at).to eq(3.days.from_now)
end
end
it 'sets auto_close_user to given user if it is a staff user' do
topic.set_auto_close(3, admin)
expect(topic.auto_close_user_id).to eq(admin.id)
end
it 'sets auto_close_user to system user if given user is not staff' do
topic.set_auto_close(3, Fabricate.build(:user, id: 444))
expect(topic.auto_close_user_id).to eq(admin.id)
end
it 'sets auto_close_user to system_user if user is not given and topic creator is not staff' do
topic.set_auto_close(3)
expect(topic.auto_close_user_id).to eq(admin.id)
end
it 'sets auto_close_user to topic creator if it is a staff user' do
staff_topic = Fabricate.build(:topic, user: Fabricate.build(:admin, id: 999))
staff_topic.set_auto_close(3)
expect(staff_topic.auto_close_user_id).to eq(999)
end
it 'clears auto_close_at if num_days is nil' do
closing_topic.set_auto_close(nil)
expect(closing_topic.auto_close_at).to be_nil
end
it 'clears auto_close_started_at if num_days is nil' do
closing_topic.set_auto_close(nil)
expect(closing_topic.auto_close_started_at).to be_nil
end
it 'updates auto_close_at if it was already set to close' do
Timecop.freeze(Time.zone.now) do
closing_topic.set_auto_close(14)
expect(closing_topic.auto_close_at).to eq(14.days.from_now)
end
end
it 'does not update auto_close_started_at if it was already set to close' do
expect{
closing_topic.set_auto_close(14)
}.to_not change(closing_topic, :auto_close_started_at)
end
end
describe '#secure_category?' do describe '#secure_category?' do
let(:category){ Category.new } let(:category){ Category.new }